APT41的Moonbounce恶意程序:潜入UEFI固件的深度威胁分析
· 3 分钟阅读 · @admin

1.1 APT41组织背景
APT41(也称为双龙、Winnti)是一个自2012年起就活跃至今的高级持续性威胁组织。该组织具有独特的双重运作模式,既执行国家支持的网络间谍活动,也从事经济利益驱动的网络犯罪行为。据安全研究机构观察,APT41已对全球14个国家和地区发起攻击,主要目标行业包括:
- 医疗保健行业
- 电信行业
- 科技行业
- 视频游戏行业
在经济利益驱动的攻击中,APT41特别关注视频游戏产业,其攻击手段包括窃取游戏源代码、盗取数字证书、操纵虚拟货币以及部署勒索软件等。
1.2 Moonbounce恶意程序简介
2022年初,卡巴斯基实验室披露了一个名为Moonbounce的复杂恶意程序,并将其归因于APT41组织。这是一起罕见的UEFI固件级攻击案例,具有以下显著特征:
持久性极强:Moonbounce通过修改UEFI固件中的DXE(Driver Execution Environment)驱动模块实现驻留。由于恶意代码位于主板固件而非硬盘,即使重装系统、格式化硬盘或更换硬盘,恶意程序仍能持续存在。
隐蔽性极高:修改后的DXE驱动能够劫持UEFI启动流程,建立复杂的多阶段感染链。整个攻击过程仅在内存中执行,不在硬盘上留下任何文件痕迹,使得传统的安全检测手段难以发现。
检测与清除困难:作为一种固件级Bootkit,Moonbounce的检测和清除难度极大,需要专业的UEFI固件分析工具和深入的技术知识。
2. 样本信息
本次分析涉及的恶意样本包括三个关键组件,它们共同构成了Moonbounce攻击链的核心部分。
2.1 被修改的UEFI DXE驱动
该文件是UEFI固件中被植入恶意代码的核心模块:
| 属性 | 值 |
|---|---|
| 文件名 | Core_dxe |
| MD5 | 2d4991c3b6da35745e0d4f76dffbca56 |
| 文件类型 | EFI_BOOT_SERVICE_DRIVER |
2.2 内核模式驱动程序
该驱动被映射到Windows内核内存空间中执行,负责监控模块加载并实施后续注入:
| 属性 | 值 |
|---|---|
| MD5 | 2ce20fbf09f74a819486a7815ae8e47d |
| 文件类型 | Kernel driver |
2.3 恶意DLL载荷
通过APC注入技术加载到svchost.exe进程中的最终载荷:
| 属性 | 值 |
|---|---|
| MD5 | bcf786ac5cfe3b6e9ceacc6733827355 |
| 文件类型 | DLL |
| 特征 | 使用MPRESS加壳 |
3. 攻击流程概览
下图展示了Moonbounce的完整攻击流程,从UEFI固件层面到最终载荷执行的各个阶段:

4. 技术细节分析
4.1 UEFI启动流程基础
4.1.1 正常启动流程
要理解Moonbounce的攻击机制,首先需要了解UEFI的正常启动流程。UEFI启动操作系统的过程可以分为以下几个关键阶段:
- SEC(Security)阶段:初始化临时内存存储,为后续阶段提供基础环境
- PEI(Pre-EFI Initialization)阶段:完成CPU和芯片组的初始化,加载UEFI平台核心模块
- DXE(Driver Execution Environment)阶段:UEFI Boot Manager枚举外部设备,加载各种UEFI设备驱动程序
- BDS(Boot Device Selection)阶段:选择启动设备,加载Boot应用程序
- TSL(Transient System Load)阶段:Windows Boot Manager(bootmgfw.efi)加载Windows Boot Loader
- RT(Runtime)阶段:Windows Boot Loader将控制权移交给Windows操作系统内核

