Cyril François

剖析 ICEDID

使用 Elastic 安全实验室开源工具的综合教程

阅读时长 14 分钟工具
Unpacking ICEDID

序言

ICEDID 是一种恶意软件家族,由 IBM X-force 研究人员于 2017 年发现,与窃取登录凭据、银行信息和其他个人信息有关。ICEDID 一直是一个普遍存在的家族,但自 EMOTET 在 2021 年初暂时中断以来,其增长速度更快。ICEDID 已被链接到多个不同的恶意软件家族的传播,包括DarkVNCCOBALT STRIKE。定期的行业报告(包括像本文这样的研究出版物)有助于缓解这种威胁。

众所周知,ICEDID 使用自定义文件格式和自定义加密方案来打包其有效负载。以下是我们最新的ICEDID 研究,其中涵盖了 GZip 变体的执行链。

在本教程中,我们将从下载伪造的 GZip 二进制文件副本开始,介绍这些工具,以剖析最新的 ICEDID 样本。

分析恶意软件可能对系统造成危险,只有经验丰富的专业人员才能在受控环境中(如隔离的虚拟机或分析沙箱)尝试进行。恶意软件可能旨在逃避检测并感染其他系统,因此务必采取一切必要预防措施并使用专用工具来保护您自己和您的系统。

54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f

环境设置

在本教程中,我们使用的是 Windows 10 和 Python 3.10。

Elastic 安全实验室正在发布一组工具,以自动化剖析过程并帮助分析师和社区响应 ICEDID。

脚本描述兼容性
decrypt_file.py解密 ICEDID 加密文件Windows 和其他(未经测试)
gzip_variant/extract_gzip.py从 ICEDID 伪造的 GZip 文件中提取有效负载Windows 和其他(未经测试)
gzip_variant/extract_payload_from_core.py从重建的 ICEDID 核心二进制文件中提取并解密有效负载Windows 和其他(未经测试)
gzip_variant/load_core.py加载并执行核心自定义 PE 二进制文件仅限 Windows
gzip_variant/read_configuration.py读取伪造的 GZip 中包含的 ICEDID 配置文件Windows 和其他(未经测试)
rebuild_pe.py从 ICEDID 自定义 PE 文件重建 PEWindows 和其他(未经测试)

为了使用这些工具,请克隆 Elastic 安全实验室发布存储库并安装 nightMARE 模块。

git clone https://github.com/elastic/labs-releases
cd labs-release
pip install .\nightMARE\

本教程中的所有工具都使用 nightMARE 模块,此库实现了我们剖析 ICEDID 中嵌入的各种有效负载所需的各种算法。我们发布 nightMARE 是因为此 ICEDID 分析需要它,但请继续关注 - 我们将继续开发和完善此框架,敬请期待。

剖析伪造的 GZip

ICEDID 伪造的 GZip 是一个伪装成有效的 GZip 文件的文件,其格式是通过使用GZip 标头和页脚封装真实数据来形成的。

GZip 魔术字节以红色显示。
GZip 标头以绿色呈现。
虚拟文件名值以蓝色显示。

GZip 标头之后是真实数据结构,我们在下面描述该结构。

我们将使用 labs-releases\tools\icedid\gzip-variant\extract_gzip.py 脚本来剖析此欺诈性 GZip。

usage: extract_gzip.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit

我们将对上面链接的 ICEDID 样本使用 extract_gzip.py,并将内容存储到我们创建的名为“ extract ”的文件夹中(您可以使用任何现有的输出文件夹)。

python extract_gzip.py 54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f extract

============================================================
Fake Gzip
============================================================
is_dll: True
core: UponBetter/license.dat (354282 bytes)
stage_2: lake_x32.tmp (292352 bytes)

extract\configuration.bin
extract\license.dat
extract\lake_x32.tmp

此脚本返回三个单独的文件,包括

  • 加密的配置文件:configuration.bin
  • 加密的核心二进制文件:license.dat
  • 持久性加载程序:lake_x32.tmp

解密核心二进制文件和配置文件

