Debugging BSOD in WinPE

When a driver is causing a crash in full Windows, its fairly easy to debug. You simply allow Windows to create the memory.dmp file, load it into you favorite debugger, and off you go. However, when you get an BSOD in WinPE, for example during OS deployment its quite different. For a start there is no pagefile by default, and a memory.dmp file is not generated automatically upon reboot either. Luckily, most times you can simply open the pagefile.sys as is, without having Windows generating the memory.dmp file. Here is a quick guide on how to enable WinPE to save the CrashDump so you can debug it.

Note: If your debugger really needs the memory.dmp file being extracted from pagefile.sys (often not needed, but still) , check my extraction tip in the end of this post.

Anyway, in this example I'm using ConfigMgr for OS Deployment, but the same techniques apply to any deployment solution.

WinPE, Pagefiles, and saving the CrashDump

WinPE based on Windows ADK 10 (Windows 10) does not create a pagefile by default, and this is something that is needed to save the crash data during a BSOD. WinPE by default is also not configured to save the crash dump, even if a pagefile exist. So basically, you need to do three things to debug a BSOD that happens in WinPE.

  • Enable WinPE to save the CrashDump
  • Configure WinPE to create a pagefile
  • Analyze the CrashDump

Step 1 – Enable WinPE to save the CrashDump

To enable WinPE to save the CrashDump, you need to edits its offline registry to enable it. Below you find a PowerShell script that does that. In this example I'm modifying a ConfigMgr (SCCM )boot image.

Note: In the script you also find an option to enable a forced CrashDump for testing purposes in Hyper-V. Once enabled, you can press and hold Right-Ctrl and press Scroll Lock twice to force a crash. This is available in WinPE v1903 or higher.

# Set some variables to resources
$BootImagePath = "E:\Sources\OSD\Boot\Zero Touch WinPE 10 x64\winpe.wim"
$MountPath = "E:\Mount"

# Some basic sanity checks
if (!(Test-Path -Path "$BootImagePath")) {Write-Warning "Could not find boot image, aborting...";Break}
if (!(Test-Path -Path "$MountPath")) {Write-Warning "Could not find mount path, aborting...";Break}

# Mount the boot image
Mount-WindowsImage -ImagePath $BootImagePath -Index 1 -Path $MountPath  

# Set the CrashDump settings in WinPE
#
# CrashDumpEnabled 0 = None
# CrashDumpEnabled 1 = Complete memory dump
# CrashDumpEnabled 2 = Kernel memory dump
# CrashDumpEnabled 3 = Small memory dump (64KB)
# CrashDumpEnabled 7 = Automatic memory dump
#
reg load HKLM\WinPE "$MountPath\Windows\System32\config\SYSTEM"
Set-ItemProperty –Path HKLM:\WinPE\ControlSet001\Control\CrashControl –Name CrashDumpEnabled –value 1

# For testing, enable keyboard-initiated crash in Hyper-V (WinPE based on Windows 10 v1903 or later)
# To use in WinPE, hold down the right Ctrl key, and press the Scroll Lock key twice
#
New-Item -Path "HKLM:\WinPE\ControlSet001\Services\hyperkbd" -Name Parameters -Force
New-ItemProperty -Name "CrashOnCtrlScroll" -value "1" -type DWORD -path "HKLM:\WinPE\ControlSet001\Services\hyperkbd\Parameters" -Force	

# Save the registry changes
reg unload HKLM\WinPE

# Save changes to the boot image
Dismount-WindowsImage -Path $MountPath -Save

Another option to create a crash for testing is to use the good old Not My Fault utility from Sysinternals (Microsoft).

Forcing a BSOD in WinPE using the native option.
Using Not My Fault from Sysinternals to force a crash.

Step 2 – Configure WinPE to create a pagefile

To create a Pagefile in WinPE, you use the builtin wpeutil.exe tool. If you need to debug a BSOD that usually happens quite early, you can create an unattend.xml file that runs it as soon as WinPE boots. Alternatively, if your blue screens happen during the task sequence, you can simply have the task sequence create it. Below is a script you can add to your task sequence that configure WinPE to create a pagefile. Add this after the action that formats the hard drive, and don't forget to enable PowerShell support to your boot image.

# Get DriveLetter for Windows volume
# Check for default labels in ConfigMgr task sequences (native and MDT)
$OSVolumeDriveLetter=(Get-Volume | Where-Object {($_.filesystemlabel -eq "Windows") -or ($_.filesystemlabel -eq "OSDisk")}).driveletter

# Create the pagefile on the OS Volume, size set to 10MB over the amount of physical RAM.
If ($OSVolumeDriveLetter -eq $null){
	Write-Output "No OS Volume found, do nothing..."
}
Else {
	Write-Output "OS Volume found, create the pagefile"
	$PagefilePath = "$OSVolumeDriveLetter"+":\pagefile.sys"
	$PagefilePathSize = ((Get-WmiObject win32_physicalmemory | Measure-Object -Property Capacity -Sum).sum)/1MB
	$PagefilePathSize = $PagefilePathSize + 10
	Start-Process -WindowStyle Hidden -FilePath wpeutil -ArgumentList "CreatePageFile",`"/path=$PagefilePath`",`"/size=$PagefilePathSize`"
}
Adding the script that creates a pagefile in WinPE.

Step 3 – Analyze the CrashDump

Once you have got the CrashDump written to disk, stored in pagefile.sys, simply copy the pagefile.sys file over to a Windows 10 machine, start WinDbg, load the CrashDump, and run !analyze -v.

Analyzing the CrashDump in WinPE.

Extracting a memory.dmp file from pagefile.sys

As I mentioned earlier, you can usually just open the pagefile.sys file directly in the debugger, but if you really need a memory.dmp file, simply copy the pagefile.sys into a mounted virtual disk (VHDX/VMDK etc.) from a virtual machine with Windows 10. Start that VM, and you find it will generates a memory.dmp file in the Windows folder.

Memory.dmp file created by tricking Windows 10 to do it 🙂
About the author

Johan Arwidmark

5 2 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

>