Files
slinky/docs/re-notes.md
T
2026-11-05 19:45:34 +01:00

66 lines
3.8 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.
# Reverse-engineering notes
Carried over from `slinkyfullsrc/SRC.md`. None of this is needed to build the
module sources.
## `.slinky0` — engine / module manager
`slinky2.decrypted/slinky0.bin` is 14 255 293 bytes (`.slinky0` of the client
image). Region map (verified):
| range | content |
|---|---|
| `0x000000–0x77FFFF` | native code + data (MSVC CRT/RTTI strings at `0x2d000–0x3c000`, engine code; clean x86-64, ~30 % printable) |
| `0x780000–0x8BFFFF` | high-entropy (7.99) blob — encrypted/compressed, not consumed by visible code |
| `0x8C0000–0x9FFFFF` | sorted `(u32 rva, u16 size)` table, 213 035 records, covers `0x36300E–0x867551`, sizes multiple of 8, dense (≈50 % of the region), deltas 2–16 bytes, overlap → looks like a per-site patch/relocation or checksum map for the code region |
| `0xA00000–0xAA0000` | table A, XOR `00 10 00 62 75 86`, 109 225 × `(u32 off, u16 size)`; offsets `0x223–0x27FFB4` fit *inside* the tail block; sizes ∈ {0,8,24,32,…,120} |
| `0xAA0000–0xAB0000` | table B, XOR `83 A7 00 10 00 53`, same 6-byte record shape |
| `0xAB0000–0xD80000` | `tail_high.bin` — 2 949 120 bytes, entropy 7.98, no standard container/PE; table A indexes into it |
| `0xD80000–0xD984BD` | `tail_code.bin` (~100 KB), mixed code/data |
Module-manager data model (recovered from the client image, used by the
reconstructed sources):
* Module descriptor in `.data` (`.rdata` string pointers + a factory/log
function at `+0x58`). `modules_real.json` lists all 67 (61 with a GUI cb).
* Per-module settings block in `.data`, variable stride, begins with three
function pointers `{gui_cb, register_settings, aux}` followed by the widget
cfg objects (`CfgBool/CfgSlider/CfgRange/CfgEnum/CfgColor/...`).
* `R_*` registration calls are made from the client into the engine manager at
DLL init (one `reg_<addr>` function per module), the `W_*` calls render the
settings pane.
The module-side functions that read the settings and implement each feature
are in `src/logic/` (see `docs/logic.md`); they were extracted 1:1 from `.text`
by `tools/extract_logic.py`.
The manager itself is in client `.text`, not `.slinky0`: constructor `0x28000`,
dispatch `0x285d0`, descriptor table `0x14f810`. It groups modules by category
and by the event callback slots at `descriptor+0x48` … `+0x1F8`, and dispatches
the enabled callbacks. See `docs/engine.md` for the full picture, including
the six engine-only modules. `.slinky0` has **no static RIP-relative
references** into the client's `.rdata`/`.data`/`.text` (checked: 0 refs), so
it receives whatever it needs through runtime-installed pointers.
### tail_high.bin
`tail_high.bin` is still packed. Findings:
* Not a PE, not ZIP/7z/RAR/gzip/zlib/LZMA (standard headers checked).
* Entropy 7.978; byte histogram ≈ uniform; no repeated 24-byte blocks.
* Table A (109 225 records) and the sorted table (213 035 records) both use the
same `(u32 offset, u16 size)` record form, sizes are multiples of 8, and both
point *into* their subject buffers with heavy overlap — this is a
*site map* (patch/relocation/checksum), not a container directory.
* The runtime copy of `.slinky0` captured in `slinky.dll` is byte-identical to
the static stream up to `0xC4B658` and zero beyond, i.e. that dump was taken
before the engine performed the tail transformation; it gives no plaintext.
* Therefore decryption requires either (a) implementing the protector's
per-site transform from the `0x8C0000` table, or (b) a live Wine trace of
the first execution that touches `slinky0+0xAB0000` (same breakpoint
technique that recovered the `.slinky2` LZMA streams).
Decrypting `tail_high.bin` is **not required** for anything in this tree: the
module callbacks/registrations are plain `.text`, and the registry data model
is plain `.data`. It is required only for the remainder of the engine internals.