Pwnable.tw seethefile
第二次做这道题了,搞懂了第一次做这题不懂的一些细节✈
程序允许我们open_file,read_file,write_file,唯一发现的漏洞是在leave_massage的时候输入name可以覆写到bss上的fd.
1 | case 5: |
并且题目功能是在于对文件的操作,调用fread,fwrite,fopen,fclose,那这题就是考察io_file了。
对于io_file的利用,一般是直接覆盖vtable结构体指针指向可控的内存,再者就是构造整个io_file_plus结构体,但这种方法要求我们构造时要绕过一些检查。
1 |
|
我们要构造出_IO_IS_FILEBUF=0的_flags,使得可以绕过上面两个检测例如_flags=0xffffdfff(原理在于0xdf=(11011111),0x20=(0010000),0xdf&0x20==0),最终执行_IO_FINISH (fp);
在C语言中,成功调用fopen函数后会在堆上分配一块空间用于存放_IO_FILE_plus结构体,并且返回结构体的首地址,而在调用fclose时,最终会通过io_file_plus里的vatble调用相应的函数。
1 | pwndbg> telescope 0x9003008 80 |
因此我们只要构造好_IO_FILE_plus结构体,并通过name的溢出改fd指向我们构造的_IO_FILE_plus结构体,再执行fclose即可完成利用。
首先要Leak,题目给了我们任意文件读的机会,因此我们可以通过读取**’/proc/self/maps’**(文件的内存信息存储于此)来得到libc地址。
接下来就是构造file_plus结构体,几处要点:
1.构造_flag=0xffffdfff,绕过检测去执行((struct IO_FILE_plus *)fp->vtable)->__finish(fp)
2.在fd指向内存的偏移为0x4位置写入’;$0’,;用来分隔命令。
3.io_file结构体大小为0x94,因此要填充满0x94。
4.vatble指针指向紧接着的file结构体的内存,方便后面的构造。
5.vtable结构体对应的__finish函数指针(第3个位置)写为system()
fake_struct:
1 | pwndbg> telescope 0x804b300 80 |
执行((struct IO_FILE_plus *)fp->vtable)->__finish(fp)相当于执行system(“xxx;$0”)得到shell🚩
EXP:
1 | from pwn import * |
fclose部分源码:
1 | /* libio/iofclose.c */ |