CTF-PWN: 什么是_IO_FILE?

重要概念:fopen()返回的是一个结构体的指针

_IO_FILE 结构体在什么时候被创建?

_IO_FILE 结构体的实例是在程序使用标准 I/O 函数(如 fopenfclosefreadfwrite 等)时创建和管理的。这个结构体实际上是 GNU C Library (glibc) 用于处理文件流的底层实现细节。当你在程序中打开一个文件或者创建一个流时,glibc 会在后台分配和初始化一个 _IO_FILE 结构体,并返回一个指向它的指针(即 FILE* 类型)。

下面是一些常见场景,说明 _IO_FILE 结构体是如何被创建和使用的:

  1. 使用 fopen 打开文件
    当你调用 fopen 打开一个文件时,glibc 会分配一个 _IO_FILE 结构体并进行初始化。例如:

    FILE *file = fopen("example.txt", "r");
    

    在这个例子中,fopen 函数会创建一个 _IO_FILE 结构体实例来管理 example.txt 文件的读操作,并返回一个指向该结构体的指针 file

  2. 使用 fdopen 关联文件描述符和文件流
    如果你有一个现有的文件描述符,并希望将其与一个标准 I/O 流关联,可以使用 fdopen 函数:

    int fd = open("example.txt", O_RDONLY);
    FILE *file = fdopen(fd, "r");
    

    fdopen 会创建一个新的 _IO_FILE 结构体实例,并将文件描述符 fd 关联到这个结构体上。

  3. 标准输入输出
    标准输入(stdin)、标准输出(stdout)和标准错误(stderr)也是通过 _IO_FILE 结构体来管理的。它们在程序启动时由运行时库自动初始化。

    fprintf(stdout, "Hello, World!\n");
    

_IO_FILE 结构体的创建过程

当函数如 fopen 被调用时,glibc 内部会进行以下步骤:

  1. 分配内存
    glibc 会调用内存分配函数(如 malloc)为 _IO_FILE 结构体分配内存。

  2. 初始化结构体
    分配内存后,glibc 会初始化 _IO_FILE 结构体的各个字段。例如,它会设置缓冲区指针、文件描述符、文件模式等。

  3. 返回指针
    初始化完成后,glibc 会返回一个指向这个 _IO_FILE 结构体的指针,即 FILE* 类型的指针。

_IO_FILE 在文件流操作中的生命周期

  1. 创建
    当你使用标准 I/O 函数(如 fopenfdopen)打开或创建一个文件流时,glibc 会创建一个 _IO_FILE 结构体实例。

  2. 使用
    在文件流的生命周期内,所有对该文件流的读写操作(如 freadfwritefgetsfputs 等)都会通过这个 _IO_FILE 结构体来管理缓冲区、文件描述符和流的状态。

  3. 销毁
    当你调用 fclose 关闭文件流时,glibc 会执行以下操作:

    • 刷新缓冲区中的数据(如果有需要)。
    • 释放与文件流关联的资源(如缓冲区内存)。
    • 关闭文件描述符。
    • 最后,释放 _IO_FILE 结构体的内存。

示例代码

以下是一个简单的示例代码,展示了 _IO_FILE 结构体实例的创建和使用过程:

#include <stdio.h>int main() {// 打开文件,创建一个 _IO_FILE 结构体实例FILE *file = fopen("example.txt", "w");if (file == NULL) {perror("Failed to open file");return 1;}// 使用文件流进行写操作fprintf(file, "Hello, World!\n");// 关闭文件,销毁 _IO_FILE 结构体实例fclose(file);return 0;
}

在这个示例中,当调用 fopen 时,glibc 会创建并初始化一个 _IO_FILE 结构体实例。当调用 fclose 时,glibc 会销毁这个实例并释放相关资源。

_IO_FILE 结构体

在 Linux 系统中,_IO_FILE 结构体是 GNU C Library (glibc) 中实现标准 I/O (stdio) 的核心数据结构之一。它用于描述文件流(FILE*)的内部状态和缓冲区信息。理解 _IO_FILE 结构体对于某些高级的漏洞利用技术(如利用格式字符串漏洞或缓冲区溢出漏洞)非常重要。

以下是 _IO_FILE 结构体的一般布局(具体布局可能会随着 glibc 版本的不同而变化):

