文件信息
该样本来自2016年boston-key-party ctf的一道pwn题–simple_calc
检查样本信息:
只开启了NX保护,64位小端程序
漏洞定位
将样本拖入IDA进行分析时,会发现text段特别多,仔细分析后会发现很多函数都没有被使用,写完wp后,我猛然发现引用这么多看似无用的text段,其实是为了引用更多的gadget,方便后面ROP链的构造。好的,废话不多说,进行漏洞分析。
分析main函数,可以发现该样本是一个菜单题,先要求输入计算的次数,输入的次数必须大于3小于等于255,正确输入后会以该值作为菜单功能循环的次数。这里直接展示程序的运行截图,如下图所示:
初步了解程序功能后,我们再详细的分析一下IDA中的伪代码,如下图所示,初次输入的值存入v24变量中,然后程序会以4倍该值的大小分配一个内存块,v25变量指向该内存地址。
接着看一下switch语句,和程序功能运行截图一样,有加减乘除以及退出5个功能,且每个功能执行后都将一个dword四字节大小的值赋值给了v25+4*i
的内存位置。然后注意一下memcpy函数,其中第一个参数v22变量位于栈空间,v25是分配的堆空间,4*v24
是拷贝的内存大小,我们可以控制v24的大小造成缓冲区溢出。
最后我们分析一下菜单函数的具体功能,具体分析后我们可以发现每个函数实现方式都大同小异,区别在于变量的存放位置和加减乘除运算。这里我们对比上面的switch分支语句分析add函数,其余函数类同,可以发现之前拷贝到v25+4*i
内存地址的值是这里加法运算后的结果dword_6CA88,该变量位于bss段,是全局变量,还有一点值得注意的是,加法的两个操作数不能小于0x27。
利用分析
经过上面的分析,我们已经发现了一个溢出漏洞,以及可以通过每次菜单功能的调用实现一次内存写。如果该题目没有开启NX保护的话,我们可以采用写入shellcode的方式,但由于开启了NX保护,所以采用构造ROP链的方式。即构造ROP链,通过程序的每次计算将ROP链的地址写入到内存中,最后退出时执行memcpy实现缓冲区溢出,执行ROP链,实现execve("/bin/sh", NULL, NULL)的系统调用。这里对于如何控制寄存器实现系统调用原理不熟悉的读者可以参考这篇博文。另外寻找gadget采用的是ROPgadget工具,不了解的读者可以百度一下。
wp
from pwn import *
# c