二進(jìn)制安全之堆溢出(系列)—— off by one
本文是二進(jìn)制安全之堆溢出系列的第六章節(jié),主要介紹off by one。
原理
由于prev_size可以復(fù)用的機(jī)制,off by one 可以更改后一個chunk的size大小
off by one 造后向合并時,如果當(dāng)前堆塊大小不屬于fastbin,注意第三個堆塊的prev_inuse需要為1
free 掉合并后的堆塊,然后malloc 取出,就造成了堆塊重疊,即大堆塊里面包含了之前的被迫合并的小堆塊,且小堆塊可以控制
后續(xù)再進(jìn)行fastbin attack!!
Demo
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
int main()
{
? ? char *p = malloc(0x18);
? ? char *q = malloc(0x18);
? ? char *r = malloc(0x18);
? ? sleep(0);
? ? strcpy(p,"aaaaaaaabbbbbbbbcccccccc\x41");?
? ? free(q);
? ? sleep(0);
? ? malloc(0x30);?
? ? printf("%p\n",p);
? ? printf("%p\n",q);
? ? printf("%p\n",r);
? ? sleep(0);
? ? return 0;
}
調(diào)試
修改 q 的 size為 0×41
pwndbg> x/20gz 0x602000
0x602000:? ?0x0000000000000000? 0x0000000000000021
0x602010:? ?0x6161616161616161? 0x6262626262626262
0x602020:? ?0x6363636363636363? 0x0000000000000041? ? ? //q的size
0x602030:? ?0x0000000000000000? 0x0000000000000000
0x602040:? ?0x0000000000000000? 0x0000000000000021
0x602050:? ?0x0000000000000000? 0x0000000000000000
0x602060:? ?0x0000000000000000? 0x0000000000000411??
0x602070:? ?0x3035303230367830? 0x000000000000000a
?
如果改為0×51,free q的時候理論上會和top chunk的prev_size和size發(fā)生合并,而此時系統(tǒng)把top chunk的fd和bk當(dāng)成prev_size和size來作為合并的檢查條件,是不合法的,并且會報錯??!
free(): invalid next size (fast)
?
查看glibc的對應(yīng)的檢查機(jī)制
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
? ? ? ? ? ? ? <= 2 * SIZE_SZ, 0)
? ? || __builtin_expect (chunksize (chunk_at_offset (p, size))
? ? ? ? ? ? ? ? ?>= av->system_mem, 0))
? ?{
? ? bool fail = true;
? ? /* We might not have a lock at this point and concurrent modifications
? ? ? ?of system_mem might result in a false positive.? Redo the test after
? ? ? ?getting the lock.? */
? ? if (!have_lock)
? ? ? {
? ? ? ? __libc_lock_lock (av->mutex);
? ? ? ? fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
? ? ? ? ? ? || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
? ? ? ? __libc_lock_unlock (av->mutex);
? ? ? }
?
? ? if (fail)
? ? ? malloc_printerr ("free(): invalid next size (fast)");
? ?}
此時的bins
0x40: 0x602020 ?— 0x0
malloc 合并后的堆塊
0x40: 0x0
已經(jīng)把合并的塊malloc出去了
此時 p q r 的地址
0x602010
0x602030
0x602050
即現(xiàn)在的r堆塊仍然邏輯上存在
free r 堆塊
0x20: 0x602040 ?— 0x0
這時我們可以通過大堆塊修改 r 塊的fd,構(gòu)造fastbin attack