struct _IO_FILE {int _flags;                // 文件流的状态标志char* _IO_read_ptr;        // 缓冲区读取指针char* _IO_read_end;        // 缓冲区读取结束指针char* _IO_read_base;       // 缓冲区读取基地址char* _IO_write_base;      // 缓冲区写入基地址char* _IO_write_ptr;       // 缓冲区写入指针char* _IO_write_end;       // 缓冲区写入结束指针char* _IO_buf_base;        // 缓冲区基地址char* _IO_buf_end;         // 缓冲区结束地址char *_IO_save_base;       // 保存的缓冲区基地址char *_IO_backup_base;     // 备份的缓冲区基地址char *_IO_save_end;        // 保存的缓冲区结束地址struct _IO_marker *_markers; // 标记链表struct _IO_FILE *_chain;   // 文件流链表int _fileno;               // 文件描述符int _flags2;               // 额外的标志__off_t _old_offset;       // 旧的偏移量unsigned short _cur_column;// 当前列号signed char _vtable_offset;// 虚表偏移char _shortbuf[1];         // 短缓冲区_IO_lock_t *_lock;         // 锁__off64_t _offset;         // 偏移量void *__pad1;              // 填充void *__pad2;              // 填充void *__pad3;              // 填充void *__pad4;              // 填充size_t __pad5;             // 填充int _mode;                 // 模式char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];// 未使用的填充
};

关键字段

  • _flags: 用于描述文件流的状态标志,例如是否为读模式、写模式等。
  • _IO_read_ptr, _IO_read_end, _IO_read_base: 分别指向当前读取的位置、读取的结束位置和读取缓冲区的基地址。
  • _IO_write_base, _IO_write_ptr, _IO_write_end: 分别指向当前写入的位置、写入的结束位置和写入缓冲区的基地址。
  • _IO_buf_base, _IO_buf_end: 分别指向缓冲区的基地址和结束地址。
  • _IO_save_base, _IO_backup_base, _IO_save_end: 用于保存缓冲区状态的指针。
  • _markers: 指向标记结构的链表,用于支持多种流操作。
  • _chain: 指向下一个文件流的指针,形成一个文件流链表。
  • _fileno: 文件描述符。
  • _flags2: 额外的标志位。
  • _old_offset: 用于记录偏移量。
  • _cur_column: 当前列号,主要用于格式化输出。
  • _vtable_offset: 虚表偏移,用于支持面向对象的操作。
  • _shortbuf: 一个短缓冲区。
  • _lock: 指向用于同步的锁。
  • _offset: 文件流的位置偏移量。
  • 填充字段: 用于对齐和扩展。

stdinstdoutstderr指针

这些指针是程序的标准输入、标准输出和标准错误流(stdinstdoutstderr)在内存中的地址。它们是全局变量,通常在程序启动时被初始化,以指向相应的 FILE 结构体。

解释每个指针

  1. stdout (标准输出)

    • 地址:0x602020
    • 指向的地址:0x00007fe6e8e03620
  2. stdin (标准输入)

    • 地址:0x602030
    • 指向的地址:0x00007fe6e8e028e0
  3. stderr (标准错误)

    • 地址:0x602040
    • 指向的地址:0x00007fe6e8e03540

每个地址如 0x602020 是全局变量的地址,而对应的值(如 0x00007fe6e8e03620)是这些全局变量指向的 FILE 结构体实例的地址。

内存布局和用途

  1. stdout:

    • 地址0x602020
    • 指向的地址0x00007fe6e8e03620
    • 用途:标准输出通常用于打印普通输出信息,默认连接到终端的显示设备。
  2. stdin:

    • 地址0x602030
    • 指向的地址0x00007fe6e8e028e0
    • 用途:标准输入用于读取输入数据,默认连接到终端的键盘输入。
  3. stderr:

    • 地址0x602040
    • 指向的地址0x00007fe6e8e03540
    • 用途:标准错误用于打印错误信息,默认也连接到终端的显示设备。

背后的机制

在程序启动时,C 标准库(如 glibc)会初始化这几个标准流。具体来说,它们会分配相应的 FILE 结构体,并将 stdinstdoutstderr 这些全局变量指向这些结构体。

以下是一个简化的示意图,展示了这些指针和 FILE 结构体的关系:

+----------------+           +----------------+
|  0x602020      | --------> | FILE for stdout|
|  (stdout)      |           | 0x00007fe6e8e03620 |
+----------------+           +----------------++----------------+           +----------------+
|  0x602030      | --------> | FILE for stdin |
|  (stdin)       |           | 0x00007fe6e8e028e0 |
+----------------+           +----------------++----------------+           +----------------+
|  0x602040      | --------> | FILE for stderr|
|  (stderr)      |           | 0x00007fe6e8e03540 |
+----------------+           +----------------+

