jafeeri/plugx-korplug-analysis
GitHub: jafeeri/plugx-korplug-analysis
一份针对 PlugX/Korplug DLL 侧加载后门的完整逆向分析报告,涵盖静动态分析与检测规则。
Stars: 0 | Forks: 0
# PlugX / Korplug — 完整恶意软件分析
**静态分析 · 动态分析 · 对 DLL 侧加载后门 (RAT) 的逆向工程**





**分析师:** Ali Mehdi Jafeeri · **日期:** 2026 年 7 月
这是系列分析中的第三篇:
[RedLine Stealer](https://github.com/jafeeri/redline-stealer-analysis) (信息窃取程序) ·
[WannaCry](https://github.com/jafeeri/wannacry-malware-analysis) (勒索软件蠕虫) ·
**PlugX** (后门 / RAT)。
## ⚠️ 安全提示
## 目录
- [执行摘要](#executive-summary)
- [为何分析此样本](#why-this-sample)
- [侧加载三件套](#the-side-loading-triad)
- [实验环境](#laboratory-environment)
- [阶段 1 — 静态分析](#phase-1--static-analysis)
- [阶段 2 — 动态分析](#phase-2--dynamic-analysis)
- [阶段 3 — 逆向工程 Loader](#phase-3--reverse-engineering-the-loader)
- [MITRE ATT&CK 映射](#mitre-attck-mapping)
- [入侵指标](#indicators-of-compromise)
- [YARA 检测规则](#yara-detection-rule)
- [防御建议](#defensive-recommendations)
- [经验总结](#what-i-learned)
## 执行摘要
PlugX(又名 **Korplug**、Sogu、Destroy RAT)是一种与某国背景的间谍活动相关联的**模块化后门**,自约 2008 年以来一直在持续使用。与独立封装的可执行文件不同,它是作为一个**三件套文件组**进行分发,并滥用 **DLL 侧加载**:一个带有真实签名的供应商可执行文件被诱骗去加载一个恶意的相似 DLL,该 DLL 随后会从一个独立的数据文件中解密并执行加密的 payload。
本次分析通过三个协同阶段确立了其完整行为。
### 关键发现
| # | 发现 |
|---|---|
| 1 | **DLL 侧加载** — 合法的、带有签名的 `adb.exe` (Android Debug Bridge) 从其所在目录侧加载了恶意的 `AdbWinApi.dll`。签名验证通过;不需要任何伪造。 |
| 2 | **自解密 shellcode** — 该 DLL 将 `AdbWinApi.dat` 读取到一个 1 MB 的 **RWX** 缓冲区中(`VirtualAlloc` → `ReadFile` → `VirtualProtect` → `call`)并跳转执行。该 payload 没有 `MZ` 头;它会在内存中自解密。 |
| 3 | **入口点劫持** — loader 用一条 `0xE9` JMP 指令覆盖了 `adb.exe` 的入口点,从而确保控制流能到达 payload,同时 ADB 看起来仍在正常运行。 |
| 4 | **注入 `msiexec.exe` 进程** — payload 被注入到一个新生成的、已签名的 Microsoft 进程中;随后短暂的 loader(约 4 秒)自行终止。 |
| 5 | **SYSTEM 权限持久化** — 安装了一个名为 **`Adb`** 的服务(自启动,LocalSystem),伪装成 *"Qihoo 360 Software (Beijing)"*,指向迁移到 `C:\ProgramData\adb\` 中的副本。 |
| 6 | **C2 = 通过 TCP/443 连接 `tools.dji8[.]me`** — 从网络层恢复。该恶意软件在发送 beacon 之前,首先会探测硬编码的公共解析器,包括 `114.114.114.114` (114DNS,中国)。 |
| 7 | **反取证** — 安装持久化机制后,loader 会从启动目录中删除原始文件,只留下隐藏在 `ProgramData` 中的副本。 |
## 为何分析此样本
我之前的两个样本都是独立的单一文件。PlugX 则截然不同:它是一个**由三个具有相反信任属性的文件组成的集合** — 一个是真正签名且无害的,一个是恶意的,一个是加密数据。这将最初的分析问题从“这个文件做了什么?”变成了**“这些文件中哪一个是恶意软件?”**。回答这个问题(证明干净的 EXE / 肮脏的 DLL 的分离)正是该样本所教授的核心技能,它也暴露了一个盲点,这个盲点击败了曾经阻止过之前两个样本的安全防御控制:**签名验证对侧加载毫无保护作用,因为被签名的二进制文件是真实的。**
| | RedLine | WannaCry | **PlugX** |
|---|---|---|---|
| 类别 | 信息窃取程序 | 勒索软件蠕虫 | **后门 / RAT** |
| 隐匿方式 | 加壳 | 嵌套加密容器 | **借用签名 (侧加载)** |
| 持久化 | 无 | 服务 + Run 键 | **服务 (SYSTEM,伪装的)** |
| 绕过签名检查? | 否 | 否 | **是** |
## 侧加载三件套

| 组件 | 文件名 | 角色 | 信任度 |
|---|---|---|---|
| 带签名的宿主 | `adb.exe` | 合法的 Android Debug Bridge;侧加载 DLL | **无害,已签名** |
| 恶意 loader | `AdbWinApi.dll` | **恶意软件本体** — 读取并执行 payload | **恶意** |
| 加密 payload | `AdbWinApi.dat` | 自解密的、位置无关的 shellcode + 配置 | **加密数据** |
这三个文件名在正常的 Android SDK 安装中会同时出现,并且在其中完全是无害的。该攻击将中间的文件替换为恶意的相似文件,并添加了加密的 `.dat`。移动其中任何一个文件都会导致引爆失败 — 因为 loader 在设计上只会从**其自身目录**中读取 `AdbWinApi.dat`。
## 实验环境
| 主机 | 地址 | 角色 |
|---|---|---|
| Windows 10 (受害者) | `192.168.56.20` | 引爆,静态工具分析 |
| REMnux | `192.168.56.102` | DNS sinkhole (dnsmasq),模拟服务 |
| 网络 | `192.168.56.0/24` | VirtualBox **Host-Only** — 无外部路由 |
DNS sinkhole (针对 INetSim 损坏的 DNS worker 的变通方法):
```
sudo dnsmasq -d --conf-file=/dev/null --no-resolv \
--listen-address=192.168.56.102 --bind-interfaces \
--address=/#/192.168.56.102 --log-queries
```
## 阶段 1 — 静态分析
**带有签名的宿主 (`adb.exe`) 实际上是无害的。** 正常的熵值 (6.54),真实的 `Microsoft Linker` 构建,ADB 预期的 `Adb*` USB 导入表,以及签名元数据 (`360安全中心`)。PEStudio 没有将其标记。根本不存在需要检测的伪造 — 攻击者只是借用了真实的二进制文件。

**该 DLL (`AdbWinApi.dll`) 就是恶意软件本体。** 它是由与真实 ADB *不同*的编译器 (VS2010) 构建的,其导入表是一个微缩版的 loader:`VirtualAlloc` + `VirtualProtect` (RWX 内存),`CreateFileW` + `ReadFile` + `GetModuleFileNameW` (读取 payload),`LoadLibraryW` + `GetProcAddress` (在运行时隐藏真实的能力集),以及 `IsDebuggerPresent` (反分析)。完全*没有*任何网络或注入 API 本身就是一个破绽 — 这些都是动态解析的。

FLOSS 提取出了 **`PADDINGXXPADDINGXXPADDING`** 标记 — 这是位置无关 shellcode 块的特征 — 随后是高熵值的噪声。

**Payload (`AdbWinApi.dat`)** 是 148.57 KiB 均匀分布的高熵数据,没有 `MZ` 头 — 是一个单一的加密块。`.dat` 扩展名只是伪装。

## 阶段 2 — 动态分析
**侧加载触发** — `adb.exe` (32位,WOW64) 加载了恶意 DLL,将三件套迁移到 `C:\ProgramData\adb\`,并使用自我指示的参数 (`adb.exe 100 1636`) 重新启动。Loader 进程存活约 **4 秒**后退出。

**注入 `msiexec.exe`** — 一个新生成的 `msiexec.exe` (SYSTEM 权限 `svchost.exe` 的子进程) 托管了正在运行的后门。一个带有签名的 Microsoft 进程发起网络连接并不引人注目 — 这正是其目的所在。

**持久化** — Regshot 差异比对显示出现了一个新服务 `Adb`:自启动,LocalSystem,ImagePath 为 `C:\ProgramData\adb\adb.exe`,伪装成 *"Qihoo 360 Software (Beijing)"*。

**命令与控制** — 除了 Windows 遥测的噪声外,恶意软件还会向 **`tools.daji8[.]me`** (已被 sinkhole) 发送 beacon,在此之前它会使用 ICMP 和直接 DNS 探测硬编码的公共解析器 — 包括中国的 `114.114.114.114`。所有探测均未返回响应,证明隔离有效。


## 阶段 3 — 逆向工程 Loader
Ghidra 直接反编译了解压后的 DLL。该 loader 是一个单独的函数:
```
GetModuleFileNameW(...); // where am I running from?
lstrcpyW(..., L"AdbWinApi.dat"); // build path to the payload beside me
Sleep(500);
lpBuffer = VirtualAlloc(0, 0x100000, 0x1000, 0x40); // 1 MB RWX
CreateFileW(L"...AdbWinApi.dat", GENERIC_READ, ...);
ReadFile(hFile, lpBuffer, 0x100000, ...); // load the ciphertext
VirtualProtect(lpBuffer, 0x100000, 0x20, ...); // PAGE_EXECUTE_READ
(*lpBuffer)(); // execute the payload
Sleep(0xFFFFFFFF); // park the thread forever
```

另一个函数劫持了 `adb.exe` 的入口点,在进行 `MZ`/`PE` 合理性检查后,用一条 `0xE9` JMP 覆盖其前几个字节,随后恢复内存保护以隐藏该修改。

**配置块恢复**尝试从活动内存中提取并如实记录:loader 的 4 秒生命周期、服务拒绝 `sc start`(错误 1053 — 它不是真正的服务二进制文件),以及 payload 是 *shellcode* 而不是被植入的 PE 文件,这些因素综合起来意味着瞬态的 RWX 区域未能在可用的时间窗口内被捕获。配置块中原本应包含的 C2 地址已通过网络独立恢复 (`tools.daji8[.]me:443`),因此分析在实质内容上是完整的;仅剩下次要的配置元数据(互斥锁、休眠间隔、活动 ID),同时记录了获取这些信息的方法(使用 `pe-sieve /shellc 3` 转储被注入的 `msiexec.exe` 区域)。
## MITRE ATT&CK 映射
| 战术 | 技术 | ID |
|---|---|---|
| 执行 | 用户执行 | T1204 |
| 防御规避 / 持久化 | **DLL 侧加载** | **T1574.002** |
| 防御规避 | 进程注入 (`msiexec.exe`) | T1055 |
| 防御规避 | 伪装 — 服务伪装为 "Qihoo 360" | T1036.004 |
| 持久化 | Windows 服务 (`Adb`,SYSTEM,自启动) | T1543.003 |
| 防御规避 | 指标移除 — 文件删除 | T1070.004 |
| 命令与控制 | 应用层协议 (TCP/443) | T1071 |
| 发现 | 系统网络配置发现 | T1016 |
## 入侵指标
完整的机器可读列表在 [`iocs/iocs.csv`](iocs/iocs.csv) 中。重点如下:
| 类型 | 指标|---|---|
| SHA-256 (`AdbWinApi.dll`,恶意软件本体) | `7050084c99d02f2e837207bff7a13a261d5435589771e9dc3f0db38841b97942` |
| SHA-256 (`adb.exe`,带签名的宿主) | `ef4c7f4c417c18cd3394dd81ccd94381af252e0af81b0ad89b7e6d81412a4706` |
| C2 域名 | `tools.daji8[.]me` |
| C2 端口 | TCP `443` |
| 硬编码的备用解析器 | `114.114.114.114` |
| 安装目录 | `C:\ProgramData\adb\` |
| 持久化服务 | `Adb` (自启动,LocalSystem,"Qihoo 360") |
| 注入目标 | `msiexec.exe` |
| 侧加载的 DLL / payload | `AdbWinApi.dll` / `AdbWinApi.dat` |
## YARA 检测规则
完整规则在 [`iocs/plugx.yar`](iocs/plugx.yar) 中。它基于恶意 DLL 的特征进行匹配 — `AdbWinApi.dat` 引用(真正的 ADB DLL 绝不会读取 `.dat` 文件)、shellcode 的 padding 标记,以及 RWX loader 的常量 — 而不是基于 ADB 的导出函数名,因为后者会在真实的动态链接库上引发误报。
## 防御建议
- **应用程序目录的 DLL 控制。** 根本原因是搜索顺序加载。应强制执行已签名 DLL 策略 / 安全的 DLL 搜索模式;对于从用户可写目录中(位于已签名二进制文件旁边)加载的未签名 DLL 发出告警。
- **寻找行为,而不是文件。** 一个带有签名的 `adb.exe`(或任何 LOLbin)从临时文件夹/桌面/`ProgramData` 路径加载 DLL,随后生成具有网络活动的 `msiexec.exe`,这就是检测特征。
- **服务创建监控。** 对于指向 `C:\ProgramData\` 中、具有供应商相似名称的新自启动 LocalSystem 服务发出告警。
- **网络。** 阻断/检查 C2 域名;关注绕过企业级解析器直接向硬编码的公共解析器(尤其是 `114.114.114.114`)发起的直接 DNS 请求。
## 经验总结
隐匿策略决定了分析策略。**加壳** (RedLine) 强制要求进行内存转储;**容器** (WannaCry) 允许你进行静态提取;而**侧加载** (PlugX) 则要求你首先证明*哪个文件*是恶意的,然后通过*第三个*进程追踪代码流。尽早识别隐匿类别是本系列中最具可迁移性的技能 — 而 PlugX 本身也提供了一个深刻的教训:4 秒寿命的 loader 是一种真正的反分析特性,而正确的捕获点是**注入目标**,而不是 loader。
*分析与写作由 **Ali Mehdi Jafeeri** 完成,2026 年 7 月。仅供教育 / 防御用途。*
标签:DAST, DLL侧加载, DNS信息、DNS暴力破解, PlugX, YARA规则, 云资产清单, 威胁情报, 开发者工具, 恶意软件分析, 逆向工程