<center>图1 - UEFI启动流程(来源:《Rootkits and Bootkits》)</center>
4.1.2 常见的UEFI Bootkit攻击点
图1中标记箭头的位置展示了UEFI固件Bootkit的常见攻击点,攻击者通常会选择以下几种方式植入恶意代码:
- 修改未签名的UEFI Option ROM:在Option ROM中嵌入恶意DXE驱动,使其在DXE阶段被执行
- 修改或添加UEFI固件中的DXE驱动:直接篡改固件中已有的DXE驱动,或添加新的恶意DXE驱动(Moonbounce采用此方式)
- 替换Windows Boot Manager:篡改bootmgfw.efi,在UEFI将控制权移交给系统引导程序时劫持执行流程
- 添加恶意Bootloader:在启动设备列表中插入恶意引导程序
4.2 CORE_DXE恶意驱动分析
4.2.1 驱动基本信息
通过分析PE文件结构,可以确认Core_dxe的subsystem字段为“EFI_driver_boot_service”,表明这是一个64位的UEFI DXE驱动程序。

时间戳分析:该DXE驱动的编译时间为2014年,直到2022年1月才被卡巴斯基实验室曝光。长达近8年的潜伏期充分体现了该恶意程序极强的隐蔽性和持久性。

目标平台识别:在Core_dxe中发现字符串常量“E7846IMS.M30”,这表明该驱动针对的是MSI(微星)公司的硬件平台,对应的UEFI固件文件名为E7846IMS.M30。通过对比原始的合法DXE驱动与被修改的恶意版本,发现两者高度相似,仅在三个关键函数中存在恶意Hook代码。

4.2.2 EFI_BOOT_SERVICE Hook技术
Moonbounce采用了精确的函数Hook技术,针对EFI_BOOT_SERVICE结构体中的三个关键函数实施内联Hook:
- coreAllocatePool:用于分配内存空间,存储后续要映射的Windows内核驱动Shellcode
- coreCreateEventEx:创建传统启动方式(Legacy Boot)事件,将恶意Shellcode设置为事件回调函数
- ExitBootService:对Windows内核函数OslArchTransferToKernel实施Hook

Hook实现机制:恶意代码采用内联Hook(Inline Hook)技术,将被Hook函数的头部修改为跳转指令,使其跳转到统一的Hook处理函数hook_dxe_code。所有三个被Hook函数都会跳转到同一个处理函数。

这种设计确保了恶意代码能够在系统启动的关键时刻获得执行机会,为后续的感染链建立基础。
4.2.3 CoreAllocatePool函数详细分析
调用链分析:DXE驱动的入口点函数为ModuleEntryPoint,在创建全局结构体gDxeCoreST和gDxeCoreRT并为其分配内存时,系统会调用AllocateRuntimeCopyPool函数。

进一步分析发现,AllocateRuntimeCopyPool函数内部会调用coreAllocatePool函数来执行实际的内存分配操作。

Hook触发机制:由于coreAllocatePool函数已被恶意代码Hook,当系统调用该函数时,控制权会转移到hook_dxe_code函数。Hook处理逻辑如下:
- 恢复函数Prologue:首先恢复被修改的函数原始字节码
- 调用原始函数:此时RAX寄存器指向未被Hook的原始
coreAllocatePool函数,使用call eax指令调用原函数 - 内存分配用途:分配的内存用于存储映射Windows内核驱动的Shellcode
Magic Number替换机制:Hook代码会巧妙地利用Magic Number进行地址替换:
rbx+0xB3地址对应coreAllocatePool函数的第三个参数位置- 内存分配成功后,该地址会被覆盖为实际分配的内存地址

具体来说,地址0x1801577EB处的Magic Number 0x1122334455667788被替换为刚刚分配的内存地址。
![]()
Shellcode地址修正:地址0x180157996(标记为shellcode_1)处的Shellcode第一条指令也包含相同的Magic Number,同样被替换为新分配的内存地址,确保后续代码能够正确引用分配的内存区域。
![]()
4.2.4 CoreCreateEventEx函数分析
Hook处理流程:当系统调用被Hook的coreCreateEventEx函数时,恶意代码会按照以下步骤执行:
- 恢复函数Prologue:首先恢复函数被修改的原始字节码
- 调用原始函数:调用原始的
coreCreateEventEx函数创建一个针对EFI_EVENT_Legacy_BOOT的事件 - 设置恶意回调:将地址
0x1801577E7处的Shellcode设置为该事件的回调函数

