Enumeração personalizada de RPC UDP e abuso de transferência de arquivos

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Mapeando objetos RPC proprietários com Frida

Títulos multiplayer mais antigos frequentemente incorporam pilhas RPC caseiras sobre UDP. Em Anno 1404: Venice isso é implementado dentro de NetComEngine3.dll pelo despachante RMC_CallMessage, que analisa 5 campos de cada datagrama:

CampoFinalidade
IDverbo RPC (16 bits)
Flagsmodificadores de transporte (confiabilidade, ordenação)
SourceID do objeto do chamador
TargetObjectinstância de objeto remota
Methodíndice do método dentro da classe alvo

Duas funções auxiliares – ClassToMethodName() e TargetName() – traduzem IDs brutos em strings legíveis para logging. Ao fazer brute-forcing de IDs de objeto de 24 bits e IDs de método de 16 bits e chamar essas funções auxiliares, podemos enumerar toda a superfície acessível remotamente sem capturas de tráfego ou symbol leaks.

Enumerador de superfície Frida (reduzido) ```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>

Ao executar `frida -l explore-surface.js Addon.exe` foi emitido o mapa RPC completo, incluindo o objeto `Player` (`0x7400000`) e seus verbs de transferência de arquivo `OnSendFileInit`, `OnSendFileData`, `OnReceivedFileData`, e `OnCancelSendFile`. O mesmo fluxo de trabalho se aplica a qualquer protocolo binário que exponha helpers de reflexão internos: interceptar o dispatcher, brute-force IDs, e registrar o que o engine já sabe sobre cada método invocável.

### Dicas

- Use os próprios buffers de logging do engine (`WString::Format` neste caso) para evitar reimplementar codificações de string não documentadas.
- Dumpe `Flags` para identificar recursos de confiabilidade (ACK, pedidos de reenvio) antes de tentar fuzzing; stacks UDP personalizados frequentemente descartam pacotes malformados silenciosamente.
- Armazene o mapa enumerado – ele serve como corpus para fuzzing e deixa óbvio quais objetos manipulam o sistema de arquivos, o estado do mundo ou o scripting dentro do jogo.

## Subvertendo RPCs de transferência de arquivo

A sincronização de saves multiplayer utilizava um handshake de dois pacotes:

1. `OnSendFileInit` — carrega o nome de arquivo UTF‑16 que o cliente deve usar ao salvar o payload recebido.
2. `OnSendFileData` — transmite o conteúdo bruto do arquivo em blocos de tamanho fixo.

Porque o servidor serializa o nome de arquivo via `ByteStreamWriteString()` imediatamente antes de enviar, um Frida hook pode trocar o ponteiro para um traversal payload enquanto mantém os tamanhos dos pacotes intactos.

<details>
<summary>Trocador de nome de arquivo</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);
}
}
});

Os clientes vítimas não faziam nenhuma sanitização e escreviam o save recebido para qualquer caminho que o host hostil fornecesse, por exemplo caindo em C:\User\user em vez da árvore pretendida ...\Savegames\MPShare. Em instalações Windows de Anno 1404 o diretório do jogo é gravável por todos, por isso o traversal torna-se instantaneamente um primitivo de escrita arbitrária de ficheiro:

  • Drop DLLs para classic search-order hijacking no próximo lançamento, ou
  • Overwrite asset archives (RDA files) para que modelos, texturas ou scripts weaponizados sejam carregados ao vivo durante a mesma sessão.

Defending / attacking other targets

  • Procure por verbos RPC chamados SendFile, Upload, ShareSave, etc., e depois intercepte o helper de serialização responsável por filenames ou diretórios alvo.
  • Mesmo que filenames sejam verificados quanto ao comprimento, muitas stacks esquecem de canonicalizar ..\ ou sequências mistas / vs \; brute-force todos os separadores.
  • Quando o receiver armazena ficheiros sob o game install path, verifique as ACLs via icacls para confirmar se um utilizador sem privilégios pode depositar código lá.

Turning path traversal into live asset execution

Uma vez que consegue upload arbitrary bytes, substitua qualquer asset carregado frequentemente:

  1. 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.
  2. Inject a malicious .gr2. O ficheiro Granny 3D trojanizado transporta o exploit de relocação que sobrescreve SectionContentArray e, através de uma sequência de relocação em duas etapas, ganha uma escrita arbitrária de 4 bytes dentro de granny2.dll.
  3. Hijack allocator callbacks. Com ASLR desativado e DEP off, substituir os ponteiros de função malloc/free em granny2.dll redireciona a próxima alocação para o seu shellcode, dando RCE imediato sem esperar que a vítima reinicie o jogo.

Este padrão generaliza-se a qualquer título que faça streaming de assets estruturados a partir de arquivos binários: combine path traversal ao nível de RPC para entrega e processamento de relocação inseguro para execução de código.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks