Remco Sprooten

EMOTET 动态配置提取

一种基于模拟动态提取 EMOTET 配置的工具。

阅读时长 16 分钟安全研究
EMOTET Dynamic Configuration Extraction

主要结论

  • EMOTET 开发人员已更改其恶意软件 64 位版本中配置的编码方式。
  • 通过使用代码模拟,我们可以绕过多种代码混淆技术。
  • 未来,在配置提取器中使用代码模拟器将变得更加普遍。

要下载 EMOTET 配置提取器,请查看我们关于该工具的帖子

序言

EMOTET 系列于 2014 年以模块化银行木马的形式出现在恶意软件领域,主要通过检查流量来收集和窃取银行帐户信息。EMOTET 已被改造为早期植入程序,用于加载其他恶意软件家族,例如 QAKBOTTRICKBOTRYUK。虽然多个 EMOTET 活动已被国际执法机构摧毁,但它仍然是最多的网络犯罪行动之一。

最近几个月,Elastic Security 观察到 EMOTET 开发人员过渡到 64 位版本的恶意软件。虽然此更改似乎不影响我们所观察到的样本的核心功能,但我们确实注意到配置和字符串的混淆方式发生了变化。在早期版本的 EMOTET 中,配置以加密形式存储在二进制文件的 .data 部分中。在新版本中,配置是在运行时计算的。因此,我们需要从二进制文件中提取配置的信息隐藏在实际代码中。

在接下来的章节中,我们将讨论与 64 位 EMOTET 样本相关的以下内容

  • EMOTET 加密机制
  • 查看 EMOTET C2 列表
  • 有趣的 EMOTET 字符串
  • EMOTET 配置提取器实用程序

加密密钥

EMOTET 使用嵌入式椭圆曲线加密 (ECC) 公钥对其网络通信进行加密。虽然在之前的版本中,密钥会存储在 XOR 加密的 blob 中,但现在内容是在运行时计算的。

相比之下,之前版本的 EMOTET 会将加密版本的密钥数据存储在二进制文件的 .text 部分中。

为了使安全研究人员更难找到给定的代码,恶意软件使用了混合布尔算术 (MBA) 作为其混淆技术之一。它将常量和简单表达式转换为包含布尔和算术运算混合的表达式。

在此示例中,实例化了一个常量数组,但查看汇编代码时,我们看到每个常量都是在运行时计算的。这种方法使得难以开发针对此函数的签名。

我们注意到,椭圆曲线 Diffie-Hellman (ECDH) 和椭圆曲线数字签名算法 (ECDSA) 密钥都使用相同的函数来解码内容。

ECDH 密钥(你可以通过其 magic ECK1 字节识别)用于加密目的,而 ECDSA 密钥 (ECC1) 用于验证 C2 服务器的响应。

通过利用 YARA 签名来查找 EMOTET 二进制文件中此解码函数的位置,我们可以观察到以下过程

  1. 查找二进制文件中的解码算法。
  2. 查找解码函数的任何交叉引用(Xrefs)。
  3. 模拟调用解码函数的函数。
  4. 从内存中读取生成的数据。

正如我们所提到的,我们首先使用 YARA 在二进制文件中找到该函数。该签名在本文章末尾提供。值得指出的是,这些 yara 签名用于识别二进制文件中的位置,但在其当前形式中,不能用于识别 EMOTET 样本。

为了自动从多个样本中检索数据,我们创建了一个配置提取器。在下面的代码片段中,我们将以高级的方式演示如何从恶意软件样本中收集配置信息。

在上面的代码片段中

  1. 首先加载 YARA 签名。
  2. 尝试查找匹配项,如果在文件中找到签名。
  3. 根据文件中的偏移量计算函数偏移量。

