Commit Graph
106 Commits
Author SHA1 Message Date
NK 1a7276b870 Update README: mark VHDX as tested (Win2003R2, Win2012R2) 2026-03-21 00:57:42 +01:00
NK 8bc31a4a36 Update README: document SAM account status and DPAPI dedup 2026-03-21 00:53:34 +01:00
NK 56632a865c Improve DPAPI and SAM display: account status, key dedup, NTFS 8.3 fix
- Show account status in SAM text output: (DISABLED), (NO PASSWORD),
  (BLANK PASSWORD) from per-user ACB flags in registry F value
- Add modification date to DPAPI master key text output from NTFS mtime
- Deduplicate DPAPI keys: show only most recent per user (--all for all)
- Filter NTFS DOS 8.3 short names in list_directory() — fixes S-1-5-~1
  SID leak from short name aliases
- Add cargo test step to CI workflow
2026-03-21 00:52:56 +01:00
NK 131a3693b2 Demote empty LSA secret warning to debug level 2026-03-21 00:10:32 +01:00
NK c336acb133 Fix DPAPI hashcat mode: distinguish local (15300/15900) from domain (15310/15910)
The hashcat mode depends on context (local vs domain user), not just the
crypto version. Domain users use NTLM pre-key derivation (modes 15310/15910)
while local users use SHA1 pre-key (modes 15300/15900). The context is
determined by whether a domain key section exists in the master key file.

Previously all hashes were reported as 15300 or 15900 regardless of context.
2026-03-21 00:06:07 +01:00
NK 52692984e6 Log warnings on I/O errors in file discovery instead of silently skipping
Previously, permission errors, mount failures, or I/O issues during VM
file discovery were silently swallowed with if-let-Ok patterns. On a NAS
with partial mounts or restricted permissions, this caused VMs to be
silently missed with no indication of the problem.

Now all I/O errors in discover.rs produce log::warn! messages:
- read_dir failures on scan directories
- metadata/stat failures on individual files
- file open failures in magic-byte checks (ELF, VMDK descriptor)

Added file_size() helper to centralize metadata reads with warnings.
2026-03-20 23:55:28 +01:00
NK 75f495134f Clean up magic numbers and improve readability
- savevm.rs: extract RAM_FLAG_MASK constant, remove unused _block_gpa_bases param
- lsa.rs: extract DES_KEY_SEGMENT constant, add [MS-LSAD] spec references,
  document key rotation algorithm with example
- cloudap.rs: extract MAX_PRT_SIZE constant, remove extra blank line
2026-03-20 23:31:34 +01:00
NK 58cc80abaf Add changelog generation to release workflow v1.3.0-beta.1 2026-03-20 22:53:10 +01:00
NK 6f0bd040b3 Bump version to 1.3.0-beta.1 and support pre-release tags in CI
Release workflow now marks tags containing -beta, -alpha, or -rc as
GitHub pre-releases.
2026-03-20 22:41:59 +01:00
NK 7ec43a1f59 Merge branch 'main' into dev
# Conflicts:
#	src/lsass/kerberos.rs
#	src/lsass/msv.rs
2026-03-20 22:38:15 +01:00
NK 9506c50bda Update README for QEMU savevm, embedded .vmsn, BitLocker, and legacy LSA support
- Add QEMU/Proxmox savevm and VMware embedded .vmsn to supported inputs
- Add ESXi 6.7 and Proxmox savevm test results to tested targets table
- Document BitLocker detection and QEMU savevm limitations
- Update target OS range to include Windows Server 2003
- Add Proxmox example to quick start
- Update module architecture and feature descriptions
2026-03-20 22:33:37 +01:00
NK 84ec71d5b9 Fix legacy LSA secret decryption (pre-Vista / Windows 2003)
Two bugs fixed:
1. LSA key derivation: MD5 input was salt+bootkey×1000 instead of
   bootkey+salt×1000 (wrong order per impacket/MS-LSAD spec)
2. Secret decryption: used RC4 instead of DES-ECB with rotating
   7-byte key segments (SystemFunction005 / [MS-LSAD] Section 5.1.2)

Implemented:
- DES-ECB decrypt with rotating key (des_ecb_decrypt_rotating)
- transformKey: 7-byte to 8-byte DES key expansion ([MS-LSAD] 5.1.3)
- LSA_SECRET_XP parsing: Length(4) + Version(4) + Secret(Length)