执行路径差异:恶意代码根据系统的启动方式选择不同的执行路径:
- 传统启动方式(Legacy Boot):当系统使用传统启动方式时,直接通过事件回调执行地址
0x1801577E7处的Shellcode,该Shellcode负责映射并执行恶意驱动 - UEFI启动方式:当系统使用UEFI启动方式时,需要执行额外的准备工作,确保恶意代码能够在正确的时机获得执行机会

这种设计使得Moonbounce能够适应不同的启动环境,确保在各种系统配置下都能成功执行恶意载荷。
4.2.5 CoreExitBootServices函数分析
Hook处理步骤:当系统调用被Hook的CoreExitBootServices函数时,恶意代码的执行流程如下:
- 恢复函数Prologue:首先恢复被修改的函数原始字节码
![]()
-
定位并修改关键指令:恶意代码会搜索
OslArchTransferToKernel函数的尾部指令,寻找特定的字节序列0xCB485541,该序列对应的汇编指令为push r13和retfq -
指令劫持:将找到的
retfq指令修改为跳转指令jmp 0x98000,使得当OslArchTransferToKernel函数执行完毕准备返回时,控制权会转移到地址0x98000处

这种技术巧妙地劫持了UEFI与Windows启动流程之间的关键转换点,为后续在内核层面的恶意代码执行奠定了基础。
4.2.6 OslArchTransferToKernel函数分析
函数作用:OslArchTransferToKernel函数是Windows启动过程中的关键函数,其正常功能是将控制权从Windows Boot Manager(winload.exe或winload.efi)交接给Windows内核入口点KiSystemStartup,在这里进行内核的初始化工作。
劫持机制:由于前一步骤中该函数的返回指令已被恶意代码修改,当内核初始化完成准备返回时,程序会跳转到地址0x98000处执行恶意Shellcode。
Shellcode功能分析:地址0x98000处的Shellcode主要执行以下操作:
- 定位内核模块:查找
ntoskrnl.exe模块的基地址,并将其保存到全局变量g_ntoskrnl_exe_image_base中 - 部署第二阶段Hook:将地址
0x18015791C处的Shellcode拷贝到ntoskrnl.exe的重定位表区域 - 内联Hook ExAllocatePool:对
ExAllocatePool函数实施内联Hook,使其跳转到标记为shellcode2_hook的恶意代码

API定位技术:在x64_Search_Ntoskrnl_Export函数中,恶意代码使用Hash值来查找ntoskrnl.exe导出的三个关键API函数,这种技术可以避免在内存中直接出现API函数名字符串,增加检测难度。

内存权限修改:由于恶意代码需要向ntoskrnl.exe内存空间写入Shellcode或修改代码,因此必须将相关内存段的属性修改为可写(Writeable)。

动态地址修正:在运行时,Magic Number会被动态修改为第一阶段使用coreAllocatePool分配的内存地址。然后使用x64_MmMapIoSpace函数将该Shellcode映射到Windows内核内存空间并执行。

最终载荷加载:恢复ExAllocatePool函数的原始Prologue后,恶意代码加载并执行内核驱动程序的入口点,完成从UEFI固件到Windows内核的完整感染链。

这一系列复杂的技术手段展示了Moonbounce攻击链的精密设计,从UEFI固件层面开始,逐步劫持系统启动流程,最终在Windows内核中执行恶意代码。
4.3 内核驱动加载机制
恶意代码使用load_driver函数将恶意内核驱动(malicious_driver)动态加载到Windows内核内存空间中,这个过程完全在内存中完成,不涉及任何文件操作。
4.3.1 内存分配
步骤1:调用ExAllocatePool函数分配足够大小的连续内存空间,该内存区域将用于映射完整的恶意驱动程序。

4.3.2 PE文件结构映射
步骤2 - 拷贝PE头部:将恶意驱动的PE文件头部数据(包括DOS头、NT头、可选头等)拷贝到分配的内存区域中。

步骤3 - 拷贝区段数据:根据PE文件中的区段表(Section Table),将各个区段(如.text、.data、.rdata等)的数据拷贝到内存中对应的偏移位置。

4.3.3 驱动程序修复
步骤4 - 重定位修复:由于驱动程序被加载到非原始基址的内存位置,需要根据重定位表(Relocation Table)修复所有绝对地址引用,确保代码和数据的正确访问。