我们提取的配置和核心二进制文件均使用 ICEDID 的自定义加密方案进行加密。我们可以使用 labs-releases\tools\icedid\decrypt_file.py 脚本解密它们。

usage: decompress_file.py [--help] input output

positional arguments:
  input       Input file
  output      Output file

options:
  -h, --help  show this help message and exit

如此处所示(请注意,可以将解密的文件写入任何有效的目标)

python .\decrypt_file.py .\extract\license.dat .\extract\license.dat.decrypted

python .\decrypt_file.py .\extract\configuration.bin .\extract\configuration.bin.decrypted

核心二进制文件和配置现在可以由其他工具处理。请参阅以下屏幕截图中显示的解密配置中的数据

读取配置

配置文件格式如下所示。

可以使用 labs-releases\tools\icedid\gzip-variant\read_configuration.py 脚本读取配置。

usage: read_configuration.py [--help] input

positional arguments:
  input       Input file

options:
  -h, --help  show this help message and exit

我们将使用 read_configuration.py 脚本读取我们在上一步中收集的 configuration.bin.decrypted 文件。

python .\gzip-variant\read_configuration.py .\extract\configuration.bin.decrypted

============================================================
Configuration
============================================================
botnet_id: 0x3B7D6BA4
auth_var: 0x00000038
uri: /news/
domains:
        alishaskainz.com
        villageskaier.com

此配置包含两个 C2 域

  • alishaskainz[.]com
  • villageskaier[.]com

对于此样本,ICEDID 使用的信标 URI 为“ /news/ ”。

重建核心二进制文件以进行静态分析

ICEDID 使用自定义 PE 格式来混淆其有效负载,从而击败期望处理正常 Windows 可执行文件的静态或动态分析工具。自定义 PE 文件格式如下所述。

如果我们想分析核心二进制文件(例如使用 IDA Pro),我们需要将其重建为有效的 PE。我们使用 labs-releases\tools\icedid\rebuild_pe.py 脚本。

usage: rebuild_pe.py [--help] [-o OFFSET] input output

positional arguments:
  input                 Input file
  output                Output reconstructed PE

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage

但是,当尝试在解密的核心二进制文件 license.dat.decrypted 上使用 rebuild_pe.py 时,我们会收到以下错误消息

python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin
Traceback (most recent call last):
  File "rebuild_pe.py", line 32, in <module>
    main()
  File "rebuild_pe.py", line 28, in main
    custom_pe.CustomPE(data).to_pe().write(args.output)
  File "nightmare\malware\icedid\custom_pe.py", line 86, in __init__
    raise RuntimeError("Failed to parse custom pe")
RuntimeError: Failed to parse custom pe

这里的微妙之处在于,自定义 PE 数据并非总是从文件的开头开始。例如,在这种情况下,如果我们像 HxD 一样在十六进制编辑器中打开该文件,我们可以观察到在实际数据之前存在一定数量的垃圾字节。

根据我们的研究,我们知道垃圾的大小为 129 个字节。

考虑到这一点,我们可以跳过垃圾字节,并使用带有 “-o 129” 参数的 rebuild_pe.py 脚本来重建核心二进制文件。这次,幸运的是,我们没有收到错误消息。core.bin 将保存到输出目录(在我们的示例中为 extract)。

python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin -o 129

重建的 PE 对象不可直接执行,但您可以使用您选择的反汇编程序对其进行静态分析。

我们为重建的二进制部分分配了自定义名称(.mare{0,1,2,...})。

我们要感谢 Hasherezade 的工作,我们从中获得灵感来构建此工具。

执行核心二进制文件(仅限 Windows)

如果没有了解 ICEDID 自定义 PE 格式以及入口点函数原型的自定义加载程序,则无法执行核心二进制文件。

根据我们的研究,我们知道入口点需要一个我们称之为上下文结构的结构,其中包含 ICEDID 核心和持久性加载程序路径及其加密的配置。上下文结构如下所述。

要本机执行核心二进制文件,我们使用 labs-releases\tools\icedid\gzip-variant\load_core.py 脚本,但在使用它之前,我们需要创建 context.json 文件,其中将包含此脚本构建此结构所需的所有信息。

