///////////////////////////////////////////////////////////////////////////////
//
// Random.cs
//
// By Philip R. Braica (HoshiKata@aol.com, VeryMadSci@gmail.com)
//
// Distributed under the The Code Project Open License (CPOL)
// http://www.codeproject.com/info/cpol10.aspx
///////////////////////////////////////////////////////////////////////////////
// Using.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
// Namespace
namespace KillForms
{
/// <summary>
/// Just a simple form.
/// </summary>
public partial class Form1 : Form
{
/// <summary>
/// Allow us to make a critical process non-critical.
/// </summary>
/// <param name="bNew"></param>
/// <param name="pbOld"></param>
/// <param name="bNeedScb"></param>
/// <returns></returns>
[DllImport("ntdll.dll", SetLastError = true)]
unsafe public static extern int RtlSetProcessIsCritical(bool bNew, out bool pbOld, bool bNeedScb);
/// <summary>
/// You can use the unsupported thing to set the criticalness of another application.
/// </summary>
/// <param name="hProcess"></param>
/// <param name="processInformationClass"></param>
/// <param name="processInformation"></param>
/// <param name="processInformationLength"></param>
/// <returns></returns>
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtSetInformationProcess(IntPtr hProcess, int processInformationClass, ref int processInformation, int processInformationLength);
/// <summary>
/// Open a thread.
/// </summary>
/// <param name="dwDesiredAccess"></param>
/// <param name="bInheritHandle"></param>
/// <param name="dwThreadId"></param>
/// <returns></returns>
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
/// <summary>
/// Kill the thread.
/// </summary>
/// <param name="hThread"></param>
/// <param name="dwExitCode"></param>
/// <returns></returns>
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);
/// <summary>
/// Win32 call to kill.
/// </summary>
/// <param name="hProcess"></param>
/// <param name="uExitCode"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
/// <summary>
/// Suspend a thread.
/// </summary>
/// <param name="hThread"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
/// <summary>
/// Resume a thread.
/// </summary>
/// <param name="hThread"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
/// <summary>
/// Constructor.
/// </summary>
public Form1()
{
InitializeComponent();
}
/// <summary>
/// Nuke the problem things.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
// Grab the value now not while executing.
bool doAffinity = checkBox1.Checked;
bool doPriority = checkBox2.Checked;
bool usePath = checkBox3.Checked;
bool atAllCosts = checkBox4.Checked;
bool hibernateOnly = checkBox5.Checked;
atAllCosts = hibernateOnly ? false : atAllCosts;
int iterations = (int)numericUpDown1.Value;
// Make a list of processes to kill.
List<string> namesToDealWith = new List<string>();
TextBox[] tb = { textBox1, textBox2, textBox3, textBox4 };
for (int i = 0; i < tb.Length; i++)
{
if (tb[i].Text.Length == 0) continue;
namesToDealWith.Add(tb[i].Text);
}
if (tb.Length == 0)
{
return;
}
// If the at all costs option is checked, make darn sure they mean it.
if (atAllCosts)
{
DialogResult dr = MessageBox.Show(
"Are you sure?\r\nUsing at \"at all costs\" may lockup the PC, " +
"rebooting may be a better option, only use if fighting off " +
"malware and there is no other choice. " +
"\r\n\r\nCheck MSDN on " +
"TerminateThread and for using NtSetInformationProcess " +
"to make a process non-critical for more information." +
"\r\n\r\nThis may crash your PC! At your own risk!",
"Just checking ...",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2);
if (dr == DialogResult.Cancel)
{
return;
}
}
// This give us some privlidges and some protection while
// making some of these calls.
if (atAllCosts)
{
Process.EnterDebugMode();
}
// Iterate many times to make sure the process stays killed.
for (int i = 0; i < iterations; i++)
{
// Get a list of processes.
Process[] p = Process.GetProcesses();
if (p == null) continue;
for (int j = 0; j < p.Length; j++)
{
// If null just continue.
if (p[j] == null) continue;
// See if p[j] is in the list.
//
// Sometimes things have a unique name, sometimes
// they borrow a common name to hide, sometimes they
// have a MainModule, sometimes they don't, some have
// file paths that use resource forks or non-text
// enterable characters. For this reason they can use
// either the common name or the full path to executable.
string name = p[j].ProcessName;
if (usePath)
{
try
{
name = p[j].MainModule.FileName;
}
catch (Exception)
{
// don't care.
}
}
if (namesToDealWith.Contains(name) == false) continue;
// Affinity.
if (doAffinity)
{
try
{
p[j].ProcessorAffinity = (System.IntPtr)1;
}
catch (Exception)
{
// Don't care keep moving.
}
}
// Priority.
if (doPriority)
{
try
{
p[j].PriorityClass = ProcessPriorityClass.Idle;
}
catch (Exception)
{
// Don't care keep moving.
}
try
{
p[j].PriorityBoostEnabled = false;
}
catch (Exception)
{
// Don't care keep moving.
}
}
if (hibernateOnly)
{
// Only hibernate, method 3.
stopProcess(p[j], 3, false);
}
else
{
// Try the ith set of methods on this process.
stopProcessAllMethods(p[j], i, atAllCosts);
}
}
}
}
/// <summary>
/// Try to kill based on the ith starting point attempt.
/// </summary>
/// <param name="p"></param>
/// <param name="seed"></param>
/// <param name="atAllCosts"></param>
private void stopProcessAllMethods(Process p, int seed, bool atAllCosts)
{
// Try one stop method, then return, get process list again.
//
// Otherwise if we just do multiples against a process that doesn't exist,
// under windows XP, the process may survive due to the efforts taken.
// There are four normal methods and two "at all costs" methods.
if (stopProcess(p, seed++, atAllCosts)) return;
if (stopProcess(p, seed++, atAllCosts)) return;
if (stopProcess(p, seed++, atAllCosts)) return;
if (stopProcess(p, seed++, atAllCosts)) return;
if (atAllCosts)
{
if (stopProcess(p, seed++, atAllCosts)) return;
stopProcess(p, seed, atAllCosts);
}
}
/// <summary>
/// Stop a process p, with either 3 methods or 4 methods.
/// </summary>
/// <param name="p"></param>
/// <param name="method">Executes method % (total allowed)</param>
/// <param name="atAllCosts">Allows the fourth method.</param>
/// <returns>True if likely killed the process.</returns>
private bool stopProcess(Process p, int method, bool atAllCosts)
{
// Limit to 0-4 if all costs, else 0-3.
method = atAllCosts? method % 4 : method % 6;
try
{
if (method == 0) p.CloseMainWindow(); // Close main window.
if (method == 1) p.Kill(); // Kill.
if (method == 2) TerminateProcess(p.Handle, 0); // Terminate win32.
if (method == 3)
{
// Suspend all it's threads, for fighting mal ware this may be
// enough to make it killable.
for (int i = 0; i < p.Threads.Count; i++)
{
ProcessThread pt = p.Threads[i];
try
{
IntPtr ptrThread = OpenThread(2, false, (uint)pt.Id);
if (System.Threading.Thread.CurrentThread.ManagedThreadId != pt.Id)
{
SuspendThread(ptrThread);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
}
// Extreme methods.
if (!atAllCosts) return false;
if (method == 4)
{
int enable = 0; // disable, set to 1 to enable
NtSetInformationProcess(p.Handle, 29, ref enable, sizeof(int));
p.Kill();
}
if (method == 5)
{
for (int i = 0; i < p.Threads.Count; i++)
{
ProcessThread pt = p.Threads[i];
try
{
IntPtr ptrThread = OpenThread(1, false, (uint)pt.Id);
if (System.Threading.Thread.CurrentThread.ManagedThreadId != pt.Id)
{
TerminateThread(ptrThread, 1);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
}
}
catch (Exception ex)
{
// Don't care keep moving.
Console.WriteLine(ex.Message);
return false;
}
return true;
}
}
}