引言
XLoader是一款具有信息窃取能力的恶意加载程序,其分析难度极高。它的代码仅在运行时解密,并受到多层加密保护,每层都使用隐藏在二进制文件不同位置的密钥进行锁定。即使使用沙箱也无济于事:其规避技术会阻止恶意分支执行,真实的C2(命令与控制)域名隐藏在数十个虚假域名之中。随着新版本的发布速度超过研究人员的分析速度,分析几乎总是一场(必输的)与时间的赛跑。
生成式AI改变了这种平衡。研究人员无需花费数天时间进行艰苦的手动分析、手动编写解密例程和逆向工程脚本,现在可以使用AI来检查复杂功能、识别算法,并在短短数小时内生成可用的工具,从而加速获取解密的代码、字符串和入侵指标(IoC)的过程。
AI辅助分析的两种方法
我们探索了两种互补的工作流程,将GPT-5应用于破解XLoader:
- 实时MCP集成:使用MCP,我们让LLM直接访问我们的分析工具(IDA Pro、x64dbg和VMware实例)。这使得AI能够实时查询反汇编器、检查内存甚至控制调试器。
- 基于ChatGPT的“离线”数据管道:我们将IDA Pro数据库(反汇编、反编译代码、字符串等)和恶意软件二进制文件导出到ChatGPT环境中。然后,我们要求ChatGPT对这些数据进行静态分析,并在其云端沙箱中生成、优化和执行自己的Python脚本。整个过程不需要与我们的工具保持实时连接。
每种方法各有其优缺点。MCP提供了一种智能体式的交互工作流,而离线管道则提供了易于共享和复现的自包含分析。
实践:分析XLoader的内置加密器
我们以SHA256为77db3fdccda60b00dd6610656f7fc001948cdcf410efe8d571df91dd84ae53e1的XLoader样本为例,展示了如何使用GPT-5进行分析。
初始分析
我们首先要求AI助手从入口点开始进行初步分析。处理这个简单的提示耗时8分46秒。结果,我们的助手正确识别了RC4实现,并得出结论:该样本是加壳的。值得注意的是,仅基于模型可用的数据,它暗示该样本看起来与XLoader相似。
解密流程分析
我们进一步要求助手查找所有加密函数调用,并分析负载是如何解密的。我们发现主负载块经过两轮RC4处理:首先对整个缓冲区进行RC4解密,然后使用不同的密钥对256字节的块进行第二轮处理。
AI助手还成功收集了以下信息:
- 解密代码中原始入口点的虚拟地址 (
0x00430CB3) - 加密块在二进制文件中的偏移量 (
0x3143) - 加密数据块的大小 (
0x44A00)
密钥获取与验证
下一步是获取实时密钥并验证结果。此时,我们转向了MCP。通过设置断点并读取内存,AI助手获取了阶段1和阶段2的RC4密钥:
- 阶段1密钥:
20EBC3439E2A201E6FC943EE95DACC6250A8A647 - 阶段2密钥:
86908CFE6813CB2E532949B6F4D7C6E6B00362EE
随后,AI助手通过分析IDA导出的数据,确定了这些密钥的计算方式(密钥来源和算法),并利用之前捕获的实时数据验证了其假设。最终,AI生成了一个能够解包被分析样本的工作脚本。然而,该脚本并不具有普适性,因为它用于定位密钥的模式与该特定样本紧密绑定。
时间消耗统计
分析过程耗时约40分钟,共进行了39次MCP调用。
| 提示内容 | 耗时 | MCP调用次数 |
|---|---|---|
| 初始提示(指令) | 37s | 0 |
| 从入口点开始对样本进行初步分析并提供简短报告 | 8m 46s | 0 |
| 查找并仔细检查对已发现加密函数的所有调用 | 4m 13s | 0 |
| 分析主负载数据块解密。确保检查了加密数据块在不同函数中的所有使用。 | 4m 13s | 0 |
| 在所需地址设置断点并捕获所需数据。同时,在调用OEP之前设置断点,并捕获OEP处的一小段解密代码块,以便稍后用于解密验证。开始前请提供计划。 | 9m 7s | 39 |
| 查找阶段1和阶段2 RC4密钥的计算方式:密钥来源和算法。请注意,IDA导出中提供了所有必需的数据。使用捕获的实时值检查您的假设。从阶段1密钥开始。 | 6m 56s | 0 |
| 转向阶段2密钥派生。 | 4m 40s | 0 |
| 为阶段1和阶段2密钥实现离线重现程序。然后实现一个完整的静态解密器,直接处理sample.bin:从二进制文件中提取加密负载并解密它。使用捕获的数据(OEP字节)验证其工作正常。 | 1m 13s | 0 |
| 总计 | 39m 8s | 39 |
解包样本分析
手动创建OEP函数后,我们再次在IDA中打开解包样本并应用导出脚本。IDA未能识别大部分代码,这表明代码可能以某种方式被混淆,或者函数被加密。实际上,XLoader使用了运行时函数解密。
我们要求AI助手在不给予指导的情况下自行分析解包样本。通过分析,我们识别出:
- 混淆的API调用
- 使用RC4加密以及在使用RC4前后的附加修改
- 某些“阶段1构建器”(加密函数的解密存根)
函数解密方案I
AI助手识别出90个相似函数。这些函数派生出6字节的头尾标记,使用这些标记定位内存中的目标区域,用六个NOP指令覆盖标记,转换该区域,然后跳转到每个包装器独有的硬编码地址。
助手还实现了内联Python代码片段,解密了其中一个加密函数,提供了所有数据、密钥以及部分解密后的代码。
然而,AI无法在没有人工帮助的情况下实现一个能解密所有函数的通用脚本。问题在于定位构建20字节有效RC4密钥所需的所有XOR修饰符。有效的RC4密钥是通过将其4字节组件与一个4字节修饰符进行XOR运算而派生的,该修饰符对于每个加密函数都是唯一的。虽然seed_internal始终位于标记附近的包装器函数内,但助手无法实现查找seed_external的通用方法,因为它可能位于调用函数内的不同位置,并可能与其他常量故意混合。
我们不得不手动修改脚本以确保它能正确找到所有外部种子。因此,AI显著减少了分析和脚本开发所需的时间,但在现阶段还无法完全取代人类。
函数解密方案II 和 III
在分析未包含有效函数序言的加密函数时,AI助手又发现了另外两种解密/打补丁方案。
- 方案二:使用4字节标记和两层加密。第一层使用专用密钥构建函数生成的20字节密钥,然后用单字节进行XOR调整。第二层密钥由4字节头部标记与十六个零字节拼接而成。解密后,包装器通过修补序言处的
55 8B EC并用NOP填充尾部来修复函数。 - 方案三:类似于方案二,但第二层密钥并非派生自头部标记。相反,每个包装器都嵌入其自己的20字节常量(五个DWORD与盐值进行XOR),用于解密前缀直到遇到前哨值,然后应用相同的序言/尾部修补。
我们总共在XLoader中识别出三种不同的函数解密方案。
通过连续四次迭代应用所有三个解密器,我们最终成功解密了101个函数。
API调用去混淆
解密样本后,我们采用相同方法分析API调用去混淆机制。样本的导入地址表为空,并且没有包含库名或函数名的明文字符串。
我们要求AI助手从OEP开始分析,以确定样本如何解析和调用Windows API。四分钟后,我们收到了算法描述。
接下来,我们使用简单提示生成用于API调用去混淆的IDAPython脚本。经过五次迭代和大约20分钟的额外调试,我们获得了一个完全可用的版本。
我们还要求助手分析备用路径(sub_404603)。经过另外五次迭代和14分钟,我们获得了一个功能齐全的脚本。
XLoader使用相同的哈希解密机制来查找沙箱工件、虚拟机和研究环境中典型的进程。修复问题时,我们还添加了基于字典的哈希暴力破解,这使我们能够自动注释函数以及与特定规避技术对应的某些字符串。
总的来说,从第一个提示到一个功能齐全的API去混淆脚本,AI助手大约工作了一小时。
| 提示内容 | 耗时 | 备注 |
|---|---|---|
| 初始提示(指令) | 1m 26s | |
| IAT为空,样本中没有明文字符串。确定样本如何解析和调用Windows API。从oep_start (0x00430CB3)开始分析。 | 4m 28s | 仅找到一个路径 (ai_apiid_decrypt)。 |
| 实现一个用于API调用去混淆的IDAPython脚本。使用Module!Function、原始ID和EA注释解析器和每个调用点;IDA 9+。记录所有去混淆尝试。 | 9m 44s | 脚本无法工作。 |
| 多次 | 20m | 脚本的本地测试和发送错误报告,5次迭代。 |
分析例程sub_404603作为备用API哈希解密器。恢复其算法。查找调用点。扩展IDAPython去混淆器。 |
4m 49s | 描述了通过 ai_apiid_decrypt_salt(原 sub_404603)的第二个API解析路径。更新后的脚本无法工作。 |
| 多次 | 14m 35s | 脚本的本地测试,发送错误报告和不正确行为说明,5次迭代。 |
| 请提供关于两种算法 ai_apiid_decrypt_salt, ai_apiid_decrypt -> ai_resolve_export 的总结 | 17s | |
| 总时间 | 55m 2s |
字符串解密
样本中不包含可读字符串。同时,代码包含一系列具有相同骨架的短例程。我们分析了其中一个函数(sub_405773),AI助手确定该函数使用先前解密的例程(ai_dec_func14)中实现的算法解密字符串。
通过简单提示,我们轻松获得了加密密钥和解密的字符串。然后,我们要求AI助手实现一个脚本以解密剩余字符串。这次我们立即获得了一个可工作的脚本,并用它解密了175个字符串。
此分析任务的总时间约为20分钟。
| 提示内容 | 耗时 |
|---|---|
| 初始提示(指令) | 1m 26s |
从 sub_405773 开始分析其功能。递归进入其被调用函数。信任反汇编中的注释。 |
7m 45s |
解密来自 sub_405773 的字符串 |
5m 10s |
实现一个解密字符串的IDAPython脚本(IDA 9+)。要求:- 查找并注释对解密函数 sub_4050F3 的每次调用,附上解密后的字符串。- 对于每个字符串,输出调试信息:加密缓冲区、XOR调整字节(BL)、长度和解密后的字节。- 以十六进制打印所有二进制数据。 |
5m 30s |
| 总时间 | 19m 51s |
解密域名
提取入侵指标(IoCs)列表始终是恶意软件分析的关键任务。网络指标(如域名和URL)尤为重要。在我们恢复的字符串中,有64个Base64编码的条目,它们代表了需要解密的域名。
为了获得解密的域名,我们需要剥离至少五层加密。同时,获取每一层的密钥是最困难的部分,因为生成它们所需的不同数据片段分散在多个函数中,很难定位。
我们开始分析处理域名的主要函数 ai_dec_func_0 (0x00404913)。分析结果表明,该函数是XLoader的阶段1域名构建器。对于给定的域名索引(1..64),它从 ai_dec_domain_NN 中提取匹配的种子字符串,进行base64解码,然后运行密钥化的RC4-with-diff转换,其密钥是存储在 ctx+0x23D0 的20字节密钥(ctx 是存储密钥、函数地址和其他数据的全局结构),并与域名索引进行字节XOR。结果被重新编码为base64并写入输出缓冲区。这是一个中间产物,不是最终的ASCII域名。
我们发现AI助手无法自行定位 ctx+0x23D0 处的密钥,因此我们手动定位了该密钥的初始化位置并将信息提供给AI。提取密钥后,我们成功获得了第一层解密后的中间值。
由于字符串仍然加密,我们要求AI助手跟踪从 ai_dec_func_0 到最终ASCII域名的完整转换链。结果我们发现,获得的Base64字符串会再次被解码,然后使用函数 ai_dec_func_11 (0x004095F3) 内部生成的20字节密钥进行第二层解密。该密钥还额外与 SALT_DWORD 进行XOR运算。然而,SALT_DWORD 的初始化信息缺失,AI助手无法自行检索。我们再次手动提供了相关代码片段来定位该值。
确认密钥正确后,AI助手成功解密了与 ai_dec_domain_01 对应的域名。随后,AI助手能够自动解密所有域名。
| 提示内容 | 耗时 | 备注 |
|---|---|---|
| 初始提示(指令) | 1m 31s | |
分析 ai_dec_func_0 (0x00404913) |
5m 22s | |
ai_dec_domain_NN 反汇编注释中包含base64编码的加密域名。取 ai_dec_domain_01 中的那个,然后用 ai_dec_func_0 转换它并返回最终字符串。 |
11m 33s | 未能获得第1层RC4密钥 |
你可以在 ai_dec_func_4 (0x00407293) 中找到 ctx+0x23D0 的初始化,也可以检查 sub_404453。 |
1m 34s | |
现在你有了所需的密钥。取 ai_dec_domain_01 中的字符串,然后用 ai_dec_func_0 转换它并返回最终字符串。 |
5m 14s | |
你返回的字符串仍然是加密的。跟踪从 ai_dec_func_0(情况2,字符串 Qvm75Acm5NpYTbnYXdcvBw==)到最终ASCII域名的完整转换链。发现任何剩余层,从上下文/初始化程序中定位并派生所有必需的密钥/参数,并引用所使用的函数名和EA。输出最终域名,以及一个简明的分步流程,将所有密钥/IV以十六进制打印。如果缺少任何值,请准确说明它是什么以及在哪里读取。 |
10m 2s | 未能获得 SALT_DOWRD |
你可以在 ai_dec_func_20 (0x00411053) 中找到 SALT_DWORD。请验证并继续:.text:004111B3 81 C7 00 20 00 00 add edi, 2000h … .text:0041182B C7 87 C8 05 00 00 00 A6 mov dword ptr [edi+5C8h], 0C6EA600h |
3m 20s | |
解密从 ai_dec_domain_00 到 ai_dec_domain_15 的域名。输出:表格(索引,src_base64,final_domain)。从 ai_dec_domain_NN 反汇编注释中获取每个函数的base64。 |
5m 36s | |
为 a5=222 且域名索引 0..15 重现 ai_dec_func_0 的输出。 |
3m 42s | |
| 总时间 | 47m 54s |
结论
从其首次出现以来,XLoader一直是移动的目标,每个新版本都为安全分析师和防御者提高了门槛。多年来,这意味着当研究人员完全解构一个样本时,攻击者已经用下一个版本领先一步。
生成式AI改变了这种平衡。结合云端分析和偶尔的MCP辅助运行时检查,我们将大部分机械性的逆向工程工作委托给了LLM。我们不再需要花费数小时手动重写解密例程,而是要求AI模型来完成,并在几分钟内获得可用的原型。
AI的使用并没有消除对专业知识的需求。XLoader最复杂的保护措施,例如分散的密钥派生逻辑和多层函数加密,仍然需要手动分析和针对性调整。但分类、去混淆和脚本编写等繁重工作现在可以显著加速。曾经需要数天的工作现在可以压缩到数小时。
对于防御者来说,这不仅仅是生产力的提升。更快的周转时间意味着更及时的IoCs、更快速的检测更新以及攻击者更短的利用窗口。对于研究人员来说,它降低了对野外一些最复杂恶意软件家族进行分析的入门门槛。
我们的研究表明,通过正确的工作流程,生成式模型已经可以作为力量倍增器——帮助安全防御者跟上那些曾经被认为耗时过长而难以分析的威胁。
然而,现在宣布胜利还为时过早,因为我们预计恶意软件作者会针对AI辅助分析调整他们的技术。反过来,我们也需要提出下一个改变游戏规则的方法。