EPT scanning (for VBS/Credential Guard VMs) is now disabled by default
and enabled with --ept, since the vast majority of VMs don't use VBS.
Previously it was enabled by default and disabled with --no-ept.
Also remove examples/ (dev-only test utilities) from tracking.
The PGM struct fields size varies by VirtualBox version:
- v14 (VBox 7.x): 78 bytes — existing behavior
- v12-13 (VBox 5.x-6.x): 74 bytes — no cBalloonedPages field
- v11 (VBox 4.1+): 70 bytes — pre-balloon support
Previously hardcoded to skip(78), which corrupted RAM extraction
for any .sav file not from VBox 7.x. Now reads the PGM unit
version from the unit header and adapts accordingly.
- VDI: search for location= attribute AFTER the UUID match, not in a
window that extends 200 bytes before it. Prevents picking a location
from a different HardDisk entry in multi-disk .vbox files.
- dump: use saturating_add/sub in coalesce_pages to prevent u64
overflow on kernel addresses near 0xFFFFFFFFFFFFF000.
The function is used by both SAM and NTDS output paths. Gating it on
ntds.dit broke compilation when sam was enabled without ntds.dit
(e.g. --features sam or --features vmfs).
- QCOW2: cap l1_table pre-allocation to 1M entries to prevent OOM
from forged l1_size in header (actual entries read from file)
- VMware tags: validate all index bytes are available before parsing,
break out of tag loop instead of producing truncated indices
- Bounds-check tag_start before slicing vmsn_data (prevents panic on
forged memory_group.offset beyond file size)
- Cap Vec::with_capacity for group_count based on actual data size
(prevents OOM from forged u32 in header)
- Cap regions Vec::with_capacity to 4096 (prevents OOM from forged
regionsCount tag value)
- SAM hashes: use saturating_add + checked_add for V-value offset
calculations to prevent overflow on crafted hive data
- ESE: check tag_idx overflow in read_tag before subtraction from
page_size (prevents wrap-around on large tag indices)
- ESE: explicit guard last_var_id < 128 in variable column parsing
to prevent underflow in offset table size calculation
- VMFS flat VMDK: guard block_size == 0 in resolve_position and Read
impl to prevent division by zero on corrupt superblock
- Truncate decrypted password to UNICODE_STRING.Length bytes (was using
MaximumLength, including garbage padding after the actual data)
- Add decode_password_bytes: hex-encode raw bytes directly for binary
passwords instead of round-tripping through lossy UTF-16LE decode
(char::REPLACEMENT_CHARACTER destroyed original bytes)
- Apply to all providers via decrypt_unicode_string_password_arch and
the SSP-specific CFB-8 variant
- Update CSV/text output to use raw hex for binary passwords
Detail the --vmfs-list device discovery with example output, single-VM
vs auto-scan extraction modes, NTFS partition filtering for batch mode,
and the on-disk resolution chain diagram.
Add documentation for two major new features:
- VMFS-6 raw SCSI device parser that bypasses ESXi file locks on running VMs
- Native Hyper-V .vmrs saved state parser (reverse-engineered, no Microsoft DLL)
On Proxmox (and ESXi with VMFS), reading disk images of running VMs
can hit transient I/O errors on individual sectors/clusters that are
temporarily locked by the hypervisor.
Instead of aborting on the first read error, all NTFS and registry
hive reading paths now use block-level resilient I/O:
- read_from_data_runs: reads 4KB blocks individually, zero-fills
blocks that fail, and continues to the next block
- resilient_read_blocks: MFT batch reads zero-fill failing records
instead of skipping entire batches
- read_file_data (ntfs_reader): falls back to chunked 4KB reads
when exact read fails
- Partition table parsing: skips unreadable GPT entries gracefully
- Hive scanning: skips unreadable chunks instead of aborting scan
- MFTMirr: accepts records without FILE signature check on first
extent (live VMs may have transient I/O on header sectors)
- $ATTRIBUTE_LIST parsing for extension MFT records (large hives)
Tested on Proxmox with running Win11 and DC VMs — extracts SAM/SYSTEM
hives and NTDS.dit successfully despite scattered I/O errors.
Self-contained VMFS-6 parser that reads flat VMDKs directly from raw
SCSI partition devices, bypassing VMFS file locks on running VMs.
Key features:
- Full VMFS-6 on-disk format parsing: LVM, superblock, FDC, SBC, PB/PB2
- Directory traversal with allocation map and entry bitmap support
- Block map building with batched PB reads (320 reads vs 262K individual)
- Sub-block resolution for small files via SBC resource metadata
- Auto-scan mode: enumerates all VMs, skips non-Windows VMDKs
- NTFS-only extraction for fast batch scanning
Verified on ESXi 8.0 datastore: 73 VMDKs scanned in <2min, 4 Windows
VMs with SAM hashes + LSA secrets + DCC2 cached credentials extracted.
SHA1 cross-validation only works for machine accounts (where
ShaOwPassword = SHA1(NTHash)). For human accounts, ShaOwPassword =
SHA1(UTF16LE(password)), so the entropy fallback could pick the wrong
offset variant (reading DPAPI Protected field as NT hash).
Two fixes:
- Track SHA1-validated variant across credentials in same LSASS process
(same Windows build → same offsets). Reuse for subsequent credentials.
- DPAPI cross-check: when isDPAPIProtected=1, reject entropy candidates
whose NT hash matches the DPAPIProtected field at offset 0x6A.
Verified: Administrator NT hash now correct (09f6ff15...) on both
Citrix DC snapshots, matching pypykatz ground truth.
- Extract pKeyList keys even when credential substructure is paged out
- Physical scan for KIWI_KERBEROS_KEYS_LIST_6 structures in LSASS pages
- Match key groups to credentials via RC4 key = NT hash correlation
- Merge Kerberos credentials by username/domain when LUID is unknown
- Remove duplicate DPAPI line (was always same as SHA1)
- Hide all-zero LM hashes in output
- --kirbi <DIR>: export individual .kirbi files per ticket
- --ccache <FILE>: export all tickets as MIT Kerberos ccache v4 format
- Uses actual Kerberos name types from ticket data for ccache principals
- Sanitizes filenames for cross-platform compatibility
Read KIWI_KERBEROS_KEYS_LIST_6 from the session entry's pKeyList
pointer, parse KERB_HASHPASSWORD_6[_1607] entries, decrypt and
extract AES128, AES256, RC4 (NTLM), and DES key material.
Offsets for Win10 1607+, Win10 1507, Win8, and Win7 variants.
Keys are displayed in both text and Display formats.
This closes the gap vs pypykatz which extracts these keys from
minidumps. VMkatz now extracts passwords, keys, and tickets.
Add LUID and username validation to reject phantom sessions caused by
wrong MSV struct offsets being applied to valid memory. Filters:
- LUID must have high 32 bits zero (real Windows LUIDs are 32-bit)
- Username must contain at least one alphanumeric char, no file paths
or control characters
Tested on SilverFort-AD (Server 2022 DC, 32GB): eliminates 3 false
sessions while preserving all 10 legitimate ones.
Accept multiple positional arguments and auto-detect file types by magic
bytes (ESE 0xEFCDAB89, registry "regf", minidump "MDMP").
- Raw NTDS.dit + SYSTEM hive: extracts AD hashes without a disk image
- Raw SAM + SYSTEM [+ SECURITY]: extracts local hashes, LSA secrets,
and cached domain credentials from exported registry hives
- Auto-detects which hive is SYSTEM (bootkey extraction), SAM, or
SECURITY — argument order does not matter
- Helpful error messages for incomplete inputs (e.g. NTDS without SYSTEM)
- LSASS minidump detection with guidance to use pypykatz (parser planned)
- Full backward compatibility with existing single-file workflows
- Fix ESE parser for 32KB large pages (Win Server 2025): use 80-byte
page header and 12-bit tag count for pages >=16KB
- Move NTDS code from src/sam/ to src/ntds/ module (ese.rs + mod.rs)
- Enable ntds.dit feature by default in Cargo.toml
- Fix conditional compilation warnings across all feature combinations
- Add test examples for ESE parser and end-to-end NTDS extraction
- Update README with NTDS usage, examples, and test results
Verified against 4 domain controllers:
- 3x Win Server 2019 (8KB pages, GOAD lab): 18/19/15 hashes
- 1x Win Server 2025 (32KB pages): 8 hashes
All hashes match impacket-secretsdump (which itself fails on 32KB pages).
- Fix DCC2 cached credentials: use NL$KM[0:16] as AES key instead of
[16:32]. The secret is already stripped of its LSA_SECRET_BLOB header,
so [16:32] was a double offset producing garbage decryption.
- Fix GMSA secrets: display managed service account passwords as hex
instead of trying to decode binary data as UTF-16LE.
- Add raw block device support for LVM thin volumes (/dev/pve/...).
Auto-detect block devices and route to SAM extraction. Use seek-to-end
for device size since metadata().len() returns 0 for block devices.
- Update README with Proxmox LVM test results and Server 2025 support.
- New --format hashcat: outputs NTLM hashes (mode 1000) and DCC2 (mode 2100)
for direct use with hashcat
- Raw disk support: handles flat VMDKs (-flat.vmdk) and raw images (.raw/.img/.dd)
as simple seek+read without sparse container parsing
- EPT walker: scans for nested hypervisor page tables (VBS/Hyper-V) when
System process not found in L1 physical memory, translates L2→L1 addresses
through Extended Page Tables to access Windows kernel structures
- Debug logging for System process scan near-misses (DTB/Flink rejections)