docs: QueryTag native-RE attempt — lightweight tooling insufficient, needs Ghidra

Recorded the native-disassembly attempt on aahClientManaged.dll (mixed-mode):
ilspycmd cannot decompile it; capstone byte-search can't locate the StartTagQuery
0x6751 marker (not a plain immediate — it's an .rdata constant loaded RIP-relative,
the .text "51 67 00 00" hits are coincidental jump-table data). Managed metadata
gives QueryTag field semantics but not the binary packet-id. Finishing QueryTag
needs Ghidra/IDA xref analysis or the live IL-rewrite capture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
Joseph Doherty
2026-06-21 15:46:54 -04:00
parent 4c9f0d476c
commit 630295bd18
@@ -51,3 +51,22 @@ discipline: no guessed wire bytes).
Probe helpers live in `Grpc/HistorianGrpcTagClient` (`ProbeStartTagQuery`, `ProbeTagQuerySequence`)
and the gated `StartTagQuery_OverGrpc_AcceptsODataFilter` test pins the StartTagQuery+OData result.
### Native-RE attempt (2026-06-21) — needs Ghidra/IDA
The QueryTag packet-id is built in native code (the C++ HCAL inside the **mixed-mode**
`aahClientManaged.dll`). Lightweight tooling was exhausted and is insufficient:
- **ilspycmd** cannot decompile or even list the mixed-mode assembly (throws).
- **capstone** byte-search: the StartTagQuery marker `0x6751` is **not** a plain `mov` immediate in
`.text` (no `66 C7 … 51 67` and no clean `B8 51 67 00 00`); the three `51 67 00 00` hits in `.text`
are coincidental jump-table data (disassembly around them is garbage). The constant lives in the
`.rdata` pool (which holds the `51 67` bytes) and is loaded RIP-relative — so the serializer can't be
found by immediate-scanning without cross-reference analysis.
- Managed metadata (`ArchestrA.CloudHistorian.Contract`) gives the field semantics —
`QueryTagRequest{SessionId, QueryHandle:uint, QueryType:ushort, StartIndex:uint, TagCount:uint}`,
DataContract code `QTLQ` (StartTagQuery = `TLQR`) — but **not** the binary packet-id/framing.
Finishing QueryTag therefore requires **Ghidra/IDA** (decompiler + xref to the `.rdata` marker constant
to find the serializer and read the QueryTag packet-id + byte layout), or the **live capture** option
(IL-rewrite `Archestra.Historian.GrpcClient.QueryTag` to log `requestBuffer` while a real 2023 R2
client browses). StartTagQuery (the hard OData part) remains cracked and live-verified.