Galaxy native client compatibility audit
The current installed executable is a different client build. Local Steam update records, depot file hashes, version resources and PE structure agree on this; the conclusion does not rely on filesystem modification times. At the initial pass, the native plugin was pinned to the old SHA-256. No hash guard, native source hook, game file or running game was changed by this audit. The closure report separately records a later, independent shared-source migration to the new exact hash without attributing or reverting it.
The new build has many matching code bodies, but a single RVA delta cannot migrate the plugin. A separate reviewed version profile is feasible from the recorded candidates. This report does not approve that profile or claim live compatibility.
Follow-up: the bounded chain-aware closure pass is now complete for the
Galaxy source addresses, registration/handle/CSM basis and the nine initially
unmatched research bodies. See
research/galaxy-client-compatibility-closure.md and the independently
verifiable artifacts/galaxy-client-compatibility/galaxy-mapping.json.
In particular, HeatTick and the seven data addresses listed below as initial
gaps are now resolved. The initial pass and its raw audit.json are retained
to distinguish new evidence from the earlier state.
Provenance and versions
| Item | Pinned copy | Current installed image |
|---|---|---|
| Product version | 4.4.2.0 | 4.4.2.1 |
| File version | 334473 | 334925 |
| File length | 103,482,368 | 103,481,344 |
| PE build timestamp, UTC | 2026-10-12 21:29:33 | 2026-10-22 21:29:44 |
| SHA-256 | 6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93 |
ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63 |
| Content SHA-1 | 6056fac2c758eee01273459c22873dff447e3055 |
a272a87e3dd64e0818b605ddde5269451170806a |
The local Steam content log records completed installations of BuildID
25906527 on 2026-10-20 and 26155938 on 2026-10-23. On October 23 it
explicitly records a download/stage, a commit from the downloading directory
to the installed Elite Dangerous directory, 87 updated files, and successful
completion at 21:50:25 local time / 13:50:25 UTC.
The retained depot manifests are:
I:/steam/depotcache/359326_1091597132551610634.manifestfor the old build.I:/steam/depotcache/359326_3767724865074145418.manifestfor the new build.
Their Products\\elite-dangerous-odyssey-64\\EliteDangerous64.exe rows each
match the respective actual file's length and complete content SHA-1.
The current appmanifest_359320.acf also identifies BuildID 26155938 and
depot manifest 3767724865074145418. Together these are positive local Steam
update provenance evidence. Neither EXE has an Authenticode certificate;
this audit does not independently authenticate Steam's cached manifest
signature. Account identifiers and download authorization URLs are excluded
from the saved evidence.
PE comparison
Both are x64 PE images with the same section RVAs, image base 140000000
and SizeOfImage=640C000. Unchanged section starts do not imply unchanged
symbols within a section.
| Property | Old | New |
|---|---|---|
| Entry-point RVA | 489BC58 |
489BBB8 |
.text virtual size |
4DB4AEE |
4DB498E |
.rdata virtual size |
10AF60C |
10AF5EC |
.data virtual size |
1F0AA0 |
1F0AA0 |
.pdata virtual size |
2E6BA8 |
2E6B3C |
.pdata function ranges |
253,518 | 253,509 |
| Certificate directory size | 0 | 0 |
Raw section offsets also changed; a file-offset patch or comparison must
resolve each image's own RVA-to-file mapping. Full per-section hashes and
all header values are in artifacts/galaxy-client-compatibility/audit.json.
Initial bounded matching method and results
research/Audit-GalaxyClientCompatibility.py reads both files without loading
or executing them. It inventories literal/named image RVAs in the current
Navigation*.cs sources, adds existing galaxy research function starts, and
adds bounded constructor/vtable/global-reference witnesses. This source
snapshot includes the new original-appearance adapter.
Each initial function signature is at most 384 bytes. Encoded RIP references, relative branch targets, absolute virtual addresses and function-local indexed jump-table RVAs are masked; all remaining bytes must match exactly. The new text section is searched for every match. Generic getters and short destructors therefore remain ambiguous rather than being assigned the nearest address. Fingerprint/mask SHA-256 values are retained for reproduction.
The final recorded pass contains:
- 240 source RVAs: 123 code addresses and 117 data addresses.
- 2,142 function seeds: 1,713 unique byte-signature candidates, 408 ambiguous, 11 insufficient signatures and 10 unmatched signatures.
- Among source code RVAs: 106 unique candidates, 15 ambiguous, one insufficient signature and one unmatched signature.
- Among source data RVAs: 110 have consistent code/vtable reference candidates, seven remain unresolved.
- 64 of 66 examined vtables have a single candidate preserving every uniquely matched slot in the bounded table window.
- All 68 source symbols that uniquely match at
.pdatarange entries also match their complete original.pdataspans after reference normalization. The other 38 unique source symbols are leaf/thunk/interior symbols and are not promoted to full-function checks.
A .pdata span can be one part of a function with chained/cold unwind ranges.
Even a complete normalized span preserves instruction operands, not the
semantics of every masked destination. Caller/callee, table and layout review
is still required before using it in a native profile.
Unique code candidates exhibit eight distinct deltas: 0, -30, -40,
-60, -A0, -C0, -E0, and -120 (hex). Data candidates include 0,
-30, and -40. These are observed candidate deltas, not a piecewise remap
function; boundaries between samples are unproven.
Useful candidate addresses
All values below are RVAs, written in hex. They are review candidates only.
| Existing symbol | Old | New candidate | Evidence |
|---|---|---|---|
| Flow update hook | 2157520 |
2157460 |
Unique normalized span |
| Physics update hook | 2E6EA20 |
2E6E960 |
Unique normalized span |
| Input evaluator hook | 2E4A8E0 |
2E4A820 |
Unique normalized span |
| FSD update hook | 2C71500 |
2C71440 |
Unique normalized span |
| Heat input observer | 38137E0 |
3813740 |
Unique normalized span |
| Body lookup hook | 3CEB400 |
3CEB360 |
Unique normalized span |
| Galaxy system-object lookup | 3C331E0 |
3C33140 |
Unique normalized span |
| Galaxy object load/poll | 3C359A0 |
3C35900 |
Unique normalized span |
| Name-to-address lookup | 3CEE0A0 |
3CEE000 |
Unique normalized span |
| Galaxy text search | 3CEB7C0 |
3CEB720 |
Unique normalized signature |
| Generated system name | 3CF14D0 |
3CF1430 |
Unique normalized span |
| NavRoute route mutation A | 26479C0 |
2647900 |
Unique normalized span |
| NavRoute route mutation B | 264BDF0 |
264BD30 |
Unique normalized span |
| NavRoute read getter | 2604E60 |
2604DA0 |
Unique normalized span |
| Cached local matchmaking mode | 1D53050 |
1D52F90 |
Unique normalized signature; remains a lazy initializer and must not be called by the read-only adapter |
| Friend/wing marker producer | 3AFF080 |
3AFEFE0 |
Unique bounded signature |
| System connector renderer | 3AF2E60 |
3AF2DC0 |
Unique bounded signature |
| System connector producer | 25FED60 |
25FECA0 |
Unique bounded signature |
The HeatTick observer at old 3814540 is only a six-byte wrapper with 28
identical matches. Its plausible nearby 38144A0 is not an independently
resolved hook target. That target needs a verified owner/vtable/caller witness.
Several short source functions have a single additional contextual candidate
without a unique intrinsic signature. Examples include original allocation
leaf 541CD0 -> 541C70, release 3C44980 -> 3C448E0, and pose-type getter
8AE6F0 -> 8AE690. The JSON keeps these in a separate
contextualFunctionCandidates collection rather than claiming unique matches.
The radius getter 3CF04B0 fails the automatic signature because its
.pdata span includes an inline switch table with absolute image-relative
entries. Manual candidate 3CF0410 has the same 217-byte range length and
matches after rebasing its four local table RVAs and encoded references.
radius-getter-manual-triage.json records every such field and zero remaining
differences. This is explicit manual triage, not an automatic hook approval.
Initial review list, with closure tracked separately
- Revalidate all hook calling conventions, original trampoline/relocation behavior, observer argument registers and owning-thread assumptions. Resolve HeatTick using original context rather than a nearby repeated byte sequence.
- Verify constructor/interface offsets, vtable order and interface adjustments for Galaxy, Names, NavRoute, registry, input, ship life and FSD. Candidate address equality does not establish lifetime or ownership invariants.
- Independently check copied account cache layouts: friends published
+220map; wing slots and local-user gate; cached mode/CSM; bookmarks; visited; exploration/trade; colonisation; power options; appearance palette trees. Keep uninitialised or unresponsive data unknown during that verification. - Review unmatched research bodies
1387A80,1388680,1399990,2175ED0,3B16B00,3B32DD0,3C3A1A4,3C3F440,3C3F5A0. An unmatched signature can reflect changed logic or embedded address data; it is not evidence that a simple delta is safe. - Resolve remaining source data addresses
51DAF4C,52406A0,5324DA8,5324DAC,5FDF490,5FDF494,5FDF498. The latter three are current appearance globals. Do not infer them solely from neighboring globals. - Keep separate exact-hash profiles; run isolated native fixtures for the new profile, then obtain actual read-only runtime evidence when the user next runs that client. This offline audit did not start the game or establish new-version live query coverage.
The offline renderer, filters and deterministic test fixtures can continue using verified pinned data while the new profile is reviewed. There is no reason to disable the version guard to continue that work.
Reproduction
The script requires pefile and capstone; the configured reverse-tool venv
already supplies them. Example from the repository root:
& 'C:/Users/XFEstudio/Desktop/work/AI/skill/game-client-to-server-reverse/.venv/Scripts/python.exe' -X utf8 research/Audit-GalaxyClientCompatibility.py
The generated JSON contains local source paths, static code fingerprints, sanitized completed-update log lines, matching depot hashes, vtable slot evidence and unresolved symbols. It contains no account names, user IDs or download authorization tokens. No game build or application build is needed.