-
-
[原创]看雪CTF2017第4题wp
-
发表于:
2017-6-9 10:28
5530
-
程序运行后,输入用户名后显示命令列表,类似于记事本存储管理,实际上只有前3项命令有用,第4项“查看”是摆设,无实际功能:
把程序扔IDA里开始先分析程序流程,对应上面的程序功能:
接着就开始找这3个主要函数的漏洞,先看创建节点的函数create,理解存储节点的大致流程:
上面代码新建的节点最后被保存到一个处于.bss段的全局数组列表里了,每个元素存储一个对应的堆地址,紧跟着后面的一个QWORD对应存储了其使用标志位g_flag_list[i]:
而对应的节点size保存在另外一个列表里,这个列表是在程序一开始时申请的堆内存里,大小为0x14,意味着预定保存5个节点的size,列表的地址保存在一个全局变量g_size_list里,同样位于.bss段里较前面的位置:
既然列表预定存储5个节点,我们先看看是否有漏洞“越界”,发现输入索引调用的函数“input_number”可以利用:
这里调用atoi函数将用户输入的字符转换为数字,返回为无符号整型数,而上层调用的接收变量定义却为整型数,于是可以输入一个负数直接造成数组“向上”越界,索引到g_node_list前面(低地址)的“负元素”。这个漏洞有什么用呢,因为g_size_list正好在g_node_list的前面位置(索引为-2),所以可以将其进行修改,填充一些大值,使得原本已经创建的节点堆块的size“无形”中变大,造成在后面编辑节点时可以进行堆溢出:
此时已具备堆溢出的条件,对0号节点进行编辑可以覆盖到1号节点所属的堆块范围,于是我们进行unlink方式的堆利用,在0号节点堆块的buf伪造好一块“已释放”的前堆块,然后覆盖1号节点堆块的pre_size头和当前size头里的前块使用标志pre_inuse,使得在释放1号节点堆块的时候认为前块堆块空闲要进行合并触发unlink操作,相关具体原理请自行查阅资料,这里贴一下本题的操作:
成功执行完unlink操作后的结果就是,0号节点的地址g_node_list[0]被修改成被伪造堆块的fd指针,也就是“g_node_list - 0x18”的位置,这样意味着,0号节点不再指向堆块,而是指向的.bss段的地址:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课