前言
鸽了好久总算来复现了,由于从libc2.34开始,取消了两个常用的hook,这给我们的攻击带来了很大的困难,于是wjh找到了一种新的攻击方式,这是一种基于一条适用于 GLIBC 2.34 及以下所有版本的 IO_File 调用链进行攻击的手法。
前置知识
(一)largebin attack
见我的另一篇文章:house of pig 攻击手法详解
(二)house of kiwi
当程序没有显示调用exit,也不会通过主函数返回,那么以往我们使用的FSOP就无法进行了,如果此时两个hook也没法利用,我们需要一种能够稳定触发IO中函数的路径,这就是house of kiwi,它利用了__malloc_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),这个函数会稳定的调用_IO_file_jumps中的sync
在house of kiwi 中,如果我们能实现一个任意地址写,那么就可以修改sync指针,并且在调用的时候还发现,rdx也很稳定的是IO_helper_jumps,此时如果我们通过任意地址写将sync指针改成setcontext+0x61,且将IO_helper_jumps+0xa0和IO_helper_jumps+0xa8改写,就可以实现栈迁移orw。
house of emma
为什么说house of kiwi 是house of emma的前置知识呢,它其实是为house of emma提供了一条调用链,house of kiwi所找到的是在assert的时候会稳定的去调用_IO_file_jumps中的sync,后续需要通过任意地址写修改sync以及其他东西,而house of emma是直接将虚表的偏移修改,修改之后,本来应该调用_IO_file_jumps中的sync,变成了调用wjh发现的几个危险的函数,这几个危险函数可以仅仅通过精心布置fake FILE实现srop,并不需要任意地址写任意内容,只需要能够做到任意地址写已知的堆地址即可,这样的条件是非常低的,largebin attack就可以做到。
其实FSOP也是可以用emma接着打的,但是个人不是很推荐,house of emma会修改TLS表上的数据,这会导致在进行FSOP的时候难度增大,还不如直接用house of kiwi一套打下来。
举一个例子:
static ssize_t
_IO_cookie_read (FILE *fp, void *buf, ssize_t size)
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
cookie_read_function_t *read_cb = cfile->__io_functions.read;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (read_cb);
#endif
if (read_cb == NULL)
return -1;
return read_cb (cfile->__cookie, buf, size);
}
可以看到这里进行的函数调用,可以说是完全依据FILE的结构来的,所以只要精心构造FILE,就可以进行任意函数调用了。
注意看一下这里:
#ifdef
PTR_DEMANGLE (read_cb);
#endif
这是一个编译选项,一般来说都是默认开启的,其作用是指针保护,它是如何实现的呢?
extern uintptr_t __pointer_chk_guard attribute_relro;
# define PTR_MANGLE(var) \