IO_file attack

IO_FILE attack

IO_file struct 认识

FILE在linux的标准IO库中用于描述文件的结构,称为文件流。FILE结构在程序执行fopen等函数是才会创建,并将其分配到中。

我们通常定义一个指向FILE结构体的指针来接受这样一个返回值

FILE struct
struct _IO_FILE {
   
   
  int _flags;       /* 文件流的状态标志,包括控制、状态和错误信息等。高阶字包含魔数(_IO_MAGIC),其余字节包含其他标志。 */
#define _IO_file_flags _flags/*对 _flags 进行重命名,用于简化使用。*/

  /* 用于支持 C++ streambuf 协议的指针, */
  /* 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;  /* 表示当前读取位置、读取区域的结束和读取区域的起始位置。 */
  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; /* 用于支持备份和撤销的指针,表示非当前读取区域的起始位置、备份区域的起始位置和非当前读取区域的结束位置。 */

  struct _IO_marker *_markers;/*指向 _IO_marker 结构体的指针,用于支持标记操作。*/

  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;/*虚函数表(vtable)的偏移量。*/
  char _shortbuf[1];/*一个字符的缓冲区,用于性能优化。*/

  /*  char* _save_gptr;  char* _save_egptr; */

  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
struct _IO_FILE_complete
{
   
   
  struct _IO_FILE _file;
#endif
#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
  _IO_off64_t _offset;
# if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
  /* Wide character stream stuff.  */
  struct _IO_codecvt *_codecvt;
  struct _IO_wide_data *_wide_data;
  struct _IO_FILE *_freeres_list;
  void *_freeres_buf;
# else
  void *__pad1;
  void *__pad2;
  void *__pad3;
  void *__pad4;

  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)];
#endif
};

如注释所说,对于进程中的FILE结构,他会通过_chain域彼此链接将所有的FILE结构体连接成一个链表,链表头部是全局变量 _IO_LIST_ALL表示,并且可以依靠该变量来遍历整个链表中的所有FILE结构

在标准I/O库中,在每个程序启动时会有三个文件流是自动打开的,分别是 stdin,stdout,stderr。所以一开始_IO_list_all会指向这样一个拥有这些文件流的链表, 但是,这里我们需要注意的是文件流位于libc.so的数据段,而我们通过fopen函数创建的文件流是分配在堆上面的

在libc文件中我们可以找到stdin,stdout,stderr以及_IO_2_1_stderr_ IO_2_1_stdout _IO_2_1_stdin这些符号,而他们之间有分别是指向关系,stdin -> _IO_2_1_stdin(这才是真正的结构file)

事实上_IO_FILE结构外围还包裹着一层 _IO_FILE_plus结构:

struct _IO_FILE_plus
{
   
   
    _IO_FILE    file;
    IO_jump_t   *vtable;
}
/*其中*vtable的偏移在libc.2.23下:32位:偏移为0x94;64位:偏移为0xd8*/

可以看到*vtable指针被定义为IO_jump_t类型,其中保存了一些函数指针,在后面我们会看到一些标准IO函数调用这里面的的一些函数指针。

void * funcs[] = {
   
   
   1 NULL, // "extra word"
   2 NULL, // DUMMY
   3 exit, // finish
   4 NULL, // overflow
   5 NULL, // underflow
   6 NULL, // uflow
   7 NULL, // pbackfail
   
   8 NULL, // xsputn  #printf
   9 NULL, // xsgetn
   10 NULL, // seekoff
   11 NULL, // seekpos
   12 NULL, // setbuf
   13 NULL, // sync
   14 NULL, // doallocate
   15 NULL, // read
   16 NULL, // write
   17 NULL,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值