| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The request entry splits on the opcode, sending values at or above 0x1000 to the 247-case
switch treated throughout this work as the dispatcher and everything below it to a
separate handler family that was never analysed. That family is recovered here and
recorded as a command map.
This invalidates the basis on which the XGMI callee-length finding was filed as latent.
The claim that the platform does not implement opcode 0xd came from checking only the
247-case switch, which serves no opcode below 0x1000. The small-opcode family has a case
for 0xd routing to a substantive handler that validates a length, calls one of the copy
sites already catalogued in this audit, and reports a result back to the caller, so the
precondition the finding was waiting on appears satisfied. The finding is reopened with
three concrete steps listed before it can be called exercisable.
The same family contains the poisoner and consumer of the open stack-overflow lead, at
opcodes 3 and 8/9 respectively.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Names alone left Hex-Rays emitting *(_DWORD *)(a1 + 7680) for the most important
expression in this audit, so this adds function prototypes and structure types, and
in the process corrects names that had drifted.
GCP logs AMD_TA_GCP: <Name> ENTER on entry to most handlers, which is ground truth.
fw/ta_name_audit.py checks every derived symbol against it and found 18 mismatches
in GCP, plus two false positives in WSPE where the logged words are ordinary prose.
Combined with a fresh decode of the dispatcher's two tbb tables, giving command to
handler address rather than the stale name-keyed map, this corrects: cmd 3 is
ActivateDRMCertAuthSession and was not defined as a function at all; FE03 to FE06
are unimplemented and share the error arm; FE07 is CreateAuthenticatedSession;
FE0C and FE0D are Create and DestroyCryptoSession; FE0A is QueryAuthenticatedSession
rather than the invented QueryAccessibilityAttributes; FE0E and FE0F likewise. The
hardware sweep independently agrees, since FE03 to FE06 all returned an identical
0x102 while FE07 alone returned 0, which had been sitting in the output mislabelled.
This also corrects a finding's wording: FE0B manages the stride-80 auth array and
FE0D the stride-88 crypto array, so they are two destroy paths over different
arrays rather than a same-type sibling pair. The in-database comment is updated,
including replacing its now-stale 'not yet shown' caveat with the hardware result.
Five structures declared and verified by reading the layout back from IDA and
comparing against the addressing the code performs; the three session arrays tile
the context exactly, which is the check. 179 prototypes applied across all twelve
TAs with no failures. Measured against a pristine database rather than one that
already carries the work: raw casts 81 to 7, anonymous parameters 113 to 0.
Method notes recorded: do not drive the TUI struct editor, since a focus change
types into the filter box and a half-applied redeclare silently truncated three
structs; declare interdependent structs in one parse unit; build prototypes from
the database rather than the stale dump; a type that misrepresents addressing is
worse than none, which is why the lvar retype was reverted; and two metric bugs
were caught only by disbelieving a number that flattered or unfairly punished the
work.
Adds fw/ta_ida.py, fw/ta_name_audit.py, fw/ta_rename_from_logstrings.py,
fw/cmdmaps/gcp_ea.json, fw/audits/name_vs_logstring.json and fw/pseudo/ artifacts.
|
|
|
All twelve TA types this card loads and invokes are now opened in idalib via
idatui, annotated and saved, with their command surfaces recovered.
Three tools carry the pass. ta_symbols.py statically recovers the info header
and the five TEE entry points from the ARM-mode trampoline, with a selftest
against HDCP 23.0.4.49 that must reproduce the dispatcher address and the
hand-read command set. It deliberately does not name command handlers any more:
its jump-table walk guessed the first bl after each arm, which is wrong when the
arm sets up arguments, and those wrong names persisted in the database and
shadowed the correct map, so every TA was re-analysed from a deleted database
once that was found.
annotate_ta.py takes the map from the decompiler's own output and applies it by
address, handling switch/case including the 1u suffix form and nested two-tier
switches, if/else-if chains, wrapper entries that tail-call the real dispatcher,
and callees that are already named. A third step promotes loc_ labels to
functions, because handlers are often reached as loc_XXXX)(args) where IDA never
made a function and the decompiler shows a cast-through-label that cannot be
renamed; that step alone took OPM from three recovered commands to nine.
Renaming is by address rather than token, since drive mv resolves names against
the current view and silently failed for six of fourteen GCP handlers.
Surfaces: GCP 21 commands, XGMI 12, OPM 9, POWERPLAY and FP and RAP 7, AUC and
MERIT 6, CSU 3, OC 2, WSPE 2, and TMZ none since it is a stub.
GCP is the most interesting of the twelve and is now fully named from its own 69
log strings: it is a DRM content-protection TA with a low family for session
lifecycle and content keys and a high 0xFE0x family for authenticated crypto
sessions, key exchange and key refresh. WSPE is fully resolved too, and shows
that the cmp constants the static pass saw were error codes rather than command
ids.
|