網(wǎng)絡(luò)安全滲透測(cè)試之musl堆利用技巧
前言
最近比賽出的musl題型的越來(lái)越多,不得不學(xué)習(xí)一波musl的堆利用來(lái)應(yīng)對(duì)今后的比賽。這里要講的是musl1.22版本的利用,因?yàn)榫W(wǎng)上可以找到很多審計(jì)源碼的文章,所以這篇文章是通過(guò)一道題目來(lái)debug去學(xué)習(xí)堆的利用技巧,這里用到的是2021第五空間線上賽的notegame題目。
題目分析
1、首先是add函數(shù),使用了calloc,申請(qǐng)的最大size是0x90
2、接著是delete函數(shù),free之后將指針清空了
3、然后是edit函數(shù),漏洞就出現(xiàn)在這里,這里存在溢出空字節(jié)的漏洞,可以對(duì)index清零指向 fake_meta
4、最后來(lái)看這個(gè)update函數(shù),這個(gè)realloc函數(shù)會(huì)將原來(lái)chunk的內(nèi)容復(fù)制到新的chunk里面,我們可以用這個(gè)來(lái)進(jìn)行泄露libc地址
調(diào)試分析
musl的chunk跟glibc的區(qū)別就是,chunk頭的結(jié)構(gòu)存放了比較少的堆塊信息,沒(méi)有像glibc那樣存放了一些指針地址信息,所以我們?nèi)绻孤秎ibc地址的話也是要特定的條件,就是要chunk里面保存著另外一個(gè)chunk的指針地址或者其他指針地址的信息,而且也再不能直接改指針去達(dá)到任意分配的效果,而是要改chunk頭僅有的信息去偽造meta進(jìn)行任意分配。
malloc_context
add(0x20,'a'*0x20)
1、secret是用來(lái)校驗(yàn)meta域的一個(gè)key
2、free_meta_head存放著釋放掉的meta,是個(gè)單鏈表結(jié)構(gòu),這里還沒(méi)有釋放,所以為空
3、active是根據(jù)size大小分出來(lái)的不同的meta
4、usage_by_class是對(duì)應(yīng)meta的數(shù)量
meta
add(0x20,'a'*0x20) add(0x20,'a'*0x20) add(0x20,'a'*0x20) add(0x20,'a'*0x20) free(3)
1、prev和next分別是上一個(gè)和下一個(gè)meta頁(yè),這里都指向本身,表示只有一個(gè)meta頁(yè)
2、 mem表示group的地址,它是由多個(gè)chunk組成
3、avail_mask表示可以分配的chunk情況,0x3f0=0b01111110000,因?yàn)槲覀円呀?jīng)分配了4個(gè)堆塊,所以這里表示前四個(gè)不可分配。
4、freed_mask表示已經(jīng)釋放的chunk情況,因?yàn)槲覀冡尫诺袅说谝粋€(gè)chunk,所以這里的0x1表示的是free掉的第一個(gè)chunk
5、last_idx表示最后一個(gè)chunk的下標(biāo),這里是0x9,總數(shù)是0xa個(gè)
6、freeable表示已經(jīng)釋放的堆塊個(gè)數(shù)
7、sizeclass表示管理的group的大小
8、maplen如果不為零表示mmap分配的內(nèi)存頁(yè)數(shù)
chunk
add(0x20,'a'*0x20) add(0x20,'a'*0x20) add(0x20,'a'*0x20) add(0x20,'a'*0x20) free(3)
1、表示距離group首地址的偏移分別為0x0、0x30、0x60,系統(tǒng)是根據(jù)這個(gè)偏移來(lái)找到對(duì)應(yīng)的meta地址,所以我們?nèi)绻芨倪@個(gè)偏移比如把chunk1的偏移置零的話,就能在chunk1-0x10的地方偽造一個(gè)meta的指針,而這個(gè)地方又是我們可以控制的chunk0的data域,于是我們就可以在任意地方偽造一個(gè)meta,不過(guò)這個(gè)地址必須是跟0x1000對(duì)齊的。
2、表示當(dāng)前chunk的下標(biāo),當(dāng)chunk被free之后會(huì)變成0xff
3、表示剩下用戶(hù)空間的大小,chunk頭后面的4個(gè)字節(jié)跟glibc的prev_size那樣可以被上一個(gè)chunk復(fù)用, 所以我們就可知道我們分配的大小跟chunk大小的關(guān)系
0x10:0-0xc 0x20:0xd-0x1c 0x30:0x1d-0x2c 0x40:0x2d-0x3c ...
chunk的分配釋放
add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) free(0) add(0x50,'a'*0x50)
avail_mask = 0x10=0b10000
freed_mask = 0x1 =0b00001
musl的chunk釋放了之后并不會(huì)馬上分配,這里group里面有5個(gè)chunk,先是申請(qǐng)了3個(gè)chunk,然后free掉第一個(gè),再次申請(qǐng)的時(shí)候并不會(huì)把第一個(gè)chunk分配出來(lái),而是把group的第四個(gè)chunk申請(qǐng)出來(lái),然后對(duì)應(yīng)的avail_mask置零
add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) free(0) free(1) free(2) add(0x50,'a'*0x50) add(0x50,'a'*0x50)
avail_mask = 0x6 =0b0110
freed_mask = 0x0 =0b0000
耗盡group的chunk的時(shí)候,musl會(huì)把釋放掉的申請(qǐng)出來(lái),并把其他chunk對(duì)應(yīng)的avail_mask置1
meta的釋放
add(0x50,'a'*0x50) free(0)
當(dāng)只有一個(gè)chunk是被分配出去的,而freed_mask=0,我們把這個(gè)chunk給free掉之后,系統(tǒng)會(huì)回收整塊meta空間
add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) add(0x50,'a'*0x50) free(0) free(1) free(2) free(3) free(4)
總結(jié)起來(lái),就是說(shuō)avail_mask |freed_mask
的結(jié)果是滿(mǎn)狀態(tài)的時(shí)候,就會(huì)釋放這個(gè)meta。
總結(jié)
本篇先通過(guò)debug的方法來(lái)簡(jiǎn)單闡述musl堆塊的結(jié)構(gòu),后續(xù)再講如何對(duì)它進(jìn)行利用。
更多關(guān)于網(wǎng)絡(luò)安全滲透測(cè)試musl堆的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
10個(gè)好用的Web日志安全分析工具推薦小結(jié)
一款簡(jiǎn)單好用的Web日志分析工具,可以大大提升效率,目前業(yè)內(nèi)日志分析工具比較多,今天推薦十個(gè)比較好用的Web日志安全分析工具。感興趣的同學(xué)可以收藏一下2020-06-06網(wǎng)站中的隱形WebEditor文件上傳漏洞補(bǔ)丁
這篇文章主要介紹了網(wǎng)站中的隱形WebEditor文件上傳漏洞補(bǔ)丁2007-02-02