二進(jìn)制安全之堆溢出(系列)——“堆基礎(chǔ)&結(jié)構(gòu)”第三節(jié)上回書(shū)說(shuō)到_int_malloc小總結(jié)本次咱們從calloc講起
在就放入fastbin不在放入unsorted bin
前向合并:向低地址合并后向合并:向高地址合并
檢查當(dāng)前的塊的prev_inuse是否為0檢查下個(gè)塊的prev_insue是否為1檢查下下個(gè)塊的prev_insue是否為1此時(shí)發(fā)生前向合并如果下下個(gè)塊的prev_insue為0,則會(huì)前向合并之后再后向合并
檢查是否有__free_hook ,利用:__free_hook->sysem如果堆塊是空則不進(jìn)行操作mmap的堆塊,使用ummap進(jìn)行釋放然后調(diào)用__int_free
? ?__malloc_hook
? ?
? ? malloc_hookl利用方法
1. 現(xiàn)在知道了system或一個(gè)shellcode的地址2. 要調(diào)這個(gè)shellcode的地址可以通過(guò)修改got表3. 在Partial RELRO保護(hù)機(jī)制下,無(wú)法寫(xiě)入got表4. 這時(shí)候可以修改__malloc_hook地址為one_gadget的地址,構(gòu)造rop鏈,自5. 動(dòng)調(diào)用shellcode,起一個(gè)bin/sh。
6. 對(duì)于__free_hook,可以將其直接修改為system的地址,最簡(jiǎn)單的就是傳入7. 7. 一個(gè)"bin/sh"的指針,這樣當(dāng)free某個(gè)堆塊的時(shí)候就會(huì)調(diào)用/bin/sh。8. 因?yàn)開(kāi)_malloc_hook的參數(shù)類(lèi)型為int,不能傳一個(gè)字符串的地址 "/bin/sh"9. 從而繞過(guò)Partial RELRO保護(hù)機(jī)制
1. 將fastbin的fd指向[__malloc_hook+0x23] 或[ __free_hook]2. 再次malloc就會(huì)將[__malloc_hook+0x23] 或[ __free_hook]分配出來(lái)3. 在[__malloc_hook+0x23] 或[ __free_hook]寫(xiě)一個(gè)地址,如"bin/sh"或shellcode,one_gadget的地址
釋放一個(gè)不屬于fastbin的chunk,并且該chunk不與top_chunk緊鄰時(shí),就會(huì)進(jìn)入unsortedbin切割一個(gè)較大的chunk時(shí),如果剩下的部分大于minsize時(shí),就會(huì)被放到unsortedbin中unsortedbin管理bins鏈的原則 : 雙向循環(huán)鏈表,F(xiàn)IFOunsortedbin只有一個(gè)鏈表,即bin數(shù)組的第一個(gè)索引處當(dāng)unsorted bin被遍歷一次之后,會(huì)觸發(fā)整理,將相應(yīng)大小的chunk place in order
0x7ffff7dd1000 0x7ffff7dd3000 rw-p 2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.solibc_arrd = libc_on - libc.symbol("main_arena") - 88
1. 構(gòu)造overlap,控制一個(gè)釋放了還能修改的chunk
2. 修改當(dāng)前chunk的fd為target -0x23 的地址 3. 在進(jìn)行斷鏈操作時(shí),當(dāng)前chunk的bk指向的地址bck賦給av->bk,將main_arena的地址賦給bck->fd,而bck->fd即當(dāng)前chunk的fd
4. 即我們將target - 0x23處寫(xiě)入了main_arena的地址 a. main_arena為libc中的地址,以0x7f打頭b. target-0x23正好向size位寫(xiě)入0x7f,只寫(xiě)size的倒數(shù)第4位c. 這樣我們就在target中寫(xiě)了一個(gè)0x7f的內(nèi)容d. 然后就可以結(jié)合fastbin,將target malloc出來(lái),完成任意地址堆塊的創(chuàng)建和讀寫(xiě) 5. 因?yàn)閙ain_arena的bk被修改了,unsortedbin的鏈表結(jié)構(gòu)被破壞
6. 因此再次分配堆塊的時(shí)候不能從unsortedbin上分配,而從fastedbin中分配(提前在fastedbin放幾個(gè)chunk)
? 3733 while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av)) //當(dāng)前chunk為空是bk指向本身
? ? last remainder
? ? 在用戶(hù)malloc請(qǐng)求分配內(nèi)存之后,ptmalloc找到的chunk與目標(biāo)申請(qǐng)的大小不一致時(shí),會(huì)進(jìn)行切割,剩余部分稱(chēng)為last remainder chunk,由 last_remainder 管理,存儲(chǔ)在unsortedbin中
? ? p main_arena可以查看last remainderlast_remainder = 0x6020a0
? ? 切割完成后會(huì)leak出<main_arena+376>的地址
? ?
? ? fast bin
單向鏈表的管理結(jié)構(gòu),類(lèi)似于C語(yǔ)言散列表的管理結(jié)構(gòu),分別以0x20,0x30,0x40到0x80為散列項(xiàng),相同的散列項(xiàng)被連接在一起ptmalloc專(zhuān)門(mén)設(shè)計(jì)了fastbin,用來(lái)管理程序在釋放一些較小的內(nèi)存塊,對(duì)應(yīng)malloc state結(jié)構(gòu)體中的fastbinY。
fastbin中的chunk的prev_inuse為1,故不會(huì)在遇到與之相鄰的chunk就發(fā)生合并,直到malloc_consolidate的時(shí)候會(huì)整理,實(shí)驗(yàn)在malloc大于0x400的時(shí)候兩個(gè)相鄰的fastbin會(huì)合并。每個(gè)bin管理的chunk默認(rèn)最大為0x80字節(jié),但是可以最大支持到0xa0字節(jié)fastbin最多支持10個(gè)bin,從0x20到0xa0
1. 當(dāng)用戶(hù)需要的chunk的大小小于fastbin中的最大大小的堆塊時(shí),ptmalloc會(huì)首先判斷fastbin中相應(yīng)的bin中是否有對(duì)應(yīng)大小的空閑塊,如果有的話(huà),直接獲取這個(gè)堆塊,沒(méi)有的話(huà),從top_chunk中分配并進(jìn)行一系列操作。 2. 出入到fastbin的堆塊采用LIFO原則 : 最近free的chunk,與main_arena直接相連,從main_arena遍歷,并且最先被分配出去 3. main_arena開(kāi)始對(duì)應(yīng)的散列項(xiàng)與0(null)相連,每插入一個(gè)chunk,在main_arena和0中間插一個(gè),每個(gè)插入的堆塊都直接和main_arena相連
ptmalloc默認(rèn)情況下會(huì)調(diào)用set_max_fast(DEFAULT_MAXFAST)將全局變量global_max_fast設(shè)置為DEFAULT_MAXFAST,即fastbin chunk的最大值。當(dāng)DEFAULT_MAXFAST設(shè)置為0時(shí),系統(tǒng)就不會(huì)支持fastbinfastbin索引的計(jì)算方法:fastbin_idx(size)
1. 構(gòu)造一個(gè)fastbin的overlap(堆塊重疊),造成釋放了當(dāng)前chunk還能對(duì)它修改 2. 修改當(dāng)前chunk的fd指向我們的target,當(dāng)釋放當(dāng)前chunk的時(shí)候,main_arena就會(huì)指向target?
3. 將偽造的地址的起始地址+0x8的內(nèi)存內(nèi)容即target的size修改為0x71或0x7f等,繞過(guò)chunk_size和prev_inuse的檢測(cè),后面的內(nèi)容可以隨意寫(xiě)入。(同一索引的chunk的大小在一個(gè)梯度內(nèi),檢查是否在此梯度)tips :libc的地址存在0x7fxxxx:0x7ffff7a0d000 0x7ffff7bcd000 r-xp 1c0000 0 /lib/x86_64-linux-gnu/libc-2.23.so4. 再次malloc的時(shí)候,就會(huì)malloc出來(lái)target的堆塊,比如target為got或任意地址,造成函數(shù)執(zhí)行和任意地址寫(xiě)
? 斷鏈過(guò)程
? ?
small bins中一共有62個(gè)循環(huán)雙向鏈表,每個(gè)鏈表中存儲(chǔ)的chunk大小一致
small bins中每個(gè)bin對(duì)應(yīng)的鏈表采取FIFO的規(guī)則
每次去bin鏈中的chunk是從bk指向的位置取的,bk指向目前最早釋放進(jìn)來(lái)的chunk
32位對(duì)應(yīng)的SIZE_T為4,64位對(duì)應(yīng)的SIZE_T為8small bins的index從2到62比如說(shuō)對(duì)于64位機(jī)器,index = 2 ,chunk_size = 32;index = 62 ,chunk_size = 992
fastbin的chunk在經(jīng)過(guò)consolidate之后都會(huì)進(jìn)入到small bin中的0x20到0x80的對(duì)應(yīng)位置
large bin一共包含63個(gè)bin,每個(gè)bin中的chunk的大小不一致,處于一個(gè)相同的范圍63個(gè)bin被分為公差一致的六組 :第一組 : 索引64-95 數(shù)量32 起始大小1024 公差64 [1024,1024+64]第二組 : 索引96-111 數(shù)量16 起始大小xxxx 公差512第三組 : 索引112-119 數(shù)量8 起始大小xxxx 公差4096第四組 : 索引120-123 數(shù)量4 起始大小xxxx 公差32768第五組 : 索引124-125 數(shù)量2 起始大小xxxx 公差262144第六組 : 索引126 數(shù)量1 起始大小xxxx 公差無(wú)限制
與smallbin一樣采取FIFO的管理方式,不同的是largebin具有兩條雙向鏈表largebin中fd_nextsize和bk_nextsize按照chunk的大小排列,分別指向下一個(gè)更大size的chunk和更小的chunkfd和bk按照chunk的free順序排列(先來(lái)的和main_arena相連)·
要求target與當(dāng)前chunk在一個(gè)鏈上,大小范圍一致
碎塊合并
bin鏈的歸屬問(wèn)題
bin鏈的整理分類(lèi)
? ? consolidate
? ? fastbin范圍的chunk的inuse位始終為1,因此不會(huì)和其他釋放的chunk合并。當(dāng)釋放的chunk與該chunk相鄰的空閑chunk合并后的大小大于FAST_CONSOLIDATION_THRESHOLD時(shí),內(nèi)存碎片可能性比較多了,我們需要把fastbins中的chunk都進(jìn)行合并,以減少內(nèi)存碎片對(duì)系統(tǒng)的影響。malloc_consolidate函數(shù)可以將fastbin中所有能和其它c(diǎn)hunk合并的chunk合并在一起。0. 碎片檢查針對(duì)于fastbin的碎片整理
? ?
? ? 1. 觸發(fā)合并
? ? 第一次合并整理的時(shí)候malloc超過(guò)0x80的空間就會(huì)觸發(fā)合并
? ? 2. 開(kāi)始合并
? ? 將fastbin上取消的堆塊合并到unsortedbin
? ?
? ? 3. 開(kāi)始查找
? ? 遍歷查找當(dāng)前unsortedbin上合適的堆塊,必要的時(shí)候切割unsortedbin
?
后續(xù)內(nèi)容請(qǐng)看下一篇哦~~
還沒(méi)有評(píng)論,來(lái)說(shuō)兩句吧...