软件安全与脆弱性分析-对于freenote小程序的Poc分析

最近上软件安全与脆弱性分析课程,对freenote小程序(貌似是某一年的CTF题)进行了依次Poc分析。感觉很有意思,在这里对分析过程进行一个总结。

1.程序功能介绍


给定的程序运行界面如上图所示,大体上分为五个模块他们分别为:(1)列出已经存储的记录、(2)添加新的记录、(3)编辑指定的记录、(4)删除已经存储的记录、(5)退出程序。

将note程序加载到ida中,可以得到程序的汇编代码部分,动态调试后可以得到程序初始化后的开始位置:

在ida中进入到不同的功能函数中,利用反汇编可以得到功能函数的伪代码部分分别如下:

(1)列出已经存储的记录功能函数的伪代码:

(2)新建记录功能函数的伪代码:



(3)编辑已经存储记录功能函数的伪代码:

(4)删除已有记录功能函数的伪代码:


(5)退出程序功能函数仅调用库函数puts()实现字符串“bye”的输出;

同时,根据note初始化函数,分析note存储结构我们可以推断其大致如下:

•       所有note都存储在堆中,块大小四舍五入到0x80字节的下一个倍数

•       有一个表存储指向note的指针,以及它们的大小和一个表示它们当前是否正在使用的标志

•       该表最多可以存储256个note,并且在程序初始化期间也被分配到堆上

•       在删除一个note时,相应的块被释放,并且在表中清除了in_use标志

其中n表示表格中可用槽的数量(256)(8字节),m表示已使用槽的数量(在上例中为两个)(8字节)。Note entry包括(8字节)标识(是否被使用),(8字节)长度,(8字节)指针。

2.Poc分析

通过上一部分的分析,我们对note程序的框架有了一个基本的了解,接下来利用动态分析,对程序的崩溃点进行分析;

我们按照Poc提示的输入内容,对程序进行实验,在输入第二次删除已有记录操作的时候,可以发现程序发生了崩溃,实验分析截图如下:

输入:

2

6

aaaaaaaaaaaaaaaaa

分析:

qword_6020A8地址如下:

 

查看该地址:

note该结构共有256(0000 00000000 0100)个可使用空间,已使用1(0000 0000 0000 0001)个空间,第一个note在使用中,标志符为1(0000 0000 0000 0001),长度为6(0000 0000 0000 0006),地址为(0000 0000 0154 2830)。查看如下:

 

输入:

2

8

bbbbbbbbbbbbbbbbbbb

分析同上:

 

 

输入:

2

10

cccccccccccccccc

分析同上:

 

输入:

4

1

分析:

 

输入:

4

1

分析:

程序crash,删除时没有检查该note是否被使用。

根据Poc的输入我们发现在对同一个记录进行两次删除操作,而导致了程序崩溃,所以我们判断对记录进行删除的功能函数里面出现了错误从而导致程序崩溃,在删除记录函数部分设置断点,进行动态调试的过程中可以发现,程序在第二次删除与第一次拥有相同记录号的记录时,发生了错误,错误的位置为调用库函数free();

找到程序错误位置后,我们再利用ida反汇编功能,进入到删除记录函数的伪代码中去仔细观察,发现程序在删除记录的时候并没有检查记录号对应的记录的状态,即并没有检查所要删除的记录是否已经被删除过,所以当再次删除已经删除的记录时,库函数free()将对已经释放的空间再次释放,从而产生double free的错误,导致程序崩溃,至此我们对note程序的崩溃有了一个完整认识。



3.漏洞利用

         通过对漏洞位置的确定,我们可以针对漏洞产生的函数free()来构造漏洞的利用手段,大体上分为两个部分,一是对程序存放堆中note起始的位置的确定,二是通过构造虚假的chunk块达到更改GOT表项free()函数对应的地址位置,来实现攻击。

3.1Linux下的堆内存管理基础

想要根据free函数进行漏洞利用,我们需要了解Linux对堆块管理的基本知识,Linux中对堆块使用malloc_chunk的数据结构进行管理,数据结构的定义如下图所示:

其中prev_size指连续虚拟地址中当前块即chunk相邻的前一块,它占据的存储空间大小;size指当前块占据的存储空间大小;fd和bk指针只有在数据块没有被使用时才有效,他们分别指向前一块没有被使用的数据块和后一块没有被使用的数据块,这里涉及到了Linux下对空闲chunk的管理,利用bins链表将空闲的存储块按照存储空间的大小进行分类管理。当程序释放一个chunk块的时候,操作系统将会在在释放快的前后连续的虚拟地址空间进行判断,看是否其前后的块已经是被释放的块,如果是则会将该块从空闲链表队列即bins队列中删除(unlink),与当前释放块进行合并后再次放入对应的bins链表中,在进行unlink操作的过程中,若对P进行删除,则会进行P->bk->fd=P->fd与P->fd->bk=P->bk这两个操作,具体的unlink函数定义如下。

