Skip to main content

白加黑利用

“白加黑”常被简单描述为“合法 EXE 加恶意 DLL”,但这个说法还不够准确。它真正滥用的是软件生态中的加载信任:一个合法、通常带有效签名的程序,会按照既定搜索规则或插件机制加载旁边的组件;攻击者控制了被加载的组件,于是恶意代码自然运行在合法程序内部。

先说结论:

白 = 原始、未被篡改的合法加载程序
黑 = 攻击者可控的 DLL、插件、配置或后续载荷
加 = 合法程序原本就具备的加载关系

白文件的有效签名只证明这个文件本身在签名后没有被修改,并且签名证书链满足校验策略。它不证明同目录中的其他文件安全,也不证明当前文件名、图标、落地路径和产品身份真实。

基本机制

Windows 程序在运行时需要解析依赖。除了系统已知 DLL,程序还可能从应用目录、系统目录、环境路径、清单、注册信息或自定义插件目录中寻找组件。

如果一个合法程序:

  • 依赖某个没有使用绝对路径定位的 DLL。
  • 会优先在自身目录寻找同名组件。
  • 缺少对被加载组件的签名、哈希或发布者约束。
  • 暴露了可被替换的插件、编解码器或扩展接口。

那么攻击者只需让它在受控目录里启动,并让一个接口兼容的恶意组件出现在预期位置,合法程序就可能主动加载该组件。这个过程不要求修改白文件,也不要求攻击者拥有白文件发布者的私钥。

受控目录
├── 看似正常的软件名.exe ← 原始合法文件,签名有效
├── 程序会寻找的组件.dll ← 未签名、伪造签名或来源异常
└── 配置 / 加密数据 ← 可选的后续载荷

用户启动 EXE

EXE 按正常逻辑寻找依赖或插件

同目录恶意 DLL 被加载

恶意代码在合法签名进程内执行

这更准确地对应 DLL 侧加载、搜索顺序劫持或插件机制滥用,而不是“把恶意代码塞进一个仍保持有效签名的 EXE”。

签名边界

Authenticode 会对 PE 主体计算专用哈希,并把摘要、签名者信息和证书链放在签名结构中。校验时不只是看文件里“有没有证书”,还要重新计算摘要并验证签名。

因此:

  • 修改已签名文件的代码段、资源、导入表或其他受哈希覆盖的内容,正常会使签名失效。
  • 复制证书表、保留公司名字符串或替换图标,不能产生该公司的有效签名。
  • “证书存在”“证书链可信”“文件摘要匹配”是不同概念,产品不能只检查前两项。
  • 某些签名格式历史上存在未覆盖区域或校验策略差异,但不能把它概括成“任意替换代码仍能保活签名”。严格、完整的校验应拒绝主体被改动的文件。
warning

如果一个工具声称某文件“有腾讯证书”,先确认它展示的是嵌入证书的主题信息,还是完整的文件摘要校验结果。只有后者成功,才能称为该文件签名有效。

“腾讯签名小 QQ”怎样出现

假设现场发现一个文件名和图标都像 QQ、属性页显示腾讯有效签名,但体积远小于当前完整 QQ 客户端。最合理的解释通常不是“攻击者把完整 QQ 压小后绕过了签名验证”,而是下面这类设计:

复用小型合法组件

大型软件套件通常不只有主程序,还包含启动器、更新器、崩溃上报器、卸载器、辅助工具和兼容性组件。这些文件可能只有几百 KB 或几 MB,同样由厂商签名。

攻击者可以原样复制其中一个较小的合法组件,把它重命名成看似主程序的名称,再配上诱导性的目录名、快捷方式和图标。因为文件字节没有变化,它的腾讯签名仍然有效。

原始身份:某套腾讯软件中的小型辅助组件
磁盘外观:QQ.exe / QQ安装程序.exe
签名结果:有效,签名者为腾讯
产品事实:它从来不是完整 QQ 客户端

Windows 的代码签名不绑定“这个文件必须叫什么名字”,也不保证“它必须位于哪个目录”,更不会因为文件名是 QQ.exe 就拿它和官方 QQ 主程序的体积进行比较。

利用原生加载能力

被挑选的白壳通常还具备某种可利用的加载能力,例如会在程序目录寻找依赖 DLL、读取插件、处理特定配置,或者调用同目录辅助模块。攻击者让黑组件满足最低加载条件,白壳便会主动把它带入进程。

“接口兼容”不等于要复刻整个原厂组件。对于分析人员而言,只需理解:黑组件会保留白壳启动所需的少量接口或初始化行为,再把控制流交给隐藏载荷;具体实现细节因组件而异。

外观伪装补全身份

攻击者还会利用快捷方式、父目录名称、版本资源、压缩包名称或诱导文案,把一个真实的小型腾讯组件包装成“QQ 主程序”。这属于身份伪装,不是签名破解。

最终形成的是:

合法签名白壳(原样)
+ 同目录黑 DLL / 插件
+ QQ 名称、图标、快捷方式等外观
= 看似“腾讯签名的小 QQ”

