深入学习一下IO的比较简单的部分的源代码,并简单写一下poc

参考链接:https://xz.aliyun.com/t/6567?time__1311=n4%2BxnD0Dg7G%3DBhDBqooGkDRm8DCY1DuAAnOoD

DEMO1-Fread

演示了如何利用fread进行任意地址写,主要就是将缓冲区构造成目标地址,需要注意的是缓冲区当占满的时候可能会被新数据覆盖,因此小心使用。简单总结一下原理:

1.将缓冲区读写和目标位置的读写分开,分成大概两个模块,一个是将缓冲区的数据读到目标位置,一个是利用系统调用将文件中的数据督导缓冲区,这两个模块都会维护读指针和缓冲区的关系。

2.总体方向就如1所说,其中的比较重要的细节可以分为(本人理解):

​ 2.1 缓冲区的分配,需要设置flag来绕过,否则就会覆盖之前构造好的指针

​ 2.2 关于其他的flag,我的建议是越少越好,flag多的话,设计的函数也会变多,虽然说逻辑可以明白,但是非常混乱,包括但不限于,save buf的交替处理,读写缓冲区共用,等等,但是中心思想还是第一点所说的,这是非常重要的。

​ 2.3 当write,read交替操作时,会先刷新write,然后尽可能移动readend和readptr,但这只是read缓冲区大小的扩充,不代表其获得了额外数据,还是得通过系统调用来调整。

/*此程序演示了向test中写内容会先把内容写到msg中*/
#include<stdio.h>
#include<stdlib.h>
int main(){
setbuf(stdout,0);
char msg[20];
char test[20];
test[20]='\x00';
msg[20] = '\x00';
FILE* fd = fopen("flag","rw+");
/*construct FILE*/
fd->_fileno = 0;
fd->_flags = 0xFBAD0000;
fd->_IO_read_base = msg;
fd->_IO_read_ptr = fd->_IO_read_end = msg + 20;
fd->_IO_buf_base = msg;
fd->_IO_buf_end = msg + 20;
fread(test,1,19,fd);
puts(msg);
return 0;
}

DEMO2-Fwrite

控制FILE结构体达成任意地址内容泄露的目的

符号位绕过两个检查:

1.overflow的分配buf的检查,如果最近没有putting过或bufbase=0则会分配buf。

2.绕过do_new_write的检查,如果非追加模式的话则会判断readend和writebase的大小,会将writebase移动到未知区域。

#include<stdio.h>
#include <string.h>
#include<stdlib.h>
#define FAKEMESSAGE "helloword\x00"

int main(){
char*fakemsg = malloc(strlen(FAKEMESSAGE)+1);
memcpy(fakemsg,FAKEMESSAGE,strlen(FAKEMESSAGE));
char*victim = "ooo";
setbuf(stdout,0);
FILE* fd = fopen("flag","rw+");
/*construct FILE*/
fd->_fileno = 1;
fd->_flags = 0xFBAD1800;
fd->_IO_read_base = 0;
fd->_IO_read_ptr = 0;
fd->_IO_read_end = 0;
fd->_IO_buf_base = fakemsg;
fd->_IO_buf_end = fakemsg + 100;
fd->_IO_write_base = fakemsg;
fd->_IO_write_end = fd->_IO_write_ptr = fakemsg+strlen(FAKEMESSAGE);
fwrite(victim,1,3,fd);
}

执行结果如下:可以看见输出了目标地址的内容(以ASCII的形式)

root@L:/home/l/poc# ./writepoc 
hellowordoooroot@L:/home/l/poc#