flare-qdb是由火眼实验室开发,旨在帮忙分析人员提高分析效率。flare-qdb是一个命令行工具,基于python开发,其中的虚拟代码执行使用了python的 vivisect库,工具可以很方便的用来查询和改变二进制样本运行时的状态变量,同时也可使用系统模拟等。
开发动机
在与恶意软件的对抗过程中,针对复杂的和混淆过的恶意程序,分析人员通常会使用调试的手法处理。然而在跟踪调试恶意软件的过程中,分析人员的分析过程通常是随着EIP指针的执行顺序执行而分析,而这种分析方法与恶意软件的执行流程相同,方法本身无可厚非。但由于计算机多线程的引入,以及分析人员对程序经过的状态变量并不能时刻的铭记于心,所以就不可避免的出现了这种情况:
调试的过程中有一些中间变量代表了某种状态,只有在这种状态下才会触发行为。在分析人员第一次调试的过程中,可能根本就不会注意到这种状态值,等到以后突然发现这个状态值代表的具体的含义时才恍然大悟,然后重新开始调试,这次调试就会关注到这个状态值的改变。
所以分析人员可能想很方便的查询到恶意软件的每个状态标志。类似于这样的:
SELECT eax, poi(ebp-0x14) FROM malware.exe WHERE eip = 0x401072
这就是flareqdb的使命所在,下面就讲述下这个工具在样本分析、模拟样本环境,做一些挑战类分析题目使的使用。
使用方法
flare-qdb 命令行语法为:
flareqdb "<cmdline>" -at <address> "<python>"
分析人员可以利用flare-qdb使分析的程序在在满足某些条件下中断,可以输出执行条件,可以显示或改变程序状态等。它内部实现了类似windbg的内置函数,用于查询与修改指令。
下面列出了一些查询示例:
-
查询传递给Beep函数的两个参数
-at kernel32.Beep –eval "dd('esp+4', 2)" -
运行到0x401072指令时,如果eax为空的话,就结束程序的运行
-at 0x401072 -if eax==0 -eval "kill()" -
在 运行到malwaremodule+0x102a 时,将ecx的值修改为'(ebp-0x14)eax'的值
-at malwaremodule+0x102a -eval "r('ecx', '(ebp-0x14)eax')
- 运行到0x401003 时,改变ebp-0x14'内存值
-at 0x401003 -eval "memset('ebp-0x14', 0x2a, 4)"
###命令行的使用
以循环处理字符串为例,下图显示使用flareqdb 工具显示出每次循环时,局部变量(放在栈空间中的)把指向的字符串的内容。这表明argv[1]传递进来的字符串被赋值给局部变量用来循环操作。
再举一个2016 FLARE-On 挑战赛的粟子,题目地址
这道题目的解题思路是:在flareon2016challenge.dll中,包含一个加密过的PE,这个加密过的PE会调用一系列的kernel32!Beep函数,每次调用kernel32!Beep函数时的参数组成一个序列,这个序列最后做为ordinal #50函数的参数,就能得到最终的Flag.
这种功能在flareqdb中如此EASY,下面一条命令就可以搞定.
flare-qdb 可以修改执行分支,显示函数指针的值,并通过反汇编函数(方便分析人员验证函数指针是否指向一个正常代码的函数)。
在下面的例子中,恶意软件与CC地址通信后取得到数据后,运行到下面的代码处。可以看到代码中功能:先验证数据的格式,然后调用了C++虚函数。可见,如果能够识别出这个虚函数,分析人员就可以更加大胆更加肆无忌蛋的推测CC地址返回的数据格式的内容。
使用flare-qdb 工具,使用-r命令改变程序流程从而绕过CC数据的格式检查,随后在运行到0x4029a4时把函数地址dump出来。基于vivisect库的强大功能,flareqdb 可以显示出函数地址的指令,从而可以用来判定函数地址是不是一个真正的函数。
命令行的含义是:在 运行到0x4016b5是,把EIP的值修改为0x4016bb(绕过CC地址返回的数据的格式的检查),然后在运行到0x4029a4时dump函数。
在虚函数的地址0x402f32处,通过IDA可以显示出为basic_streambuf::xsputn函数,这个函数功能是向文件流中插入一系列的字符。这说明恶意软件有通过CC地址提供文件名或者文件数据来执行文件的写入功能。
使用flareqdb的python模块
在对付一些更复杂的情况时,作为python模块存在的flare-qdb就可以大展身手了。flare-qdb 允许使用功能强大的vivisect库,如下图显示了一个提权工具的部分代码。提权工具在使用提权漏洞 CVE-2016-0040之前,调用 GetVersionExW, NetWkstaGetInfo, IsWow64Process 函数判断程序的运行环境。
显然,提权工具本打算运行在32位windows5.1+, 6.0, and 6.1系统中。通过下图中的脚本,使提权工具运行12次,通过模拟不同的GetVersionExW和NetWkstaInfo函数返回来验证提权工具的运行环境。每次执行程序时,flare-qdb都会检测程序是不是运行到尝试提权代码。将定义为局部变量的字典传递给Qdb实例用于每次执行,在脚本中打印出当前正在模拟的WINDOWS版本。GetVersionExW函数在返回之前通过OSVERSIONINFOEXW类型修改后进行返回。NetWkstaGetInfo函数只是手工进行了修改,这是因为缺少对WKSTA_INFO_100 结构的定义。
运行结果:
对于下面的例子,我们先假设分析人员遇到的情况:解密二进制--->确定解密出代码注入的地址--->解密二进制--->确定解密出代码注入的地址--->解密二进制………………
使用flare-qdb来简化上面的过程:
在对应的CALL尾部设置断点,使用vivisect的envi模块枚举所有的未命名的RWX内存区域。然后在调用detach()之间使用park()函数,目的是使代码在一个无限循环中运行。此后分析人员可以使用调试器ATTACH到进程中,进行后续人工分析。
可以看到,在使程序死循环与detach之前,脚本打印出了注入的地址,
使用IDA附加可以看到,flare-qdb在入口处写入了死循环。park()函数会将程序的原始的字节存储在jmp指令的后面。分析人员可以通过命令windbg命令r eip=1DC129B到程序原始内容处执行。
这种暂停进程的方式可以更方便的快照恶意软件执行VM,可以远程连接到IDA作为调试器,IDA会方便的显示出代码区域。 因为相同的操作系统进程可以用于多个调试会话,所以脚本生成的内存映射在调试会话中保持不变。 这也就意味着当多次调试程序时,在IDA Pro中创建的注释仍然是有效的(这里的有效,是指不会由于调用VirtualAlloc返回的地址的不同而代码位置改变)。
总结
flare-qdb提供了命令行工具,可以快速查询二进制的状态内容。 除了查询状态,flare-qdb可以用来改变程序流程和模拟不同系统场景。 对于复杂的情况,flare-qdb提供了脚本脚本。可以使用脚本处理诸如字符串解码,恶意软件解密等过程。