借助hitcon training
的题目对三种堆的利用方法进行了一个系统的学习,刚入坑的堆小白们可以一起学习一下。题目链接:https://github.com/scwuaptx/HITCON-Training
mkdir + name
touch + name
echo 'context' > name
cat name
这是一个典型的use after free
很适合初次接触的人进行练习
可以发现是一个note
,这里有三个功能
可以发现add的功能是添加字条,第一个段是8字节然后用来储存函数指针 第二段是用来储存我们的输入的
这里可以发现del是一个删除操作,但是并没有让指针置0所以存在use after free
漏洞
是一个调用函数指针的一个过程
解题思路
chunk1
,chunk2
其中大小随意不要超过fastbin
的范围就可以了free chunk1
free chunk2
fastbin
中的分布是chunk2(8) -> chunk1(8)
chunk2(32) -> chunk1(32)
chunk3
大小为8
这个时候系统先分配chunk1(8)
的大小存放puts函数
然后分配chunk2(8)
作为我们的context
这个时候我们可以在这里写上magic函数
执行获取flag
简单的说use after free
就是利用free
之后指针没有被设置成NULL
然后我们可以在此malloc
出来使用。
第三个参数为unsigned
符号,当-1
时及0xffffffff
任意大小读
top chunk
的size域
malloc
分配的大小这里利用house of force
进行利用,题目的下方会对house of force
进行一个原理讲解
0x10
的空间给hello message
和goodbye_message函数
这里可以看见这里总共有5个选项其中选项1就是show item
,remove
就是正常的删除操作,5是正常的退出操作。接下来我们仔细看2,3两个选项
malloc
item
值就可以了修改物品的名字,根据给定的索引,以及大小,向指定索引的物品中读取指定长度名字。这里长度由用户来读入,也存在任意长度堆溢出的漏洞。
这里有一个我们的flag文件
可以让我们利用
malloc
一个块change the item in the box
进行长度的修改使得我们可以覆盖到top chunk
的size位置修改top chunk size=-1
(因为在其中size是无符号整数-1
会被解释为0xffffff
)所以size肯定就够我们用了house of force
的方法将top chunk
的位置放在heap base地址
0x10
的块,去修改函数指针为我们Magic
的地址
整个利用这样就完成这里利用house of force
top chunk
的大小malloc
将top chunk
放置到我们需要改写的那个地址上,可以是got表
的地址可以是分配的堆块地址。故名思义,就是对一个堆块进行了两次free, 但是free了同一个堆块两次,其中在glibc中对此有一个检查
其中是检查main_arean
是否指向向了原来的一个chunk
,这个就是非常容易绕过的只需要free(p1);free(p2);free(p1)
就可以绕过了。
这是我们执行doublefree
之后的图,此时malloc
出chunk1
,更改chunk1
的fd
,又因为此时chunk1
是在fastbin list
,也就是结构变成了下图
可以看见现在fastbin list
中会多指向一个我们的fakebin
(此时就可以进行任意地址写了)
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr (check_action, errstr, chunk2mem (victim));
return NULL;
}
其中会有一个对fakebin
,size
大小的检查,如果不满足当前fastbin链
中应该有的大小则会显示异常。
堆题一般都是些菜单题,这又是一道菜单题
add函数就是正常的malloc出堆块,然后输入一些数据,这里并没什么漏洞
visit函数就是遍历刚才我们所有建立的东西
一个删除函数,其中对指针进行了置0所以无法使用use after free,但是这里似乎可以利用double free
把所有已经创建了的都进行一个了删除
这是一个get_flag
的函数
利用的思路还是比较明显的,利用double free
进行一个got表
的改写。首先add函数
建立2个堆块,然后free(chunk1)->free(chunk2)->free(chunk1)
进行一个检查的bypass
。然后再执行add函数
,进行chunk1堆块
的fd指针
改写,然后连续free出chunk2,chunk1
和我们构造的fake_chunk
(这个chunk
的地址在got表
上),对got表
进行一个覆写,将puts函数``got表
改写成magic函数
的地址。
因为要bypass
对fakebin_size
的检查,所以在选got表
地址的时候需要gdb调试
一下,看存储的数的低四位满足要求,这里就选用了0x601ffa
,刚好可以满足条件
从这些3个利用方式来看,堆的学习主要是建立在对源码和对堆分配,回收等操作的熟悉的基础上。这里推荐用pwndbg
进行调试,还有一些大佬会用gef
和peda
以及一些插件的方法进行调试,具体看个人的习惯了。