为了找到此函数的 Xref,我们使用了出色的 SMDA 反编译器。找到 Xref 后,我们可以使用 CPU 模拟器 Unicorn 开始模拟过程。

  1. 初始化 Unicorn 模拟器。
  2. 将 PE 文件中的可执行代码加载到内存中。
  3. 反汇编该函数以找到返回和执行结束。
  4. 二进制文件将尝试使用 Windows HeapAlloc API 为解码的数据分配空间。由于我们不想模拟任何 Windows API,因为这会增加不必要的复杂性,因此我们挂钩到代码以便我们可以自己分配空间。
  5. 在模拟运行后,64 位“long size”寄存器(RAX)将包含指向内存中密钥数据的指针。
  6. 为了以更易读的方式显示密钥,我们将其转换为标准 PEM 格式。

通过模拟我们感兴趣的二进制文件部分,我们不再需要静态地击败混淆才能检索隐藏的内容。此方法为创建配置提取器增加了一定程度的复杂性。但是,由于恶意软件作者正在添加越来越多的混淆,因此需要一种通用方法来击败这些技术。

C2 服务器列表

跟踪恶意软件家族的一个重要部分是通过识别和发现他们用来操作其网络的 C2 服务器来获得新的见解。

在 EMOTET 的 64 位版本中,我们看到 C2 服务器的 IP 和端口信息也是在运行时动态计算的。每个 C2 服务器都由一个函数表示,该函数计算并返回 IP 地址和端口号的值。

这些函数没有可用于搜索的直接交叉引用。但是,一个过程会引用所有 C2 函数并创建 p_c2_list 指针数组。

之后,我们可以单独模拟每个 C2 服务器函数,以检索如下所示的 IP 和端口组合。

字符串

相同的方法适用于内存中字符串的使用。每个字符串都有自己的函数。在以下示例中,该函数将返回指向字符串 %s\regsvr32.exe "%s" 的指针。

所有 EMOTET 字符串都共享一个公共函数,以在运行时解码或解析字符串。在我们在此处分析的样本中,字符串解析器函数被引用了 29 次。

这允许我们遵循与之前所述相同的方法来解码所有 EMOTET 字符串。我们使用 YARA 精确定位字符串解码函数,找到交叉引用,并模拟生成的函数。

配置提取器

自动从 EMOTET 中提取有效负载是威胁搜寻的一个重要方面,因为它使人们可以了解活动和威胁参与者部署的恶意软件,使从业者能够及时发现新的未知样本。

% emotet-config-extractor --help
usage: Emotet Configuration Extractor [-h] (-f FILE | -d DIRECTORY) [-k] [-c] [-s] [-a]

options:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  Emotet sample path
  -d DIRECTORY, --directory DIRECTORY
                        Emotet samples folder
  -k                    Extract Encryption keys
  -c                    Extract C2 information
  -s                    Extract strings
  -a                    Extract strings (ascii)

我们的提取器可以采用带有 -d 选项的样本目录或 -f 的单个样本,然后可以输出值得注意的配置部分,具体来说

  • -k:提取加密密钥
  • -c:提取 C2 信息
  • -s:提取宽字符字符串
  • -a:提取 ASCII 字符字符串

EMOTET 使用不同的例程来解码宽字符和 ASCII 字符串。这就是提取器提供标志以分别提取它们的原因。

C2 信息显示样本中找到的 IP 地址列表。值得注意的是,EMOTET 下载子模块来执行特定任务。这些子模块可以包含自己的 C2 服务器列表。提取器还可以处理这些子模块。

我们观察到的子模块不包含加密密钥。处理子模块时,可以省略 -k 标志。

[...]
[+] Key type: ECK1
[+] Key length: 32
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2DWT12OLUMXfzeFp+bE2AJubVDsW
NqJdRC6yODDYRzYuuNL0i2rI2Ex6RUQaBvqPOL7a+wCWnIQszh42gCRQlg==
-----END PUBLIC KEY-----
[...]
[+] Key type: ECS1
[+] Key length: 32
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9C8agzYaJ1GMJPLKqOyFrlJZUXVI
lAZwAnOq6JrEKHtWCQ+8CHuAIXqmKH6WRbnDw1wmdM/YvqKFH36nqC2VNA==
-----END PUBLIC KEY-----
[...]
[+] Found 64 c2 subs
174.138.33.49:7080
188.165.79.151:443
196.44.98.190:8080
[...]
[+] Starting emulation
[+] String BLOB address: 0x4000000
KeyDataBlob
[...]
[+] String BLOB address: 0x4000000
bcrypt.dll
[...]
[+] String BLOB address: 0x4000000
RNG

