参考链接:1b3K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6r3k6Q4x3X3c8%4K9h3E0A6i4K6u0W2L8%4u0Y4i4K6u0r3M7s2N6F1i4K6u0r3L8r3W2F1N6i4S2Q4x3V1k6#2M7$3g2J5i4K6u0V1L8h3!0V1k6g2)9J5c8X3W2G2i4K6u0V1k6X3W2D9k6g2)9J5c8X3W2F1N6s2u0G2k6s2g2U0N6r3W2G2L8W2)9J5c8R3`.`.033K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6r3k6Q4x3X3c8%4K9h3E0A6i4K6u0W2L8%4u0Y4i4K6u0r3M7s2N6F1i4K6u0r3L8r3W2F1N6i4S2Q4x3V1k6#2M7$3g2J5i4K6u0V1L8h3!0V1k6g2)9J5c8X3W2G2i4K6u0V1k6X3W2D9k6g2)9J5c8X3k6S2K9$3g2Q4x3X3c8$3N6r3q4T1L8r3g2Q4x3X3c8W2P5s2m8D9L8$3W2@1i4K6u0r3记一次跟着ctiwiki学习IO_FILE Exploitation的过程,我会在有些地方调试看看,加深理解。大部分内容都是来自ctfwiki。我这里是为了链接libc2.23版本的,方便后面调试。下载有调试符号和没调试符号的libc这里的the_end程序其实就是后面2018 HCTF the_end题目的源程序查看libc文件的调试链接更改链接为有调试符号的修改前的效果修改之后的效果FILE 在 Linux 系统的标准 IO 库中是用于描述文件的结构,称为文件流。 FILE 结构在程序执行 fopen 等函数时会进行创建,并分配在堆中。我们常定义一个指向 FILE 结构的指针来接收这个返回值。FILE 结构定义在 libio.h 中,如下所示进程中的 FILE 结构会通过_chain 域彼此连接形成一个链表,链表头部用全局变量_IO_list_all 表示,通过这个值我们可以遍历所有的 FILE 结构。在标准 I/O 库中,每个程序启动时有三个文件流是自动打开的:stdin、stdout、stderr。因此在初始状态下,_IO_list_all 指向了一个有这些文件流构成的链表,但是需要注意的是这三个文件流位于 libc.so 的数据段。而我们使用 fopen 创建的文件流是分配在堆内存上的。我们可以在 libc.so 中找到 stdin\stdout\stderr 等符号,这些符号是指向 FILE 结构的指针,真正结构的符号是p _IO_list_all可以看到_IO_list_all是指向_IO_2_1_stderr_,而且地址位于libc.so上。注意结构体是_IO_FILE_plus,后面会说到p _IO_2_1_stderr_再看_IO_2_1_stderr_的结构,可以看到_chain指向了_IO_2_1_stdout_p _IO_2_1_stdout_再看_IO_2_1_stderr_的结构,可以看到_chain指向了_IO_2_1_stdin_p _IO_2_1_stdin_看_IO_2_1_stdin_的结构,可以看到_chain是指向0x0,为空。从这四个图可以看到链表指向是_IO_list_all IO_2_1_stderr IO_2_1_stdout IO_2_1_stdin在初始状态下,链表中只有这三个文件流。但是事实上_IO_FILE 结构外包裹着另一种结构_IO_FILE_plus,其中包含了一个重要的指针 vtable 指向了一系列函数指针。在 libc2.23 版本下,32 位的 vtable 偏移为 0x94,64 位偏移为 0xd8从上面三张图可以看到_IO_2_1_stderr_,IO_2_1_stdout,_IO_2_1_stdin_都是这种结构,vtable指向的地址都是一样的。也可以看到64位下偏移是0xd8vtable 是 IO_jump_t 类型的指针,IO_jump_t 中保存了一些函数指针,在后面我们会看到在一系列标准 IO 函数中会调用这些函数指针p *(struct _IO_jump_t *)0x7ffff7dd06e0查看vtable的结构,以 __GI_为前缀的符号通常是 glibc 内部用于绑定到实际实现函数的别名,其真正的函数名是去掉__GI_的先下个源码wget 819K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3N6s2m8Q4x3X3g2Y4L8Y4g2Q4x3X3g2G2M7X3N6Q4x3V1k6Y4L8Y4g2Q4x3V1k6Y4L8r3W2T1j5#2)9J5c8X3N6D9K9h3u0U0i4K6u0V1x3W2)9J5k6e0t1K6i4K6u0W2N6r3q4J5i4K6u0W2P5s2Z5`.,方便后面看fread这些函数tar -xvf glibc-2.23.tar.xzfread 是标准 IO 库函数,作用是从文件流中读数据,函数原型如下fread 函数的各个参数作用如下:cat glibc-2.23/libio/iofread.c,fread 的代码位于/libio/iofread.c 中,函数名为_IO_fread,可以看到这个函数会接着调用_IO_sgetn函数。_IO_sgetn函数定义在libio/genops.c这个文件内,grep -C 3 "_IO_sgetn" glibc-2.23/libio/genops.c,可以看到在_IO_sgetn 函数中会直接返回_IO_XSGETNgrep -C 3 "_IO_XSGETN" glibc-2.23/libio/libioP.h_IO_XSGETN是一个在 glibc 的 IO 系统内部用于实现多态调用的宏,它的定义位于头文件 libio/libioP.h中,AI是这样解释的:这里的 JUMP2是另一个宏,负责最终的函数跳转。它的作用是:根据传入的 FILE 结构体 (**FP****) 找到其对应的虚函数表 (vtable),然后从表中取出 ****__xsgetn**函数指针并调用它,同时将参数 FP, DATA, N传递过去也就是说fread最后会调用vtable表中的__xsgetn函数指针,最后调用了__GI__IO_file_xsgetn。这个以 __GI_为前缀的符号通常是 glibc 内部用于绑定到实际实现函数的别名,其真正的函数定义就是 _IO_file_xsgetngrep -A 60 "_IO_file_xsgetn" glibc-2.23/libio/fileops.c这个函数内还调用了vtable中的__underflow指针类似地最终会调用系统接口 read 函数fread _IO_sgetn _IO_XSGETN __xsgetn __IO_file_xsgetn __underflow
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289374.htm
初识IO_FILE Exploitation
177 浏览
0 回复
暂无回复,快来抢沙发吧!