前言
偶然在推特看到的这个比赛, 搜了下似乎国内没什么人参加, 但是往年题目质量还不错(?), 摸鱼打了打, 4道pwn只做了2个, 剩下一个是Windows Pwn一个是GameBoy, 都不太熟= =.
onetestament
glibc 2.23的heap菜单题, some old tricks 😀
限制因素:
- 能申请的
mem size
只有四种:0x18 0x30 0x60 0x7c
- 只有在
add
的时候可以leak信息,show
函数是没用的 - 用的是
calloc
, 会把申请到的chunk清零 - 最多只允许调用11次
calloc
(0-10) delete
里用了一个标志变量判断是否有double-free
漏洞点:
edit
有off-by-one
, 在可以改下一个chunk header
的size
- 读入菜单选项的函数存在一个字节的溢出, 可以把第4块chunk(编号从0开始)是否被free过的标志变量覆写, 从而达到
double free
这里有一个小知识点, 在glibc-2.23/malloc/malloc.c
的__libc_calloc
函数中(3259行):
/* Two optional cases in which clearing not necessary */
if (chunk_is_mmapped (p))
{
if (__builtin_expect (perturb_byte, 0))
return memset (mem, 0, sz);
return mem;
}
可以看到calloc
函数不会把 mmap
系统调用拿到的内存清零, 这是因为mmap系统调用拿到的内存本身就是清零的, 为了节省性能开销这里就不再调用memset
清了.
因此如果能覆写chunk的IS_MMAPED
位, 就可以绕过calloc
的清零操作. 参考chunk结构图可以发现当一个chunk的data部分大小为0x18时, 其利用edit中的off-by-one就正好可以覆盖下一个chunk的IS_MMAPED
位:
那么现在思路其实很明确了, 主要步骤:
- 用0x18的chunk作为辅助编辑块, 负责修改其下一个chunk的
IS_MMAPED
绕过calloc
的清零 - 用
0x7c
大小的unsorted bin chunk泄露libc基址 - 用
0x60
大小的chunk做fastbin attack
, 拿到一块指向__malloc_hook
的fake chunk - 覆写
__malloc_hook
为one gadget
, 调用一次add
拿到shell
继续阅读“Insomni’hack teaser 2022 Pwn writeup”