malloc源码分析(4)--free后mallocdouble free
文章目錄
- 測試代碼
- __libc_malloc
- __libc_malloc調用_int_malloc
- _int_malloc回到__libc_malloc
- 如何利用double free
- 測試代碼
- 測試代碼2
之前我們從源碼的角度分析了如何初始化heap并且從top chunk分配出了第一個塊fast bin,那么這次我們結合free fastchunk來分配相同size的fastbin
測試代碼
#include<malloc.h> int main(){void *p=malloc(0x18);*(int *)(p+8)=0xdeadbaaf;free(p);p=NULL;void *p1=malloc(0x18);return 0; }其實代碼很簡單,我們主要就是跟蹤一下從freechunk里面malloc出來究竟有哪些check
大概運行到這里吧,然后我們跟進
__libc_malloc
我們首先看看現在的main_arena
可以看到對應大小有一個空閑塊,并且flags是0代表有fastchunks
同時__malloc_hook為NULL,只要我們不設置,初始化后他就一直是NULL.所以我們這里不會去調用
獲取ar_ptr并且進入_int_malloc
__libc_malloc調用_int_malloc
這個函數兩個作用
- 如果需要的size太大,就返回0
- 正常請求就轉化成具體需要的size(需要考慮header)
那么多大算太大呢
internal_size_t也就是8,minsize也就是0x20,所以就是(unsigned)-0x200
具體為什么這個值我也不清楚,但一般情況下肯定都是滿足的
大部分都類似于之前提到的malloc
這里因為我們大小確實滿足,所以會進來,之前由于沒有初始化所以進不來
非常熟悉的操作,尋找到對應的fastbiny的地址
這里我們肯定會執行一次因為do while,如果victim==NULL代表里面確實沒有就跳出,然后while的成立的條件其實是寫入失敗,因為寫入成功最后會返回victim,那么就相當于是false,所以一般我們也會成功,這里寫while可能會涉及多線程,但單線程的時候如果有free chunk就相當于我把victim->fd寫到fastbiny里面,就相當于拿出來一個
這里其實是檢查fastbiny的大小是否和我們需要的size匹配,一般來說是匹配的,如果失敗說明這個fastbin鏈表被修改了
額這個是源碼里面的
結果我直接跳到這里來了
感覺是這個優化的有點奇怪,我單步執行一下,好像執行了void *p=chunk2mem(victim);
然后這個allo_perturb和free_perturb都是一樣的,都不會執行
那么就回到了__libc_malloc
_int_malloc回到__libc_malloc
這里我們已經獲取到了要分配的區域,所以不會進去
解鎖
簡單檢查一下
就回來了
可以看到我們這里malloc的就是剛剛釋放的,并且里面還有數據
所以一般提倡malloc后立馬memset清空
如何利用double free
測試代碼
#include<malloc.h> int main(){void *p=malloc(0x18);void *p1=malloc(0x18);free(p);free(p1);free(p);void *p2=malloc(0x18);*(size_t*)p2=0xdeadbaff;return 0; }回到我們上次提到的double free,為了避免free check double free的情況,我們中間需要隨便free掉一個heap,然后就形成了這樣環形的情況
我們首先malloc一個
大家知道由于malloc不會清空heap內容,所以我們現在fastbiny保存的就應該是0x405020,然后這個時候我們修改一下fd的指針
可以看到變成這個樣子了
所以我們如果再malloc三次的話,第三次就應該可以malloc到我們需要任意寫的地方
為什么可以這樣呢?
其實我們通過剛才簡單的free malloc可以看出,我們fastbiny他是以0作為結束標準的,他不會去記錄你到底進去了幾個出來了幾個,只要里面不是0,我認為就還有,還可以分配,所以當我們修改了鏈之后,他就會乖乖去跟著fd去遍歷
而一般來說fd都是可以控制的,它屬于我們的data區域
那么我們接著攻擊,看可以可以malloc三次
測試代碼2
因為中間兩次的malloc其實是沒什么用的,所以我就沒保留指針
#include<malloc.h> int main(){void *p=malloc(0x18);void *p1=malloc(0x18);free(p);free(p1);free(p);void *p2=malloc(0x18);*(size_t*)p2=0xdeadbaff;malloc(0x18);malloc(0x18);void *p3=malloc(0x18);return 0; }如愿以償的修改成了deadbaff,我們執行一下
報錯,奧段錯誤,確實,這個地方不一定有內容,我們指向別的吧
這里其實我們要獲取__malloc_hook就要知道libc加載地址,但這里我遇到了點問題
dlopen是可以用來獲取so加載地址,類似于windows下的GetProcAddr,但這里如果我用的不是系統自身版本的libc就會報錯,暫時還不知道為什么
這里我們先寫死吧
這里可以看到我具體的加載地址
那么對于我就是這樣的
我們執行到這里可以看到,bins已經被修改到malloc_hook,也就是說我們malloc的第三個就在malloc_hook附近
臥槽,報錯了??,我們跟蹤一下
一直到_int_malloc都沒什么問題
問題還是出現在了這里
由于victim就是我們當前將要分配的區域,他會檢查這個大小是否匹配,如果不匹配就不分配
所以我們先要繞過這個大小檢查
這個也是fastbin attack里面需要特別構造的一點,就是大小匹配
注意到malloc上面這一塊,有一個比較特殊的偏移
可以看到有個7f的區域
那么我們再去看看chunksize的實現
size_bits其實就是4+2+1=7
所以相當于就是
fastbin_index的實現呢
左移4位減去2,剛好就是5,而5對應的大小就是0x70,所以我們要保證最后分配的塊實際大小是0x70
為什么這里0x78也可以呢,還記得我說idx是/16嘛,所以你多一點沒關系,畢竟我是整除,其實我個人覺得如果畢竟chunksize(victim)==size最好
因為這種不嚴格的判斷才導致我們可以利用0x7f來繞過,而且在實際中,一般塊的大小也只會收到1,2,4標記位的影響,我們chunksize已經去掉了,不知道這里為什么還要多此一舉反而可以讓我們繞過
接下來就是修改一下payload,因為要保證獲取0x70
#include<malloc.h> int main(){void *p=malloc(0x68);void *p1=malloc(0x68);free(p);free(p1);free(p);void *p2=malloc(0x68);*(size_t*)p2=0x7ffff7fcbb10;-0x23malloc(0x68);malloc(0x68);void *p3=malloc(0x68);return 0; }首先運行一下,可以看到成功分配
我們再調試一下
這個就是__malloc_hook上面的那個地址
bytes是我們需要的,nb是實際的,idx就是實際需要的fastbin對應的索引
當前的fastbiny地址和空閑塊地址
victim就是我們這里的pp
這里因為剛好符合我們的涉及就準備返回
回到主函數,確實也被修改了
這才是完整的malloc_hook對應的heap
我們找找malloc_hook的偏移0x23-0x10=0x13
這里我們測試就寫個deadbaaf,實際上需要寫一個one_gadget
所以總的大概double free就這樣啦
總結
以上是生活随笔為你收集整理的malloc源码分析(4)--free后mallocdouble free的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 远程计算机未配置身份验证出现问题怎么办,
- 下一篇: IDEA配置JDK、Maven 常见错误