House of Roman 实战
前言
这是前几天国外一个 老哥 提出的一种思路 ,学习了一下感觉其中的堆布局的手法还不错,做个分享与记录。
这种利用手法的主要特点是不需要 leak libc
的地址,通过 堆内存的布局 和 堆相关的漏洞(uaf
等) 就可以 getshell
。下面一个示例的题目为例介绍一下
相关文件位于
|
|
漏洞分析
查看开启的保护措施
|
|
开了 pie
.
程序主要就三个功能
Malloc
, 用户输入size
, 然后malloc(size)
, 大小不限Write
, 往指定heap_ptr
写入size+1
字节数据,一字节溢出Free
, 调用free
释放掉heap_ptr
,不过没有清零,double free
和uaf
(Write
时只是校验 指针是否为0
).
漏洞利用
思路
因为没有 leak
的机会,同时还还有 aslr
, 因为 aslr
随机化的 比特数是有限的, 低 12bit
的随机化程度还是比较小,这就给了爆破的机会。
House of Roman
的一个核心思路就是利用 局部写 减少随机化的程度,从而给出爆破的可能。
程序开了 pie
,一般的思路就是 写 malloc_hook
或者其他的一些 hook
, 然后触发 malloc
, getshell
。
其中如果是
64
位程序,通过malloc_printerr
触发malloc
,基本可以稳定getshell
。
总的一个利用步骤如下 (chunk
指的是 malloc
源码中的 chunk
,包含元数据)
- 首先分配
3
个chunk (A , B, C)
,大小分别为0x20, 0xd0, 0x70
- 在
B + 0x78
处设置p64(0x61)
, 作用是fake size
,用于后面 的fastbin attack
- 释放掉
B
,B
进入unsorted bin
, 此时B+0x10
和B+0x18
中有main_arean
的地址 - 再次分配
0xd0
, 会分配到B
, 此时B+0x10
和B+0x18
中main_arean
的地址依然存在 - 然后分配
3
个0x70
的chunk (D , E, F)
, 为后续做准备 - 在
A
触发 单字节溢出,修改B->size = 0x71
. 然后释放C , D
, 此时C , D
进入fastbin
, 同时D->fd = C
. 由于chunk
之间的相对偏移固定,于是利用uaf
修改D->fd
的低 字节 ,使得D->fd=B
- 此时
B->size = 0x71
,同时B + 0x78
为p64(0x61)
(第2步设置), 这就成功伪造了一个0x70
大小的fastbin
。 此时B->fd
为main_arean
的地址,于是通过 修改 低2
个字节,可以修改到malloc_hook - 0x23
处 (malloc_hook - 0x23 + 0x8
处的值为p64(0x7f)
) - 然后分配
3
次0x70
的chunk
, 就可以拿到包含malloc_hook
的chunk
, 此时malloc_hook
内容为0
- 然后利用
unsorted bin
修改malloc_hook
内容为main_arean
的地址 - 利用部分写修改
malloc_hook
为one_gadget
- 多次释放一个指针,触发
double free
异常,进而触发malloc_printerr
,getshell
下面根据 exp
具体看看。
exp分析
分配 3
个 chunk
,在 B + 0x78
处设置 p64(0x61)
, 作用是 fake size
,用于后面 的 fastbin attack
|
|
释放掉 B
, 然后分配同样大小再次分配到 B
, 此时 B+0x10
和 B+0x18
中有 main_arean
的地址。分配 3
个 fastbin
,利用 off by one
修改 B->size = 0x71
|
|
生成两个 fastbin
,然后利用 uaf
,部分地址写,把 B
链入到 fastbin
|
|
调试看看此时 fastbin
的状态
|
|
0x555555757020
就是chunk B
然后通过修改 B->fd
的低 2
字节, 使得 B->fd= malloc_hook - 0x23
|
|
然后分配 3
个 0x70
的 chunk
,就可以拿到 malloc_hook
所在的那个 chunk
.
|
|
然后 free
掉 E
,进入 fastbin
,利用 uaf
设置 E->fd = 0
, 修复了 fastbin
(好思路)
|
|
然后是 unsorted bin 攻击,使得 malloc_hook 的值为 main_arena+88
|
|
利用 修改 malloc_hook
的低三个字节 ,使得 malloc_hook
为 one_gadget
的地址
|
|
然后 free
两次同一个 chunk
,触发 malloc_printerr
, getshell
|
|
上面的偏移为一次调试所得,开启 aslr
后,需要跑很多次 (碰运气, 写个脚本重复执行
|
|
跑啊跑就出 shell
总结
总的思路就是 部分地址写 + 爆破 绕过 aslr
. 其中的有趣的部分是堆布局,利用 off by one
伪造 fastbin
链 , 利用 unsorted bin attack
设置 libc
的地址的部分。
调试 pie
程序,关了 aslr
方便调试
|
|
参考
|
|
本站文章均原创, 转载注明来源
本文链接:http://blog.hac425.top/2018/05/08/house_of_roman.html