首先查看程序的基本功能,基本的菜单形式,主要提供了三个功能,创建,删除,打印。(即malloc堆块,free堆块,printf堆块中的数据)
查看程序基本信息
拖进ida中进行伪代码审计,由于此题没有去掉符号表,因此审计相对比较简答。创建和打印部分的代码均没有什么漏洞,在删除功能处可以发现很明显的UAF漏洞,在free掉content指针和结构体指针后均没有将其置为NULL。
另外可以找到程序中存在后门函数magic
进行调试分析,首先创建两个note(note0和note1),大小都为0x10,gdb查看堆的具体情况。
可以看到总共有4个chunk,其中我们申请的chunk为chunk2和chunk4,大小为0x20。chunk1和chunk3为对应的结构体指针,大小为0x10。接下来具体看一下每个chunk块数据部分的内容,chunk1是结构体指针包含了两部分内容,第一部分0x080485fb为print_note_content函数地址,第二个部分0x087ec170为note0数据部分的地址(chunk2的mem指针)。chunk2是content指针,存储了具体的内容(0xa61–>‘a\n’)。chunk3、chunk4和chunk1、chunk2类似,这里就不再展开分析了。
现在整理一下思路,chunk1和chunk3中都存在print_note_content函数地址,在当我们执行打印功能的时候会被调用。设想如果我们可以修改chunk中的地址为magic函数的地址,那当我们再次执行打印功能的时候就可以除法后门函数,获得shell。但是此时的chunk1和chunk3都是结构体指针,我们无法对其数据进行修改。那么我们怎么样才能进行修改呢?我们继续尝试和分析。。。
接下来我们将两个note都删除,再次查看堆的情况。
可以看到现在4个chunk都已将被free掉了,(这里由于我的libc版本的问题所以被free的chunk被放入了tcache中,如果是较低的libc版本会被放入fastbin中)。但是由于存在UAF漏洞所以我们依旧可以正常执行打印的功能,所以我们要设法将其中一个结构体指针申请回来,并且要成为新的note的content指针,这样我们就可以修改print_note_content函数地址为magic函数地址,实现漏洞利用。具体做法也比较简答,我们只需要申请一个新的note,大小为0x8就可以了。申请0x8大小是为了我们可以把原来的结构体指针申请回来作为新的content指针。
当我们申请0x8大小的note后,首先会malloc一块0x10大小的chunk作为结构体指针,查看bin后可以找到0x9276190 和 0x9276160都满足,根据free的顺序首先取出0x9276190作为新note的结构体指针,然后根据申请的大小0x8进行malloc,查找后取出0x9276160作为新note的content指针。这里注意此时的0x9276160既是新note的content指针也是note0的结构体指针。所以我们可以实现对note0结构体指针的修改,我们将0x080485FB(print_note_content)修改为0x08048945(magic)。
现在打印note0就可以获得shell了。
exp如下:
from pwn import *
from LibcSearcher import LibcSearcher
from</