- Introduction
- Quick Start
- Basic Usage
- Advanced Features
- Python Scripting
- Common Workflows
- Output Interpretation
- Best Practices
inVtero.net is a memory forensics tool that analyzes physical memory dumps to extract processes, detect hypervisors, and perform virtual machine introspection. Unlike traditional tools, it doesn't require OS-specific profiles or configuration.
- ✅ Detect and extract processes from memory dumps
- ✅ Identify nested hypervisors (VMware, Xen)
- ✅ Work with multiple OS types (Windows, Linux, BSD)
- ✅ Verify code integrity using cryptographic hashes
- ✅ Support multiple dump formats (.vmem, .vmsn, .dmp, .raw, .xendump)
- ✅ Provide Python scripting interface for custom analysis
- ✅ Resolve symbols automatically from Microsoft symbol server
| Format | Description | Source |
|---|---|---|
.vmem |
VMware snapshot memory | VMware Workstation/ESXi |
.vmsn |
VMware suspended state | VMware Workstation |
.dmp |
Windows crash dump | Windows blue screen |
.raw, .dd |
Raw memory dump | Various acquisition tools |
.xendump |
Xen memory dump | Xen hypervisor |
| Generic | Flat binary file | Custom tools |
# Basic analysis
quickdumps.exe -f "C:\dumps\memory.dmp"
# Save results to file
quickdumps.exe -f "C:\dumps\memory.dmp" > analysis.txtcd inVtero.core/quickcore/bin/Release/net6.0
dotnet quickcore.dll -f "/path/to/memory.dump"# Windows
cd Scripts
ipy Analyze.py
# Edit MemList in Main.py or Analyze.py to point to your dumpsSyntax:
quickdumps [options]
Common Options:
-f <file> Specify memory dump file
--save Save analysis state
--load Load previous analysis state
--verbose Enable verbose output
--generic Force generic scanning (for unknown OS)
Example:
quickdumps.exe -f "Windows2016.vmem" --save --verboseProcess CR3 [00000002DD41F000] File Offset [0000000293A12000] Type [Windows]
159 candidate process page tables found
- CR3: Page table base register value (process identifier)
- File Offset: Location in dump file
- Type: Detected OS type
Hypervisor: VMCS revision field: 16384 [00004000]
Hypervisor: Windows CR3 found [00000000016A0000] @ PAGE/File Offset = [00000001262DA000]
- VMCS: Virtual Machine Control Structure detected
- Shows nested VM instances and their CR3 values
MemberProces: Group 1 Type [Windows] Group Correlation [100.000%] PID [1AB000]
MemberProces: Group 1 Type [Windows] Group Correlation [90.909%] PID [16A0000]
- Groups processes by shared memory regions
- High correlation = same VM/OS instance
- Multiple groups = multiple VM instances or nested VMs
After detection, processes are grouped and can be accessed via the API or scripts.
For dumps with sparse storage (e.g., from EnCase):
copts = ConfigOptions()
copts.ForceSingleFlatMemRun = True # Treat as contiguous
copts.FileName = "memory.dump"Scan for specific OS or hypervisor types:
from inVtero.net import PTType
copts.VersionsToEnable = PTType.Windows # Windows only
copts.VersionsToEnable = PTType.LinuxS # Linux only
copts.VersionsToEnable = PTType.FreeBSD # FreeBSD only
copts.VersionsToEnable = PTType.VMCS # Hypervisors only
copts.VersionsToEnable = PTType.GENERIC # All typesAutomatic symbol downloading:
from System import Environment
# Set symbol path before analysis
sympath = "SRV*C:\\Symbols*http://msdl.microsoft.com/download/symbols"
Environment.SetEnvironmentVariable("_NT_SYMBOL_PATH", sympath)
# Load symbols for a process
kvs = proc.ScanAndLoadModules()# Extract entire address space to file
proc.DumpASToFile("output.bin")
# Extract specific virtual address range
mem_region = proc.MemAccess.ReadVirtualMemory(0x7FF00000, 0x1000)from inVtero.net.Hashing import HashDB
# Verify process code pages against known hashes
hashdb = HashDB()
integrity_map = proc.VerifyIntegrity(hashdb)
# Check for modifications
for addr, hash_result in integrity_map:
if hash_result.Modified:
print(f"Modified page at: {addr:016X}")import clr
import System
clr.AddReferenceToFileAndPath("inVtero.net.dll")
from inVtero.net import *
# Configure options
copts = ConfigOptions()
copts.FileName = "C:\\dumps\\memory.dmp"
copts.VersionsToEnable = PTType.GENERIC
# Analyze
vtero = Scan.Scanit(copts)
# Access detected processes
for proc in vtero.Processes:
print(f"Process CR3: {proc.CR3Value:016X}")
print(f"Type: {proc.PT.RootTableType}")Example from Analyze.py:
def WalkProcListExample(vtero, proc):
"""Walk the Windows EPROCESS list"""
# Get kernel symbols
kvs = proc.ScanAndLoadModules()
# Find PsActiveProcessHead
ps_head_addr = kvs.PsActiveProcessHead
# Get _EPROCESS type
eproc_type = kvs.GetTypeInfo("_EPROCESS")
# Walk the list
current = ps_head_addr
while True:
# Read EPROCESS structure
eproc = proc.GetStructure(current, eproc_type)
# Extract process name
image_name = eproc.ImageFileName
pid = eproc.UniqueProcessId
print(f"PID: {pid} Name: {image_name}")
# Next entry
current = eproc.ActiveProcessLinks.Flink
if current == ps_head_addr:
break# Scan physical memory for a byte pattern
pattern = b"\x4D\x5A\x90\x00" # MZ header
matches = vtero.MemAccess.ScanFor(pattern)
for match_addr in matches:
print(f"Found pattern at: {match_addr:016X}")Using dynamic types:
# Define structure layout
class MyStruct:
def __init__(self, mem, addr):
self.field1 = mem.ReadUInt64(addr)
self.field2 = mem.ReadUInt64(addr + 8)
self.name = mem.ReadString(addr + 16, 32)
# Use it
my_struct = MyStruct(proc.MemAccess, 0x12345000)
print(my_struct.name)graph LR
subgraph "📥 Input"
A[Memory Dump]
end
subgraph "🔄 Common Workflows"
B[Extract All<br/>Processes]
C[Verify System<br/>Integrity]
D[Dump Specific<br/>Process]
E[Nested VM<br/>Analysis]
F[Malware<br/>Hunt]
end
subgraph "📤 Output"
G[Process List]
H[Integrity Report]
I[Memory Dump]
J[VM Extraction]
K[YARA Matches]
end
A --> B
A --> C
A --> D
A --> E
A --> F
B --> G
C --> H
D --> I
E --> J
F --> K
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:3px,color:#000
style B fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000
style C fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000
style D fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
style E fill:#fce4ec,stroke:#c2185b,stroke-width:2px,color:#000
style F fill:#ffebee,stroke:#d32f2f,stroke-width:2px,color:#000
style G fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
style H fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
style I fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
style J fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
style K fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
# 1. Configure
copts = ConfigOptions()
copts.FileName = "Windows10.vmem"
copts.VersionsToEnable = PTType.GENERIC
# 2. Scan
vtero = Scan.Scanit(copts)
# 3. Group processes
groups = vtero.GroupDetectedProcesses()
# 4. For each group (VM instance)
for group_id, procs in enumerate(groups):
print(f"\n=== VM Instance {group_id} ===")
# 5. Select kernel process (lowest CR3)
kernel_proc = min(procs, key=lambda p: p.CR3Value)
# 6. Load symbols
kvs = kernel_proc.ScanAndLoadModules()
# 7. Extract process list
# (use WalkProcListExample from above)# 1. Analyze dump
vtero = Scan.Scanit(copts)
kernel_proc = vtero.KernelProc
# 2. Load symbols
kvs = kernel_proc.ScanAndLoadModules()
# 3. Verify kernel modules
for module in kvs.Modules:
hash_matches = module.VerifyHash()
if not hash_matches:
print(f"MODIFIED: {module.Name}")
else:
print(f"OK: {module.Name}")# 1. Find target process
target_cr3 = 0x1AB000 # From initial scan
target_proc = next(p for p in vtero.Processes if p.CR3Value == target_cr3)
# 2. Extract full address space
output_file = "process_dump.bin"
target_proc.DumpASToFile(output_file)
# 3. Or extract specific regions
user_space = target_proc.ExtractUserSpace()
kernel_space = target_proc.ExtractKernelSpace()# 1. Scan for hypervisors
copts.VersionsToEnable = PTType.VMCS
vtero = Scan.Scanit(copts)
# 2. Extract nested VMs
for vm in vtero.VMCSDetected:
print(f"VMCS at: {vm.PhysicalAddress:016X}")
print(f"EPTP: {vm.EPTP:016X}")
print(f"Guest CR3: {vm.GuestCR3:016X}")
# 3. Extract guest memory
guest_mem = vm.ExtractGuestMemory()
# 4. Analyze guest memory
# (recursive analysis possible)import clr
clr.AddReferenceToFileAndPath("libyaraNET.dll")
from libyaraNET import *
# 1. Compile YARA rules
rules = YaraCompiler.CompileRulesFile("malware_rules.yar")
# 2. Scan each process
for proc in vtero.Processes:
matches = rules.ScanMemory(proc.MemAccess)
if matches:
print(f"Process CR3={proc.CR3Value:X} matched: {matches}")graph TD
Start([▶️ Start Analysis]) --> Scan[⏱️ Performance Metrics]
Scan --> Detect{🔍 Detection Phase}
Detect -->|Found| Proc[👤 Process Detection]
Detect -->|Not Found| Error[❌ No Processes]
Proc --> Corr{📊 Correlation Analysis}
Corr -->|100%| Perfect[✅ Perfect Match<br/>Same VM]
Corr -->|90%| Good[✔️ Good Match<br/>Shared Kernel]
Corr -->|<50%| Poor[⚠️ Different VM<br/>or Corrupted]
Perfect --> Group[👥 Process Groups]
Good --> Group
Poor --> Review[🔄 Review Settings]
Group --> Type{🖥️ Process Type}
Type -->|Windows| Win[🪟 Windows Process]
Type -->|Linux| Lin[🐧 Linux Process]
Type -->|BSD| BSD[😈 BSD Process]
Type -->|VMCS| VM[🌀 Hypervisor]
Win --> Results[📈 Analysis Results]
Lin --> Results
BSD --> Results
VM --> Results
Error --> Review
Review --> Detect
style Start fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
style Results fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
style Perfect fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff
style Good fill:#9ccc65,stroke:#558b2f,stroke-width:2px,color:#fff
style Poor fill:#ffb74d,stroke:#ef6c00,stroke-width:2px,color:#000
style Error fill:#ef5350,stroke:#c62828,stroke-width:2px,color:#fff
style Win fill:#64b5f6,stroke:#1976d2,stroke-width:2px,color:#fff
style Lin fill:#4db6ac,stroke:#00796b,stroke-width:2px,color:#fff
style BSD fill:#ba68c8,stroke:#7b1fa2,stroke-width:2px,color:#fff
style VM fill:#ff8a65,stroke:#d84315,stroke-width:2px,color:#fff
PART RUNTIME: 00:00:08.5211677 (seconds)
INPUT DUMP SIZE: 4,303,692,448 bytes
SPEED: 466,980 KB/second
- Runtime: Time for complete analysis
- Speed: Processing throughput (higher is better)
- Typical speeds: 200MB/s - 1GB/s depending on hardware
Group Correlation [100.000%] = Perfect match (same VM)
Group Correlation [90.909%] = Shared kernel, likely same VM
Group Correlation [< 50%] = Different VM or corrupted data
In the above example, VMWARE's EPTP is at index 14 in its VMCS.
- EPTP location varies by hypervisor/version
- Once identified, can be reused for same hypervisor version
- Index 14 is common for VMware
- Windows: Detected Windows process (self-pointer found)
- Linux: Linux process (kernel direct map)
- FreeBSD: BSD process (recursive PD)
- VMCS: Hypervisor instance
- GENERIC: Unknown OS type
-
Verify dump integrity:
md5sum memory.dump # Compare with known hash if available -
Check dump size:
- Should match source system's RAM size
- Smaller = incomplete or compressed dump
-
Ensure sufficient disk space:
- Analysis cache: ~10% of dump size
- Symbol cache: ~1-5 GB
- Extracted memory: up to dump size
-
Start with conservative settings:
Vtero.VerboseOutput = False # Reduce noise Vtero.DisableProgressBar = False # Monitor progress
-
Save state for large dumps:
copts.IgnoreSaveData = False # Enable caching vtero.CheckpointSaveState() # Save intermediate results
-
Monitor resource usage:
- RAM: Should not exceed physical RAM + dump size
- CPU: All cores should be utilized
- Disk I/O: High during initial scan
-
Review detected processes:
- Verify process count matches expectations
- Check for anomalous CR3 values
-
Validate symbols:
- Ensure PDBs downloaded correctly
- Check symbol cache directory
-
Document findings:
- Save output to file
- Record EPTP indices for reuse
- Note any anomalies
- Use SSD for dump storage
- Increase RAM for large dumps (16GB+ recommended)
- Disable antivirus scanning of dump directory
- Use local symbol cache to reduce network overhead
- Batch process multiple dumps with saved state
-
Isolate analysis environment:
- Use VM or separate system
- Disconnect from network if analyzing compromised system
-
Handle dumps as sensitive data:
- May contain passwords, keys, private data
- Use encryption for storage/transfer
-
Verify dump source:
- Unknown dumps may contain malware
- Sandbox analysis if suspicious
No processes detected:
- Try different
PTTypesettings - Check if dump is corrupted
- Verify dump format
Low correlation scores:
- May indicate nested VMs
- Check for multiple OS instances
- Review memory run detection
Symbol failures:
- Check internet connection
- Verify
_NT_SYMBOL_PATH - Try alternative symbol server
Out of memory:
- Reduce concurrent processing
- Increase system RAM
- Use 64-bit version
Complete analysis session:
C:\> cd inVtero\Scripts
C:\inVtero\Scripts> ipy
IronPython 2.7.7
>>> import Main
Current directory [C:\inVtero\Scripts]
>>> MemList = ["C:\\dumps\\win10.vmem"]
>>> test(MemList)
++++++ ANALYZING INPUT [C:\dumps\win10.vmem] ++++++
PART RUNTIME: 00:00:15.2341234
159 candidate process page tables
Hypervisor: VMCS detected
Hypervisor: Windows CR3 found [16A0000]
Group 1: Type [Windows] Correlation [100%]
Process count: 47
++++++ DONE ++++++
>>> vtero = test(MemList)
>>> kernel = vtero.KernelProc
>>> kvs = kernel.ScanAndLoadModules()
Loading symbols for ntoskrnl.exe...
Found 234 modules
>>> # Now use vtero, kernel, kvs objects for analysis
>>> WalkProcListExample(vtero, kernel)
PID: 4 Name: System
PID: 88 Name: Registry
PID: 384 Name: smss.exe
...- Architecture: See ARCHITECTURE.md
- API Reference: See API_REFERENCE.md
- Development: See DEVELOPMENT.md
- Example Scripts: See Scripts/ directory
- GitHub Issues: https://github.com/K2/inVtero.net/issues
If you encounter issues:
- Check INSTALLATION.md troubleshooting section
- Enable verbose output to diagnose problems
- Search existing GitHub issues
- Create new issue with:
- Dump format and size
- Source OS details
- Error messages
- Steps to reproduce