mirror of
https://github.com/mandiant/gopacket
synced 2026-06-21 13:57:02 +00:00
8127aece41
Rewrites the hand-rolled DRS_MSG_GETCHGREPLY_V6 parser as a declarative NDR struct walker. The old parser used empirical byte offsets that were wrong in several places and drifted out of alignment within the first few REPLENTINFLIST entries, so secretsdump emitted zero NTDS hashes against any modern DC (issue #9). New files: pkg/dcerpc/drsuapi/ndr.go - NDR Decoder primitives: alignment, conformant arrays, pointer referents, UTF-16LE strings, GUIDs, with a sticky error model so partial results survive downstream faults. pkg/dcerpc/drsuapi/getncchanges_v6.go - V6/V7/V9 reply parser driven by MS-DRSR struct definitions. Correctness points that were wrong in the old parser: 1. V6 fixed header is 148 bytes, not 136. The old code omitted cNumValues + rgValues + dwDRSError and treated those 12 bytes as pNC's DSNAME. 2. DSNAME.StringName is a pure conformant array (NDRUniConformantArray), not conformant-varying. No Offset/ActualCount between NameLen and the WCHAR elements. 3. UPTODATE_VECTOR is V2_EXT on current DCs: 32-byte cursors (UUID + USN + DSTIME), not the V1 24-byte cursors the old parser hard-coded. 4. REPLENTINFLIST is serialized as a linked list via pNextEntInf. NDR uses strict DFS through the first-encountered pointer in each struct, which lays out all N fixed parts consecutively, then the non-pNext deferreds (pName, pAttr, pParent, pMeta) unwind bottom-up - the deepest node's appear first, the head's last. The parser iterates captured headers in reverse to match. 5. PROPERTY_META_DATA_EXT_VECTOR alignment: the array's MaxCount is hoisted to the front by NDR early conformance, but hoisted MaxCount uses only its primitive (4-byte) alignment. The struct's 8-byte alignment applies AFTER MaxCount, before cNumProps and the elements. Getting this wrong drifted every entry whose prior pParent UUID landed on a 4-aligned (non-8-aligned) position. Verification against live GOAD sevenkingdoms.local DC: 17/17 NTDS password hashes (Administrator, krbtgt, vagrant, KINGSLANDING\$, ESSOS\$, NORTH\$, and all domain users) match impacket-secretsdump byte-for-byte. Independent Python byte-level reference walker confirms the same 17 unicodePwd-bearing entries offline. Also removes ~950 lines of the now-unreachable legacy V6 helpers (parseGetNCChangesResponseV6, skipDSNAME, skipUpToDateVector, skipPropertyMetaDataExtVector, parsePrefixTable, parseREPLENTINFLIST, parseENTINF, findValidDSNAME, parseDSNAMEIntoObject, parseATTRBLOCK) from getncchanges.go. Closes #9.