PWN堆IO_FILE基础
-
参考博客:[原创]无路远征——GLIBC2.37后时代的IO攻击之道(零)-Pwn-看雪-安全社区|安全招聘|kanxue.com
-
IO
也就是输入输出的意思,但是C
语言的输入输出的函数有很多,例如:puts
、printf
、write
、stdin
、stdout
、scanf
、read
等与输入输出相关的函数。 -
而我们所说的打
IO
打的是我们封装到比较上层的函数,比如puts
、printf
这类的上层封装的函数。read
、write
这两个是比较底层的,系统调用syscall
的输入输出,一般都是调用这两个函数。puts
、printf
等这些IO
函数最后都会通过write
这个底层函数与操作系统交互。- 所以我们所说的打
IO
,打的就是这种上层输入输出函数。在调用这些函数的时候会经过一些指针
、结构体
、函数指针
等,所以我们通过劫持指针
、伪造IO结构体
、绕过检查机制
从而getshll
或者执行shellcode
。 - 与
IO
相关的都可以在glibc
源码中,/path/to/glibc2.23/libio
中可以看到。
-
由于高版本的
glibc
中hook
指针被删除了,所以余下可用的函数指针只有io
相关的函数指针了,在高版本堆利用的时候IO
利用就成了基础了。
IO_FILE起源及结构体
- 如果出过
pwn
题或者做过全缓冲
的pwn
题就会了解到这个函数。和缓冲区的三种工作模式,无缓冲
、行缓冲
、全缓冲
。
1 | setvbuf(stdin,NULL,_IONBF,0); |
- 为什么要设置这三种模式,这就和
硬件
、操作系统
、程序
三者有关。首先程序要读写硬盘或者是输出到屏幕中,这些都是要通过系统调用syscall
,进行write
、read
系统调用。 - 而何时进行系统调用,这就成为了设计
IO
的一个重要问题。如果每一个字节都需要使用syscall
系统调用(即无缓冲模式)。向硬件进行读写操作,这就会大大降级操作系统的效率,并且硬件频繁读写也会造成更快的损坏。 - 为了减少这种情况,在设计
IO
的时候就会出现导致,设置了缓冲区
,要输入的数据或者要输出的数据都会先被放入缓冲区,直到缓冲区满了之后,再进行系统调用,将缓冲区存储的内容写入到屏幕或者其他硬件中(全缓冲),以便提高操作系统的效率,提高硬件的使用寿命,这也就出现了现在的IO_FILE
结构体。 - 接下来总结一下
glibc
封装的上层函数中与输入输出相关的函数,对于IO
的攻击一般就攻击这些IO
函数的结构体``。- 标准输入函数
gets()
、fgets()
、scanf()
、fscanf()
、sscanf()
、getc()
、fgetc()
、getchar()
、getline()
、getdelim()
- 标准输出函数
printf()
、fprintf()
、sprintf()
、snprintf()
、putc()
、fputc()
、putchar()
、puts()
- 文件操作函数:
fopen()
、freopen()
、fdopen()
、fclose()
、fflush()
、setbuf()
、setvbuf()
、fread()
、fwrite()
、fseek()
、ftell()
、fewind()
、rewind()
- 格式化字符串相关函数:
printf()
、fprintf()
、sprintf()
、snprintf()
、vprintf()
、vfprintf()
、vsprintf()
、vsnprintf()
- 其他相关函数:
perror()
、tmpfile()
、clearerr()
、feof()
、ferror()
、stdout
、stdout()
、stdin()
、stderror()
- 标准输入函数
IO_FILE相关动调
-
写介绍几个比较重要的
IO
结构体,并且说明这写结构体在glibc2.23
源码的什么位置。 -
这里先汇总一下与
IO_FILE
相关动调命令,与IO_FILE
相关的调试基本上就是打印结构体。可以在gdb
中使用p
命令打印出结构体的具体存储的值
1 | p stdout |
- 接下来调试几个上层的输出函数。来对
IO
调用有个总体了解。
IO_FILE相关源码
IO_FILE基础
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iyheart的博客!