在上一篇中,我提出怎么控制size_t _IO_default_xsputn (FILE *f, const void *data, size_t n)
这个函数的三个参数呢?
一般来说这是很难做到的,因为如果能够3个参数都能控制,能做的事情就太多了,getshell
简直是手到擒来。所以,house_of_魑魅魍魉
与其说是一种攻击链,不如说是一种攻击思路,当IO中存在以下条件都可以继续挖掘,本人利用_IO_helper_jumps
中的内容也只是攻击手段之一,不是绝对手段。
本篇文章介绍的攻击主要是利用_IO_helper_overflow
在执行_IO_sputn (target, s->_wide_data->_IO_write_base, used)
时,3个参数均能控制,然后利用memcpy、memmove
等函数实现house of 秦关汉月
,其中一条链如下。
一般来说一类跳表只有一个,但_IO_helper_jumps
比较特殊,通过下面可以看出,跳表会根据COMPILE_WPRINTF
值不同而生成不同的,但可能libc
在编译时调用两次,所以我们可以在内存中看到两个_IO_helper_jumps
,每种各一个。其中,COMPILE_WPRINTF==0
先生成,COMPILE_WPRINTF==1
后生成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static const struct _IO_jump_t _IO_helper_jumps libio_vtable
=
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_wdefault_finish),
JUMP_INIT (overflow, _IO_helper_overflow),
JUMP_INIT (underflow, _IO_default_underflow),
JUMP_INIT (uflow, _IO_default_uflow),
JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
JUMP_INIT (xsputn, _IO_wdefault_xsputn),
JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
JUMP_INIT (seekoff, _IO_default_seekoff),
JUMP_INIT (seekpos, _IO_default_seekpos),
JUMP_INIT (setbuf, _IO_default_setbuf),
JUMP_INIT (sync, _IO_default_sync),
JUMP_INIT (doallocate, _IO_wdefault_doallocate),
JUMP_INIT (read, _IO_default_read),
JUMP_INIT (write, _IO_default_write),
JUMP_INIT (seek, _IO_default_seek),
JUMP_INIT (close, _IO_default_close),
JUMP_INIT (stat, _IO_default_stat)
};
static const struct _IO_jump_t _IO_helper_jumps libio_vtable
=
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_default_finish),
JUMP_INIT (overflow, _IO_helper_overflow),
JUMP_INIT (underflow, _IO_default_underflow),
JUMP_INIT (uflow, _IO_default_uflow),
JUMP_INIT (pbackfail, _IO_default_pbackfail),
JUMP_INIT (xsputn, _IO_default_xsputn),
JUMP_INIT (xsgetn, _IO_default_xsgetn),
JUMP_INIT (seekoff, _IO_default_seekoff),
JUMP_INIT (seekpos, _IO_default_seekpos),
JUMP_INIT (setbuf, _IO_default_setbuf),
JUMP_INIT (sync, _IO_default_sync),
JUMP_INIT (doallocate, _IO_default_doallocate),
JUMP_INIT (read, _IO_default_read),
JUMP_INIT (write, _IO_default_write),
JUMP_INIT (seek, _IO_default_seek),
JUMP_INIT (close, _IO_default_close),
JUMP_INIT (stat, _IO_default_stat)
};
同样,面对不同的COMPILE_WPRINTF
所对应的helper_file
也有所不同,区别在于是否需要伪造struct _IO_wide_data _wide_data;
。
同样,这个函数在内存中也有2份。通过测试发现,如果使用COMPILE_WPRINTF==0
的情况,在攻击过程中s->_IO_write_base
会变成largebin->bk_size
指针,从而被强制修改无法控制。为了方便,我们使用COMPILE_WPRINTF==1
所生成的_IO_helper_overflow
。(第2个生成的)
通过上面函数可以清楚看出,在执行size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, used);
时