所谓“绕过签名验证”,实际往往是绕过了错误的信任决策:安全产品只验证启动 EXE 的签名,随后直接给整个进程或目录放行,没有继续检查它加载了什么、从哪里加载,以及加载后的行为是否合理。签名验证本身并没有被数学意义上绕过。

变体

DLL 搜索顺序劫持

合法程序通过名称解析依赖,攻击者控制了优先搜索位置。检测重点是白程序所在目录、缺失或异常的依赖、加载路径以及 DLL 签名。

插件与扩展滥用

合法程序明确支持加载第三方插件,但没有充分限制插件来源。它与侧加载的区别在于:插件加载是产品设计的一部分,风险来自扩展信任边界过宽。

配置驱动的后续加载

白壳先读取同目录配置、脚本或数据,再据此加载模块或发起网络请求。此时“黑”不一定直接表现为 DLL,也可能是被解释、解密或下载的内容。

白壳作为代理执行器

有些合法组件本来就能注册组件、运行安装动作或调用系统功能。攻击者传入恶意输入,让白程序代为执行。此类行为更接近系统二进制代理执行,不一定存在 DLL 侧加载。

抽象案例

一个压缩包中只有一个体积很小的 QQ.exe、一个名称普通的 DLL 和一个数据文件。检查发现:

  • QQ.exe 的完整 Authenticode 校验成功,签名者确为腾讯。
  • 文件哈希能对应到某个历史版本软件包中的辅助程序,而不是 QQ 主程序。
  • 文件名与原始名称不同,落地在用户临时目录。
  • 启动后从自身目录加载未签名 DLL。
  • 随后进程出现与该辅助程序职责无关的持久化或公网通信。

这条证据链足以说明“合法组件被重新投放并用于侧加载”。不应写成“腾讯签名被伪造”,也不能仅凭签名者名称归因于腾讯软件供应链。

检测

不把签名当白名单

合理的信任模型至少要同时考虑:

维度需要回答的问题
完整性文件摘要是否与签名匹配,而不只是包含证书
身份原始文件名、产品名、版本、哈希是否符合官方基线
位置签名厂商、产品与当前路径是否匹配
来源文件由谁下载、解压或释放,是否带网络来源标记
依赖它加载了哪些 DLL,组件签名和路径是否可信
行为当前进程的网络、持久化、凭据与注入行为是否符合职责

高价值组合

下面这些组合通常比“有效签名”更有研判价值:

  • 大厂签名的小型组件被重命名为旗舰产品主程序。
  • 合法文件出现在下载、临时、公共用户或随机目录。
  • 签名 EXE 从同目录加载未签名、低信誉或刚落地的 DLL。
  • EXE 的原始文件名、产品描述、当前文件名和父目录相互矛盾。
  • 组件版本明显陈旧,且与同目录其他文件的版本不一致。
  • 合法宿主执行了与原始职责无关的联网、键盘读取、截屏、令牌操作或持久化。
  • 内存中的模块与磁盘基线不一致,或存在没有正常模块记录的可执行私有内存。

取证顺序

  1. 对白壳执行完整签名验证,并记录摘要、签名者、时间戳和校验策略。
  2. 用哈希和版本信息确认它原本属于哪个产品、承担什么角色。
  3. 检查当前文件名、原始文件名、路径、下载来源和首次落地进程。
  4. 建立模块加载清单,重点看应用目录中的 DLL 与插件。
  5. 比较同一进程启动前后的文件、注册表、网络和内存行为。
  6. 对同目录文件整体隔离取证,不能只删除黑 DLL 或只信任白 EXE。

缓解

  • 允许规则优先绑定发布者、产品、原始文件名、版本范围和受控路径,不要只绑定签名者。
  • 对来自互联网或用户可写目录的签名文件保留行为检测,不自动提升到全信任。
  • 监控签名进程加载同目录未签名模块,建立官方安装目录和模块哈希基线。
  • 软件开发侧使用安全的 DLL 搜索策略、绝对路径、受控插件目录及组件签名校验。
  • 清理不再使用的旧组件,并阻止企业环境中不受支持版本任意运行。

ATT&CK 对照

Technique适用含义
T1574.002 DLL Side-Loading合法程序加载攻击者控制的 DLL
T1574.001 DLL Search Order Hijacking利用依赖搜索顺序抢先加载恶意 DLL
T1036 Masquerading文件名、图标、路径或产品身份伪装
T1553.002 Code Signing盗用证书、恶意签名或其他代码签名滥用;不要把所有白加黑都机械归到这里

小结

“有腾讯有效签名、体积却远小于 QQ”的文件,并不神秘:它很可能本来就是腾讯软件套件中的一个小型合法组件,只是被原样复制、改名和重新投放。攻击者没有修改白壳,所以签名仍有效;真正的恶意能力来自白壳随后加载的黑组件。

因此最重要的判断是:

有效签名证明文件完整性和签名者
不证明当前名称、路径、用途和运行时依赖可信

防守方必须把签名、文件身份、落地路径、模块加载和运行行为放在一起判断。