7.7 KiB
Offline Reverse Engineering & Development Guide for AI Agents
(How to Develop and Debug Game Servers Without Keeping the Game Running with Frida)
Target Audience: AI Assistants (ChatGPT, Claude, Codex, Copilot) assisting developers on the
GaC-hkrpg-goemulator and similar Unity/il2cpp game server projects.
Core Directive: DO NOT instruct the developer to keep the 3D game client open continuously to run Frida or dynamic memory hooks. Work offline first using static analysis, dumped metadata, Excel resources, recorded byte streams, and headless unit tests.
1. Why Continuous Live Hooking (Frida) is Anti-Pattern
Demanding that a developer keeps a live 3D game client running with dynamic Frida hooks in the background causes severe friction:
- Resource Drain: High GPU/CPU and VRAM consumption leads to system slowdown and crashes while editing/compiling code.
- Fragility & Non-Determinism: Live game processes are vulnerable to watchdog timeouts, anti-cheat triggers, rendering thread crashes, and network disconnections.
- Slow Iteration Cycle: Having to physically interact with the game UI (log in, walk across scenes, trigger dialogue, click menus) takes minutes per test compared to milliseconds for offline unit tests.
- Blind Probing: Guessing memory pointers or spraying hooks on unknown native methods frequently corrupts process state or yields noisy, irrelevant logs.
2. The 5 Pillars of Offline Emulation Development
Every feature or bug in a game server project can be solved using one or more of the following offline pillars:
flowchart TD
A["Problem / Feature Request"] --> B{"Is it a Schema, Class, or Enum?"}
B -- Yes --> C["Pillar 1: Static Dumps<br>(Dummy DLLs / dump.cs / Proto)"]
B -- No --> D{"Is it Game Data, Stats, or Formulas?"}
D -- Yes --> E["Pillar 2: Excel / Resource JSON<br>(ExcelBinOutput / Configs)"]
D -- No --> F{"Is it Protocol / Byte Wire Bug?"}
F -- Yes --> G["Pillar 3: Packet Capture & Replay<br>(*.bin payloads / Go tests)"]
F -- No --> H{"Is it State Machine / Flow Logic?"}
H -- Yes --> I["Pillar 4: Headless Unit Tests<br>(Mock Sessions / State Simulation)"]
H -- No --> J["Pillar 5: Bounded One-Shot Capture<br>(Targeted probe -> Save JSON -> Exit)"]
Pillar 1: Static Metadata & C# Assembly Inspection (No Game Required)
For Unity/il2cpp games, all types, classes, interfaces, protobuf fields, enums, RPC CmdIDs, and method signatures are static per client patch.
- Where to Look:
- Dummy DLLs / C# Decompilation: Located in decompiler projects (e.g.,
dnSpy,ILSpy,Cpp2IL). dump.cs/script.json: Generated once viaIl2CppDumper. Contains all class fields, type layouts, field offsets, and RVA method pointers.- Protocol Definitions: Protobuf
.protofiles and CmdID mapping tables (e.g.,cmd_ids_*.json,protocol/).
- Dummy DLLs / C# Decompilation: Located in decompiler projects (e.g.,
- What to Search:
- Want to know what fields
GridFightQuitScRspcontains? Inspect the compiled Protobuf class in the decompiled assembly or.proto. - Want to know enum values (e.g.,
GridFightPhaseType,BattleEndStatus)? Look them up indump.csor the dummy DLLs. - Never ask the user to hook memory just to read a struct layout.
- Want to know what fields
Pillar 2: Data-Driven Resource & Excel Configs (No Game Required)
Game balance, IDs, stage requirements, drop tables, rank thresholds, and scoring rules are stored in static JSON tables (exported from game Excel data).
- Where to Look:
resources/(e.g.,resources/CurrencyWarsCatalog.json,resources/CurrencyWarsXaodev.json).ExcelBinOutput/*.jsonor community resource dumps (e.g.,StarRailRes).
- Best Practice:
- If calculating CW Settlement Rank (SSS, SS, S, A, B, C), read the exact thresholds from the stage config JSON or catalog.
- Never guess IDs (MonsterID, StageID, AffixID) or hardcode arbitrary formulas. Check the static catalog first.
Pillar 3: Packet Capture & Offline Replay (No Game Required)
Instead of launching the game to test serialization and network handling:
- Save Once: When a packet is sent or received during any prior session, save the raw protobuf byte stream as a
.binor hex file (e.g.,battle_last.bin,battle_last_response.bin). - Inspect Offline:
- Use offline parsing scripts (e.g., Go scripts or tools like
cmd/inspect_...) to unmarshal the bytes into Go structs. - Print the decoded JSON to see exactly what the client sent or received.
- Use offline parsing scripts (e.g., Go scripts or tools like
- Verify Wire Compliance:
- Compare marshaled Go output with the captured
.binto ensure field tags and types match 1:1.
- Compare marshaled Go output with the captured
Pillar 4: Headless State Simulation & Unit Tests (No Game Required)
Complex game flows (e.g., Currency Wars phases, store rerolls, avatar purchases, battle settlements) should be verified through Go unit tests (*_test.go) or CLI mock runners.
- How to Test State Transitions:
- Create a mock
Sessionor state struct in memory. - Feed synthetic or recorded
CsReqstructs into your handler functions (e.g.,HandleGridFightQuitCsReq). - Assert that:
- The returned
ScRsphasRetcode == 0. - State variables (e.g., Gold, HP, Level, Score, Items) mutate correctly according to game rules.
- The returned
- Create a mock
- Speed & Reliability:
- Runs in
< 10 millisecondsviago test ./.... - Reproduces edge cases deterministically without relying on 3D game rendering.
- Runs in
Pillar 5: Bounded One-Shot Dynamic Probe (Only When Strictly Unavoidable)
If and only if an obfuscated runtime value (e.g., dynamic salt, encrypted token, or un-obfuscated runtime reflection) cannot be deduced statically:
- Do NOT run interactive Frida loops.
- Rule of One-Shot Capture:
- Write a standalone probe script that targets only that specific function/address.
- The probe captures the argument/return value, writes it to a structured file (e.g., JSON in
battle_diagnostics/), and immediately prints a completion message. - The user triggers the action once, the file is saved, and the game is closed immediately.
- Script Hygiene:
- Store diagnostic probes outside
scripts/(e.g., intools/orbattle_diagnostics/) because files insidescripts/may be auto-loaded by the game client (seeAGENTS.md).
- Store diagnostic probes outside
3. Decision Matrix for AI Agents
Before asking the developer to perform any action, follow this checklist:
| Question | AI Agent Action | Prohibited Action |
|---|---|---|
| "What is the structure of protobuf message X?" | Inspect protocol/, dummy.dll, or dump.cs. |
Do not ask the user to inspect memory with Frida. |
| "What is the formula or ID for feature Y?" | Search resources/ or Excel JSON tables. |
Do not guess or invent arbitrary IDs in code. |
| "Did my server handler process the request correctly?" | Write a Go unit test (_test.go) with mock data. |
Do not ask the user to open the game just to check. |
| "Why does the client reject packet Z?" | Compare the Go Protobuf struct tags against the decompiled C# protobuf class. | Do not tell the user to blindly inject random packets. |
| "Need to inspect a native runtime value?" | Provide a single-use script that saves output to a file and exits. | Do not tell the user to keep the game running in the background. |
4. Repository Rules Compliance (AGENTS.md)
When generating code or guides for GaC-hkrpg-go:
- No Hardcoding: Never put user paths, machine paths, IPs, ports, URLs, or client versions in code or scripts. Use
server.json/server.local.json. - Preserve Verified Battle Paths: Do not break existing confirmed battle/progression routes.
- Probe Cleanup: Never leave experimental probe scripts in
scripts/. - Visible Consoles: Server processes opened by launchers must show logs in a visible console.