Tested on Windows Server 2003 R2 SP2 VHDX: DPAPI_SYSTEM keys and all
LSA secrets now decrypt correctly.
2026-03-20 22:27:59 +01:00
NK 313b0df30a Fall back to legacy LSA key when PolEKList is missing despite modern revision
Windows Server 2003 R2 SP2 reports PolRevision 0x10007 (modern) but uses
the legacy PolSecretEncryptionKey scheme. Try PolEKList first; if not found,
fall back to PolSecretEncryptionKey instead of failing.
2026-03-20 21:40:11 +01:00
NK 49a3991faa Detect BitLocker-encrypted partitions and warn the user
Check for the -FVE-FS- OEM ID in partition boot records before
attempting NTFS parsing. When BitLocker is detected, skip the
partition and display a clear error message instead of failing
silently with "No registry hives found".

Applied to SAM extraction, LSA secrets, and NTDS.dit extraction paths.
2026-03-20 21:33:51 +01:00
NK febbb0e4d9 Fix embedded .vmsn memory and hide machine account passwords
VMware layer:
- Fix base_offset not set when .vmsn has region tags but no separate
  .vmem file (embedded memory). Reads were at wrong file offset.
- Tested on ESXi 6.7 with Win Server 2016 embedded .vmsn snapshot.

Display:
- Don't display Kerberos/WDigest passwords for machine accounts (username
  ending with $) — they are binary blobs, not useful plaintext. The
  Kerberos keys (AES256, RC4=NT hash) are the exploitable forms.
- Don't count machine passwords in the summary line.
- Truncate long hex passwords to "(hex, N bytes) first32bytes..." when
  displayed for other non-printable passwords.
2026-03-20 21:27:51 +01:00
NK abb72761ab Add QEMU/KVM/Proxmox savevm state parser and improve System process discovery
New parser (src/qemu/savevm.rs):
- Parse QEVM magic, RAM block list, and page entries (PAGE/ZERO)
- MMIO gap remapping for q35+UEFI (below_4g=0x80000000)
- Skip non-RAM device sections (dirty-bitmap, etc.) via forward scanning
- HashMap-based deduplication for dirty page iterations (last-write-wins)
- Auto-detection via QEVM magic in format dispatcher

System process discovery improvements:
- Validate candidates by translating Flink VA to physical and checking the
  linked EPROCESS has a printable ImageFileName and valid kernel-mode Flink
- Rejects stale EPROCESS remnants with corrupted page tables

Tested on Proxmox VMs: DC25 (Win Server 2025, 4GB) and WKS11 (Win11, 8GB)
2026-03-20 19:28:54 +01:00
NK 552d444cfe Unify Kerberos credential extraction for x64/x86
- Merge 8 duplicated _x86 functions into single arch-aware implementations:
  walk_avl_tree, read_kerb_external_name, extract_kerb_password,
  extract_tickets_from_list, extract_single_ticket, detect_kerb_offsets,
  extract_kerb_keys, extract_kerberos_credentials
- All structure offsets computed from arch.ptr_size() and arch.ustr_size()
- Delete extract_kerberos_credentials_arch wrapper and all _x86 variants
- Net reduction: -580 lines
2026-03-20 19:27:19 +01:00
NK 649976e96a Unify MSV session and credential extraction for x64/x86
- Merge extract_msv_sessions_arch and extract_msv_credentials_arch into the
  main functions, selecting offset variants by arch at runtime
- Make all walkers arch-aware: walk_session_buckets, walk_session_list,
  walk_msv_list, walk_hash_table, find_inline_hash_table,
  find_credentials_ptr_in_entry
- Delete 258 lines of duplicated x86 code (extract_msv_sessions_arch,
  extract_msv_credentials_arch, try_extract_primary_cred_x86)
- x86 now gets scoring, enrichment, multi-pass credential scanning, and
  SHA1 validation — previously x64-only features
- Add variant_order_for_build_arch for x86 build-aware variant ordering
2026-03-20 19:26:55 +01:00
NK b0c8bcae49 Refactor LSASS providers: extract shared helpers and unify x64/x86 code paths
- Add read_ptr_from_buf, walk_list, read_data_section, scan_data_for_list_head
  to types.rs, eliminating ~200 lines of duplicated boilerplate across providers
- Unify kerberos.rs: merge 8 duplicated _x86 functions into arch-aware versions
  (walk_avl_tree, extract_single_ticket, read_kerb_external_name, etc.), -440 lines
- Fix CloudAP: read account name from toName_ptr (+0x58) instead of hashName (+0x68)
  which is a SHA hash, not the readable UPN. Add 3 offset variants (1507-1607,
  1703-1709, 1803+) with auto-detection. Remove useless hashName fallback.
- Fix walk_session_buckets using x64-only read_win_unicode_string and read_virt_u64
  for pointers — now uses arch-aware read_ustring and read_ptr
