1. common tips:
environ
指向的地址 -30*size 为main
函数的返回地址的栈地址申请分配large chunk时,会进行
malloc_consolidate
,清空fastbins
表,进行合并scanf
,printf
当输入、输出过长时,会调用malloc
、free
addr(
main_arena
)-0x10 = addr(__malloc_hook
)unsorted bin泄露libc
malloc
、calloc
、realloc
区别calloc
在分配后会自动进行清空,libc 2.23版本如果设置 is_mmap不会清空- 当
realloc(ptr,size)
的size不等于ptr的size时- 如果申请size>原来size
- 如果chunk与top chunk相邻,直接扩展这个chunk到新size大小
- 如果chunk与top chunk不相邻,相当于
free(ptr)
,malloc(new_size)
- 如果申请size<原来size
- 如果相差不足以容得下一个最小chunk(64位下32个字节,32位下16个字节),则保持不变
- 如果相差可以容得下一个最小chunk,则切割原chunk为两部分,free掉后一部分
- 如果申请size>原来size
- 当
realloc(ptr,size)
的size等于0时,相当于free(ptr) - 当
realloc(ptr,size)
的size等于ptr的size,不进行任何操作
check_action & 2 = 0
时,堆错误不会退出,只会打印错误信息,同时设置main_arena->flags | 0x100
free_pertube
调用发生在向前合并和向后合并之前,所以如果设置了pertube位,不会将合并后增加的堆区域的内容设置为pertube
2. Heap exploit
unlink attack
条件:
- 存在堆溢出,可以伪造堆块和控制下一个堆块的头部
- 存在全局指针ptr指向堆块
方法:
- 伪造堆块
- fake_size = (current_size - size*2) | 1
- fd=ptr-size*3
- bk=ptr-size*2
- unlink成功之后
- ptr=ptr-size*3
- 编辑ptr指向的内容,修改ptr指向got表,再编辑ptr即可overwrite got表
- 伪造堆块
1
2
3
4
5
6
7
8
9
10chunk0 malloc返回的ptr chunk1 malloc返回的ptr
| | | |
+-----------+---------+----+----+----+----+----+------+------+----+----+------+
| | |fake|fake|fake|fake| D | fake | fake | | | |
| | |prev|size| FD | BK | A | prev | size&| | | |
| prev_size |size&Flag|size| | | | T | size | flag | | | |
| | | | | | | A | | | | | |
| | | | | | | | | | | | |
+-----------+---------+----+----+----+----+----+------+------+----+----+------+
|--------new_size--------|
fastbin attack
house of spirit
- 伪造chunk,free之后再次申请chunk进行攻击
- double free
- 重复释放同一个chunk,实现类似类型混淆的效果
Arbitrary Alloc(分配的堆块大小为0x70,限64位)
利用:
__malloc_hook
地址-0x28+5 作为伪造的fd指针(地址错位 ),填充0x13字节+ onegadget_addr1
2
3
4
5
6
7
8
9
102 = (void *(**)(size_t, const void *)) 0x7ff5dd109b10 <__malloc_hook>
dqs 0x7ff5dd109b10-0x28+5
00:0000│ 0x7ff5dd109aed (_IO_wide_data_0+301) ◂— 0xf5dd108260000000
01:0008│ 0x7ff5dd109af5 (_IO_wide_data_0+309) ◂— 0x7f
02:0010│ 0x7ff5dd109afd ◂— 0xf5dcdcae20000000
03:0018│ 0x7ff5dd109b05 (__memalign_hook+5) ◂— 0xf5dcdcaa0000007f
04:0020│ 0x7ff5dd109b0d (__realloc_hook+5) ◂— 0x7f
05:0028│ 0x7ff5dd109b15 (__malloc_hook+5) ◂— 0x0
...
07:0038│ 0x7ff5dd109b25 (main_arena+5) ◂— 0xc7604a04a0000000利用堆漏洞触发堆异常调用
malloc_printerr
打印堆错误,会调用malloc函数,执行one_gadget满足下列条件的one_gadget 触发更稳定
1
2
30xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
unsorted bin attack
- 条件:
- 能够控制 Unsorted Bin Chunk 的 bk 指针(bk = target_addr - 0x10)。
- 效果:
- 实现修改任意地址值为一个较大的数值(unsorte bin地址),例如
global_max_fast
,例如_IO_list_all
(house of orange)
- 实现修改任意地址值为一个较大的数值(unsorte bin地址),例如
House of Lore(small bin attack)
- 条件:
- 能够修改small bin中的bk指针
- 方法:
- 修改small bin中的bk指针指向伪造的chunk,同时令fake chunk的fd指针不等于small bin中的最后一个chunk
- 效果:
- 任意地址写
House Of Einherjar (small或large bin attack, top chunk)free时触发
- 条件:
- 需要有溢出漏洞可以写物理相邻的高地址的 prev_size 与 PREV_INUSE 部分。
- 我们需要计算fake_chunk与 被覆盖大小的chunk 地址之间的差,所以需要泄漏地址
- prev_size = &fake_chunk - & overwritten_prev_size_chunk_addr
- 我们需要在目的 chunk 附近构造相应的 fake chunk,从而绕过 unlink 的检测
- fake_chunk->fd = &fake_chunk
- fake_chunk->bk = &fake_chunk
- 方法:
- 覆盖相邻到地址的prev_size与PREV_INUSE标志位
- 效果:
- 任意地址写
House Of Force (top chunk)
- 条件:
- 能够以溢出等方式控制到 top chunk 的 size 域
- 能够自由地控制堆分配尺寸的大小
- 方法:
- 修改top chunk size域为-1,然后分配指定大小的堆块(计算偏移)
- 效果:
- 能够在任意地址分配堆块,实现任意地址写
House Of Orange (top chunk + unsorted bin + FILE attack)
- 条件:
- 首先需要目标漏洞是堆上的漏洞
- 不存在free函数或其他释放堆块的函数
- 方法:
- 伪造top chunk的size,满足
- 伪造的size必须要对齐到内存页
- size要大于MINSIZE(0x10)
- size要小于之后申请的chunk size + MINSIZE(0x10)
- size的prev inuse位必须为1
- 伪造top chunk的size,满足
- 效果:
- control the world