免责声明:当我看到类似的事情时,我将公开我的工作流程。我不是告诉你这是最好的或更快的,我相信你有很多其他的方法来处理这个问题。但这应该让您深入了解如何做到这一点。
由于您的问题非常广泛,并且不包含任何详细信息(恶意软件名称、哈希或“无法分析”的含义),因此我的答案也是如此。
工艺镂空
启动您最喜欢的调试器,加载您的二进制文件,并在CreateProcessInternalW、ZwUnmapViewOfsection、WriteProcessMemory和ResumeThread上放置断点。
这应该允许您观察完整的过程中空技术。
Hit to CreateProcessInternalW:将要发生注入的进程由加载程序创建。您应该看到创建标志设置为 0x4(暂停)。如果您打开 procexp 或类似的东西,您应该能够观察到您环境中挂起的进程。
Hit to ZwUnmapViewOfsection:之前创建的进程内容是擦除。这将为稍后注入的恶意代码腾出空间。
Hit to WriteProcessMemory:恶意代码被注入到空的挂起进程中。这可以逐节完成,也可以从包含完整 PE 的大 blob 中完成。您可能希望通过查看WriteProcessMemory调用的源缓冲区从这里转储它。
Hit to ResumeThread:恶意进程然后准备恢复。您的第二个选择是将它转储到那里,当您确定目标进程已准备好启动时。
获得转储后,首先查看 PE-bear(或等效物)中的部分以取消映射。由于您的转储是从内存中获取的,因此这些部分没有按照应在磁盘上的方式对齐。
重新对齐所有内容后,请检查您的 IAT 是否连贯。即使它使用一些 API 散列技术,您至少应该找到LoadLibrary和GetProcAddress的条目。这将确认您的转储在磁盘上正确对齐。(此外,如果您执行它,它应该运行)。
您现在可以将其导入 IDA 并开始分析。
API 哈希
对于这部分,您要反转散列算法。
首先,找到负责执行此操作的函数。它应该很容易发现,因为它应该以 DWORD 作为参数和字符串(如果 DLL 名称也经过哈希处理,则为另一个 DWORD)。字符串是 API 来自的 DLL 的名称,DWORD 是 API 哈希。小提示:您还可以按调用次数列出函数。API解析函数应该从代码中大量不同的地方调用,通常是引用较多的地方。
在 API 解析函数之前解码/解密 DLL 名称并非不可能。
如果您不确定,请在调试器中打开它,并在入口点之后执行随机指令,直到您可以观察到解析机制。
如果 DLL 名称已编码/加密(通常是这种情况),请从反转算法开始。它也可以是另一种散列算法(甚至与 API 相同的算法)。一般来说,这部分更容易处理,您将面临一些用于恢复 DLL 名称的基本字符串操作。
一旦你理解了它,编写一个小函数,它应该采用加密/编码的 DLL 名称,并返回明文名称。然后,您可以将其转换为 IDAPython 脚本,该脚本将使用纯文本名称标记您的 idb。
一半的工作在这里完成。现在,专注于 API 散列技术。首先检查散列是否不是标准的(CRC 或其他)。如果这是手动完成的,请尝试查看散列算法是否不容易受到某些可能导致恢复明文相关散列的反向操作的影响。
如果算法足够强大,您将无法从散列中恢复 API 名称,但您必须对其进行暴力破解。幸运的是,您已经有了要导入 API 的 DLL 的名称。所以你知道这个散列解析为预先定义的 API 列表中的某些内容。
这个想法是重新实现散列算法,获取目标 DLL 中定义的 API 列表,并将它们传递给您的算法。然后,将哈希与正确的 API 名称匹配。
再一次,您可以使用 IDAPython 脚本自动执行此操作,以标记您的 idb,让您的工作更轻松。
您现在有了一些更具可读性的东西,您应该能够理解此恶意软件的总体目标。
RC4加密
这部分是标准的,因为 RC4 算法有据可查,不难逆转,容易发现,并且在恶意软件中非常流行。
与往常一样,尝试识别您的加密功能。您可以搜索具有一些硬编码常量的算法的某些特定部分(KSA、PRGA 和 XOR)。最容易停止的是 KSA 中的“for”循环,它应该为您提供以下伪代码:
for (int i = 0; i < 0x100; i++) {
S[i] = i;
[...]
}
每次看到这个,就可以确定这是 RC4。
现在,将这些函数追溯到主加密包装器。如果这是标准的,您应该看到两个缓冲区被传递给函数:一个用于加密内容,另一个用于密钥。
再一次,编写一个小脚本来解码这个(RC4 的大量库),你应该能够恢复纯文本字符串。
不要忘记在多个加密字符串上测试您的脚本,因为每个字符串的密钥可能不同。
一旦你用纯文本字符串标记了你的 idb,你就应该拥有分析这个恶意软件的一切。