2026-03-20 19:26:30 +01:00
NK 35fc30e0a3 Add GitHub issue templates for bug reports and feature requests
Bug template requires: vmkatz version, input format, guest OS/arch,
host platform, filesystem, full command output, and file details.
Blank issues disabled to enforce structured reports.
2026-03-18 23:26:06 +01:00
NK d3ab21d11b Handle Kerberos ISO passwords, SmartCard PINs, and MSV CredentialKeys
Kerberos:
- Detect Credential Guard ISO-encrypted passwords (type==1 at cred+0x28)
  on Win10 1607+. Report as "(Credential Guard ISO)" instead of silently
  failing to decrypt.
- Extract SmartCard PINs from SmartcardInfos pointer (CSP_INFOS.PinCode)
  when regular password is empty. Stored as "[PIN] <pin>".
- Add smartcard_infos offset to KerbOffsets for Win10 1607+ variants.

MSV:
- Walk the KIWI_MSV1_0_PRIMARY_CREDENTIALS linked list via next pointer
  to find the "Primary" entry, instead of assuming the first entry is it.
- Recognize "CredentialKeys" (ANSI_STRING len=14) entries alongside
  "Primary" (len=7) during structure scanning and inline byte matching.
- Skip CredentialKeys entries (DPAPI key material already extracted by
  DPAPI provider) with a log message.
2026-03-18 00:17:04 +01:00
NK 3706710552 Add x86 EPROCESS offsets for Vista/Win7/Win8/8.1 and fix Vista x86 classification
- Add EPROCESS offset tables for Vista SP2 x86, Win7 SP1 x86, Win8/8.1 x86
- Fix is_prevista_x86 threshold: Vista x86 (PID=0x9C) uses AES/3DES like
  Win7+, not DES-X/RC4. Tighten cutoff from 0xA0 to 0x98.
- Update README: 18 offset tables, correct x86 support status
2026-03-18 00:03:20 +01:00
NK e2c078d4f7 Bump version to 1.2.2 v1.2.2 2026-03-17 23:27:00 +01:00
NK 06397923d2 Flip EPT scanning to opt-in and remove dev examples from repo
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.
2026-03-17 23:24:03 +01:00
NK 97d1d18c6f Support VBox 5.x-7.x PGM saved state versions in .sav parser
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.
2026-03-17 23:16:40 +01:00
NK 6a52381e46 Update README.md
- Split Quick Start into basic and advanced sections
- Fix binary size: ~5 MB → ~3 MB in ESXi deploy section
- Update module architecture tree with all source files:
  disk/ (vmdk, vdi, qcow2, vhd, vhdx, raw), sam/ (hive, bootkey,
  hashes, lsa, cache, dpapi_masterkey, ntfs_fallback), paging/
  (translate, entry, filebacked), pe/, utils
2026-03-17 14:42:46 +01:00
NK 4afa6eec69 Update README.md
- Add DPAPI master key hashes (hashcat 15300/15900) to disk extraction list
- Document missing CLI options: -r/--recurse, --scan, --provider, --no-ept,
  -v/--verbose, --build, --format brief
- Add brief format to output formats table
- Add dissect.vmfs (Fox-IT) and vmfs-tools to acknowledgements
2026-03-17 14:18:13 +01:00
NK 90074c601a Update README.md 2026-03-17 12:23:09 +01:00
NK 2f01b48258 Validate GPT entry size before allocation and slice access
Reject entry_size outside 128-4096 range to prevent:
- panic on slice &entry[0..16] when entry_size < 16
- OOM allocation from forged u32 entry_size
GPT spec mandates minimum 128 bytes per partition entry.
2026-03-17 02:16:51 +01:00
NK a1e0a65e7f Fix VDI parent resolution and coalesce_pages overflow
- 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.
2026-03-17 01:52:05 +01:00
NK 75b2351363 Fix cfg gate on fmt_lm_pwdump: sam feature, not ntds.dit
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).
2026-03-17 01:48:26 +01:00
NK 09dae5b16c Cap QCOW2 L1 table allocation and fix VMware tag parsing
- 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
2026-03-17 01:41:56 +01:00
NK 873c93357d Validate NTFS boot sector cluster_size and record_size
Reject zero values parsed from untrusted NTFS metadata to prevent
division-by-zero panics in cluster offset and MFT record calculations.
2026-03-17 01:40:05 +01:00
NK f99b1a4c74 Guard VMware parser against malformed .vmsn files
- 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)
2026-03-17 01:33:35 +01:00
NK e538e27209 Harden SAM/ESE/VMFS parsers against malformed inputs
- 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
2026-03-17 01:29:33 +01:00
NK f798f59224 Harden parsers against malformed inputs
- MSV: propagate arch parameter instead of hardcoding Arch::X64,
  fixes credential extraction on x86/WoW64 processes
- VMDK: validate grain_size != 0 and numGTEsPerGT != 0 (div-by-zero)
- VMDK: reject extent number 0 in parse_extent_number (underflow)
- VHDX: validate block_size and logical_sector_size != 0
- VHD: validate block_size != 0 in dynamic header
- VMFS: guard file_block_size, clusters_per_group, and
  parent_resources_per_group against zero (div-by-zero)
