# # dump_vm.ps1 v0.1 # Created by: Ulf Frisk - pcileech@frizk.net # $vm_name = $args[0] $dst_path = $(If ($args[1] -ne $null) {$args[1]} Else {$PSScriptRoot}) $keep_checkpoint = $(If (($args[2] -ne $null) -And ($args[2] -ne "false")) {$true} Else {$false}) $copy_pagefile = $(If (($args[3] -ne $null) -And ($args[3] -ne "false")) {$true} Else {$false}) function Test-Administrator { [OutputType([bool])] param() process { [Security.Principal.WindowsPrincipal]$user = [Security.Principal.WindowsIdentity]::GetCurrent(); return $user.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator); } } function Get-Checkpoint($vm, $checkpoint_name, $timeout_seconds) { $waitedTime = 0 while ($waitedTime -lt $timeout_seconds) { $checkpoint = Get-VMSnapshot @vm | Where-Object { $_.Name -eq $checkpoint_name } if ($checkpoint -ne $null) { return $checkpoint } Start-Sleep -Seconds 1 $waitedTime++ } return $null } if ($vm_name -eq $null) { Write-Host " dump_vm.ps1: Dump memory from a running Hyper-V VM from the Hyper-V host. The script creates a Checkpoint and copies the memory and optionally the page file (pagefile.sys). Run as elevated administrator. This is done on running Hyper-V VMs without any interruption to the VM. dump_vm.ps1 syntax: .\dump_vm.ps1 = required: VM Name or VM ID. = optional: directory where to save result. Default = script directory. = optional: flag to keep checkpoint (true/false). Detault = false. = optional: flag to try to copy pagefile.sys best effort. Detault = false. Example #1: dump the vm TEST to C:\Temp: .\dump_vm.ps1 TEST C:\Temp Example #2: dump the vm TEST to C:\Temp including best-effort page file dump: .\dump_vm.ps1 TEST C:\Temp false true " Exit } # # Ensure script is running as Elevated Administrator # if(-not (Test-Administrator)) { PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Unrestricted -File ""$PSCommandPath""' -Verb RunAs}"; Exit } # # Verify destination path # if ((Test-Path -Path $dst_path -PathType Container) -eq $false) { Write-Host "" Write-Host "Fail! Dump Path: '$dst_path' is not a valid directory." Write-Host "" Exit } # # Retrieve the VM # try { $vm = Get-VM -Id "$vm_name" $vm_id = $vm.VMId if($vm_id.ToString().ToString().Length -ne 36) { $vm = $null } $vm_name = $vm.Name } catch { $vm = $null } if ($vm -eq $null) { try { $vm = Get-VM -Name "$vm_name" $vm_id = $vm.VMId if($vm_id.ToString().ToString().Length -ne 36) { throw [System.IO.FileNotFoundException]::new('The VM does not exist.'); } } catch { Write-Host "" Write-Host "Fail! Could not retrieve VM: '$vm_name'." Write-Host "" Exit } } # # Ensure VM is running # if ($vm.State -ne 'Running') { Write-Host "" Write-Host "Fail! VM: '$vm_name' is not running." Write-Host "" Exit } $file_date = (Get-Date -Format FileDateTime) $checkpoint_name = "memdump-$file_date" # # Take checkpoint # Checkpoint-VM @vm -SnapshotName $checkpoint_name $checkpoint = Get-Checkpoint $vm $checkpoint_name 10 if ($checkpoint -eq $null) { Write-Host "" Write-Host "Fail! VM: '$vm_name' unable to create checkpoint '$checkpoint_name'." Write-Host "" Exit } # # Fetch VMRS path # $file_src = Join-Path -Path $checkpoint.Path -ChildPath "$($checkpoint.Id).vmrs" if ((Test-Path -Path $file_src) -eq $false) { $file_src = Join-Path -Path $checkpoint.Path -ChildPath "Snapshots" $file_src = Join-Path -Path $file_src -ChildPath "$($checkpoint.Id).vmrs" } if ((Test-Path -Path $file_src) -eq $false) { Write-Host "" Write-Host "Fail! VMRS path: '$file_src' not found. Ensure VM have 'Standard checkpoints' enabled (and 'Production checkpoints' disabled)." Write-Host "" Exit } $file_dst = Join-Path -Path $dst_path -ChildPath "$vm_name-$file_date.vmrs" Write-Host "" Write-Host "====================================================================================" Write-Host " - SAVE VIRTUAL MEMORY STATE OF VM" Write-Host " - ID: $vm_id" Write-Host " - Name: $vm_name" Write-Host " - Keep checkpoint: $keep_checkpoint" Write-Host " - Copy pagefile: $copy_pagefile" Write-Host " - Source: $file_src" Write-Host " - Destination: $file_dst" Write-Host "====================================================================================" Write-Host "" # # Copy VMRS memory # Copy-Item -Path $file_src -Destination $file_dst # # Try copy pagefile.sys (best effort) # if ( $copy_pagefile ) { try { $file_pagefile_dst = Join-Path -Path $dst_path -ChildPath "$vm_name-$file_date-pagefile.sys" $mountedDrive = Mount-VHD -Path $checkpoint.HardDrives.Path -Passthru -ReadOnly | Get-Disk | Get-Partition | Where-Object { $_.Type -eq "Basic" } | Get-Volume $file_pagefile_src = "$($mountedDrive.DriveLetter):\pagefile.sys" Copy-Item -Path $file_pagefile_src -Destination $file_pagefile_dst } catch { Write-Host "" Write-Host "Warn: Fail retrieving page file." Write-Host "" } try { Dismount-VHD -Path $checkpoint.HardDrives.Path } catch { } } # # Delete checkpoint # if ($keep_checkpoint -eq $false) { Remove-VMSnapshot @checkpoint -Confirm:$false } Write-Host "" Write-Host "Finished!" Write-Host ""