4 Commits

Author SHA1 Message Date
Jacob Paullus 703070cbd1 registry: add tests for resident-length guards
Cover the GetValueData guard added in the previous commit with two
table-driven tests: the rejection path (dataLen ∈ {5, 8, 0xFF,
0x7FFFFFFF} with resident bit set) confirms the guard fires without
panicking and surfaces a helpful error; the happy path (dataLen ∈
{1, 2, 3, 4}) confirms the inline DataOffset bytes are returned
correctly so the guard didn't regress valid hives.

The matching guards in SetValueData (resident + non-resident write
paths) and enumSubKeys (riSig branch) require full NK/VK/sub-list
hive synthesis to exercise end-to-end; they're structurally identical
to the read-path guard and are validated by build/vet plus the lab
regression check on secretsdump. Worth a follow-up to extend the
synth helpers and cover them directly.
2026-05-11 23:54:22 -05:00
Jacob Paullus d6089390bd registry: harden hive parser against malformed inputs
Four parser-panic / silent-corruption bugs in pkg/registry/hive.go,
all reachable from attacker-controlled hive bytes:

1. GetValueData resident branch: VKRecord.DataLen lower 31 bits are
   read verbatim and used to slice a 4-byte buffer at [:dataLen]. A
   DataLen of 0x80000005 panics with "slice bounds out of range".
   Found by kajaaz using Zorya (issue #25); fix matches her suggested
   one-line bounds check.

2. SetValueData resident branch (structurally identical to #1): the
   existing len(newData) == dataLen check doesn't enforce the 4-byte
   cap, so a hostile dataLen=5 with a matching 5-byte newData slices
   one byte past the DataOffset field into the adjacent cell. Same
   guard.

3. SetValueData non-resident branch: vk.DataOffset is attacker-
   controlled and the code does copy(h.data[dataPos:dataPos+dataLen],
   newData) without ever validating the destination. Hostile offsets
   either panic on out-of-bounds or silently scribble over arbitrary
   hive bytes (a value of 0xFFFFF000 lands near the regf header). Route
   through readCell (which validates the cell header and bounds) and
   verify dataLen fits before mutating.

4. enumSubKeys riSig branch: readCell can return a slice shorter than
   the 4-byte cell header (minimum-size cell with no usable bytes), so
   the immediate subCell[0:2] / subCell[2:4] reads can panic on a
   malformed sub-list. The sibling code at line 397/437 already guards
   the analogous index; mirror it here.

Fixes #25 plus three structurally similar bugs surfaced while patching.
2026-05-11 23:48:10 -05:00
psycep 2ba52b5116 registry/hive: reject malformed cell sizes instead of panicking
readCell trusted the cell's size header without bounds-checking the
positive side, so any cell whose raw size field was 0 or a negative
value with absolute magnitude smaller than the 4-byte cell header
produced an inverted slice expression (h.data[pos+4 : pos+size] with
size < 4) and crashed the process. Reported as a runtime panic
`slice bounds out of range [5052:5048]` in secretsdump's cached
domain logon parse path.

Treat raw size >= 0 as free/invalid (return error) and require the
allocated size to be at least 4 bytes so the data slice is never
inverted. Regression test synthesizes a minimal hive with each of
the previously-panicking inputs.

Removes the now-resolved entry from KNOWN_ISSUES.md and renumbers
the remaining sections.
2026-04-23 15:23:59 -05:00
Jacob Paullus 160b6a4280 Initial commit 2026-04-17 14:20:41 -05:00