Skip to content

Instantly share code, notes, and snippets.

@jborean93
Created December 3, 2024 02:08
Show Gist options
  • Save jborean93/c04426e88d62d09f539088f5bd54bc7d to your computer and use it in GitHub Desktop.
Save jborean93/c04426e88d62d09f539088f5bd54bc7d to your computer and use it in GitHub Desktop.
PowerShell script that can be used to generate an executable that can send CTRL+C or CTRL+BREAK to a target process by id
<#
This must be run in Windows PowerShell (5.1). This will not work in PowerShell 7.x
as Add-Type cannot generate an output executable.
#>
Add-Type -OutputType ConsoleApplication -OutputAssembly kill.exe -TypeDefinition @'
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Kill
{
public static class Program
{
private const int CTRL_C_EVENT = 0;
private const int CTRL_BREAK_EVENT = 1;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AttachConsole(
int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(
int dwCtrlEvent,
int dwProcessGroupId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeConsole();
public static int Main(string[] args)
{
string help = "usage: kill.exe pid [-ctrl_c|-ctrl_break]";
if (args.Length == 0 || args.Length > 2)
{
string msg = string.Format(
"Expecting at least 1 argument for the process id to send the signal to{0}{1}",
Environment.NewLine,
help);
Console.Error.WriteLine(msg);
return 1;
}
else if (args[0].ToLowerInvariant() == "--help")
{
Console.WriteLine(help);
return 0;
}
int procId;
if (!int.TryParse(args[0], out procId))
{
string msg = string.Format("Failed to parse '{0}' as process id.", args[0]);
Console.Error.WriteLine(msg);
return 1;
}
int ctrlEvent = CTRL_C_EVENT;
if (args.Length == 2)
{
string argSignal = args[1].ToLowerInvariant();
if (argSignal == "-ctrl_break")
{
ctrlEvent = CTRL_BREAK_EVENT;
}
else if (argSignal != "-ctrl_c")
{
string msg = string.Format("Invalid ctrl event found '{0}', expected -ctrl_c or -ctrl_break.", args[1]);
Console.Error.WriteLine(msg);
return 1;
}
}
if (!FreeConsole())
{
int errCode = Marshal.GetLastWin32Error();
string errMsg = new Win32Exception(errCode).Message;
string msg = string.Format("Failed to free console 0x{0:X8} - {1}", errCode, errMsg);
Console.Error.WriteLine(msg);
return errCode;
}
if (!AttachConsole(procId))
{
int errCode = Marshal.GetLastWin32Error();
string errMsg = new Win32Exception(errCode).Message;
string msg = string.Format("Failed to attach console to process {0} 0x{1:X8} - {2}", procId, errCode, errMsg);
Console.Error.WriteLine(msg);
return errCode;
}
if (!GenerateConsoleCtrlEvent(ctrlEvent, 0))
{
int errCode = Marshal.GetLastWin32Error();
FreeConsole();
string errMsg = new Win32Exception(errCode).Message;
string msg = string.Format("Failed generate ctrl event 0x{0:X8} - {1}", errCode, errMsg);
Console.Error.WriteLine(msg);
return errCode;
}
FreeConsole();
return 0;
}
}
}
'@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment