PWN系列-初探IO
PWN系列-初探IO
记录一下自己理解的IO,文章的代码均是glibc-2.23版本下的代码。
由于笔者才疏学浅,学识有限,文章中难免会有疏漏和错误之处,恳请各位师傅批评指正,多多包涵。
什么是IO
IO中的I其实就是in,O其实就是out,一个输入,一个输出。
IO长什么样子
_IO_FILE_plus
首先先来认识一下_IO_FILE_plus
结构体
struct _IO_FILE_plus
{
_IO_FILE file; /* 基础的文件结构体 */
const struct _IO_jump_t *vtable; /* 虚表指针 */
};
总结起来,_IO_FILE_plus
结构体通过包含 _IO_FILE
结构体和一个虚表指针。
_IO_FILE
_IO_FILE
结构体定义:
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; /* 文件描述符 */
#if 0
int _blksize; /* 块大小 */
#else
int _flags2; /* 额外标志 */
#endif
_IO_off_t _old_offset; /* 旧的偏移量 */
#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
unsigned short _cur_column; /* 当前列号 */
signed char _vtable_offset; /* 虚表偏移量 */
char _shortbuf[1]; /* 短缓冲区 */
#endif
_IO_lock_t *_lock; /* 锁 */
#if defined _LIBC_REENTRANT
_IO_lock_t *_lock_owner; /* 锁的拥有者 */
unsigned int _lock_count; /* 锁计数 */
#endif
_IO_off64_t _offset; /* 偏移量 */
void *__pad1; /* 填充1 */
void *__pad2; /* 填充2 */
void *__pad3; /* 填充3 */
void *__pad4; /* 填充4 */
size_t __pad5; /* 填充5 */
int _mode; /* 模式 */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
/* 未使用的填充空间 */
};
此结构体定义了标准C库中用于文件操作的内部数据结构。以下是每个成员变量的简要说明:
_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
: 当前的文件偏移量。__pad1
,__pad2
,__pad3
,__pad4
: 用于填充的指针,确保结构体对齐。__pad5
: 用于填充的大小。_mode
: 文件模式。_unused2
: 未使用的填充空间,用于确保结构体的大小和对齐。
_IO_jump_t
struct _IO_jump_t
定义如下:
struct _IO_jump_t
{
size_t __dummy;
size_t __dummy2;
_IO_finish_t __finish;
_IO_overflow_t __overflow;
_IO_underflow_t __underflow;
_IO_underflow_t __uflow;
_IO_pbackfail_t __pbackfail;
_IO_xsputn_t __xsputn;
_IO_xsgetn_t __xsgetn;
_IO_seekoff_t __seekoff;
_IO_seekpos_t __seekpos;
_IO_setbuf_t __setbuf;
_IO_sync_t __sync;
_IO_doallocate_t __doallocate;
_IO_read_t __read;
_IO_write_t __write;
_IO_seek_t __seek;
_IO_close_t __close;
_IO_stat_t __stat;
_IO_showmanyc_t __showmanyc;
_IO_imbue_t __imbue;
};
这些字段是指向不同函数类型的指针,用于实现多态性和灵活的文件操作。以下是这些函数指针的大致功能说明:
__finish
: 完成流的操作。__overflow
: 处理输出缓冲区溢出的操作。__underflow
: 处理输入缓冲区空的操作。__uflow
: 处理输入缓冲区下溢的操作。__pbackfail
: 处理向输入缓冲区放回字符失败的操作。__xsputn
: 写入多个字符的操作。__xsgetn
: 读取多个字符的操作。__seekoff
: 相对偏移位置的文件定位操作。__seekpos
: 绝对位置的文件定位操作。__setbuf
: 设置缓冲区的操作。__sync
: 同步文件缓冲区的操作。__doallocate
: 分配缓冲区的操作。__read
: 读取数据的操作。__write
: 写入数据的操作。__seek
: 文件定位的操作。__close
: 关闭文件的操作。__stat
: 获取文件状态的操作。__showmanyc
: 显示字符数的操作。__imbue
: 设置区域设置信息的操作。
_IO_list_all
_IO_list_all
是一个全局变量,在 GNU C 库(glibc)中用于管理所有打开的文件流。它是一个指向 _IO_FILE
结构体链表的指针。通过这个链表,glibc 可以跟踪和操作所有当前打开的文件流。
链表结构
_IO_list_all
是一个指向 _IO_FILE
结构体的指针,而 _IO_FILE
结构体本身包含一个 _chain
指针,指向下一个文件流。因此,所有打开的文件流形成了一个链表。这个链表的头部是 _IO_list_all
。
作用
- 管理文件流: 通过维护这个链表,glibc 能够方便地管理所有打开的文件流。每当有新的文件流创建时,会将其添加到链表中;当文件流关闭时,会将其从链表中移除。
- 文件操作: 许多内部文件操作函数,例如刷新所有文件流、关闭所有文件流等,都需要遍历这个链表,以对每个文件流执行相应的操作。
IO的利用思路
IO利用的大致思路都是构造fake_io结构体,布置一些数据和函数,通过程序正常的执行流程走到IO操作来劫持程序流来getshell。
这就是我目前所认识的IO,IO涉及到很多攻击手法,我应该会另写一篇文章来进行记录各种板子。
这篇文章中的图片来源两位师傅的博客,但是我一下子找不到这两位师傅的博客地址了,故没有在文章末尾添加参考文章,先冒昧的直接拿来了,望见谅。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理