0x04 [2020 DawgCTF] Tik Tok – 500pt

题目类型:Pwn

checksec结果:
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)

题目分析

题目除了给定了一个二进制文件,同时给定了需要使用的libc以及一个songs的压缩包,解压后内部是若干文本文件。

我们为了方便读取这些文件,我们给与这些文件最高权限

程序逻辑

由于程序保留了一定的符号,这方便我们分析功能,程序有以下功能:

  1. 程序中的数据结构为:
    struct Songs{
       char path[0x18];
       _DWORD *fd;
       _DWORD *padding;
       _QWORD *dir;
       _QWORD *name;
       _QWORD *play_content;
    }
    
  2. Import_song:首先执行ls -R,遍历当前目录下的文件,然后用户输入一个<dir>/<file_name>.<ex_type>的路径保存在songs[song_count].path里,尝试打开那个路径所代表的文件,将文件句柄放在songs[song_count].fd里。接着若以下条件均满足则继续运行,否则程序退出:
    1. songs[song_count].fd不为-1(文件打开成功)
    2. songs[song_count].path[0]为可读字符(一定程度防止读非法文件)
    3. songs[song_count].path中不存在flag../(防止读flag文件以及防止跨目录读文件)

    <dir>保存在songs[song_count].dir里,将<file_name>保存在songs[song_count].file_name里,song_count增加1

  3. Show_playlist:遍历整个songs数组,若songs[i].dir不为空,则打印i+1songs[song_count].dirsongs[song_count].file_name

  4. Play_song:读取一个index,检查index - 1是否小于song_countindex - 1是否大于0songs[index-1].dir是否为空。接着,若songs[index-1].play_content为空,从songs[song_count].fd读取四个字节,转换成long型数值作为size,然后分配一个size + 1大小的chunk放在songs[index-1].play_content中,接着从songs[song_count].fd读取size个字节存入chunk中,打印存入的内容,返回。

  5. Remove_song:读取一个index,检查index - 1是否小于song_countindex - 1是否大于0songs[index-1].dir是否为空。接着清空songs[index-1].dirsongs[index-1].file_name,释放songs[index-1].play_content,指针置零,清空songs[song_count].path,关闭songs[song_count].fd并将该位置置空。

漏洞分析

  1. 首先,我们遇到的最大困难就是向chunk的写入看似不可控,因此我们要想办法让某个song的文件描述符为0,这样我们就可以通过stdin向其中写入数据了。
  2. play_song功能中,程序没有对size进行任何检查且其为无符号变量,这将会导致堆溢出,若我们能控制size-1,将会调用malloc(0),且将允许向返回的Chunk写入极大量的数据!

漏洞利用

创建可控Chunk

利用open函数的漏洞,对于open函数,我们可以输入一个目录,它也将会成功的打开而不会返回失败,且这个目录允许添加多个/

image-20200421202547915

此处存在:

  1. path成员和fd成员直接相邻,且在向path成员写值时存在逻辑,当且仅当path成员的末尾是\n时,才会将其替换成\x00否则不作任何操作!
  2. 程序限定song_count的上限是0x31,而fd处存放的是文件描述符,而这个文件描述符将会由3开始递增,当其递增到0x2E时,若path中没有.,将会把这个文件描述符替换成NULL。

于是我们的利用脚本如下:

for i in range(3,0x2F):
    import_song(sh,'Animal/'.ljust(0x18,'/'))

image-20200421204616484

⚠️:此处还有一点需要注意!正如我们在程序逻辑中说明的那样,一旦我们对这个歌曲执行了释放操作,程序将关闭fd指针处的文件流,而在此处,这意味着stdin将会被关闭,因此我们必须防止其被释放!

分类: CTF

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注