- QEMU ELF: use checked arithmetic for program header offsets
- VMware tags: bounds-check data_size before advancing parse position
- Process walk: guard flink_phys underflow in enumerate_processes
2026-03-17 01:22:11 +01:00
NK 1658606d1a Bump version to v1.2.1
- Fix SSP decryption: use AES-CFB-8 instead of CFB-128 (matches mimikatz)
- Fix machine account password display: raw hex instead of lossy UTF-16
- Truncate decrypted passwords to UNICODE_STRING.Length (drop padding)
v1.2.1
2026-03-16 23:34:33 +01:00
NK 5115e632ef Fix lossy password decoding for machine accounts
- 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
2026-03-16 23:28:18 +01:00
NK 5f24e8f528 Add missing vmrs.rs module 2026-03-16 23:02:10 +01:00
NK dab403c139 Bump version to v1.2.0
- Fix SSP decryption: use AES-CFB-8 (8-bit segments) instead of CFB-128.
  SSP is the only LSASS provider using CFB-8 (mimikatz: KP_MODE_BITS=8).
  Previously produced garbage output for SSP passwords.
- Fix .vmsn hang: mmap metadata instead of loading entire multi-GB file
- Reduce EPT scan budget (4GB cap, 1GB gap) for faster non-VBS bail-out
- Fix crash on ESXi: spawn 8MB stack thread (ESXi default is 512KB)
- Add credential deduplication: merge duplicate sessions by default (-a for all)
- Add version banner at startup
- Fix snapshot labels: recognize .vmss and .vmrs extensions
- Add Hyper-V VMRS saved state support
- Add Clone derives on credential types
v1.2.0
2026-03-16 22:57:08 +01:00
NK 55aa12199c Update README.md 2026-03-16 18:08:30 +01:00
NK 9014a3f2ef Bump version to v1.1.1
- Fix .vmsn hang: use mmap instead of fs::read for metadata parsing,
  avoiding multi-GB allocation on embedded memory snapshots
- Reduce EPT scan budget (4GB cap, 1GB gap limit) for faster bail-out
  on non-VBS VMs (70s → 10s on 16GB snapshot)
v1.1.1
2026-03-16 18:05:57 +01:00
NK f6001f8a0b Bump version to v1.1.0
New features: VMFS-6 raw SCSI parser, native Hyper-V VMRS parser.
v1.1.0
2026-03-10 11:01:47 +01:00
NK 9c74207520 Expand VMFS-6 section with discovery, auto-scan, and internals
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.
2026-03-10 10:55:32 +01:00
NK 8ddbcd28c4 Update README with VMFS-6 raw parser and Hyper-V VMRS support
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)
2026-03-10 10:53:45 +01:00
NK 6c35d9f242 Add VMFS feature flag, device enumeration, and fix all clippy warnings
VMFS module:
- Gate behind `vmfs` Cargo feature (included in defaults, depends on sam)
- Add --vmfs-list to discover VMFS-6 devices and flat VMDKs on ESXi
- Add --vmfs-device/--vmdk auto-scan with NTFS partition pre-check
- Fix label reading: use data_offset at LVM header 0x7A (not 0xC8)
- Filter out duplicate vml. symlink devices

Clippy fixes across all feature combinations:
- Remove unused fields, methods, constants in vmfs.rs
- Remove redundant `as u64` casts, use div_ceil()
- Gate MSSK_TAG and fmt_lm_pwdump behind their feature flags
- Simplify boolean expressions in ntfs_fallback.rs
- Suppress unit-type warnings for PagefileRef/DiskPathRef cfg stubs

Zero warnings on: --features vmware, all-except-vmfs, --all-features.
2026-03-10 03:01:13 +01:00
NK 2beb89a745 Add resilient I/O for reading live/in-use block devices
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.
2026-03-10 03:00:59 +01:00
NK 0a1febd8f0 Add VMFS-6 raw parser for direct ESXi SCSI device access
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.
2026-03-10 02:31:40 +01:00
NK a386bc19d5 build: replace env_logger with inline logger (3.0M → 2.3M)
env_logger pulled in regex + jiff (~700KB). Replace with a 10-line
SimpleLogger that writes to stderr. Same behavior, zero dependencies.
v1.0.0
2026-03-09 16:53:27 +01:00
NK 85348ed84f build: optimize binary size (4.0M → 3.0M)
- Add opt-level = "z" to release profile (size-optimized codegen)
- Remove redundant strip/editbin steps from CI (strip = true in Cargo.toml
  already handles all targets)
- Remove redundant --features "ntds.dit" (already in default features)
2026-03-09 16:39:30 +01:00