server-re/docs/WORKFLOW.md
2026-10-15 09:08:48 -04:00

199 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Workflow — reverse-engineering a server binary
The repeatable process used for `Agent_Release_x64.exe`. Follow it for each
binary in `decomp/INVENTORY.md`. Ground rules, layout and tooling are in
`AGENTS.md`. What has been learned so far is in `docs/ARCHITECTURE.md`.
Every finding is recorded as **observed**, **inference** or **unknown**, with an
Evidence ID or decomp file reference. Static analysis never establishes runtime
behaviour.
---
## 0. Prerequisites (once per machine)
- Ghidra is at `/opt/ghidra`, and Java 21 and Node come from `mise.toml`.
- REA MCP is registered project-locally in `opencode.json`.
- Don't reinstall any of these; repair the configuration instead.
- **Ghidra headless fails with `UnsupportedClassVersionError` (class file
71.0):** its compiled-script cache was built by a newer JDK.
- Move `~/.config/ghidra/ghidra_<ver>_DEV/osgi/compiled-bundles` aside.
- Ghidra rebuilds the cache on the next run.
## 1. Identify the binary (cheap, before any decompilation)
```sh
sha256sum binaries/<X>.exe
objdump -p binaries/<X>.exe | grep -E 'DLL Name|Subsystem|MajorLinker|pdb'
```
In REA:
1. Run `open_binary` with the original path under `binaries/`.
2. Run `binary_overview`.
3. Run `search_strings` (regex) for config paths, log text, protocol names and
class names.
Record the SHA-256, linker version, PDB path, imports and procedure count in
`decomp/<X>/evidence.md`.
## 2. Determine language and toolchain
Check for these C++ markers:
- RTTI descriptors (`strings -a | grep '^\.?AV'`)
- `__CxxFrameHandler3`
- an `MSVCP*.dll` import
All 16 servers are MSVC 2010 C++ (see `docs/ARCHITECTURE.md`). Re-check each
new binary and record the result.
## 3. Discover third-party libraries and acquire their sources (**mandatory**)
Any library you can match against upstream source saves you from
decompiling it, and gives names, struct layouts and intent that the binary
lacks. **Every time a library is found, search for its source online before
continuing.**
### 3a. Find candidates
| Signal | How |
|---|---|
| Imported DLLs | `objdump -p` DLL names, cross-checked against `binaries/*.dll` |
| DLL version resources | `strings -el <dll> \| grep -A1 -E '^(FileVersion\|ProductName\|CompanyName)$'` |
| Embedded version text | `strings -a \| grep -iE '<lib>/[0-9]\|part of OpenSSL\|libcurl/'` |
| Statically linked C++ libraries | RTTI class prefixes (`TiXml*`, `Proud::*`, `ATL::*`) |
| Library-specific strings | assert/error messages (`Proud::CNetServerImpl::…`, TinyXML error table) |
| PDB paths | e.g. `…\OpenLibrary\openssl-1.0.0d\…`, which names the exact version |
### 3b. Pin the version
Use, in this order of preference:
1. An explicit version string (VERSIONINFO, `"OpenSSL 1.0.0d 8 Feb 2011"`).
2. A version in the PDB path.
3. **Differential evidence:** download several candidate releases and compare a
distinctive artefact with the binary. Examples are error-string tables,
exported symbol lists and header constants.
- Example: the TinyXML error table contains `Memory allocation failed.`.
That entry exists in 2.5.x and was removed in 2.6, which gives 2.5.1–2.5.3.
4. If none of these work, choose the closest era-compatible release and mark it
**closest, not exact**.
### 3c. Search for the source
Search in this order:
1. Official release archives (project site or SourceForge; check `old/` and
`archeology/` paths).
2. Official git tags (`git ls-remote --tags <repo>`), or a GitHub tag archive
if the release tarball no longer exists.
3. Vendor package repositories. These often contain headers only.
4. Clean-room equivalents (for example mingw-w64 headers for Microsoft APIs)
or open reimplementations (for example Wine).
5. `gh search repos <lib>` for forks or mirrors. Treat these as unverified and
label them that way.
Verify each download against an official checksum where one exists. Always
record its SHA-256.
### 3d. Check the licence and place the files
| Licence | Location | Committed? |
|---|---|---|
| Open source (OpenSSL, curl/MIT, zlib, BSD, public domain) | `third-party/<lib>-<version>/` | Yes |
| Proprietary or EULA-restricted (e.g. ProudNet) | `third-party/_local/<lib>-<version>/` | **No.** It is gitignored. Ask the user before fetching. |
| No public source (XTrap, Apex, HASP runtime) | nothing downloaded | Record acquisition routes only |
Other rules:
- Keep upstream files unmodified. If you must change one (for example curl's
version stamp), record exactly what changed.
- Read the licence before committing anything. If redistribution is
prohibited, it goes in `_local/` or isn't fetched.
### 3e. Document it
Add a row or section to `third-party/README.md` with:
- the observed identity in the binary, with where it was seen;
- the version and how it was pinned;
- the source URL, tag or commit, and SHA-256;
- match quality (exact / closest / headers only);
- the licence;
- any local edits.
Also:
- Mention the library in `docs/ARCHITECTURE.md` if it is statically linked.
- Add it to the list in `AGENTS.md`.
- If no source exists, add it to the "No public source" and "Acquisition
routes" tables instead.
### 3f. Use it
- Label library functions in the decompiled output from known exports, class
method tables, error strings and the matched headers.
- Exclude labelled library code from application analysis.
## 4. Decompile
In REA, choose seeds from distinctive strings or imports and use
`trace_feature` to find the functions that reference them. Then run
`procedure_pseudo_code` / `batch_decompile` on those functions.
For full coverage, run Ghidra headless with the repo scripts:
```sh
analyzeHeadless /tmp/opencode/ghproj X -import binaries/<X>.exe -overwrite \
-scriptPath decomp/scripts -postScript ExportDecomp.java "$PWD/decomp/<X>/full" -deleteProject
analyzeHeadless /tmp/opencode/ghproj X -import binaries/<X>.exe -overwrite \
-scriptPath decomp/scripts -postScript VTableMap.java "$PWD/decomp/<X>/full/vtables.tsv" -deleteProject
```
This produces:
- `full/functions/<addr>.c` and `full/index.tsv` from `ExportDecomp.java`;
- `full/vtables.tsv` from `VTableMap.java`, which maps class vftable slots to
functions.
Generate `cpp/classes.hpp` from `vtables.tsv`, then check that it compiles:
`g++ -fsyntax-only`.
## 5. Record evidence
In `decomp/<X>/`:
1. Run `export_evidence_bundle` to write `evidence-bundle.json`.
2. Extract the REA pseudocode to `<addr>.pseudo.c` and the overview to
`binary_overview.json`.
3. Write `evidence.md`: the findings table (conclusion → type → evidence), the
proposed function names, and the open questions.
4. Update the status and role of the binary in `decomp/INVENTORY.md`.
## 6. Lift to readable C++
`decomp/<X>/cpp/*.cpp` holds hand-lifted code for the analysed functions:
- Cite the original address on each function.
- Mark every name as inferred.
- Record the original bugs you notice (leaks, races).
## 7. Porting spec
There is no source tree in this repo. The earlier `src/` reconstructions were
removed on 2026-10-15. Instead, record the facts a re-implementation needs in
`decomp/<X>/porting.md`:
- the behaviour to reproduce, with decomp addresses;
- a substitution table: original address → Win32 API → nearest Linux
equivalent → behaviour difference;
- the original bugs, and what is unknown or unrecovered.
## 8. Close
Run `close_binary` when the investigation is complete. Before closing, export
the Evidence bundle, because session annotations are temporary.
---
## Checklist per binary
- [ ] SHA-256, imports, linker and PDB recorded
- [ ] Language confirmed
- [ ] **Every third-party library identified, its version pinned, its source
searched for and downloaded where licensing allows, and it documented in
`third-party/README.md`**
- [ ] Key functions decompiled; `full/` export done
- [ ] `evidence.md`, `INVENTORY.md`, `docs/ARCHITECTURE.md` updated
- [ ] `cpp/` lift and `porting.md` updated, if in scope
- [ ] Evidence bundle exported; REA session closed