Heap--初探--基本漏洞

First fit规则

在malloc一个chunk时,先在bins中寻找能满足用户需求大小的chunk,也就是大于等于用户需求的大小然后返回,而不是一直遍历到完全符合的chunk。
比如说在unsortedbin中,找到了一个大于用户申请的chunk那么就会把这个chunk截断成最符合用户申请的大小然后返回,而剩下的那一块被填入Prev_size size等控制字段重新放入unsortedbin中。

利用这个规则可以产生UAF(use after free)漏洞。
实在找不到就从top chunk 去切,还不行就调用brk函数增大top chunk(增加量不是很大),用户需求的brk无法满足,就会调用mmap函数去映射一大块虚拟内存给用户使用。

UAF漏洞原理

void* ptr = malloc(0xn)
...
free(ptr)
...
void* matr = malloc(0xm) //其中m小于n

这里在free了这个chunk后并没有让留有该chunk地址的ptr置空,即ptr还是指向者该chunk的user data处地址,毕竟free只是改变了关键控制字段而已。
然后再次malloc一个小于n的m空间,依据first fit规则会将上个chunk的user data处地址返回到matr中。
所以这个chunk就被两个指针控制。

例子:how2heap

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    fprintf(stderr, "This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.\n");  <==== stderr输出错误信息,没有缓冲区
    fprintf(stderr, "glibc uses a first-fit algorithm to select a free chunk.\n");
    fprintf(stderr, "If a chunk is free and large enough, malloc will select this chunk.\n");
    fprintf(stderr, "This can be exploited in a use-after-free situation.\n");

    fprintf(stderr, "Allocating 2 buffers. They can be large, don't have to be fastbin.\n");
    char* a = malloc(0x512);
    char* b = malloc(0x256);
    char* c;

    fprintf(stderr, "1st malloc(0x512): %p\n", a);
    fprintf(stderr, "2nd malloc(0x256): %p\n", b);
    fprintf(stderr, "we could continue mallocing here...\n");
    fprintf(stderr, "now let's put a string at a that we can read later \"this is A!\"\n");
    strcpy(a, "this is A!");
    fprintf(stderr, "first allocation %p points to %s\n", a, a);

    fprintf(stderr, "Freeing the first one...\n");
    free(a);

    fprintf(stderr, "We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at %p\n", a);

    fprintf(stderr, "So, let's allocate 0x500 bytes\n");
    c = malloc(0x500);
    fprintf(stderr, "3rd malloc(0x500): %p\n", c);
    fprintf(stderr, "And put a different string here, \"this is C!\"\n");
    strcpy(c, "this is C!");
    fprintf(stderr, "3rd allocation %p points to %s\n", c, c);
    fprintf(stderr, "first allocation %p points to %s\n", a, a);
    fprintf(stderr, "If we reuse the first allocation, it now holds the data from the third allocation.\n");
}

这里先malloc了两个chunk,然后free掉chunk_a,继续malloc一个0x500的chunk_c.那么就会把之前chunk_a的user data地址返回(first fit规则)。
在chunk_a中先放入 this is A! free后chunk_c再次指向同一个chunk,然后填充 this is C 所以i 最后输出chunk_c 和 chunk_a的内容都是一样的:this is C。如下

This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.
glibc uses a first-fit algorithm to select a free chunk.
If a chunk is free and large enough, malloc will select this chunk.
This can be exploited in a use-after-free situation.
Allocating 2 buffers. They can be large, don't have to be fastbin.
1st malloc(0x512): 0x1526010   <======
2nd malloc(0x256): 0x1526530
we could continue mallocing here...
now let's put a string at a that we can read later "this is A!"  <======
first allocation 0x1526010 points to this is A!
Freeing the first one...
We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at 0x1526010
So, let's allocate 0x500 bytes
3rd malloc(0x500): 0x1526010   <======
And put a different string here, "this is C!"   <======
3rd allocation 0x1526010 points to this is C!   <======
first allocation 0x1526010 points to this is C!  <======
If we reuse the first allocation, it now holds the data from the third allocation.

至于为啥要mallocyige0x256,这个是为了防止free了chunk_a后chunk_a 和相邻 的top chunk合并(两个相邻的free chunk,fastbin的chunk除外),如果合并了那么chunk_a就没了就不会有first fit来利用了。

Double free

顾名思义就是程序对同一个chunk进行了两次free

void* ptr = malloc(0xn)
void* ptr1 = malloc(0xm)
...
free(ptr)
...
free(ptr1)
...
free(ptr)

注意不能接连两次free同一个chunk,稍微高一点版本的glibc就会报错。
大概情形如下

这个时候ptr会认为自己得到了一个可以使用的chunk,而这个chunk就是chunk1,与此同时fastbin以为自己这里还有一个free chunk—–chunk1.即chunk1同时被两个指针指向。
那么我就可以用ptr来修改chunk1中fd字段指向某个地址,使得fastbin以为自己除了chunk1又有了一个chunk。

Unsorted bin attack

unsorted bin取出chunk的部分:
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

所以在取出一个free chunk之前如果能把该chunk的bk字段改为一个特殊地址-0x10那么,就会让unsortedbin认为在取出该free chunk后还要连接bk指向的chunk:

如上图,那么target(特殊地址)将会被填入bin_addr,而bin_addr放在libc.so的数据段所以会是一个很大的数字。我们就可以达到一个任意地址写入一个大数的目的。主要来修改一些起到限制作用的字段,如fastbins的最大链表。可以为其他的攻击创造环境

House_of_force

利用堆溢出修改top chunk的 size字段。

我们利用覆盖将top chunk的size覆盖为0xfffffffff(32位最大地址)那么top chunk就会被堆管理器认为是这么大,就可以来覆盖高地址内存空间的值(stack)
那么如果我想覆盖下面低地址的值呢,malloc负数即可,因为malloc里的那个参数是定义为无符号数,所以负数会被判定为很大的数。如-1就是0xffffffff(4字节)负数以补码形式存在。
现在malloc(-16) ===> malloc_base + 0xfffffff0 ====> (malloc_base-16) + 0xfffffff0+16 ===>malloc_base-16.

这样就可以修改一些数据


  转载请注明: Squarer Heap--初探--基本漏洞

 上一篇
XCTF-CHALLENGE-note-service2 XCTF-CHALLENGE-note-service2
checksechunter@hunter:~/PWN/XCTF/xctf_challenge$ checksec note-service2 [*] '/home/hunter/PWN/XCTF/xctf_challenge/note-s
2020-09-11
下一篇 
XCTF-CHALLENGE-greeting_150 XCTF-CHALLENGE-greeting_150
昨天好不容易装上pwndbg,总是因为最后./setup时报错,说python3.6找不到命令,在网上找了很多教程都没用,最后把了解到pwndbg相当于一个加强版的gdb,然后我就把gdb删了就顺利装上了😭废话少说,回到题目~~ chec
2020-09-03
  目录