没有附件,只能对着别人文章硬看了。(哪个师傅有附件的话联系我一下,感激不尽)
从肥猫师傅本人的 文章 中得知使用 kiwi 的条件有两点:
1、能够触发 __malloc_assert
2、有任意写的能力,修改 _IO_helper_jumps 结构体
kiwi 的流程是 __malloc_assert -> fflush(stderr) -> _IO_helper_jumps->sync
当 top chunk 大小不够分配时,会进入 sysmalloc 中
assert ((old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0));
这里会对 top chunk 的 size 进行判断,如果 top chunk 的 size 没有页对其,那么就会触发 assert
static void __malloc_assert (const char *assertion, const char *file, unsigned int line, const char *function) { (void) __fxprintf (NULL, "%s%s%s:%u: %s%sAssertion `%s' failed.\n", __progname, __progname[0] ? ": " : "", file, line, function ? function : "", function ? ": " : "", assertion); fflush (stderr); abort (); }
这里会调用 fflush (stderr) ,fflush 则会调用 _IO_file_jumps 的 sync 指针。以上就是 kiwi 的调用链。
附加了 srop , glibc 从 2.29 以后 setcontext 由之前的 rdi 控制转为了 rdx 控制。进过调试可知在调用 _IO_helper_jumps->sync 的同时 rdx 指针始终指向 _IO_helper_jumps,也就是说如果我们再把 _IO_helper_jumps + 0xA0 和 0xA8 的位置分别改为存放 ROP 的位置和 ret 的位置,那么就可以直接进行 orw。