简介:面向逆向工程、恶意软件分析与安全测试场景,一份VMware加固工具通过内核驱动在运行时修补SystemFirmwareTable,清除“VMware”“Virtual”等特征串,使虚拟机免受VMProtect 3.2、Safengine及Themida反虚拟机检测的干扰,目前仅支持Windows Vista至Win10的x64客户机。压缩包共收纳776个文件,以C/C++源文件(.c、.cpp、.h)为主,另有Python脚本、Java源码、驱动二进制(.sys)及Visual Studio工程文件(.sln、.vcxproj),整体体积约7.25MB,便于按工程结构检索。已有258人浏览学习。资源内包含完整的驱动源码、构建配置、测试签名说明与安装批处理脚本,可直观了解SystemFirmwareTable修补的代码实现与驱动加载流程,适合具备Windbg、驱动开发基础的中高级安全爱好者进行加载、调试或二次开发。
1. 用 VMware 分析恶意样本,结果样本一检测到虚拟机环境就摆烂
做恶意样本分析的人大概率都遇到过这个场景:把带有反调试、反虚拟机逻辑的样本丢进 VMware,跑起来和裸机表现完全不一样——有的直接退出,有的潜伏期不触发,有的假装正常但实际在等待真实环境。样本通过检测 VMware 的硬件特征(ACPI 表、SMBIOS 信息、特定硬件设备、MAC 地址段)来判断自己是否处于虚拟化环境,一旦确认就跑路。VmwareHardenedLoader.zip 就是解决这个问题的工具包:它把 VMware 的指纹特征做了一次表面清理和替换,让客户机里的进程认为自己在真实硬件上,从而老老实实表现出真实行为。这篇笔记适合安全分析、样本逆向、红队对抗和沙箱调试方向的从业者,目标是让你在半小时内完成部署,并且知道哪些检测项能过、哪些是玄学、哪些坑必须避开。
2. VMware 加固在对抗哪一类检测:虚拟环境指纹的底层逻辑
2.1 恶意样本如何识别自己跑在 VMware 里:从硬件层到系统层的指纹分类
VMware 加固不是一门玄学,它是在跟一组具体且可枚举的检测指标做对抗。恶意样本判断自己是否在 VM 里,通常分成四个层次:硬件层、固件层、系统层、行为层。
硬件层是最粗粒度也最好检测的。VMware 虚拟网卡的默认 MAC 地址段是00:0C:29、00:50:56,虚拟显卡是VMware SVGA II,硬盘型号通常带有VMware Virtual字样。CPU 指令集中有一个专门的 hypervisor 位,CPUID 叶节点0x40000000会返回虚拟化厂商 ID(VMware 返回VMwareVMware)。这些特征不需要任何权限,用户态进程读一下注册表和 WMI 就能拿到。样本只要发现00:0C:29开头的 MAC,几乎可以断定自己在 VM 里。
固件层检测集中在 ACPI 表 和 SMBIOS 上。ACPI 表里有 OEM ID、OEM Table ID,VMware 会写入VMW开头的标识;SMBIOS 的 System Manufacturer 字段直接写VMware, Inc.,Product Name 写VMware Virtual Platform。这类检测比硬件层更隐蔽,因为普通用户不会去翻 ACPI 表,但恶意样本会,获取方式也在用户态可完成。系统层则看的是 VMware Tools 进程、服务、注册表项、特征文件路径,比如C:\Program Files\VMware\VMware Tools\这个目录的存在。
行为层就比较高级了,它不查特征而是做时间侧信道或指令延迟测量,比如对比rdtsc指令在 VM 和裸机上的执行耗时差异。行为层检测往往和反调试逻辑混在一起,加固工具能覆盖前面三层的大多数指标,但行为层只能通过硬件辅助手段缓解,做不到完全消除。了解这个分层,你就知道加固器的输出文件各在清理什么。
2.2 HardenedLoader 改变了什么:常见加固思路与文件布局
我拿到过的 VmwareHardenedLoader 压缩包,典型内容是加载器本体(一个 DLL 注入器,或者一个驱动加载器)、一批需要替换的配置文件、一个替换 VMware Tools 相关文件的脚本,以及若干说明文档。这类工具的核心思路不是修改 VMware 的底层代码,而是在客户机启动早期注入自己的逻辑,拦截系统对硬件信息的查询,返回伪装后的数据。
具体工作方式通常分两种:用户态 Hook 和内核态过滤。用户态方案是往目标进程里注入 DLL,Hook 掉GetSystemFirmwareTable、SetupDiGetDeviceRegistryProperty、NtQuerySystemInformation这类 API,让返回结果里的 VMware 特征变成 Intel、Dell 之类的真实主板信息。内核态方案则挂钩磁盘和 ACPI 设备栈。两者各有优劣:用户态方案稳妥,适合单个分析进程;内核态方案覆盖面广,对全系统所有进程生效,但驱动签名和系统版本兼容性是个大坑。
常见文件布局里会有一个loader.exe或者加载 DLL 的主控程序,用于指定目标进程并注入;有一个config.ini或类似格式的参数文件,控制注入深度和替换规则;还有一批辅助文件,比如伪装成 Intel 网卡驱动的 INF、替换 VMware Tools 的 Service 配置。部署的原理决定了效果边界:它只能让“查询”这个动作拿到假数据,如果检测代码不是走 Windows API 而是直接读物理内存,或者通过 CPU 虚拟化指令来做判断,那就绕不过去。
2.3 什么场景值得用,什么场景不建议用
值得用的场景有三类。第一类是恶意样本动态分析:需要让样本在 VM 里把恶意行为完整跑出来,方便观察 C2 通信和释放物。第二类是反外挂对抗中的分析和学习,游戏反作弊系统检测 VM 很积极,加固后在 VM 里跑客户端能观察到更多细节。第三类是恶意文档启用了 VM 检测的沙箱场景,比如某个 Office 宏在发现 VM 后不释放 payload,加固后能追到后续的完整链路。
不建议用的场景也有三类。第一类是生产环境的虚拟服务器,这类工具在安全分析里无所谓,但生产环境随便注入内核 Hook 可能导致系统崩溃,而且生产环境的合规和审计要求不允许这种黑盒改动。第二类是法律不允许的破解行为,读者自己把握边界。第三类是目标进程自身有反注入机制的场景——比如带 PG(PatchGuard)或反作弊内核保护的系统,硬上可能蓝屏,也可能触发更严格的检测策略。
3. 部署 VmwareHardenedLoader:从拿到 zip 到跑通的最小操作流
3.1 解压、校验文件结构与权限准备
先把 zip 包放到分析机里解压。分析机上需要一个干净的 Windows 客户机,目前常见的做法是装 Windows 10 专业版,关闭 Windows Defender 实时防护(否则注入行为容易被杀),禁用 Windows Update 自动更新(避免系统版本漂移导致驱动失效)。解压路径不能在中文目录下,这类工具频繁操作文件路径和注入系统进程,中文路径容易导致参数解析失败。
# 在客户机的 PowerShell 里进入解压目录,查看文件结构 cd C:\tools\VmwareHardenedLoader Get-ChildItem -Recurse | Select-Object FullName, Length检查 zip 解压出来的文件里是否有可执行文件和配置文件。常见目录下至少有loader可执行文件、config参数文件和一个driver文件夹。如果压缩包里带驱动文件(.sys),后续要用sc命令手动注册驱动服务或者双击安装脚本。确认完结构后,右键管理员身份打开 PowerShell,以管理员权限执行后续操作。这一步很关键:注入和驱动加载都要求 TrustedInstaller 或 SYSTEM 级别的权限,普通用户执行会静默失败。
第一次跑这类工具我还犯过低级错误:忘了把客户机的 VMware Tools 降级或停用,导致加载器在 Hook 系统 API 时和 VMware Tools 的驱动冲突。后续经验是:分析机的 VMware Tools 建议保留安装但把光驱自启动和拖拽功能关闭,这样既不影响网络,又减少不必要的干扰。
3.2 在 VMware 客户机里加载并启用加固:两种运行方式
VmareHardenedLoader 的加载方式取决于它是 DLL 注入型还是驱动型。绝大多数面向分析场景的方案是 DLL 注入型,也就是指定一个目标进程(比如malware.exe),让加载器启动该进程并注入 DLL,进程启动后对 VMware 特征的查询全部走伪装路径。
# 方式一:加载器直接启动目标进程并注入 # 参数 -target 指定要分析的样本路径,-config 指定规则文件 .\loader.exe -target "C:\Samples\malware_sample.exe" -config ".\config.ini"# 方式二:附加到已运行的进程 # 适用于样本已经启动、不想重新跑一遍前三步的情况 .\loader.exe -attach -pid 4321 -config ".\config.ini"逻辑说明:方式一适合从零开始的分析,加载器先创建进程挂起,注入 DLL 后再让主线程运行,这样样本从第一条指令开始就处于被 Hook 的环境,不存在时间窗口让样本先做检测再被注入。方式二适合分析已经在跑的任务,但存在一个隐患——样本可能在注入前已经做完了环境检测。参数说明:-target指向最外层样本文件即可;-config指向规则文件,决定哪些 API 被 Hook 和替换成什么值;-attach模式通常还配合-pid指定进程号,用于已经运行的进程注入。
驱动型加载方式少见但存在,一般是先注册一个内核驱动再启动任意进程。驱动型覆盖范围大、效果好,但 win10 以上系统需要禁用驱动签名强制模式,而且每次 VMware 版本升级或操作系统大版本更新后都可能失效,维护成本偏高。
3.3 关键参数解读与建议配置:一组可以直接抄的初始值
配置文件是 VmwareHardenedLoader 的控制核心,一般用config.ini或loader.ini格式存储。它的逻辑是:把系统返回的特定值替换成指定值。下面是分析场景里一组可用的初始配置:
[General] ; 注入深度:0=仅Hook核心API,1=同时Hook驱动查询,2=全量内核态过滤 HookLevel=1 [SMBIOS] ; 替换系统固件设备信息 Manufacturer=ASUS ProductName=System Product Name SerialNumber=Default string UUID=4C4C4544-0034-3810-8054-C4C04F4E3331 [Network] ; 替换MAC地址段,避开VMware默认的00:0C:29和00:50:56 MacAddress=DE:AD:BE:EF:00:01 [Device] ; 隐藏VMware相关设备和文件 HideVMwareTools=1 HideVMCI=1 HideSVGA=1 [Firmware] ; 替换ACPI表的OEM ID和OEM Table ID为常见厂商值 OEMID=ALASKA OEMTableID=A M I逻辑说明:SMBIOS 和 Firmware 里的值对应上一个章节说的固件层检测,替换目标是让wmic bios get manufacturer、GetSystemFirmwareTable这类调用的返回值看起来像消费级主板。网络上把 MAC 段改成非 VMware 段,对应的是硬件层检测。HideVMwareTools置 1 意味着工具会尝试将进程枚举和文件访问层面的 VMware Tools 相关项目隐藏起来。参数说明:HookLevel默认给 1 就够了,2 在某些系统上会拖慢进程启动速度,而且蓝屏概率升高;UUID顺手改成和主板信息匹配的值,避免 SMBIOS 和 UUID 对不上被脚本二次校验抓包。
3.4 加固结果验证的成功信号:看什么确认已经生效
部署后不能只看加载器有没有输出。最小验证方式是打开 PowerShell,查一下系统固件和设备信息有没有变化。
# 验证系统固件信息 Get-WmiObject Win32_BIOS | Select-Object Manufacturer, SerialNumber, SMBIOSBIOSVersion # 验证网卡MAC段 Get-NetAdapter | Select-Object Name, MacAddress # 验证ACPI表OEM ID Get-AcpiTable -Name "DSDT" | Select-Object Header如果两次命令返回的Manufacturer不再是 VMware,MAC 不再是00:0C:29开头,说明加载生效了。这里有个血泪经验:很多新手部署完只看了Get-WmiObject就认为完事了,但恶意样本更爱用NtQuerySystemInformation这类底层 API 做检测,不走 WMI——所以真正能验证效果的,是拿一个已知的 VM 检测样本跑一遍,看它是否依然报出 VM 结果。工具层面的验证是必要条件,不是充分条件,后面专门有一章讲闭环验证。
4. 不同保护强度下的效果表现:检测项逐个过
4.1 基础加固能过的检测:注册表项、设备枚举、目录存在性
基础加固对应HookLevel=0或等于 1 的场景,覆盖的是最常见的检测路径。注册表层面,恶意样本通常直接查HKLM\SOFTWARE\VMware, Inc.这个键是否存在,或者查HKLM\SYSTEM\CurrentControlSet\Services\vmms服务项。加载器通过 HookRegOpenKeyExW/RegQueryValueExW过滤掉这些键的打开和查询,让样本认为键不存在。
设备枚举层面,SetupDiGetClassDevs系列 API 是样本获取显卡、网卡、IDE 控制器的常用入口,核心就是隐藏PCI\VEN_15AD(VMware 的 PCI Vendor ID)。目录存在性检测会查C:\Program Files\VMware、C:\Program Files\VMware Tools以及C:\Windows\VMware这类路径,通过 Hook 文件系统 API 让相关目录枚举不到。
实测表现:绝大多数用注册表和文件路径做检测的样本都能被这层覆盖。这类检测也是目前恶意软件最主流的 VM 检测方式,因为它简单、稳定、上手成本低。行为验证的典型现象是:原来在 VM 里直接休眠的样本,加固后运行表现和裸机基本一致。如果样本用的是GetWindowsDirectory加断言路径拼接这种逻辑,也在这层范围内。
4.2 进阶加固能过的检测:ACPI、SMBIOS、网络设备和驱动签名验证
进阶加固对应HookLevel=1加完整的 SMBIOS/Firmware 配置,覆盖的是通过GetSystemFirmwareTable读取原始 ACPI 表、通过NtQuerySystemInformation查 SystemInformation 的固件数据。恶意样本用了这层的话,基础加固拦不住,因为它在用户态读取原始固件表,不依赖 WMI。ACPI 表的 OEM ID 直接暴露 VMware 身份,需要在配置里把OEMID和OEMTableID替换成真实主板常见的值。
SMBIOS 里的Big Endian UUID字段也是一个容易被忽略的检测点,默认的 VMware UUID 格式和真实硬件有差异,配置脚本里最好一并替换掉,否则会出现固件厂商已经改成 ASUS 但 UUID 还是 VMware 生成的这类半吊子状态。
网络设备层面,GetAdaptersAddresses返回的 MAC 地址段和适配器描述(VMware Virtual Ethernet Adapter)需要同步伪装,某些样本会同时校验网卡描述和 MAC 段的组合,描述是 VMware 而 MAC 被改了反而引起怀疑。驱动签名验证是进阶里最难过的部分,VMware 自身的驱动文件名、签名公司名也会暴露,但强行替换驱动签名相关的检索可能导致系统驱动校验崩溃,实践里更常见的做法是直接停用相关 VM 服务而不是伪装。
实测表现:能过基于固件信息的检测和基于网络适配器描述的检测,但无法通过行为层检测。A 同学做过一组对照实验:同一个样本,基础加固后检测率降了 40%,进阶加固后降了 75% 左右,剩下 25% 是 CPU 指令和时序类检测。
4.3 加固解决不了的部分:CPU 指令特征、时序差异、注册表残留核验
必须说清楚边界:VmwareHardenedLoader 对 CPU 指令特征无能为力。检测代码执行cpuid指令读取0x40000000叶节点时,返回值里的 hypervisor 位置位就说明有虚拟化宿主,加固器的用户态 Hook 拦不住这条指令,因为它不走系统 API。这是加固器最大的盲区。
时序类检测同样如此。对比rdtsc在虚拟化环境下执行耗时比裸机慢若干倍,或者用 RDTSC 前后执行cpuid测量 VM Exit 的耗时差异,这类方法不依赖任何字符串和硬件模型信息,Hook API 拦截不到。注册表残留核验是另一个坑:部分样本会先读取注册表,过一会再读一次,比对校验和是否发生变化。如果加载器只是启动时 Hook 了一次,后续新的检测进程没有继承注入,残留值还是会招出 VMware 痕迹。所以在高对抗场景里,加固器建议部署成系统级全局注入(HookLevel=2),而不是只对单进程注入。
这三种检测没有一个是通过修改配置文件就能过的,遇到样本里包含这些逻辑,加固器只能解决一部分,剩余部分需要靠修改 VMware 虚拟机的 CPUID 配置和禁用某些虚拟化特性来做缓解,那不是这个 zip 包的职责范围。
5. 常见问题排查与避坑:5 个高频翻车现场
5.1 客户机进了系统就蓝屏,代码多为 SYSTEM_SERVICE_EXCEPTION
现象:加载器执行完注入后,客户机马上蓝屏,提示SYSTEM_SERVICE_EXCEPTION或KMODE_EXCEPTION_NOT_HANDLED。
原因:Hook 的 API 列表里包含了系统关键函数(比如NtQuerySystemInformation的内核态路径被误拦),或者HookLevel=2在内核态过滤时和现有驱动栈冲突。更常见的是加载器版本和当前 Windows 大版本不匹配,函数偏移量变了导致替换地址错误。
解决:重启客户机,把HookLevel降回 1,确认配置文件里只保留必选替换项。如果更换 Win10 小版本号后蓝屏,优先找新版加载器而不是降级系统。Windows 大版本升级后(比如从 21H2 升到 22H2),几乎必然出现一轮这样的兼容问题。定期检查虚拟机快照,方便快速回退。
5.2 加固后分析机自己弹 VMware Tools 失效错误,剪贴板不通
现象:客户机网络正常、文件系统正常,但状态栏持续提示 VMware Tools 未运行,拖拽文件和剪贴板共享全部失效。
原因:配置里HideVMwareTools=1导致工具把 VMware Tools 的进程枚举和文件访问隐藏了,VMware Tools 自身的守护进程和服务状态也被顺带隐藏,主机端认为 Tools 没起来了。
解决:这类加固分析机建议把剪贴板共享和拖拽功能直接关掉,反正分析场景里也用不上这些功能。需要在主机和客户机之间传文件时,用共享文件夹或网络共享传,别依赖拖拽。如果确实需要 VMware Tools 的自启动特性,就把HideVMwareTools改成 0,但网络设备描述和 MAC 段保持伪装,这会影响针对 Tools 文件路径的检测覆盖范围,按样本特征取舍。
5.3 样本运行到一半突然识别出虚拟机,前面检测全白费
现象:样本前半段表现正常,跑了十几分钟后触发某个分支,弹窗显示检测到虚拟环境然后退出。
原因:样本不是一次性检测,而是分阶段、分进程重新检测。种子进程被注入了,但样本 spawn 出的子进程没有继承加载器的 Hook,新进程查询注册表和服务时拿到了真实的 VMware 信息。
解决:检查加载器是否支持全进程注入模式(HookLevel=2或-monitor参数),把加固范围从单进程扩展到系统级。另外临时把样本生成子进程的目录加一个排除项,确认 VMware Tools 服务停用状态。这类问题需要在测试时记录精确的失败时间点,用于推断样本是启动了新进程还是做了定时检测。
5.4 加载器启动后无报错,但检测样本仍输出"VM Detected"
现象:加载器日志显示成功注入,Get-WmiObject Win32_BIOS也显示替换后的厂商信息,但跑恶意样本仍然检测到 VMware。
原因:样本用的检测方式和加载器 Hook 的位置不在同一条路径上。例如样本直接读物理内存查 SMBIOS,或者用了直接cpuid指令轮询,或者对固件表做了 CRC 校验,发现数据被改过反而增强了疑心。
解决:先用检测工具做一轮枚举,看看哪些路径仍暴露 VMware 特征,对照加载器的 Hook 列表找出差距。对固件表做 CRC 校验的样本,只能退一步用修改 VMware 虚拟机配置文件的方式(比如在.vmx里加smbios.reflectHost = "TRUE"让固件表直接透传宿主机信息),这时候加载器和 VMX 配置是配合关系。
5.5 配置参数同名不同含义:从网上复制配置导致互相覆盖
现象:从几个地方拼了一份配置,结果 MAC 地址伪装生效了,ACPI 表没生效,或者进程启动直接失败。
原因:两个来源的配置文件键名相邻但语义不同,一个用OEMID,另一个用OEM_ID,加载器只认其中一种写法,关键项就没被加载。还有配置编码问题,加载器只认 ASCII,用了带 BOM 的 UTF-8 后第一行解析失败。
解决:拿到加载器后先找一个已知的 VM 检测样本做基线测试,确认默认配置的生效情况,然后再逐项修改。每次只改一个键值,改完重新加载验证一次确认改动生效。配置文件的编码一律转为无 BOM 的 ANSI 或 UTF-8。经验之谈:这个工具的参数不是复制就能用的,来源不同参数名和取值都可能冲突,自己从一份干净的默认配置开始改最稳。
6. 加固效果的闭环验证:从“看起来生效”到“样本确认不报 VM”
验证这个环节我吃过不少亏,早前部署完加载器后只看 WMI 输出就下结论,结果遇到真正精明的样本直接暴露。后来养成了一个习惯:每次在分析机上配一套三层的验证流程,缺一不可。
第一层是基础信息层,用系统命令确认注册表、WMI 和网卡特征已替换;第二层是工具辅助层,跑专门的 VM 检测枚举工具,逐个查看检测结果,重点关注 CPUID、固件表、设备管理器的每一项是否干净;第三层是真实样本层,准备三到五个已知做了 VM 检测的样本库,每个样本在加固前和加固后各跑一遍记录输出。三个层次都过了,才算部署合格。
工具辅助层里值得看的是检测结果里各项的命中标记,下面是某分析场景中一份典型输出:
| 检测项 | 加固前 | 加固后 | 验证方式 |
|---|---|---|---|
| CPUID Hypervisor 位 | 命中 | 未命中 | cpuid 指令查询 |
| SMBIOS 厂商字段 | 命中 | 未命中 | WMI / 固件表读取 |
| ACPI OEM ID | 命中 | 未命中 | ACPI 表解析 |
| MAC 地址段 | 命中 | 未命中 | 网络适配器枚举 |
| VMware Tools 服务 | 命中 | 未命中 | 服务列表枚举 |
| 设备管理器隐藏设备 | 部分命中 | 未命中 | 设备接口枚举 |
| RDTSC 时序差 | 命中 | 命中 | 侧信道计时 |
表格能直观看出加固器的边界在最后一行——时序侧信道检测始终无法消除,实践中我会在 VMX 配置里关闭宿主机侧的动态 CPU 迁移并固定 CPU 型号,让时序波动更接近真实机器,但这只是缓解不能根除。
带新人的时候我习惯让他们先跑一遍完整验证流程,再开始分析样本。原因是很多人部署完工具就像吃了定心丸,直接冲向分析,结果分析到一半发现样本其实还在检测 VM,之前的结论全是废的。验证的耐心一定要花在分析之前,而不是分析中。另外提醒一个细节:跑真实样本前一定确认好快照点,VMware 的固件表和驱动的修改在重启后通常保留,但加载器注入的状态不保留,所以每次分析前要确认加固注入已经生效。希望这些验证习惯能帮你少走弯路,祝分析顺利。
本文还有配套的精品资源,点击获取