示例代码验证

下面是一些示例代码,可以用来验证这些指针的地址:

#include <stdio.h>int main() {printf("Address of stdout: %p\n", (void*)&stdout);printf("Address of stdin: %p\n", (void*)&stdin);printf("Address of stderr: %p\n", (void*)&stderr);printf("Pointer value of stdout: %p\n", (void*)stdout);printf("Pointer value of stdin: %p\n", (void*)stdin);printf("Pointer value of stderr: %p\n", (void*)stderr);return 0;
}

运行这段代码,你应该会看到标准流指针的地址和它们指向的 FILE 结构体的地址,这与你提供的内存地址应该是一致的。

总结

这些指针(stdoutstdinstderr)是全局变量,指向标准 I/O 流的 FILE 结构体实例。这些实例在程序启动时由 C 标准库初始化,用于管理标准输入、输出和错误流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/58397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache paimon-CDC

CDC集成 paimon支持五种方式通过模式转化数据提取到paimon表中。添加的列会实时同步到Paimon表中 MySQL同步表:将MySQL中的一张或多张表同步到一张Paimon表中。MySQL同步数据库:将MySQL的整个数据库同步到一个Paimon数据库中。API同步表:将您的自定义DataStream输入同步到一…

电子信息-毕业设计选题推荐

人工智能与电子信息工程的融合 基于深度学习的电子信息系统故障诊断 人工智能算法在电子信息工程中的优化应用 电子信息工程中的智能图像识别技术 无线传感器网络 无线传感器网络在环境监测中的电子信息采集 多传感器融合的无线传感器网络应用 无线传感器网络中的数据压缩算法与…

linux 删除当前目录下修改时间超过1天的文件

在Linux中&#xff0c;你可以使用find命令结合-mtime选项来删除当前目录下修改时间超过1天的文件。以下是具体的命令示例&#xff1a; find . -type f -mtime 1 -delete解释一下上述命令&#xff1a; find&#xff1a;这是用于在文件系统中查找文件和目录的命令。.&#xff1…

【面试全纪实 | Linux 01】请回答,你真的了解Linux吗?

1. 什么是Linux Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位 硬件。Linux继承了Unix以网络为核心的设计思想&#…

代码随想录训练营Day11 | 226.翻转二叉树 - 101. 对称二叉树 - 104.二叉树的最大深度 - 111.二叉树的最小深度

226.翻转二叉树 题目链接&#xff1a;226.翻转二叉树思路&#xff1a;遍历二叉树&#xff0c;遍历的时候交换左右节点即可代码&#xff1a; TreeNode* invertTree(TreeNode* root) {reverse(root);return root;}// 迭代法&#xff0c;层序遍历void f2(TreeNode* root) {queue…

易友BOM管理软件

易友BOM管理软件介绍 易友BOM管理软件是一款功能齐全、操作简便、安全可靠的BOM管理系统。它为企业提供了多方面的BOM管理解决方案&#xff0c;帮助企业提高生产效率、降低成本、增强灵活性并提升竞争力。制造企业&#xff0c;都可以通过易友BOM管理软件来实现BOM管理的优化和…

安全见闻-二进制与网络安全的关系

一、二进制的基本概念 二、二进制在网络安全中的重要性 三、二进制安全的概念与范畴 1. 二进制安全的定义 2. 范畴 四、二进制安全的渗透测试方法 1. 静态分析 2. 动态分析 3. 模糊测试 4. 漏洞利用 5. 代码审计 五、结论 学习视频泷羽sec&#xff1a;安全见闻&…

git 怎么保留某个文件夹忽略其下面的所有文件?

在 Git 中&#xff0c;如果你想要保留某个文件夹&#xff08;比如 folder/&#xff09;但忽略其下面的所有文件&#xff0c;可以使用 .gitignore 文件来实现。需要注意的是&#xff0c;Git 不会自动创建空目录。因此&#xff0c;为了让 Git 记录这个空目录&#xff0c;你需要在…

【模型学习之路】手写+分析bert

手写分析bert 目录 前言 架构 embeddings Bertmodel 预训练任务 MLM NSP Bert 后话 netron可视化 code2flow可视化 fine tuning 前言 Attention is all you need! 读本文前&#xff0c;建议至少看懂【模型学习之路】手写分析Transformer-CSDN博客。 毕竟Bert是tr…