在了解了Linux下的堆内存存储管理后,我们还需要了解GOT表项,简单来说在Linux下,如果一个程序执行的过程中需要调用外部库函数,则会去GOT表项中寻找对应的外部库函数的地址,例如本程序在执行free操作的时候,就会去GOT表项中寻free函数对应的地址,拿到对应的地址之后便可以执行free操作。

3.2note堆首地址确认

这一部分,主要实现对存储note的堆的基址的确认,只有确认了基址我们才能在后面的步骤中进行chunk的伪造。确认地址的步骤如下:

(1)新建四个note,分别记为note0、note1、note2、note3存储“a”或任意其他字符,得到的note表已经具体的chunk布局如下:


(2)依次将note0与note2进行free操作,此时可以在bins链表中找到note0与note2对应的地址,表示他们已经作为未被使用的chunk被系统所回收,且note0的bk指针将会指向note2;

(3)再次创建一个新的note,使其满足8字节的内容大小如“12345678”,系统根据FIFO原则会将首次释放的note0空间分配给新的note,且note0中fd指针的位置会被新note的数据内容所覆盖,而bk指针因为新存note的长短则不会被覆盖,又因为新存入的字符串没有结束符,则在读取字符串的过程中会将其后面的bk内容也读出,根据bk所指向的地址空间位置,进行简单地计算后我们便能够得出存储note0的位置;

3.3构造伪chunk替换GOT中的free函数地址

在上一小节中,我们得到了存储note的首地址,根据首地址我们重新建立三个note,第一个note包含我们伪造的chunk,其中这个伪造的chunk我们使其状态为已经释放,且fd指向chunk的bk与bk指向chunk的fd相同(满足后面所述的unlink条件),第二个note为真chunk,将其内容存为“/bin/sh”,第三个note存储若干伪chunk,内容可以用字符串“a”代替,在进行了上述操作后,我们得到了两个chunk组,一个为真一个为假,他们布局分别如下图所示:

接下来我们要进行的操作就是修改GOT表项中free函数的地址使其被我们想要执行函数的地址所替代。

由上图可知,一开始创建的四个note中note3地址为0X6049d0,所以首先对note3进行释放操作,此时操作系统会检测当前地址前一个chunk所处的状态,而其前一个chunk,根据size与pre_size计算得出刚好就是我们新建的note0中的伪造的那部分chunk,由于当前释放的chunk中0x90字段的最低位表示了前一个chunk为释放状态,且它的fd与bk在构造时满足unlink条件(fd->bk=bk->fd=p)则会对其进行unlink后与当前请求释放chunk进行合并操作。

  

合并前note表部分布局如下图所示,其中note0的地址是正常的存储note0内容的地址。

 

在进行unlink的过程中,设unlink的对象为P,P结构如下所示。

则会进行P->bk->fd=P->fd与P->fd->bk=P->bk的操作,那么P->bk指向的地址为0X603020,它所表示的chunk的fd指针的地址为0X603030,其内容0X604830将会被改写为P->fd即0X603018。同理p->fd所指向的地址为0X603018,它表示的chunk的bk指向的地址也为0X603030,其中内容将会被改写为P->bk即0X603018,得到note表如下图:


此时如果我们对note0记录进行编辑操作,系统会按照note0对应的地址对note0进行修改(实际上已经在修改note表项),那么我们可以将note0对应的地址改为GOT表项的地址,当我们查看note0时,系统将会根据note0在note表中的地址(此时已经是GOT表项)打印给我们,这时,我们可以根据free字段去修改free函数对应的函数地址,将其改为我们想要程序执行的函数如system,这是如果我们再次释放note1,则程序会利用GOT表项中的free字段对应的函数地址(此时已经为system函数地址)来调用system(“/bin/sh“)了。

至此,我们通过利用Linux堆内存管理体制中unlink操作下的漏洞成功攻击了程序,实现了note程序的漏洞利用。

参考资料:

http://rk700.github.io/2015/04/21/0ctf-freenote/
https://kitctf.de/writeups/0ctf2015/freenote
https://www.cnblogs.com/alisecurity/p/5520847.html



猜你喜欢

转载自blog.csdn.net/sinat_29447759/article/details/79304236