House of apple 一种新的glibc中IO攻击方法

🚀 优质资源分享 🚀

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

目录* House of apple 一种新的glibc中IO攻击方法
+ 前言
+ 利用条件
+ 利用原理
+ 利用思路
- 思路一:修改tcache线程变量
- 思路二:修改mp_结构体
- 思路三:修改pointer_guard线程变量之house of emma
- 思路四:修改global_max_fast全局变量
+ 例题分析
- 题目分析
- 利用过程
+ 总结

House of apple 一种新的glibc中IO攻击方法

提出一种新的glibcIO利用思路,暂且命名为house of apple

前言

众所周知,glibc高版本逐渐移除了__malloc_hook/__free_hook/__realloc_hook等等一众hook全局变量,ctfpwn题对hook钩子的利用将逐渐成为过去式。而想要在高版本利用成功,基本上就离不开对IO_FILE结构体的伪造与IO流的攻击。之前很多师傅都提出了一些优秀的攻击方法,比如house of pighouse of kiwihouse of emma等。

其中,house of pig除了需要劫持IO_FILE结构体,还需要劫持tcache_perthread_struct结构体或者能控制任意地址分配;house of kiwi则至少需要修改三个地方的值:_IO_helper_jumps + 0xA0_IO_helper_jumps + 0xA8,另外还要劫持_IO_file_jumps + 0x60处的_IO_file_sync指针;而house of emma则至少需要修改两个地方的值,一个是tls结构体的point_guard(或者想办法泄露出来),另外需要伪造一个IO_FILE或替换vtavlexxx_cookie_jumps的地址。

总的来看,如果想使用上述方法成功地攻击IO,至少需要两次写或者一次写和一次任意地址读。而在只给一次任意地址写(如一次largebin attack)的情景下是很难利用成功的。

largebin attack是高版本中为数不多的可以任意地址写一个堆地址的方法,并常常和上述三种方法结合起来利用。本文将给出一种新的利用方法,在仅使用一次largebin attack并限制读写次数的条件下进行FSOP利用。顺便说一下,house of banana 也只需要一次largebin attack,但是其攻击的是rtld_global结构体,而不是IO流。

上述方法利用成功的前提均是已经泄露出libc地址和heap地址。本文的方法也不例外。

利用条件

使用house of apple的条件为:
1、程序从main函数返回或能调用exit函数
2、能泄露出heap地址和libc地址
3、 能使用一次largebin attack(一次即可)

利用原理

原理解释均基于amd64程序。

当程序从main函数返回或者执行exit函数的时候,均会调用fcloseall函数,该调用链为:

  • exit
    • fcloseall

      • _IO_cleanup

        • _IO_flush_all_lockp
          • _IO_OVERFLOW

最后会遍历_IO_list_all存放的每一个IO_FILE结构体,如果满足条件的话,会调用每个结构体中vtable->_overflow函数指针指向的函数。

使用largebin attack可以劫持_IO_list_all变量,将其替换为伪造的IO_FILE结构体,而在此时,我们其实仍可以继续利用某些IO流函数去修改其他地方的值。要想修改其他地方的值,就离不开_IO_FILE的一个成员_wide_data的利用。

struct \_IO\_FILE\_complete
{
  struct \_IO\_FILE \_file;
  \_\_off64\_t _offset;
  /* Wide character stream stuff. */
  struct \_IO\_codecvt *\_codecvt;
  struct \_IO\_wide\_data *\_wide\_data; // 劫持这个变量
  struct \_IO\_FILE *\_freeres\_list;
  void *_freeres_buf;
  size\_t __pad5;
  int _mode;
  /* Make sure we don't get into trouble again. */
  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size\_t)];
};

amd64程序下,struct _IO_wide_data *_wide_data_IO_FILE中的偏移为0xa0

amd64:

0x0:'\_flags',
0x8:'\_IO\_read\_ptr',
0x10:'\_IO\_read\_end',
0x18:'\_IO\_read\_base',
0x20:'\_IO\_write\_base',
0x28:'\_IO\_write\_ptr',
0x30:'\_IO\_write\_end',
0x38:'\_IO\_buf\_base',
0x40:'\_IO\_buf\_end',
0x48:'\_IO\_save\_base',
0x50:'\_IO\_backup\_base',
0x58:'\_IO\_save\_end',
0x60:'\_markers',
0x68:'\_chain',
0x70:'\_fileno',
0x74:'\_flags2',
0x78:'\_old\_offset',
0x80:'\_cur\_column',
0x82:'\_vtable\_offset',
0x83:'\_shortbuf',
0x88:'\_lock',
0x90:'\_offset',
0x98:'\_codecvt',
0xa0:'\_wide\_data',
0xa8:'\_freeres\_list',
0xb0:'\_freeres\_buf',
0xb8:'\_\_pad5',
0xc0:'\_mode',
0xc4:'\_unused2',
0xd8:'vtable'

我们在伪造_IO_FILE结构体的时候,伪造_wide_data变量,然后通过某些函数,比如_IO_wstrn_overflow就可以将已知地址空间上的某些值修改为一个已知值。

static wint\_t
_IO_wstrn_overflow (FILE *fp, wint\_t c)
{
  /* When we come to here this means the user supplied buffer is
 filled. But since we must return the number of characters which
 would have been written in total we must provide a buffer for
 further use. We can do this by writing on and on in the overflow
 buffer in the \_IO\_wstrnfile structure. */
  _IO_wstrnfile *snf = (_IO_wstrnfile *) fp;

  if (fp->_wide_data->_IO_buf_base != snf->overflow_buf)
    {
      _IO_wsetb (fp, snf->overflow_buf,
		 snf->overflow_buf + (sizeof (snf->overflow_buf)
				      / sizeof (wchar\_t)), 0);

      fp->_wide_data->_IO_write_base = snf->overflow_buf;
      fp->_wide_data->_IO_read_base = snf->overflow_buf;
      fp->_wide_data->_IO_read_ptr = snf->overflow_buf;
      fp->_wide_data->_IO_read_end = (snf->overflow_buf
				      + (sizeof (snf->overflow_buf)
					 / sizeof (wchar\_t)));
    }

  fp->_wide_data->_IO_write_ptr = snf->overflow_buf;
  fp->
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值