When Windows drops DLL .text pages from the working set, it zeros the
PTE knowing the data can be re-read from the DLL file. This commit
reads DLL files from the disk image via NTFS and serves those pages
when a zero-PTE fault occurs in a known non-writable DLL section.
Architecture:
- FileBackedResolver reads PE files from disk, extracts non-writable
sections (.text, .rdata), maps them to module_base + VirtualAddress
- Binary search resolves VA to on-disk section data
- Integrated into ProcessMemory::read_virt() as fallback on PageFault
- Works synergistically with pagefile resolution (DLL .text enables
pattern scans that discover structures whose data pages are in pagefile)
Results on VMware test snapshots:
- 472 sections loaded from 93 DLLs (~40 MB)
- 12,020 DLL pages resolved from disk per snapshot
- 2,235 pagefile pages resolved (up from 0 without file-backed)
- New --disk flag for single-file mode, auto-discovered in folder mode
When page table pages (PDPT/PD/PT) are themselves swapped to
pagefile.sys, the parent entry becomes a pagefile PTE. The new
translate_with_pagefile() method resolves page table pages from
the pagefile at each walk level before continuing translation.
Also wire pagefile into ProcessMemory::read_virt() to resolve
data pages that are in pagefile (PageFileFault handling).
Phase 2c: fragmented hive assembly from scattered hbin blocks.
When registry hives are fragmented by NTFS (regf header at one location,
hbin blocks scattered across non-contiguous clusters), the grain scan now:
- Collects ALL hbin blocks during grain scan (not just offset=0 roots)
- Groups blocks by offset_in_hive into a candidate map
- Backtracking DFS (small hives ≤256KB): proximity-sorted candidates,
strict then relaxed validation fallback
- Greedy assembly (large hives): first-match with zero-filled gaps
- Two-tier validation: strict (expected subkeys) → structural (root name)
- Broadened regf path matching for SYSTEM/SECURITY hives
- Default bins_size inference when no matching regf header exists
For incomplete delta disks (e.g., Windows10vstdio with 50% missing extents),
hives are now found and the error is specific ("Select not found" vs
generic "SYSTEM not found").
- Add scan_all_grains() to VmdkDisk: iterates physically allocated grains
bypassing LBA translation, for fast scanning of incomplete VMDK images
- Add grain-direct fallback in SAM extraction pipeline: scans grains for
regf/hbin signatures, assembles hives from virtual disk space
- Fix NK root key detection: remove KEY_HIVE_ENTRY (0x04) flag requirement
since SAM's root key only has KEY_COMP_NAME (0x20)
- Add offset_in_hive validation when reading contiguous hbin blocks to
prevent mixing blocks from different hives
- Add hive content validation (Select/Domains/Policy subkey checks) to
reject false matches from non-system config hives
Two bugs fixed:
- Wrong AES mode: was using AES-256-CBC, should be AES-256-ECB
(confirmed by mimikatz CRYPT_MODE_ECB, impacket per-block CBC
reinit, pypykatz AESModeOfOperationECB)
- Wrong LSA key offset: PolEKList Secret is NT6_SYSTEM_KEYS struct
(per mimikatz), actual key at offset 68 in decrypted blob, not 44
DefaultPassword now decrypts correctly (was garbled), DPAPI_SYSTEM
now shows correct 44-byte structure with valid version field.
When a VM directory contains both memory snapshots and disk images,
open pagefile.sys from the VMDK/VDI/QCOW2 disk to resolve pages
that Windows swapped out. Uses pre-built NTFS data run map with
RefCell<Box<dyn DiskImage>> for interior mutability.
- PTE pagefile detection (bits 0/10/11 + pagefile number/offset)
- PageFileFault error variant in page table walker
- PagefileReader: opens disk, extracts pagefile.sys data runs,
binary-search page resolution
- --disk CLI option for explicit disk image in single-file mode
- Folder mode auto-discovers disk and opens pagefile automatically
- Feature-gated behind "sam" (requires NTFS + disk image support)
- Makefile with release/debug/strip/install/check/clippy/test targets
- Show full help with examples when run without arguments (instead of
cryptic clap error)
- Add --version flag, EXAMPLES section, supported input types in help
- Validate --format to text|csv|ntlm
EPROCESS.ImageFileName is a fixed 15-byte field, causing names like
"fontdrvhost.ex", "StartMenuExper", "VGAuthService." to be truncated.
Now reads PEB → ProcessParameters → ImagePathName (UNICODE_STRING) using
each process's own DTB for address translation, extracting just the
filename. Falls back to the 15-byte ImageFileName for kernel processes
(PEB=0) or when PEB pages are paged out.
- Skip PID 0 (System Idle Process) in enumeration: has no valid DTB,
PEB, or name, only adds noise to the listing
- Filter ImageFileName to printable ASCII to prevent replacement
characters from non-UTF8 bytes (e.g. 0xFF fill in Idle process)
- Add hbin-based fallback scan for NTFS-fragmented hives where regf
header and hbin data are at non-contiguous disk locations
- Validate hive sizes: reject SYSTEM < 512KB and SAM < 16KB to avoid
false matches (e.g. 28KB volatile "System" hive)
Three extraction modes:
- LSASS: credentials from .vmem/.vmsn/.sav snapshots (9 SSP providers)
- SAM: NT/LM hashes + LSA secrets from .vdi/.vmdk/.qcow2 disk images
- Folder: auto-discover and process all VM files in a directory
Key features:
- VMware twoGbMaxExtentSparse VMDK with snapshot chain support
- VMDK descriptorless mode for orphan extent files with gap handling
- VirtualBox .sav SSM format with LZF decompression
- VDI dynamic/differencing images with parent chain
- QCOW2 L1/L2 address translation with backing file chain
- MBR/GPT partition tables, NTFS navigation via ntfs crate
- Raw regf + hbin scan fallbacks for incomplete disk images
- Hive size validation to reject false matches
- All 9 mimikatz SSP providers with physical scan fallbacks