为了使社区能够进一步防御现有和新的 EMOTET 变种,我们正在根据 Apache 2 许可证开源有效负载提取器。访问有效负载提取器文档和二进制文件下载

EMOTET 的未来

EMOTET 的开发者正在实施新的技术,以隐藏其配置,从而躲避安全研究人员的分析。这些技术会减缓初始分析的速度,然而,EMOTET 最终必须执行才能达到其目的,这意味着我们可以收集信息,用于揭示更多关于该活动和基础设施的信息。通过使用代码模拟器,我们仍然可以从二进制文件中找到并提取信息,而无需处理任何混淆技术。EMOTET 是一个很好的例子,它展示了多种混淆技术如何使静态分析更加困难。当然,我们预计会有更多的恶意软件作者效仿。这就是为什么我们预计未来会看到更多基于模拟的配置提取。

检测

YARA

Elastic Security 创建了 YARA 规则来识别此活动。此处显示的 YARA 规则并非仅用于检测 EMOTET 二进制文件,它们是为了支持配置提取器而创建的。用于检测 EMOTET 的 YARA 规则可以在 protections-artifacts 存储库中找到。

EMOTET 密钥解密函数

rule resolve_keys
{
meta:
     author = "Elastic Security"
     description = "EMOTET - find the key decoding algorithm in the PE"
     creation_date = "2022-08-02"
     last_modified = "2022-08-11"
     os = "Windows"
     family = "EMOTET"
     threat_name = "Windows.Trojan.EMOTET"
     reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
   strings:
       $chunk_1 = {
        45 33 C9
        4C 8B D0
        48 85 C0
        74 ??
        48 8D ?? ??
        4C 8B ??
        48 8B ??
        48 2B ??
        48 83 ?? ??
        48 C1 ?? ??
        48 3B ??
        49 0F 47 ??
        48 85 ??
        74 ??
        48 2B D8
        42 8B 04 03
     }
   condition:
       any of them
}

EMOTET C2 聚合

rule c2_list
{
     author = "Elastic Security"
     description = "EMOTET - find the C2 collection in the PE"
     creation_date = "2022-08-02"
     last_modified = "2022-08-11"
     os = "Windows"
     family = "EMOTET"
     threat_name = "Windows.Trojan.EMOTET"
     reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
  strings:
     $chunk_1 = {
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
     }
  condition:
     any of them
}

EMOTET 字符串解码器

rule string_decode
{
   meta:
     author = "Elastic Security"
     description = "EMOTET - find the string decoding algorithm in the PE"
     creation_date = "2022-08-02"
     last_modified = "2022-08-11"
     os = "Windows"
     family = "EMOTET"
     threat_name = "Windows.Trojan.EMOTET"
     reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
  strings:
     $chunk_1 = {
        8B 0B
        49 FF C3
        48 8D 5B ??
        33 CD
        0F B6 C1
        66 41 89 00
        0F B7 C1
        C1 E9 10
        66 C1 E8 08
        4D 8D 40 ??
        66 41 89 40 ??
        0F B6 C1
        66 C1 E9 08
        66 41 89 40 ??
        66 41 89 48 ??
        4D 3B D9
        72 ??
     }
     $chunk_2 = {
        8B 0B
        49 FF C3
        48 8D 5B ??
        33 CD
        0F B6 C1
        66 41 89 00
        0F B7 C1
        C1 E9 ??
        66 C1 E8 ??
        4D 8D 40 ??
        66 41 89 40 ??
        0F B6 C1
        66 C1 E9 ??
        66 41 89 40 ??
        66 41 89 48 ??
        4D 3B D9
        72 ??
     }
  condition:
     any of them
}