diff --git a/pause-process.ps1 b/pause-process.ps1 new file mode 100644 index 0000000..500bad8 --- /dev/null +++ b/pause-process.ps1 @@ -0,0 +1,170 @@ +# Pause/unpause a process. Just provide a PID or a PID from the pipeline +# by Mick Douglas @BetterSafetyNet + +# License: Creative Commons Attribution +# https://creativecommons.org/licenses/by/4.0/ + +# Warning: +# This script will pause (and unpause) running programs. +# Obviously, this can cause system stability issues. +# The author and contributors of this script assume NO liability for the use of this script. +# Users of this script are **stridently** urged to test in a non-production environment first. + +# todos: +# Easy +# create better error logics +# make better help messages + +# Mid-level +# add logics to detect if debugger is attached +# add input validation checks +# - is ID an int? + +# HARD!! +# - re-introduce the -Duration option & use ScheduledJob instead of sleep + +# Credits: +# Shout out to Dave Kennedy for pointing me to this StackOverflow article. +# https://stackoverflow.com/questions/11010165/how-to-suspend-resume-a-process-in-windows + +# Reference links: +# calling Windows API from PowerShell +# https://blog.dantup.com/2013/10/easily-calling-windows-apis-from-powershell/ + +# https://blogs.technet.microsoft.com/heyscriptingguy/2013/06/25/use-powershell-to-interact-with-the-windows-api-part-1/ + +# https://msdn.microsoft.com/en-us/library/windows/desktop/ms679295(v=vs.85).aspx + +# Highly interesting article on how to use specific methods in a dll in PowerShell +#https://social.technet.microsoft.com/Forums/ie/en-US/660c36b5-205c-47b6-8b98-aaa97d69a582/use-powershell-to-automate-powerpoint-document-repair-message-response?forum=winserverpowershell + + + +<# + +.SYNOPSIS +This is a PowerShell script which allows one to Pause-Process or +UnPause-Process. + +.DESCRIPTION +This script will allow users to pause and unpause running commands. This is +accomplished by attaching a debugger to the selected process. Removing the +debugger allows the program to resume normal operation. + +Note: not all programs can be paused in this manner. + +.EXAMPLE +Import-Module .\pause-process.ps1 + +.EXAMPLE +Pause-Process -ID [PID] + +.EXAMPLE +UnPause-Process -ID [PID] + +.NOTES +This script is under active development. +Until you are comfortable with how this works... DO NOT USE IN PRODUCTION! + +.LINK +https://infosecinnovations.com/Alpha-Testing + +#> + + + +$script:nativeMethods = @(); +function Register-NativeMethod([string]$dll, [string]$methodSignature) +{ + $script:nativeMethods += [PSCustomObject]@{ Dll = $dll; Signature = $methodSignature; } +} + +function Add-NativeMethods() +{ + $nativeMethodsCode = $script:nativeMethods | % { " + [DllImport(`"$($_.Dll)`")] + public static extern $($_.Signature); + " } + + Add-Type @" + using System; + using System.Runtime.InteropServices; + public static class NativeMethods { + $nativeMethodsCode + } +"@ +} + + +# Add methods here +Register-NativeMethod "kernel32.dll" "int DebugActiveProcess(int PID)" +Register-NativeMethod "kernel32.dll" "int DebugActiveProcessStop(int PID)" + +# This builds the class and registers them (you can only do this one-per-session, as the type cannot be unloaded?) +Add-NativeMethods + + +function Pause-Process { + +[CmdletBinding()] + + Param ( + [parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)] + [alias("OwningProcess")] + [int]$ID + ) + + + Begin { + # Test to see if this is a running process + # Future feature: Do checks to see if we can pause this process. + write-verbose ("you entered an ID of: $ID") + } + + + Process { + $PauseResult = [NativeMethods]::DebugActiveProcess($ID) + } + + + End { + if ($PauseResult -eq $False) { + Write-Error ("Unable to pause process: $ID") + + } else { + Write-Verbose ("Process $ID was paused") + } + + } +} + + +function UnPause-Process { + +[CmdletBinding()] + + Param ( + [parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)] + [alias("OwningProcess")] + [int]$ID + ) + + Begin{ + Write-Verbose ("Attempting to unpause PID: $ID") + } + + + Process { + # Attempt the unpause + $UnPauseResult = [NativeMethods]::DebugActiveProcessStop($ID) + } + + End { + if ($UnPauseResult -eq $False) { + Write-Error ("unable to unpause process $ID. Is it running or gone?") + + } else { + Write-Verbose ("$ID was resumed") + } + } +} \ No newline at end of file