到这里,算是勉强进入了glibc的大门吧(逃
house of系列其实就是堆的一些利用组合拳,这个豪撕欧符奇异(house of kiwi)是fmyy师傅最先在安全客提出来的一种船新的利用手法。
它新就新在提供了一种船新的进入IO流的方式。当程序使用_exit结束进程时,就没有机会调用IO clean。并且高版本中我们的malloc hook和free hook都是大寄特寄的情况下,kiwi给我们带来了一条新道路。听懂掌声
一、house of kiwi
1、原理
house of kiwi是通过🐏top chunk 触发malloc_assert这个断言,从而进入到fflush。
malloc_assert:
1 | static void |
在fflush里会调用_IO_file_jumps
中的sync指针
这里我带来了我的图图,方便理解
正是在这call qword ptr [rbp + 0x60]
的地方,调用了这个sync(这里我已经将其🐏成了setcontext+61,原本是指向sync的),而此时我们的rbp值为_IO_file_jumps
,所以我们可以借此来定位到这个函数指针,修改此处即可执行任意函数。
众所周知,高版本的情况下,我们的setcontext是通过rdx来索引传参的,而在调试的过程中我们不难发现rdx的值始终为IO_helper_jumps
的指针。
2、利用
至此我们可以总结出豪撕欧符奇异的利用条件,需要两次任意地址写以及一次打爆top chunk触发assert的机会。
因为要触发assert的断言, 在_int_malloc
中存在一个 assert (chunk_main_arena (bck->bk));位置可以触发,此外当top_chunk
的大小不够分配时,则会进入sysmalloc中检查top chunk的size|flag进行判断。
所以要么我们打main_arena中负责管理top chunk的地方,要么有一次malloc大堆块导致top chunk大小不够的机会,并且要打爆top chunk的size位(个人认为第二种很麻烦,条件也苛刻,不如直接打main_arena
两次任意地址写:
一次修改函数指针
1 | _IO_file_sync = setcontext + 61 |
一次修改IO_helper_jumps
+0xa0和IO_helper_jumps
+0xa8
1 | `IO_helper_jumps`+0xa0=fake_rsp |
1 | `IO_helper_jumps`+0xa8=fake_rip |
二、例题:dest0g3-520招新赛 ezkiwi
1、程序分析:
存在off by one,手动清空了hook并且没有exit,menu(666)给了一次malloc很大堆块的机会,但是没有开沙箱。
2、利用思路:
利用off by one伪造unsorted bin来leak libc
利用残留指针leak heap_addr
利用割unsorted bin的方式造成堆块复用打tcache poison三次,实现两次任意地址写和一次打top chunk
利用gift触发assert
3、调试过程中的小tips
这里我是gdb进fflush里面找_IO_file_sync,不知道为什么 _IO_file_jumps + 0x60 这个地址和我call的那个老不同。
而且syscall ;ret这个gadget用ROPgadget和ropper都没找出来,找出来的前面都有很多别的汇编,手动去gdb里找到syscall开始的那个地址即可。
4、exp:
这里是笨方法修改next指针打tcache poison,堆布局比较弱智,打tcache struct就不用那么麻烦了
1 | from pwn import* |
下班吃饭
5、没开沙箱的exp two
因为这里题目没有开沙箱,所以我们可以直接打sync为system,并且是传入stdrr作为参数,这里打成\bin\sh即可get shell
1 | from pwn import* |
三、后记
vmtool挂了装不好之后,直接心狠手辣删了整个20.04的镜像。陪伴我pwn了这么久的镜像挂了,换了一个船新的22.04,当事人表示新版本很舒服很好用(不是渣男。
pwn真好玩