FiveM 里的“约翰叔叔”:GP212887 感染链与安全处置
解释“约翰叔叔”在这里指代的 FiveM 后门感染链,梳理已确认样本、检测证据、自动修复边界和服务器处置方法。
本文中的“约翰叔叔”不是人物介绍,也不用于推断现实身份。它是对一类 FiveM resource 感染链的社区称呼。CK 最初核验的样本名为 ox_lib-GP212887.zip,因此工具内部也使用 GP212887 作为这条精确样本链的标识。
这类问题的重点不是资源名称,而是攻击代码如何藏进正常 resource、如何被 manifest 接入,以及外部内容如何进入动态执行。最初样本出现在 ox_lib,不代表只有 ox_lib 会被感染。当前扫描器会遍历 resource、整个 resources 目录和 ZIP,并对所有匹配的 Lua、JavaScript、HTML、manifest、配置和二进制候选执行静态检查。
约翰叔叔感染链是什么
GP212887 不是一个孤立的恶意文件,而是多个文件互相接线形成的执行链。已确认样本同时修改资源入口、NUI 页面、Lua 初始化代码,并加入伪装成字体和正常前端文件的载荷容器。
| 样本位置 | 在感染链中的作用 | 当前处置 |
|---|---|---|
fxmanifest.lua |
把 NUI 切换到恶意 dashboard,并加载额外 loader | 精确恢复目标行,保留其他内容 |
resource/init.lua |
通过字符拼接隐藏 load,尝试从伪字体读取并执行内容 |
只移除确认追加的恶意块 |
client/loader.js |
读取资源内容,Base64 解码后交给动态函数执行 | 确认命中后删除 |
web/static/dashboard.html |
内嵌远程取回并动态执行的前端载荷 | 确认命中后删除 |
web/fonts/Verdana.ttf |
伪装成字体,实际字体头无效并带有活动域名 | 确认命中后删除 |
manifest 是这条链的重要连接点。单独存在一个可疑文件,不一定会被 FiveM 加载;当 manifest 同时把页面和脚本接入资源,多个信号才形成完整的高置信结论。
当前样本里确认了什么
分析过程只读取 ZIP 条目名和文件字节,计算 SHA-256,并对文本、Base64 和字符串混淆做静态还原。没有提取到可运行 resource,也没有调用 Lua、JavaScript、HTML 或 FiveM 运行环境。
当前样本中确认了这些事实:
client/loader.js存在 Base64 解码后交给new Function的路径。- dashboard 中的静态 Base64 内容会访问外部地址,并把响应交给动态执行。
- 伪
Verdana.ttf没有合法 TTF 或 OTF 文件头,并包含经过插入字符混淆的同一活动域名。 - manifest 同时接入 dashboard 和 loader。
resource/init.lua中存在人为追加的伪字体动态加载入口。
样本签名包记录的历史活动域名包括:
jokerx1zai.comjokery1zai.com
域名单独出现只能作为 IOC 线索,不能成为自动删除文件的唯一依据。正常文档、黑名单或安全工具也可能包含这些字符串。
报告中的字体偏移矛盾
原检查报告描述,Lua 会从 Verdana.ttf 的第 87565 字节开始取得载荷。但实际 ZIP 中的这个文件只有 91 字节,对当前副本执行同样的切片会得到空内容。
这个矛盾说明报告不能直接变成修复脚本,也不能说明样本安全:
- 当前副本中的 Lua 字体取载荷路径可能无法按报告描述完成。
- manifest 接入的 JavaScript loader 仍然存在。
- dashboard 的远程取回和动态执行链可以独立成立。
- 伪字体仍包含同一活动域名。
- 其他变体可能携带更长的字体载荷。
因此 CK 的规则同时检查已知哈希和结构证据,不依赖单一文件尺寸或一条报告描述。
为什么不能看到 load 就删除
FiveM resource 中很多能力本身是正常的。PerformHttpRequest、fetch、Discord Webhook、Base64、Buffer.from、String.fromCharCode、load、os.execute 或混淆标记,单独出现都不足以证明后门。
扫描器只有看到稳定的数据流或多个独立信号时才升级结论,例如:
- 外部网络响应或网络事件参数成为不可信输入。
- 输入经过 Base64、XOR、LZString、KVP 或伪装文件持久化。
- 结果进入
load、loadstring、eval、new Function、Node VM 或系统命令执行。 - manifest 又明确加载了对应脚本。
这种“来源、处理、执行、接线”的组合判断,比关键词扫描更慢一些,但能显著减少误删正常资源。
不只扫描 ox_lib
CK 扫描移除后门 当前会扫描所有传入目标,而不是只认 ox_lib 目录名。v0.2.0 除了 GP212887 精确链,还覆盖:
- Lua HTTP 响应直接进入
load或loadstring。 - Lua 网络事件参数直接进入动态执行。
- JavaScript 网络取回与 XOR、Base64、LZString、Node VM、
eval或new Function的组合链。 fxmanifest.lua和 legacy__resource.lua对已确认恶意脚本的接线。- Blum、Warden、Cipher 等公开 FiveM 后门活动的组合 IOC。
- txAdmin 核心文件篡改标记和
JohnsUrUncle管理员。 - cfg、JSON、C#、DLL 和 EXE 字节中的已知 C2 字符串。
不同类型的处置强度并不相同。高置信恶意 JavaScript 可以在备份后移除并同步清理 manifest;完整闭合的单行 Lua RCE 可以精确删行。多行 Lua RCE、txAdmin 核心文件、管理员记录和二进制只告警,留给人工复核。
扫描与修复为什么分开
组件把操作拆成三个阶段:
scan:只读扫描,返回路径、规则、证据、严重度和是否可修复。repair:默认只生成修复预览,显式确认写入后才创建备份并修改。restore:按 Run ID 检查并恢复,发现修复后文件又被修改时默认拒绝覆盖。
目录修复会把备份放在目标 resource 外部,避免备份文件再次被 manifest 打包或加载。ZIP 默认生成新的 *.cleaned.zip,原 ZIP 保持不变。修复后必须重新静态扫描;仍有可自动修复的高危项时,目录写入会自动回滚,清洁 ZIP 也不会交付。
组件还会拒绝自动处理路径穿越、符号链接、重复路径、损坏或异常压缩比的 ZIP,防止“扫描恶意包”本身变成新的写入风险。
GP212887 的验证结果
对固定样本的 v0.2.0 回归结果为:
| 项目 | 结果 |
|---|---|
| 初始静态发现 | 15 项 |
| Critical | 14 项 |
| 自动修复动作 | 5 项 |
| 精确修改文件 | 2 个 |
| 删除恶意新增文件 | 3 个 |
| 保持哈希不变的其他文件 | 109 个 |
| 清洁副本复扫 | 0 项发现 |
5 个动作只修改 fxmanifest.lua、resource/init.lua,并删除三份确认恶意的新增文件。没有因为扩展通用规则而扩大这个样本的写入范围。
当前仓库的 15 项自动测试也全部通过,覆盖正常 HTTP/Base64 不误报、目录与 ZIP 修复、备份恢复、冲突保护、单行与多行 Lua 的处置差异、txAdmin 人工告警和通用 JavaScript 投递链。
服务器命中后还要做什么
清理 resource 只能阻止这份文件继续执行,不能证明服务器和开发机从未受影响。若感染版本曾经启动过,建议继续完成:
- 先隔离样本并保留只读副本、日志和哈希。
- 停止使用受影响 resource,检查其他资源和下载来源。
- 轮换数据库、面板、API、SSH、RDP 和机器人凭据。
- 检查计划任务、启动项、新账号、新文件和异常外联。
- 核对 txAdmin 管理员和核心文件,必要时用匹配版本重新部署。
- 让曾连接的客户端执行终端安全检查。
- 从可信来源重新取得关键组件,再进行差异核对。
不要在生产目录上直接批量搜索替换,也不要为了“确认行为”去运行可疑 ZIP。先扫描、预览和备份,再做最小范围修复。
能证明与不能证明的边界
静态扫描可以证明文件中存在特定字节、危险数据流、manifest 接线或已知样本哈希。它不能单独证明代码已经在某台服务器执行,也不能根据一个昵称、域名或文件推断现实攻击者身份。
工具也不是操作系统杀毒软件。它关注 FiveM resource 和相关配置中的静态链路。若服务器已经发生凭据泄露、系统持久化或横向移动,需要按完整安全事件处理。
项目与公开依据
本文最后核验:2026-07-17。IOC、后门实现和公开规则会变化,处置前应重新查看项目最新 Release 与覆盖文档。
