当前位置: 首页 > 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作为一款成熟的邮件营…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!

多连接 BLE 怎么设计服务不会乱&#xff1f;分层思维来救场&#xff01; 作者按&#xff1a; 你是不是也遇到过 BLE 多连接时&#xff0c;调试现场像网吧“掉线风暴”&#xff1f; 温度传感器连上了&#xff0c;心率带丢了&#xff1b;一边 OTA 更新&#xff0c;一边通知卡壳。…...