How2heap--house_of_orange Hitcon2016--houseoforange

house of orange

修改topchunk->size为一个缩小的并且满足页对齐的大小,malloc一个大于size的块(但也不要大于mmap threshold),会导致原来topchunk被放入unsorted bin。

当topchunk不足以分配所需空间时,会调用sysmalloc分配额外空间。一般情况下,main_arena中old top chunk和新分配的top chunk首尾相邻,从而会进行合并。当我们将topchunk->size减小后,会检测不到相邻,也就不会合并了。设置好fencepost chunk,会执行_int_free (av, old_top, 1)将其放入unsorted bin。

代码涉及_int_malloc后边和sysmalloc

How2heap--house_of_einherjar SECON2016--tinypad

house of einherjar

和house of force很像,都是篡改top chunk。

off-by-one覆盖victim chunk的pre_in_use位,并修改victim->pre_size为距离目标地址的大小,在目标地址处伪造chunk,释放victim时,发生backward consolidate,合并到目标地址。

victim需要临近top chunk,backward consolidate结束,接着与top chunk进行forward consolidate。如果不这样,这个块被放入unsorted bin,而在unsorted bin中分配会过不了以下检查。

1
2
3
4
if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
              || __builtin_expect (chunksize_nomask (victim)
				   > av->system_mem, 0))
		malloc_printerr ("malloc(): memory corruption");

How2heap--large_bin_attack 0ctf2018--heapstorm2

large bin attack

对已存在于large bin中的chunk的bk、bk_nextsize字段进行更改,在unsorted bin中取出插入该large bin时,会将bk->fd、bk_nextsize->fd_nextsize的位置覆盖成chunk的地址。涉及的代码就是unsorted bin遍历取出插入那块。和先前的unsorted bin attack类似,通常为进一步攻击做准备,如修改global_max_fast。

这里比较难理解就是large bin的结构,特别是先前我被一个large bin结构图所误导,下面给出我画的结构图(如果有错误o((⊙﹏⊙))o,请帮忙指出)。

glibc large bin

0ctf2018 heapstorm2

1
2
3
4
5
Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

功能分析

程序首先使用mallopt函数将global_max_fast设置为0,也就是不使用fastbin。

How2heap--unsorted_bin_attack 0ctf2016--zerostorage

unsorted bin attack

对unsorted bin中的chunk->bk进行修改,接下来该chunk分配出去时,chunk->bk->fd就被赋值为unsortedbin头结点地址。

1
2
3
4
bck = victim->bk;
/* remove from unsorted list */
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

在glibc2.28中增加了以下检查,使得此攻击失效。

1
2
if (__glibc_unlikely (bck->fd != victim))
	malloc_printerr ("malloc(): corrupted unsorted chunks 3");

unsorted bin attack通常为进一步的攻击做准备,比如覆写global_max_fast。

0ctf2016 zerostorage

1
2
3
4
5
6
Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled
FORTIFY:  Enabled

关键数据结构

image-20200712102723178

flag:标识该节点是否存在

size:记录大小

content:数据块指针

程序有以下功能

1
2
3
4
5
6
7
1. Insert
2. Update
3. Merge
4. Delete
5. View
6. List
7. Exit

insert:获取数据块大小,并读入数据。数据块大小在128~4096这个范围内

update:对数据块进行大小内容进行更新

merge:将两节点合并。这里存在漏洞,输入两次相同的id,导致UAF。这个漏洞我没发现,思维还不够猥琐啊

delete:释放数据块,清空节点

总体思路

通过UAF,首先泄露libc基址,然后修改其bk指针,使用unsorted bin attack修改global_max_fast变量;fastbin bin attack覆写__free_hook为system函数地址。

How2heap--house_of_force Bctf2016--bcloud

House of force

溢出修改topchunk的size,分配一个使size_t溢出的evil_size,使下一次分配在目标位置,进行修改。

1
2
3
4
5
6
7
8
9
/*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = dest - 2sizeof(long) - old_top - 2sizeof(long)
* req = dest - old_top - 4*sizeof(long)
*/

Bctf2016 bcloud

分析

1
2
3
4
5
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x8047000)

程序一开始让输入name、org、hostname,输入字符串函数存在null byte overflow。

输入name函数中,字符串数组在栈中后部紧邻指针变量,所以strcpy会将该指针一并拷贝入0x40的空间(实际可用0x44),并且null byte覆盖topchunk的最低字节。可以泄露堆的地址

输入org、hostname函数中,存在同样问题,可覆盖的更多的字节。可以覆盖topchunk的size