首页
社区
课程
招聘
[原创]新人PWN入坑总结(七)
发表于: 2021-8-8 09:16 17986

[原创]新人PWN入坑总结(七)

2021-8-8 09:16
17986

一、_IO_FILE_plus:

1.结构定义:在libio.h中找不到它的结构定义,但是wiki上说是如下的:

虽然网上相关定义的里面包含的是_IO_FILE,但是实际上在内存中_IO_FILE却会被完善成_IO_FILE_complete:

(1)两条黄线之间的数据即为struct _IO_FILE_complete,包含struct _IO_FILE

(2)第一条黄线至蓝线的即为struct _IO_FILE

(3)最下面的就是struct _IO_jump_t

2.符号内容:

以上三个符号就是程序被加载之后的_IO_FILE_plus这个结构体生成的结构体指针。

 

 

二、_IO_FILE和_IO_FILE_complete(libio.h中)

1._IO_FILE结构定义:

2._IO_FILE_complete结构定义:

3.实际内存情况:

由于程序中基本都会自动完善,所以只能查看到_IO_FILE_complete的实际内存结构

4.符号内容:

这三个符号就是struct _IO_FILE的结构体指针,但是实际会被完善为_IO_FILE_complete。

 

 

三、IO_jump_t结构:

1.结构定义:

2.实际内存情况:

3.符号内容:

_IO_file_jumps

这个符号是全局变量符号,可以直接查看,能算出固定偏移。

vtable

这个符号不是之前介绍的几个符号,不是全局的,里面保存着IO_file_jumps的地址,只能通过前面几个全局符号来对应偏移搜索,没办法在gdb中直接查看。stdin之类的三个输入输出流如果想调用_IO_file_jumps里面的函数,只能通过vtable来调用,所以如果我们可以伪造一个IO_jump_t结构体,使得vtable指向这个伪造的结构体,根据偏移就可以调用里面伪造的函数指针。比如修改stdin结构中的vtable指向伪造的IO_jump_t结构体,并且将伪造的IO_jump_t结构体的__overflow劫持为system函数地址,那么使用stdin调用__overflow时就相当于调用system函数。

 

 

四、_IO_FILE_plus中各个结构的成员含义:

1._IO_FILE_:这个结构体生成的指针就是我们实际上编程时用fopen返回值指针。

(1)int _flags:给vtable中的各类函数指针传入的第一个参数。(之后会讲到)

(2)

这一系列就是对应的stdin,stdout,stderr中读取地址,写入地址,buf地址。可以通过修改stdin结构体中的buf_base和buf_end,改为某个bss段地址,来使得scanf之类的读取函数读到bss段上。其它用法类似,ctfwiki详解。

(3)

这段就不知道干啥的了,应该需要具体调试才知道具体用法,网上也搜不到。

(4)struct _IO_FILE *_chain:

保存的是一个_IO_FILE指针,实际应该是_IO_FILE_plus指针,指向下一个_IO_FILE_plus结构体。

有一个全局变量_IO_list_all,里面保存_IO_2_1stderr的地址,且距离_IO_2_1stderr偏移不远:

这其实是一个链表,由_IO_list_all进行访问维护,形式如下:

程序会通过_IO_list_all来找到这三个输入输出流。

(5)

这段也不知道干啥用的。

(6)

这段在_IO_FILE_complete中定义的也不知道干啥用。

2.IO_jump_t结构,也就是vtable中的,里面都是一些函数指针,程序调用对应的输入输出流就会调用对应的vtable中的函数指针。这边挑一些常用的函数:

(1)_IO_xsgetn_t:实际是__GI_IO_file_xsgetn,会被fread函数调用。

(2)_IO_xsputn_t:实际是__IO_new_file_xsputn,会被fwrite函数调用,还有printf/puts等一些输出流函数。

(3)fopen和fclose会将三大输入输出流从_IO_list_all,chain域,链表脱链。

▲fopen情况下_IO_FILE_plus结构体会位于堆内存中

 

 

五、FSOP的触发与伪造:File Stream Oriented Programming

1.伪造:

劫持_IO_list_all的值,指向伪造的_IO_FILE_结构体stderr。

2.触发:

借助_IO_flush_all_lockp触发,这个函数会刷新每个_IO_FILE结构体,同样调用里面vtable中的_IO_overflow。那么如果_IO_overflow为system,并将flag=/bin/sh,那么就可以getshell了。

▲而_IO_flush_all_lockp这个函数不需要手动触发,以下情况程序会自己触发:


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-8-8 09:19 被PIG-007编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//