[原创]无路远征——GLIBC2.37后时代的IO攻击之道(四)house_of_魑魅魍魉
2023-2-9 16:5:4 Author: bbs.pediy.com(查看原文) 阅读量:16 收藏

在上一篇中,我提出怎么控制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);


文章来源: https://bbs.pediy.com/thread-276044.htm
如有侵权请联系:admin#unsafe.sh