DLL 侧加载(DLL Sideloading)借微软签名二进制的信任链,让恶意 DLL 在「Microsoft 签名进程」的光环下加载,EDR 对用户态写入与内存执行天然高看一眼。2026 年红队最稳健的 EDR 绕过手段,APT41、Lazarus、MuddyWater 都在用。

一、技术全貌:这是什么?

如果说 2023 年是「直接系统调用 + Unhook」的天下,2024-2025 年是「内核回调移除 + BYOVD」的主场,那么到了 2026 年,在微软驱动黑名单与 HVCI 的双重夹击下,一个看似「上古」的技术反而成了红队手里最稳的一张牌——DLL 侧加载(DLL Sideloading)

所谓 DLL 侧加载,是指找到一个微软官方签名、但加载 DLL 时 搜索顺序可被劫持的合法二进制,把我们的恶意 DLL 以同名丢进它所在的可写目录,再启动这个签名程序。于是恶意代码借壳运行在「Microsoft 签名进程」的信任光环之下,EDR 对用户态的内存写入、模块加载、线程执行天然「高看一眼」,行为检测阈值被直接拉高。

RingSafe 在 2026 年 7 月的复盘把当前 EDR 绕过划为四大家族,其中明确写道:DLL 侧加载(通过签名二进制)至今仍高度有效(still highly effective)。APT41 借 Trend Micro 签名二进制侧载、Lazarus 借 Sangfor 签名驱动侧载、MuddyWater 借 SentinelOne 与 Fortemedia 签名二进制侧载——国家级对手都在用,因为它稳。

一句话:它不杀 EDR、不拦 EDR、不断 EDR,它只是「借一个好人身份干坏事」。

二、为什么这个技术如此重要

传统 EDR 压制手段有三个绕不开的死穴:

方法

致命缺陷

防火墙封禁 EDR 进程

留下明确规则痕迹,SIEM 一眼看穿

WFP 丢包(EDRSilencer 等)

产生 packet-drop 日志,可溯源

直接杀 EDR 进程

触发进程终止告警,立即响应

而 DLL 侧加载不杀、不拦、不断,它只是「借壳」。更关键的是:绝大多数 EDR 对 Microsoft 签名进程的内存读写、模块加载事件默认信任,侧载进来的 DLL 继承了这份信任,ETW 线程审计、行为关联引擎都很难把它和合法加载区分开。

这就是为什么在「上下文联动分析」成为主流的 2026 年,依赖特征码与简单 API 混淆的时代终结后,侧加载反而逆势回潮——它攻击的不是 EDR 的检测能力,而是 EDR 的信任模型本身

三、技术原理解析

要点一:DLL  搜索顺序的「应用目录优先」

当一个 Windows 程序不指定完整路径LoadLibrary 一个 DLL 时,系统会按固定顺序查找。默认顺序里,应用程序所在目录排在第一位,先于 C:WindowsSystem32

1. 应用程序所在目录        ← 攻击者把恶意 DLL 放这里
2. C:WindowsSystem32
3. C:WindowsSystem
4. C:Windows
5. 当前工作目录
6. 系统 PATH
7. 用户 PATH

只要我们在「签名二进制」同目录放一个同名、且导出函数签名匹配的恶意 DLL,Windows 就会先加载我们的版本。

要点二:签名信任链的「光环效应」

EDR 的进程树/父子关系分析通常信任微软签名父进程拉起的子模块。恶意 DLL 被加载进 OneDrive.exeTeams.exepdf24.exe 这类签名进程后,其内存执行、网络连接都被打上「可信进程」的标签。签名校验的是包装器,而不是它加载的内容——这是整个技术的命门。

要点三:可侧载目标的「NAME NOT FOUND」挖掘

最聪明的挖掘方式是用 Sysinternals Process Monitor:过滤 Operation = CreateFileResult = NAME NOT FOUNDPath ends with .dll。任何签名二进制对某个 DLL 返回 NAME NOT FOUND,都是潜在侧载点。公开已知的稳定目标包括:

宿主二进制

缺失 DLL

备注

msdtc.exe

winmm.dll

Microsoft 分布式事务协调器

OneDriveStandaloneUpdater.exe

version.dll

微软签名二进制

notepad++.exe

SciLexer.dll

流行签名应用

Teams.exe

dbghelp.dll

微软 Teams

关键代码示例(演示用,仅授权实验环境)

下面是一段最小化演示 DLL(以 version.dll 为例),其 DllMain 在校验当前目录合法后仅弹出计算器,用于验证侧载链路是否打通。真实攻击会用 C2 beacon 替换 payload,本文不提供任何武器化代码。

// payload.c —— DLL 侧加载演示模板(良性,仅 calc.exe)
#include <windows.h>

// 演示用:仅启动计算器验证链路,不承载任何恶意逻辑
void demo_payload(void) {
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    CreateProcessA("C:\Windows\System32\calc.exe", NULL,
                   NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
}

BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) {
        demo_payload();
    }
    return TRUE;
}
// 必须导出宿主期望的函数,否则签名程序会因缺失导出而崩溃。
// version.dll 常见导出(保留空实现即可,重点是 DllMain 已执行):
__declspec(dllexport) DWORD WINAPI GetFileVersionInfoSizeW(LPCWSTR p, LPDWORD h) { return 0; }
__declspec(dllexport) BOOL WINAPI GetFileVersionInfoW(LPCWSTR p, DWORD h, DWORD s, LPVOID d) { return FALSE; }
__declspec(dllexport) DWORD WINAPI VerQueryValueW(LPCVOID b, LPCWSTR s, LPVOID* p, PUINT l) { return 0; }

用 MinGW 编译为同名 DLL 投递到宿主目录:

x86_64-w64-mingw32-gcc -shared -o version.dll payload.c -luser32

OPSEC 提醒:真实侧载必须精确匹配宿主期望的导出表(可用 dumpbin /exportsobjdump 逆向确认),否则宿主进程因缺导出直接崩溃,反而暴露痕迹;同时侧载 DLL 自身建议经合法签名或做内存加载,避免落地即被杀。

实战应用场景

  1. 初始访问后的「免杀落地」:钓鱼/漏洞拿到一个低权限 foothold,把「签名二进制 + 同名恶意 DLL」打包进 ISO/ZIP 诱导双击,恶意代码在可信进程内执行,绕开进程创建类检测。

  2. EDR 内存扫描规避:合法进程上下文内的内存执行,被 ETW 与行为关联引擎归类为「白进程行为」,RWX 区段、远程线程等特征被信任光环稀释。

  3. 持久化与横向:配合计划任务/服务,把侧载目录固化,重启后自动在签名进程下复活。

  4. 国家级 APT 标配:MuddyWater 借 SentinelOne 的 fmapp.exesentinelmemoryscanner.exe 侧载;APT41 借 Trend Micro 签名二进制;Lazarus 借 Sangfor 签名驱动——证明该技术在真实战场上的鲁棒性。