首页
社区
课程
招聘
[原创]AppDomainManager 注入:从GAC 利用到无文件加载的多种实现
发表于: 2天前 983

[原创]AppDomainManager 注入:从GAC 利用到无文件加载的多种实现

2天前
983

过去的注入技术(如跨进程注入)依赖底层的 Windows API(如 VirtualAllocEx、WriteProcessMemory、CreateRemoteThread),这些 API 目前已被 EDR和杀毒软件严密监控。传统的 dll 劫持则需要依靠文件路径、容易被 DLL 签名校验发现 ,也容易存在重名文件导致劫持失败。

AppDomainManager 注入则避免使用敏感 API, 转向利用 .NET 原生框架(如运行时)的合法功能,而且通过设置全局环境变量,可实现所有 .NET 程序启动即感染。其核心思路是: 攻击者编写一个恶意的 C# 类,继承自官方的 System.AppDomainManager,然后通过修改配置文件或环境变量,欺骗一个合法的、有签名的 .NET 程序在启动时将这个恶意类作为其“AppDomainManager”加载。

当编写并编译一个 .NET 程序(如 C# 或 VB.NET)时,它并不会直接变成计算机 CPU 能听懂的机器码(0101),而是变成一种中间语言(MSIL/CIL)。.NET 运行时的任务就是负责把这些中间代码翻译成机器码,并全程管理程序运行时的各种需求,特别是内存管理需求。在 .NET 中,为了防止内存泄漏,运行时会自动追踪不再使用的对象并回收内存;而不是像 C++ ,开发者必须手动申请和释放内存。在 Windows 平台上,它最核心的部分被称为 CLR (Common Language Runtime,公共语言运行时)。

AppDomainManager 注入技术是安全专家 Casey Smith 在 2017 年首次提出。与传统的 DLL 劫持(DLL Side-Loading)不同,这利用的是 .NET 自身正常的程序集解析和加载机制,行为更加隐蔽,安全软件很难在不影响正常业务的前提下进行拦截。换句话说,AppDomainManager 注入的核心价值在于利用“受信任的微软签名程序”来加载“不受信任的代码”,属于 LOLBins (Living Off The Land Binaries) 。

AppDomain(应用程序域): 在 .NET 框架中,AppDomain 是进程内的一个轻量级隔离边界。一个操作系统进程(PID)可以包含多个 AppDomain。这种机制使得 .NET 程序可以安全地加载和卸载程序集(Assembly),防止不同的代码段互相干扰。

AppDomainManager: 这是一个官方提供的基类,用于让宿主(Host)自定义如何创建和管理新的 AppDomain。当一个 .NET 应用程序启动并初始化它的第一个 AppDomain 时,它会检查是否配置了自定义的 AppDomainManager。如果有,.NET 运行时会优先加载并执行这个管理器代码

AppDomainManager 不依赖于文件缺失,也不需要复杂的远程线程注入。它利用的是 CLR 加载机制中的“配置优先”原则,代码运行环境极其“纯净”且受信任。AppDomainManager 允许代码在目标程序的 Main 函数执行之前就获得控制权。这意味着攻击者可以在安全软件还没来得及挂钩(Hook)或初始化监控之前,就已经完成了反调试、反沙箱或内存补丁等恶意操作。

以下测试均基于.NET Framework 4.x,虽然 .NET Core 及更高版本(.NET 5/6/7/8)也支持 AppDomainManager,但其加载机制(如 app.config 的处理方式)和 GAC 的概念已经发生了巨大变化。

使用 C# 创建一个类库(DLL),包含一个继承自 AppDomainManager 的类,并重写 InitializeNewDomain 方法。在该方法中放入恶意代码。具体编译过程:新建一个文件 MyPayload.cs,使用记事本输入以下 C# 代码。这段代码继承了 AppDomainManager,重写了InitializeNewDomain(),实现在.NET 程序初始化时启动计算器。

图片描述

打开命令提示符(cmd),进入 MyPayload.cs 文件所在目录,利用系统自带的 .NET 编译器 (csc.exe) 将源码编译为 AppVStreamingUX_Multi_User.dll。运行以下命令:

图片描述

选择 .NET 框架自带的合法且有微软签名的程序 dfsvc.exe 作为启动测试 dll 的目标程序,将其复制到AppVStreamingUX_Multi_User.dll 所在目录,并重命名为AppVStreamingUX.exe,稍微伪装一下

图片描述

dfsvc.exe (Deployment File Service) 是 Microsoft .NET Framework 的一部分,主要负责 ClickOnce 应用程序的安装、更新和管理。它是合法的 Windows 系统进程,通常随 .NET Framework 运行。虽然它是正常的部署服务,但也可能被滥用为执行恶意代码的白名单程序。

图片描述

不过,安全软件可能会校验文件名与签名中的原始文件名是否匹配,如果不匹配,反而会增加风险。这里仅仅做个测试,就先不管这么多了。

在目标 .NET 程序AppVStreamingUX.exe(原名为dfsvc.exe )同目录下创建一个名为 (目标程序名).exe.config 的文件。在配置文件中指定恶意 DLL (AppVStreamingUX_Multi_User.dll)和类名(MyAppDomainManager)。

当受害者或攻击者运行该合法 exe( AppVStreamingUX.exe)时,.NET 运行时会自动读取 .config 文件(AppVStreamingUX.exe.config),并静默加载 AppVStreamingUX_Multi_User.dll 执行其中的恶意代码(弹出计算器)。

将以下 XML 内容写入该文件:

图片描述

点击运行程序AppVStreamingUX.exe,计算器顺利弹出 图片描述

通过火绒剑可以观察到AppVStreamingUX.exe 进程创建后,很快就打开并读取了配置文件AppVStreamingUX.exe.config 图片描述

接着又打开了文件 AppVStreamingUX_Multi_User.dll 图片描述

可以清楚地看到,这个AppVStreamingUX.exe 加载了 AppVStreamingUX_Multi_User.dll。 图片描述这次测试成功实现了利用配置文件的 AppDomainManager 注入。

编译新的 dll

图片描述

运行命令,将以上代码编译为 GlobalManager.dll

图片描述 图片描述

管理员权限打开 Powershell,依次执行以下命令 图片描述 图片描述

接着把 dll 文件放到文件夹C:\test,然后设置环境变量 图片描述

点击运行AppVStreamingUX.exe,创建了 success.txt 文档,说明注入成功 图片描述

注意,.NET Core 和 .NET 5+ 之后,环境变量的前缀从 COMPLUS_ 变更为 DOTNET_(例如 DOTNET_AppDomainManagerAsm)

将GlobalManager.dll放进 .NET Framework 的核心目录里,例如C:\Windows\Microsoft.NET\Framework64\v4.0.30319,该路径下有几个常用的.NET 程序,例如MSBuild 和RegAsm 图片描述

和之前的环境变量设置方法有点不同,由于 DLL 就在路径里,不再需要版本号、Token 等复杂信息。

图片描述

设置好环境变量之后,可以看一下注册表HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment 验证一下 图片描述

环境变量的设置确实生效了,然后点击RegAsm.exe,通过火绒剑看到RegAsm.exe 打开了GlobalManager.dll,并执行了这个 dll 创建了success.txt 文档 图片描述

这与 DLL 劫持不同的是,这个是“一对多”的关系,即不仅是RegAsm.exe,此文件夹下的其他很多程序在运行时都会加载这个 dll。

利用 GAC 实现 AppDomainManager 注入,是指通过将具备强签名的恶意 DLL 植入受信任的系统GAC(全局程序集缓存),并配置特定的环境变量,可迫使 CLR 在启动任意 .NET 进程时,优先从 GAC 加载该恶意类并实例化为 AppDomainManager。此过程无需篡改合法宿主文件,即可在主程序代码执行前静默劫持控制流,实现高隐蔽、全局性的系统级权限驻留。

全局程序集缓存 (Global Assembly Cache, GAC) 是 .NET Framework 中的一个专用、系统范围的中央存储库,用于存储被多个应用共享的“强名称程序集”。它能解决版本冲突,节省磁盘空间,并支持强名称和数字签名验证。GAC 主要存在于 .NET Framework 环境中(例如 C:\Windows\assembly),在 .NET Core 及后续版本中已被弃用

有分析报告显示,在国内比较猖獗的银狐木马曾在攻击中使用这种技术。

打开 Visual Studio,新建一个 “类库 (.NET Framework)”,注意.NET 的版本,要与虚拟机中的.NET 版本保持一致,否则可能无法成功实现注入。

图片描述

然后编译生成文件GacInjectTest.dll 图片描述

GAC(全局程序集缓存)里面的 DLL 会被全系统所有的 .NET 程序共享调用,权限极高。在 Visual Studio 里做的这个“新建签名”操作,本质上就是利用非对称加密算法(RSA),给 DLL 盖上了一个独一无二的“加密防伪钢印”,这个在 .NET 术语中就叫 “强名称(Strong Name)”。

全世界可能有成千上万个程序员都写了一个名叫 Utils.dll 的文件。如果都塞进 GAC 里,系统就彻底乱套了。给程序集签名后,系统识别这个 DLL 就不再只看名字了,而是看它的 “四元组身份”:文件名 + 版本号 + 语言文化 + 公钥标记 (PublicKeyToken)

将 dll 注册到系统的 GAC 中,方便所有的 .NET 程序共享调用,可以通过在 Powershell 执行以下命令实现注册:

图片描述

注册完成之后,执行以下命令获取一下已注册 dll 的“四元组身份”:文件名 + 版本号 + 语言文化 + 公钥标记 (PublicKeyToken),方便后续的环境变量设置。

获取的文件“四元组身份”:GacInjectTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9416298015f19395

在 .NET 程序集的强名称中,Culture 指的是该程序集所包含的区域性(语言和区域)资源,它决定了程序集是主程序集还是附属(卫星)程序集。


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

最后于 2天前 被ZyOrca编辑 ,原因: 调整排版,修正错误
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回