4.3.4 导入函数解析
步骤5 - 导入表解析:恶意代码需要解析驱动程序的导入表,获取所需Windows内核API函数的实际地址:
- 使用
RtlInitAnsiString和RtlAnsiStringToUnicodeString将API函数名转换为Unicode字符串 - 调用
MmGetSystemRoutineAddress函数获取对应内核API的实际地址 - 将获取的函数地址写入导入函数地址表(IAT)中

4.3.5 驱动执行
步骤6 - 入口点调用:从PE文件的可选头中获取驱动程序的入口点地址(DriverEntry),然后调用该函数正式启动恶意驱动程序。

这种完全在内存中进行的驱动加载技术避免了传统的文件系统操作,极大地增强了恶意程序的隐蔽性,使得传统的安全检测手段难以发现其存在。
4.4 内核驱动功能分析
4.4.1 模块加载监控
恶意驱动的入口点DriverEntry函数调用了PsSetLoadImageNotifyRoutine内核API,建立模块加载通知回调机制。这意味着每当系统中有新的模块被加载时,恶意驱动的回调函数NotifyRoutine都会被自动执行。

目标识别机制:在回调函数中,恶意代码会检查以下条件来确定是否执行攻击:
- 模块检查:判断正在加载的模块是否为
kernel32.dll - 进程检查:判断加载该模块的进程是否为
svchost.exe,且命令行参数包含-k等特征
选择原因:恶意代码需要利用kernel32.dll导出的API函数来将PE文件映射到内存中,因此必须等待kernel32.dll在目标进程中成功加载。

4.4.2 APC注入机制
内核APC初始化:恶意代码创建一个结构体作为内核APC(Asynchronous Procedure Call)回调函数kernelRoutine的参数,这个结构体包含了注入过程中所需的各种信息。

工作队列机制:在内核APC回调函数kernelRoutine中,恶意代码会:
- 初始化传递给用户模式回调函数所需的参数
- 创建Work Item并将其插入系统工作队列中
- 等待系统工作线程执行该Work Item
4.4.3 用户模式Shellcode注入
用户APC创建:在Work Item的回调函数中,恶意代码会创建用户模式APC,用于向目标svchost.exe进程注入Shellcode。KeInitializeApc函数的关键参数包括:
- 第6个参数:要注入的Shellcode,即加载恶意DLL的代码
- 最后一个参数:指向数据结构的指针,包含了加载DLL时所需的各种数据,如API地址、恶意文件信息等

注入技术优势:这种多层级的APC注入技术具有以下特点:
- 隐蔽性强:通过内核级API实现注入,避免了传统的用户模式注入手段
- 时机精确:等待特定模块加载完成后再执行,确保注入成功率
- 绕过检测:利用系统正常的APC机制,难以被安全软件检测和拦截
这种复杂的注入机制确保了恶意DLL能够在目标进程中成功加载并执行,完成Moonbounce攻击链的最终阶段。
4.5 最终载荷DLL分析
4.5.1 加壳与脱壳分析
通过对恶意DLL文件进行分析,发现其使用了MPRESS壳进行压缩保护。MPRESS是一种常用的可执行文件压缩工具,可以有效减小文件体积并增加静态分析的难度。

经过脱壳处理后,可以清楚地看到DLL的核心代码逻辑。
4.5.2 核心功能分析
主要功能:脱壳后的代码分析显示,该恶意DLL的主要功能是文件下载,这是Moonbounce攻击链的最终载荷执行阶段。
下载机制:文件下载功能的核心代码使用了网络API来从远程服务器获取文件。下载链接通过DLL入口点DllEntryPoint的第三个参数传递给恶意代码。

