|
|
controls twice
Defining PSP structs by hand needs evidence, and the evidence is which offsets the code
touches through each pointer and at what WIDTH. This reads that out of Hex-Rays output rather
than re-implementing register dataflow: the decompiler has already resolved which register
held an argument, and it writes accesses in forms that state offset and width directly.
The value is in the control, and the control failed three times before it meant anything.
First failure was circular. Validating on GCP after the pipeline had already applied
GCP_DECLS meant the array accesses rendered as 'ctx->auth[i]', which the harvester skips by
design, so it was being asked to rediscover a layout from a database that already had it. The
control has to run on a freshly analysed, untyped build.
Second failure was real and the harvester's fault. Array bases are not written against the
argument: GCP computes 'v6 = a1 + 80 * HIBYTE(v4)' and then reads '*(_DWORD *)(v6 + 768)', so
0x300 only ever appears as an offset on the derived pointer. Scanning accesses through the
argument alone can never see an array base. One level of alias tracking fixes it, and a scaled
derivation is what distinguishes an array base from a field offset carried through.
Third failure was the control itself being wrong. Demanding the literal bases 0x300 and 0x800
is not satisfiable even in principle, because the index is folded into the derived pointer and
what is observable is base + FIELD -- the bare base shows up only when the field offset is
zero. The requirement is now that each known region is reached and that offsets seen inside it
lie within one element, which is what folding the index implies.
With that, GCP's proven layout is rediscovered from code alone: auth[16] at 0x300 stride 80
(offsets 0x304/0x318/0x348 -> fields 4/24/72), crypto[64] at 0x800 stride 88 (0x820 -> field
32), and asd_refcount exactly at 0x1E00. drm[32] at base 0 is excluded from the control
because offset 0 is indistinguishable from ordinary field access.
Caveat to carry into the authoring work: the 'a1[i]' index form is scaled by the pointer's
declared element width, so when Hex-Rays types an argument as _BYTE * the reported offsets are
byte-scaled and will not line up with dword fields. XGMI arg1 shows offsets 0x1/0x2/0x3 at
4-byte width from exactly this, and they should not be read as real fields.
|