Dest0g3 520迎新赛 pwn ez_kiwi
漏洞分析
题目环境:glibc-2.31
如图在edit的过程中对重新输入的字符长度未有效检查,造成单字节溢出。
这时我们就可利用这一漏洞让堆块重叠,从而泄漏libc的地址
泄漏libc的地址首先想到的就是unsorted bin中的main_arena,由于存在tcache,必须释放8个大小相同才会进入unsorted bin;在add的过程中输入的idx可以小于0xf,但实际上超过9就无法正常申请,所以我们在申请释放时要小心堆块不够和top chunk的合并。
1 |
|
这时就可以得到libc的地址。
1 |
|
一般情况下我们会修改tcache的fd指针,指向__malloc_hook
和__free_hook
,再次申请时就使用system或者one_gadget去填充该地址。但是这题故意不让你去这样去使用,每次重新开始循环时会调用clear函数将__malloc_hook
和__free_hook
全部重置为0。
house of kiwi
这时我们就需要使用house of kiwi这种方式,修改_IO_file_sync
和_IO_helper_jumps
中的值。
具体过程便是触发__malloc_assert
后,去执行fflush (stderr),会使用_IO_file_jumps
中的_IO_file_sync
,RDX寄存器的值为IO_helper_jumps
指针,RDX始终是一个固定的地址。
然后通过 setcontext 控制寄存器的值。
1 |
|
设置rdx + 0xa0
来控制rsp,也就是控制了栈的地址,通过最后的ret指令就可以执行ROP。
攻击流程如下
将_IO_file_jumps
中的_IO_file_sync
修改为setcontext + 61
的地址,让程序执行setcontext中的代码;同时修改_IO_helper_jumps + 0xa0 和 _IO_helper_jumps + 0xa8
分别存放有ROP的位置和ret指令的gadget位置。题目提供了libc文件,只需在libc中找到相应的gadget再加上libc的基地址即可,可以通过泄漏堆的地址来存放gadget。
具体实现
关于IO_helper_jumps的地址寻找:由于pwntools无法从文件直接得到IO_helper_jumps的信息,于是我们可以直接通过这道题提供的libc文件利用ida中找到偏移;但如果是从pwndbg中寻找,找到的地址并不是_IO_file_sync
中所利用的那个地址,对比下图和上图就会发现需要-0xc0才是我们所需要的地址。
1 |
|
利用0x20大小的堆块重叠,可以修改tcache中的fd指针,就可对IO_file_jumps
的地址修改,并泄漏堆的地址。
1 |
|
使用ROPgadget 找到相应的gadget,利用系统调用去执行execve(“/bin/sh”,NULL,NULL) (储存/bin/sh的地址自己找好偏移即可)
1 |
|
继续利用0x20大小的堆块重叠,去修改_IO_helper_jumps + 0xa0 和 _IO_helper_jumps + 0xa8
中的地址。
1 |
|
关于触发__malloc_assert
:在top chunk不够使用时就使用sysmalloc,同时对top chunk进行一系列检查,这里我们不是为了绕过检查,而是故意让其不能通过检查。这里改变top chunk的大小,使其不能页对齐,并使用gift()函数申请0x25000大小的堆块。
1 |
|
完整的exp
1 |
|