不用求人,4个方法快速恢复小米手机删除短信

手机短信作为我们日常办理事情的重要验收通道&#xff0c;往往承载着许多重要的信息。然而&#xff0c;由于各种原因&#xff0c;我们可能会不小心删除了重要的短信。那么&#xff0c;小米手机用户如何恢复这些被删除的短信呢&#xff1f;接下来&#xff0c;我们将分点为您详细…

爆肝整理14天AI工具宝藏合集(三)

&#x1f6e0;️以下是我为大家整理的AI工具宝藏合集&#xff08;三&#xff09;&#xff1a; &#x1f4a1;AI搜索 1️⃣ 天工AI搜索 2️⃣ 秘塔AI搜索 3️⃣ 夸克AI搜索 4️⃣ 开搜AI搜索 &#x1f4a1; AI视频 1️⃣ 可灵AI 2️⃣ 即梦AI 3️⃣ Vidu 4️⃣ Stable Video …

vue版本太低无法执行vue ui命令

连接 ui和create目前都只支持3.0以后得版本才能使用 https://blog.csdn.net/m0_67318913/article/details/136775252?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-136775252-blog-121204604.235v43pc_blog_bottom_relevance…

ETL集成工具丨如何运用ETLCloud单步调试断点功能

在现代数据处理领域&#xff0c;ETLCloud 的单步调试断点功能正成为数据管理的重要工具。ETLCloud 是一个强大的云端数据处理平台&#xff0c;它提供了灵活的单步调试功能&#xff0c;使得用户能够逐步跟踪和分析数据处理流程。本文将探讨如何运用 ETLCloud 的单步调试断点功能…

python 模块和包、类和对象

模块 模块是包含 Python 代码的文件&#xff0c;通常用于组织相关的函数、类和其他语句。模块可以被导入并在其他 Python 文件中使用。 创建模块 假设你创建了一个名为 mymodule.py 的文件&#xff0c;内容如下&#xff1a; # mymodule.pydef greet(name): return f"…

通信原理概论复习笔记(2):模拟调制与数字调制

5 模拟调制系统 调制: 将消息信号搭载(边带)到载波参数上(调幅; 调频; 调相); 边带滤波器 h ( t ) ↔ H ( ω ) h(t)\leftrightarrow H(\omega) h(t)↔H(ω). 载波: 高频周期性震荡信号; c ( t ) A cos ⁡ ( ω c t φ ) c(t)A\cos(\omega_c t\varphi) c(t)Acos(ωc​tφ)…

Linux系统用户操作以及权限管理

用户账号 用户账号&#xff1a;linux系统当中用户的角色&#xff0c;以及用户所拥有的权限 超级管理员&#xff1a;root roottest1&#xff1a;~# 命令含义root表示当前的登录用户test1当前主机名~当前目录#表示当前用户时管理员$表示当前用户是普通用户 exit&#xff1a;…

全新更新!Fastreport.NET 2025.1版本发布,提升报告开发体验

在.NET 2025.1版本中&#xff0c;我们带来了巨大的期待功能&#xff0c;进一步简化了报告模板的开发过程。新功能包括通过添加链接报告页面、异步报告准备、HTML段落旋转、代码文本编辑器中的文本搜索、WebReport图像导出等&#xff0c;大幅提升用户体验。 FastReport .NET 是…

Unity(四十八):Unity与Web双向交互

效果 游戏对象绑定脚本 游戏脚本源码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Tent : MonoBehaviour {public Camera camera;// Start is called before the first frame updatevoid Start(){}// Update is called once…

Docker:容器化和虚拟化

虚拟化 虚拟化是一种资源管理技术&#xff0c;它将计算机的各种实体资源&#xff08;如CPU、内存、磁盘空间、网络适配器等&#xff09;予以抽象、转换后呈现出来&#xff0c;并可供分割、组合为一个或多个电脑配置环境。这些资源的新虚拟部分是不受现有资源的架设方式、地域或…

【果蔬识别】Python+卷积神经网络算法+深度学习+人工智能+机器学习+TensorFlow+计算机课设项目+算法模型

一、介绍 果蔬识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;通过收集了12种常见的水果和蔬菜&#xff08;‘土豆’, ‘圣女果’, ‘大白菜’, ‘大葱’, ‘梨’, ‘胡萝卜’, ‘芒果’, ‘苹果’, ‘西红柿’, ‘韭菜’, ‘香蕉’, ‘黄瓜’&#xff09;…