对于此样本,我们复制伪造的 gzip 中包含的信息,并使用加密的配置文件的路径。我们在 gzip_variant/context.json.example 中包含了一个示例。

请注意,“field_0”“stage_2_export” 值必须在反转样本时找到。

这里我们使用之前研究中的值作为占位符,但我们无法保证样本100%有效。 例如,在这个样本中,我们不知道 #1 序号导出是否是持久性加载器的实际入口点。

我们还通过创建 UponBetter 目录并将 license.dat 文件移动到其中来重现第一阶段的行为。

我们使用 解密的内核 二进制文件:license.dat.decryptedcontext.json 文件,执行 labs-releases\tools\icedid\gzip_variant\load_core.py 脚本。

警告:此脚本将以原生方式加载/执行二进制文件,Elastic Security Labs 对您的系统造成的任何损害概不负责。请仅在安全环境中执行。

usage: load_core.py [--help] [-o OFFSET] core_path ctx_path

positional arguments:
  core_path             Core custom PE
  ctx_path              Path to json file defining core's context

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage

由于我们存在与上一节所述相同的垃圾字节问题,因此我们使用 “-o 129” 参数来跳过垃圾字节。

python .\gzip-variant\load_core.py .\extract\license.dat.decrypted .\gzip-variant\context.example.json -o 129

============================================================
Core Loader
============================================================
Base address: 0x180000000
Entrypoint: 0x180001390

Press a key to call entrypoint...

启动后,脚本会在调用入口点之前等待用户输入。我们可以轻松地将调试器附加到 Python 进程,并在 ICEDID 内核入口点(在本例中为 0x180001390 )设置断点。

按下按键后,我们就到达了入口点。

如果我们让二进制文件执行,我们会看到正在创建的 ICEDID 线程(在以下屏幕截图中指示)。

从重建的内核二进制文件中解包和重建有效载荷

为了提取嵌入在内核二进制文件中的任何有效载荷,我们将使用 labs-releases\tools\icedid\gzip-variant\extract_payloads_from_core.py 脚本。

usage: extract_payloads_from_core.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit

我们将在重建的内核二进制文件上使用此脚本。

python .\gzip-variant\extract_payloads_from_core.py .\extract\core.bin core_extract

core_extract\browser_hook_payload_0.cpe
core_extract\browser_hook_payload_1.cpe

从这里,我们输出两个二进制文件,对应于 ICEDID 用于 Web 浏览器挂钩功能的有效载荷,但是,它们仍然是自定义 PE 格式。

根据我们的研究,我们知道 browser_hook_payload_0.cpe 是浏览器挂钩有效载荷的 x64 版本,而 browser_hook_payload_1.cpe 是 x86 版本。

为了重建它们,我们再次使用 rebuild_pe.py 脚本,这次没有垃圾字节需要跳过。

python .\rebuild_pe.py .\core_extract\browser_hook_payload_0.cpe .\core_extract\browser_hook_payload_0.bin

python .\rebuild_pe.py .\core_extract\browser_hook_payload_1.cpe .\core_extract\browser_hook_payload_1.bin

现在我们有两个 PE 二进制文件( browser_hook_payload_0.binbrowser_hook_payload_1.bin ),我们可以进一步分析。

细心的读者可能会注意到,我们跳过了从内核二进制文件中解包 VNC 服务器 的步骤,这是我们有意做出的决定。我们将在未来的研究中与其他工具一起发布它,敬请期待!

结论

在本教程中,我们介绍了 ICEDID GZip 变体的解包,从提取伪造的 GZip 二进制文件开始,然后重建内核二进制文件并解包其有效载荷。

ICEDID 在不断发展,我们将继续监控重大变化,并根据我们的研究更新我们的工具。如果某些内容损坏或未按预期工作,请随时 提出问题向我们发送消息

Elastic Security Labs 是一个由专业研究人员和安全工程师组成的团队,致力于通过发布详细的检测逻辑、保护和应用威胁研究来破坏攻击者的活动。

@elasticseclabs 上关注我们,并访问我们的研究门户以获取更多资源和研究。

参考文献

以下内容在上述研究中被引用