/
Set-AnyProcessAsCritical.ps1
147 lines (119 loc) · 6.37 KB
/
Set-AnyProcessAsCritical.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
Function Add-DynamicParameters{
<#
.SYNOPSIS
Add-DynamicParameters is a function which adds dynamic parameters based on the name value pair hashtable
.DESCRIPTION
Add-DynamicParameters is a function which adds dynamic parameters based on the name value pair hashtable
.Notes
Author: Gurpreet Singh Jutla
.EXAMPLE
C:\PS> Add-DynamicParameters -parameterTable @{
"ForeColor" = @{
Value = ([enum]::GetValues([System.ConsoleColor]))
IsMandatory = $false
}
"BGColor" = @{
Value = ([enum]::GetValues([System.ConsoleColor]))
IsMandatory = $false
}
}
In the above example the Add-DynamicParameters will create a dictionary collection of two parameters naming ForeColor and BG Color both having a set of
system color collection. The IsMandatory field specifies if the parameter is mandatory or not
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $True)]
[Hashtable]$parameterTable
)
#$colors = [enum]::GetValues([System.ConsoleColor])
$RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
foreach($key in $parameterTable.keys){
$ParamAttrib = New-Object System.Management.Automation.ParameterAttribute
$ParamAttrib.Mandatory = $parameterTable[$key].IsMandatory
$ParamAttrib.ParameterSetName = '__AllParameterSets'
$AttribColl = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
$AttribColl.Add($ParamAttrib)
$AttribColl.Add((New-Object System.Management.Automation.ValidateSetAttribute($parameterTable[$key].ValidateSet)))
$RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter($key, [string], $AttribColl)
$RuntimeParamDic.Add($key, $RuntimeParam)
}
return $RuntimeParamDic
}
Function Set-AnyProcessAsCritical {
<#
.SYNOPSIS
Makes a process critical. Closing the process would cause the system to crash
.DESCRIPTION
The code referred in this article is written to demonstrate the power of Powershell
as a scripting language. Please use this wisely, only for educational purposes or for
collecting a memory dump on application crash is needed with usermode along with kernel
stacks or a complete memory dump.
This code can make any running user mode application/service/process a critical process.
Closing the application would lead to a system crash. Please ensure you save any unsaved data.
The system crash will not cause any other issues but I will not be responsible for any losses
while running this application on production systems.
I cannot be held responsible for any issues caused by this application.
If you do not have good knowledge of Powershell, Windows, Debugging or IT systems I would highly
advise you engage a responsible and experienced IT professional before trying this code.
Run this in a test isolated environment only.
Please note that you will need to setup the registry key to generate a complete memory dump as I
do not set that registry key explictly.
.NOTES
Credits:
Originally the Code was written by "Matthew Graeber", I just changed it to work with any process instead of the powershell process itself
Read my article here
https://docs.microsoft.com/en-us/archive/blogs/ntdebugging/bugchecking-a-computer-on-a-usermode-application-crash
.EXAMPLE
C:\PS> Set-CriticalProcess
#>
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')]
Param (
#Crash system immediately by closingthe proces after making it a critical process
[Switch]$ExitImmediatelyandCrash
)
DynamicParam{
Add-DynamicParameters -parameterTable @{
"process" = @{
ValidateSet = (Get-process | select @{l="Process";e={("{0} ({1})" -f $_.processname, $_.id)}}).Process
IsMandatory = $false
}
}
}
process {
$processID = ($PSBoundParameters.process).split("(")[1].replace(")","")
#Check if you are running powershell with administrative credentials
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw 'You must run Set-AnyProcessAsCritical from an elevated/Administartive PowerShell interface.'
}
$dynamicAssembly = New-Object System.Reflection.AssemblyName('BlueScreen')
$assemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($dynamicAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
$moduleBuilder = $assemblyBuilder.DefineDynamicModule('BlueScreen', $False)
$typeBuilder = $moduleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class')
$null = $typeBuilder.DefinePInvokeMethod('NtSetInformationProcess','ntdll.dll',
([Reflection.MethodAttributes] 'Public, Static'),
[Reflection.CallingConventions]::Standard,
[Int32],
[Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]),
[Runtime.InteropServices.CallingConvention]::Winapi,
[Runtime.InteropServices.CharSet]::Auto)
$ntdll = $typeBuilder.CreateType()
$procObj = [Diagnostics.Process]::GetProcessById($ProcessID)
$procHandle = $procObj.Handle
$procName = $procObj.ProcessName
$returnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
$processBreakOnTermination = 29
$sizeUInt32 = 4
try{
$null = $ntdll::NtSetInformationProcess($procHandle, $processBreakOnTermination, [Ref] $returnPtr, $sizeUInt32)
}
catch {
Write-Host ("Process '{0}' with id: '{1}' could not be marked as a critical process" -f $procName, $ProcessID)
return
}
Write-Host ("Process '{0}' with id: '{1}' is now marked as a critical process and will blue screen the machine upon exiting the process." -f $procName, $ProcessID)
if ($ExitImmediately){
Stop-Process -Id $PID
}
}
}