From 630295bd18bc6e2479075804aee719c624270724 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 21 Jun 2026 15:46:54 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20QueryTag=20native-RE=20attempt=20?= =?UTF-8?q?=E2=80=94=20lightweight=20tooling=20insufficient,=20needs=20Ghi?= =?UTF-8?q?dra?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC --- .../grpc-tag-query-odata.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/reverse-engineering/grpc-tag-query-odata.md b/docs/reverse-engineering/grpc-tag-query-odata.md index 26c18db..b86a97e 100644 --- a/docs/reverse-engineering/grpc-tag-query-odata.md +++ b/docs/reverse-engineering/grpc-tag-query-odata.md @@ -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.