TSCTF2019 Final fileSystem
前言
填坑,当时做的时候卡在unsorted bin attack改掉限制
程序逻辑
决赛的题最深的感触就是题目的代码量比平时见到的多,自己读代码能力太弱,这道题还稍微好点,以后遇到这种链表什么的最好动态地去看,直观一点。
程序的功能是可以创建文件夹,在文件夹的下面可以创建文件,看代码+动态调可以复原出几个比较重要的结构体。
dir为文件夹结构体,其中前0x20字节存储文件夹名,另一个成员存储文件夹中包含文件的最后一个(比如文件夹中包含文件0123,这个指针为file3的文件指针),在0x603050处用mmap分配了一块地址,所有的文件夹结构体都存储在这个结构体中
file_chunk为文件结构体,前0x20字节存储文件名,0x30处存储content_size,0x38处存储同一个文件夹下的它的前一个文件指针(0123的话3的prev_file_chunk为2),content_chunk存储文件内容。每次创建文件固定分配0x48为file_chunk,用户指定size分配content_chunk
delete_node为删除的文件临时存储的结构,每次删除文件都会分配这样一个结构体,把结构体存放在0x603058所在的map_addr+0x280中,每次要恢复的时候从刚释放的文件找起,遍delete_note获取要恢复的文件
程序的功能如下:
最开始有一个Init_set函数来mmap一个地址存储后面的各种结构体,用这样一个随机的地址可以避免unlink
CreateDir函数最多可以创建16个文件夹,初始化其中的成员为0
CreateFile函数创建文件,限制每个文件大小不大于0x9f。在使用snprintf的时候,存在漏洞,即输入file_name长度+格式化字符串长度超过0x30时,snprintf返回0x31,从而可以写content_size一个字节,进而在写content_chunk的时候产生溢出。
ShowFile函数输出content_chunk的内容
DeleteFile删除文件,放入delete_node中,free并没有清空文件内容
RecoverFile恢复文件,将deleted_node的节点加回到链表尾部
漏洞利用
经过上述分析,有两个漏洞,一个snprintf可以造成堆溢出,对于一个节点,Delete再Recover之后可以再Delete,为double free(因为Recover并没有重新malloc,而是把释放过的节点又连接到了链表尾部)。
我们首先分配一个0x90的块,按照上述方法,free->recover->show可以泄露libc。同理free两个fast bin大小的块再recover再show可以泄露heap_base。
分配一个0x38一个0x48的块(从第一个Unsorted bin分配),释放它们让他们进入fast bin,分配一个0x90的块再释放(这个块在第一个Unsorted bin的下方),得到unsorted bin,再分配一个content_chunk大小为0x38的块,用掉刚才的fast bin,用snprintf的漏洞,可以让这个content_chunk覆写到Unsorted bin,修改其bk = 0x603068-0x10,再分配0x90的块就可以让0x603068写入main_arena+88,但是这里有个坑,就是每次都是要先分配0x58大小的堆作为file_chunk,这里就从Unsorted bin里分配,我们知道Unsorted bin攻击之后就只能用fast bin或者small bin进行分配了,因此这里会出错。解决方案就是提前分配一堆0x48的块,释放进0x50的fast bin,从此CreateFile都从它们中取,同理,我们double free需要的file_chunk也要从它们取,另外还要提前布置好0x70的fast bin的环境,突破限制之后直接一顿分配即可。最后分配0x10的块,使用Unsorted bin报错从而调用Malloc_hook得到shell。
1 | #coding=utf-8 |
收获
看代码,做题专注,不要太着急,慢慢调试慢慢理清思路,注意总结以前的思路。(感谢姚老板赛后给我的wp,获益匪浅)