导语:在阅读hasherezade的关于Hidden Bee恶意程序家族的定制文件格式(本文示例)的研究时,我突然想到这个用例似乎特别适合于IDA的定制装载模块。
本文源自我自己受到的启发,也许将来有人会从源代码中获益。
在阅读hasherezade的关于Hidden Bee恶意程序家族的定制文件格式(本文示例)的研究时,我突然想到这个用例似乎特别适合于IDA的定制装载模块。IDA装载模块方法与前一种方法相比有一些优点:它是完全自动化的,不需要额外的程序、插件或脚本;这些导入具有专有名称和类型信息,允许IDA的普通P.I.T.算法传播这些信息;用户可以将数据库重新定位到任意的基本地址。
考虑到定制装载是我尚未编写的IDA插件的唯一变体,这似乎是一个不错的小范围项目。对于该项目,我的一个非常小的贡献是Hidden Bee格式的IDA定制装载,在我的GitHub上可以找到该装载。IDAPython代码要求安装Ero Carrera的pefile模块,比如通过pip。
Hidden Bee
简而言之,Hidden Bee恶意程序家族以定制的文件格式传播有效负载,该文件格式是PE文件格式的简化版本。hasherezade的文章中包含了所有细节。并没有对该项目做原始的恶意软件分析;我只是读了她的博客文章,想到了如何将细节转换成一个装载插件,然后根据hasherezade提供的示例链接对其进行调试。和往常一样,Chris Eagle的IDA Pro Book第二版很有用。关于装载API的一些细节在IDA 7.x AP中已经更改。x API端口,但是Hex-Rays的移植指南提供了信息,并且IDA 7.1 SDK中的装载示例也被移植到最新的API。
简单介绍一下IDA装载模块
1. IDA装载模块只是一个具有良好定义接口的IDA插件。当将任意文件加载到IDA中时,都将调用IDA装载模块。他们有两项主要责任:
允许访问文件字节,确定该文件是否为装载模块能够处理的格式。为此,每个IDA装载模块都必须导出一个名为accept_file的函数。如果无法识别文件格式,该函数返回0;如果可以识别,则返回非零值。
2. 如果文件类型模块可以加载,并且用户选择使用这个模块加载文件,执行实际的加载过程,如使用IDB创建片段、从文件中复制字节到片段、处理重定位、解析导入、添加entrypoints,等等。为此,每个IDA装载模块必须导出一个名为load_file的函数。
这两个函数都将“linput_t *”对象作为输入,该对象的行为类似于C FILE *对象,它支持查找指定位置、从文件中读取字节数组等等。由于Hidden Bee的格式包括重定位,我选择实现第三个可选的IDA loader模块函数:move_segm。当用户请求将数据库重新定位到另一个地址时,IDA内核将调用此函数。
为Hidden Bee写一个加载模块
在阅读了前面的文章后,我发现在IDA中加载Hidden Bee图像的唯一困难是: A)Hidden Bee定制头通过散列而不是名称指定API导入; B)它包含重定位信息。从概念上讲,通过散列进行重新定位和导入查找非常简单,但是关于如何更好的将它们与IDA结合的详细信息并不清楚。遗憾的是,在阅读了SDK中的装载模块示例后,我对这些任务没有信心。在该项目上80%的时间花在了逆向工程%IDADIR%\loaders\pe.dll上——PE文件格式的装载模块——特别关注它对重定位和导入的处理。
导入
为了通过hash处理导入,hasherezade的工具链最终会生成一个文本文件,其中包含导入散列名称的地址及其对应的明文API字符串。然后,她使用另一个插件在导入散列DWORD的地址上创建重复的注释。与之相反,我想让IDA以与普通二进制文件相同的方式显示导入信息,即我希望IDA在每个导入上设置正确的类型签名。我想这可能有点困难,但几小时后逆向工程pe_import_visitor_t类(部分记录在%IDASDK%\ldr\pe\common.hpp)的虚函数,证明你所要做的触发此功能只是DWORD的名称设置为从类型库加载的东西。
下面的截图显示IDA成功地将类型信息应用于API:
重定位
对于PE文件中常见的IMAGE_REL_BASED_HIGHLOW重定位来说,每个重定位最终都可以通过将重定位信息直接转换到IDA的fixup_data_t数据结构中进行处理,然后将它们传递给set_fixup API。SDK示例并没有提供如何正确处理PE IMAGE_REL_BASED_HIGHLOW重定位的直接概念,因此我逆向工程了PE.dll来精确的计算出重定位需要发生什么。(幸运的是,由于其SDK的可用性,逆向工程IDA可做可不做。)如果愿意,可以在do_reloc函数中看到结果。不要让我解释它为什么有效;事实证明它确实工作。
下面是将数据库从基地址0x0到基地址0x12340000的前后对比。特别注意,红色下划线的字节发生了变化。之前:
之后: