当前位置: 首页 > news >正文

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 标准库初始化,用于管理标准输入、输出和错误流。

相关文章:

CTF-PWN: 什么是_IO_FILE?

重要概念:fopen()返回的是一个结构体的指针 _IO_FILE 结构体在什么时候被创建&#xff1f; _IO_FILE 结构体的实例是在程序使用标准 I/O 函数&#xff08;如 fopen、fclose、fread、fwrite 等&#xff09;时创建和管理的。这个结构体实际上是 GNU C Library (glibc) 用于处理…...

前端八股文第二篇

11.事件循环 事件循环&#xff08;Event Loop&#xff09;是 JavaScript 运行时中的一种机制&#xff0c;用于处理异步操作和事件驱动的编程。在浏览器环境中&#xff0c;事件循环是指浏览器通过事件队列&#xff08;Event Queue&#xff09;来管理和调度异步任务的执行顺序。…...

springboot汽车保修服务管理系统-计算机毕业设计源码00052

摘 要 随着汽车数量的不断增加和汽车保修服务需求的日益增长&#xff0c;建立一套高效的汽车保修服务管理系统变得至关重要。基于Spring Boot框架的汽车保修服务管理系统旨在整合汽车保修流程&#xff0c;简化管理流程&#xff0c;提高服务质量和用户体验未来&#xff0c;我们将…...

分布式架构搭建博客网站

目录 运行环境基础配置需求准备工作配置静态ip修改主机名及host映射开启防火墙时间同步配置免密ssh登录 环境搭建Server-Web端安装LNMP环境软件Server-NFS-DNS端上传博客软件Server-NFS-DNS端设置NFS共享Server-Web设置挂载远程共享目录nginx设置在数据库中创建数据库和用户重启…...

python-opencv给图片或视频去水印

文章目录 引言inpaint函数的使用方法鼠标事件回调函数cv2.setMouseCallback介绍去水印步骤实现代码 引言 本文主要基于cv2.inpaint函数实现图片的水印去除。 inpaint函数基于图像修复算法&#xff0c;通过对缺陷区域周围像素的分析和插值&#xff0c;生成合适的像素值来填充缺…...

免费送源码:Java+ssm+Springboot Springboot手办定制销售系统 计算机毕业设计原创定制

Springboot手办定制销售系统 摘 要 随着人们生活水平的提高和互联网的发展&#xff0c;人们消费思想和消费方式的逐渐改变&#xff0c;使得消费者开始追求自身品味和个性。手办定制就是在这种条件下应运而生。手办定制是基于客户需求来定制产品&#xff0c;满足客户对其功能、结…...

卡夫卡的使用

关于消息队列的使用 一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveM…...

mac|maven项目在idea中连接redis

安装maven brew install maven idea-setting导入redis插件 idea新建maven项目 构建系统选择maven 项目右侧数据库图标导入redis 新建一个数据库&#xff0c;名称必须为数字&#xff0c;测试一下是否可以连接&#xff0c;连接成功后选择确定 pom.xml导入redis <depende…...

Python基础学习------第一天

print("hello world") 1.括号和引号&#xff0c;必须使用的是英文 被双引号包围起来的称为字符串。 python注释&#xff1a;单行注释&#xff1a;1.井号# 2.多行注释 &#xff1a;""" """ print输出多个内容是中间用逗号隔开就好…...

MySQL的SQL语句之触发器和存储过程的应用

触发器 Trigger 一.触发器 作用&#xff1a;当检测到某种数据表发生数据变化时&#xff0c;自动执行操作&#xff0c;保证数据的完整性。 1.创建一个触发器 如上图所示&#xff0c;查看这个create的帮助信息的时候&#xff0c;这个create trigger就是创建触发器的意思。 如…...

【MD5】密码加密之加盐算法

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 本期主要是给大家分析一下, 密码的如果加密存储的, 学习加盐算法的思想, 通过一个简单的案例, 即可快速学习. 一起来看看叭~ 适用于编程初学者&#xff0c;感兴趣的朋友们可以订阅&…...

服务器虚拟化

前言 服务器虚拟化是一种技术&#xff0c;它通过将一台物理服务器的软件环境分割成多个独立分区&#xff0c;使每个分区都能模拟出一台完整的虚拟服务器。这种技术利用虚拟化技术充分发挥服务器的硬件性能&#xff0c;提高运营效率&#xff0c;节约能源并降低经济成本。 通过…...

贪心算法理论基础和习题【算法学习day.17】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…...

爬虫ip技术未来发展趋势

各位朋友&#xff0c;大家好&#xff01;有伙伴问爬虫技术未来会有更好的发展么&#xff0c;那今天小蝌蚪来跟大家聊聊爬虫技术未来的发展趋势分享一下行业咨询。 大家在日常工作和生活中&#xff0c;都希望事情能更省心、高效吧&#xff1f;未来的爬虫技术就朝着这个方向发展…...

推荐一款功能强大的文字处理工具:Atlantis Word Processor

Atlantis word proCEssor是一款功能强大的文字处理工具。该软件可以让用户放心的去设计文档&#xff0c;并且软件的界面能够按用户的意愿去自定义&#xff0c;比如工具栏、字体选择、排版、打印栏等等&#xff0c;当然还有更多的功能&#xff0c;比如你还可以吧软件界面中的任何…...

语言≠思维,大模型学不了推理:一篇Nature让AI社区炸锅了

转自&#xff1a;机器之心 大语言模型&#xff08;LLM&#xff09;为什么空间智能不足&#xff0c;GPT-4 为什么用语言以外的数据训练&#xff0c;就能变得更聪明&#xff1f;现在这些问题有 「标准答案」了。 近日&#xff0c;一篇麻省理工学院&#xff08;MIT&#xff09;等…...

Ubuntu 安装 npm

1. 升级apt sudo apt-get update 2. 安装nodejs sudo apt install nodejs 3. 安装npm sudo apt-get install npm 4. 查看版本 node -v npm -v 完成安装&#xff01;...

Go:package

文章目录 标准库概述regexp包锁和sync包自定义包和可见性基本格式导入外部安装包包的初始化 自定义包使用godoc自定义包的目录结构 标准库概述 在之前的部分已经用了很多和标准库有关的内容&#xff0c;比如有fmt&#xff0c;os这种功能 unsafe: 包含了一些打破 Go 语言“类型…...

大数据之微服务注册、发现与熔断方案

大数据微服务注册、发现与熔断方案 介绍实现框架利用Spring Cloud实现微服务注册&#xff0c;发现&#xff0c;熔断实例&#xff1f; 一&#xff0c;介绍 大数据微服务注册、发现与熔断是微服务架构中的关键概念&#xff0c;它们各自在微服务架构中扮演着重要的角色。以下是对这…...

最新出炉!2024年邮件营销平台综合盘点

随着数字化营销的不断发展&#xff0c;邮件营销依然是企业与客户保持联系的重要渠道之一。2024年&#xff0c;邮件营销平台市场竞争激烈&#xff0c;各大平台纷纷推出新功能&#xff0c;以满足企业日益增长的需求。在众多平台中&#xff0c;Zoho Campaigns作为一款成熟的邮件营…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...