欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

从printf源码看libc的IO

来源:本站整理 作者:佚名 时间:2017-09-29 TAG: 我要投稿

咱们彷佛每天都在应用IO,最典型的应用便是printf,scanf,曩昔咱们只晓得printf会有格式化字符串破绽,然则咱们并无怎样穷究过IO详细的是怎样回事,和详细有甚么可以或许入侵攻击的点。
2016 HITCON有一道 house of orange,是一道可谓经典的标题,第一次(或许彷佛是第一次?)让咱们把入侵攻击的思想往IO FILE里去斟酌,因而咱们开端思虑libc的虚表的可入侵攻击性,可怜的是,libc的开辟职员也很快认识到了这个虚表的成绩,在2.24的libc版本中对vtables停止了加固:
2.24 libc更新日记中的一个内容:
  [20191] stdio: libio: vtables hardening
因而这个方法逐步变得艰苦了起来,还好咱们的思绪不仅仅是如许……
本文主要从经典的虚表道理开端提及,中央弥补一下scanf和printf的道理,末了提到一种较新的(或许是我觉得较新的?)思绪。
从虚表开端提及
起首咱们来看下经典的(固然彷佛是2016以后才风行起来的)_IO_FILE_plus的虚表入侵攻击方法。
1._IO_FILE 与 _IO_FILE_plus
源码永久是答复心中疑难的好先生,起首来看看对于这两个布局体的源码:
// libio/libio.h _IO_FILE 布局体
struct _IO_FILE {
  int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */
  struct _IO_marker *_markers;
  struct _IO_FILE *_chain;
  int _fileno;
#if 0
  int _blksize;
#else
  int _flags2;
#endif
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];
  /*  char* _save_gptr;  char* _save_egptr; */
  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
和_IO_FILE_plus:
// libio/libioP.h
#define JUMP_FIELD(TYPE, NAME) TYPE NAME
#define JUMP0(FUNC, THIS) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS)
struct _IO_jump_t // 虚表布局体
{
    JUMP_FIELD(size_t, __dummy);
    JUMP_FIELD(size_t, __dummy2);
    JUMP_FIELD(_IO_finish_t, __finish);
    JUMP_FIELD(_IO_overflow_t, __overflow);
    JUMP_FIELD(_IO_underflow_t, __underflow);
    JUMP_FIELD(_IO_underflow_t, __uflow);
    JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
    /* showmany */
    JUMP_FIELD(_IO_xsputn_t, __xsputn);
    JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
    JUMP_FIELD(_IO_seekoff_t, __seekoff);
    JUMP_FIELD(_IO_seekpos_t, __seekpos);
    JUMP_FIELD(_IO_setbuf_t, __setbuf);
    JUMP_FIELD(_IO_sync_t, __sync);
    JUMP_FIELD(_IO_doallocate_t, __doallocate);
    JUMP_FIELD(_IO_read_t, __read);
    JUMP_FIELD(_IO_write_t, __write);
    JUMP_FIELD(_IO_seek_t, __seek);
    JUMP_FIELD(_IO_close_t, __close);
    JUMP_FIELD(_IO_stat_t, __stat);
    JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
    JUMP_FIELD(_IO_imbue_t, __imbue);
#if 0
    get_column;
    set_column;
#endif
};
struct _IO_FILE_plus
{
  _IO_FILE file; // 便是一个libio.h中的_IO_FILE 布局体
  const struct _IO_jump_t *vtable; // 多出一个vtable
};
咱们可以或许看到_IO_FILE_plus的构成,实在便是一个_IO_FILE布局体自己再加之一个跳表,从plus这个称号咱们也能看进去,实在这个处所是为了兼容C++,对付C++的工具来讲,除数据之外另有方法,方法的完成是会用到跳表的,为了可以或许兼容,除_IO_FILE自己之外,只能再增加一个跳表,而后应用新的布局体来停止兼容。
现实上在libc外部对付FILE布局体便是用_IO_FILE_plus来停止表现的,然则对付pwn选手来讲,只需有函数指针,就有节制履行流的能够,独一的成绩是,用谁的函数指针?
这个实在并非一个难事,由于每个文件必定都有3个FILE,也便是如下三个,我想人人曾经不能再认识他们了:

[1] [2] [3] [4] [5] [6] [7] [8]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载