zoukankan      html  css  js  c++  java
  • Pwn with File结构体(二)

    前言


    本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274


    最新版的 libc 中会对 vtable 检查,所以之前的攻击方式,告一段落。下面介绍一种,通过修改 _IO_FILE 实现任意地址读和任意地址写的方式。

    正文

    _IO_FILE 通过这些指针,来读写数据。

    如果我们修改了它们,然后通过一些文件读写函数时,我们就能实现 任意地址读写。

    任意地址读

    代码示例

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char * argv[])
    {   
       FILE *fp; 
       char *msg = "hello_file";
    
       char *buf = malloc(100);
       read(0, buf, 100);
       fp = fopen("key.txt", "rw");
    
       // 设置 flag 绕过 check
       fp->_flags &= ~8;
       fp->_flags |= 0x800;
    
       // _IO_write_base write数据的起始地址, _IO_write_ptr  write数据的终止地址
       fp->_IO_write_base = msg;
       fp->_IO_write_ptr = msg + 6;
    
       //绕过检查
       fp->_IO_read_end = fp->_IO_write_base;
    
       // write 的目的 文件描述符, 1 --> 标准输出
       fp->_fileno = 1;
       fwrite(buf, 1, 100, fp);
    
       return 0;
    }
    
    

    任意地址写

    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char * argv[])
    {   
       FILE *fp; 
       char msg[100];
    
       char *buf = malloc(100);
       fp = fopen("key.txt", "rw");
    
       // 设置 flag 绕过 check
       fp->_flags &= ~4;
    
       // _IO_buf_base buffer 的起始地址, _IO_buf_end  buffer 的终止地址
       // fread 先把数据读入 [_IO_buf_base, _IO_buf_end] 形成的 buffer
       // 然后复制到目的 buffer
       fp->_IO_buf_base = msg;
       fp->_IO_buf_end = msg + 100;
    
       // 设置 文件描述符, 0---> stdin, 从标准输入读数据
       fp->_fileno = 0;
       fread(buf, 1, 6, fp);
       
       puts(msg);
       puts(buf);
    
       return 0;
    }
    
    

    利用 stdin / stdout 任意地址写/ 读

    puts, scanf 等一批系统函数默认使用的 stdin , stdout ,stderr 等结构体进行操作,通过修改这些结构体的内容,可以更方便的实现任意地址读,任意地址写。

    stdin 也是 _IO_FILE 结构体

    
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int global_val = 0xaabbccdd;
    
    
    int main(int argc, char * argv[])
    {   
       FILE *fp; 
       int var;
    
       fp = stdin;
    
       fp->_flags &= ~4;
    
       fp->_IO_buf_base = stdout;
       fp->_IO_buf_end = stdout + 100;
    
    
       scanf("%d",&var);
       
       printf("0x%x
    ", global_val);
    
       return 0;
    }
    
    

    运行之

    成功修改 stdout 结构体

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char * argv[])
    {   
       FILE *fp; 
       char *msg = "hello_stdout";
    
       char *buf = malloc(100);
    
       fp = stdout;
    
       // 设置 flag 绕过 check
       fp->_flags &= ~8;
       fp->_flags |= 0x800;
    
       // _IO_write_base write数据的起始地址, _IO_write_ptr  write数据的终止地址
       fp->_IO_write_base = msg;
       fp->_IO_write_ptr = msg + 12;
    
       //绕过检查
       fp->_IO_read_end = fp->_IO_write_base;
    
       // write 的目的 文件描述符, 1 --> 标准输出
       fp->_fileno = 1;
       puts("<----->this is append on msg ");
    
       return 0;
    }
    
    

    成功读到了, msg 的内容。

    参考:

    https://www.slideshare.net/AngelBoy1/play-with-file-structure-yet-another-binary-exploit-technique

  • 相关阅读:
    常见的行元素与块元素
    [转]SVN服务器部署并实现双机同步及禁止普通用户删除文件
    [转]Axure共享工程Shared Project(二):编辑修改和提交
    如何添加网络打印机
    [转]JSON 转换异常 死循环 There is a cycle in the hierarchy
    比较常用的Properties配置文件的使用方法示例
    解决Tomcat项目重复加载导致pemgen space内存溢出
    怎样批量删除.svn文件
    [转]前端工程师必须掌握的知识点
    Freemarker 使用
  • 原文地址:https://www.cnblogs.com/hac425/p/9416830.html
Copyright © 2011-2022 走看看