C2服务器信息:分析中发现的下载链接为hxxp://mb.glbaitech.com/mboard.dll。这个链接现在可能已经失效,推测原因包括:
- 时间因素:Moonbounce恶意程序从2014年开始潜伏,到2022年被发现时已经过了8年时间,C2服务器可能早已停止服务
- 攻击响应:在安全研究人员曝光该攻击后,攻击者可能主动关闭了C2基础设施
- 域名过期:相关域名可能因为各种原因已经过期或被注销
攻击目的:通过分析这个最终的下载行为,可以看出Moonbounce的主要目的是建立持久的后门访问能力,允许攻击者根据需要下载和执行更多的恶意载荷,从而实现对被感染系统的长期控制。
5. 威胁指标(IOC)
以下是与Moonbounce攻击相关的威胁指标,可用于检测和防御:
5.1 网络指标
C2服务器URL:
hxxp://mb.glbaitech.com/mboard.dll
5.2 文件哈希值(MD5)
被修改的UEFI DXE驱动:
2d4991c3b6da35745e0d4f76dffbca56
内核模式驱动程序:
2ce20fbf09f74a819486a7815ae8e47d
恶意DLL载荷:
bcf786ac5cfe3b6e9ceacc6733827355
5.3 检测建议
组织和安全团队可以使用上述IOC进行以下安全检测:
- 网络监控:在网络流量中搜索与C2服务器相关的通信
- 固件扫描:使用专业的UEFI固件分析工具检查是否存在异常修改
- 哈希匹配:将系统中的驱动和DLL文件与已知恶意哈希值进行对比
- 行为监控:监控svchost.exe进程的异常加载和注入行为
6. 参考资料
本分析报告参考了以下高质量的安全研究资源:
-
Binarly深度分析报告 “A deeper UEFI dive into MoonBounce” 提供了关于Moonbounce UEFI固件层面的深入技术分析
-
卡巴斯基实验室威胁报告 “MoonBounce: the dark side of UEFI firmware” 首次公开披露Moonbounce恶意程序的安全研究报告
-
技术参考书籍 《Rootkits and Bootkits》 深入讲解UEFI/BIOS Rootkit和Bootkit技术的权威参考书籍
7. 总结与防护建议
7.1 攻击链总结
Moonbounce代表了固件级恶意程序的高级形态,其攻击链可以总结为以下关键阶段:
- UEFI固件植入:修改MSI主板的UEFI固件中的Core_dxe驱动
- 启动流程劫持:在DXE阶段Hook关键EFI_BOOT_SERVICE函数
- 内核层渗透:通过多阶段Shellcode在Windows内核中建立立足点
- 驱动映射加载:在内存中映射并执行恶意内核驱动
- 用户态注入:通过APC机制向svchost.exe进程注入恶意DLL
- 远程载荷下载:从C2服务器下载额外的恶意载荷
7.2 技术特点
Moonbounce展现了APT41组织在固件级攻击方面的高超技术能力:
- 极强的持久性:位于固件层面,不受操作系统重装和硬盘更换影响
- 高度的隐蔽性:完全在内存中执行,不在硬盘留下文件痕迹
- 精密的设计:多层级的Hook和注入机制,充分利用系统正常功能
- 广泛的兼容性:同时支持传统启动和UEFI启动方式
7.3 防护建议
面对此类固件级威胁,建议采取以下防护措施:
7.3.1 预防措施
- 启用安全启动(Secure Boot):防止未签名的固件修改被执行
- 固件更新管理:仅从官方渠道获取固件更新,验证数字签名
- 访问控制加强:限制对UEFI固件的写入权限,需要多重认证
- 网络隔离:对关键系统实施网络分段,限制异常外联行为
7.3.2 检测措施
- 固件完整性检查:定期使用工具检测UEFI固件是否被篡改
- 行为监控:监控异常的内核驱动加载和进程注入行为
- 网络流量分析:检测与已知C2服务器的通信
- IOC匹配:使用本文提供的威胁指标进行扫描
7.3.3 响应措施
如果发现系统感染Moonbounce或类似固件级恶意程序:
- 隔离受感染系统:立即断开网络连接,防止横向移动
- 专业固件恢复:联系硬件厂商,重新刷写官方固件
- 全面安全审计:检查网络中其他系统是否受到影响
- 事件溯源分析:分析攻击者的初始入侵路径,修复安全漏洞
Moonbounce的出现提醒我们,网络安全防护不能仅关注操作系统和应用层面,固件层的安全同样至关重要。只有建立多层次、全方位的安全防护体系,才能有效应对日益复杂的高级持续性威胁。

