using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.InteropServices; using System.Diagnostics; using System.Security.Permissions; using Microsoft.Win32.SafeHandles; using System.Runtime.ConstrainedExecution; //Portions taken from http://csharptest.net/1051/managed-anti-debugging-how-to-prevent-users-from-attaching-a-debugger/ namespace guardPoke { class Mebugger { public Mebugger(int ipid) { pid = ipid; } //DebuggerWatcher dbgWatch = new DebuggerWatcher(); //Thread watchThread; private int pid; private volatile bool _shouldStop = false; private const int DBG_CONTINUE = 0x00010002; private const int DBG_EXCEPTION_NOT_HANDLED = unchecked((int)0x80010001); private enum DebugEventType : int { CREATE_PROCESS_DEBUG_EVENT = 3, //Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure. CREATE_THREAD_DEBUG_EVENT = 2, //Reports a create-thread debugging event. The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure. EXCEPTION_DEBUG_EVENT = 1, //Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure. EXIT_PROCESS_DEBUG_EVENT = 5, //Reports an exit-process debugging event. The value of u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure. EXIT_THREAD_DEBUG_EVENT = 4, //Reports an exit-thread debugging event. The value of u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure. LOAD_DLL_DEBUG_EVENT = 6, //Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure. OUTPUT_DEBUG_STRING_EVENT = 8, //Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure. RIP_EVENT = 9, //Reports a RIP-debugging event (system debugging error). The value of u.RipInfo specifies a RIP_INFO structure. UNLOAD_DLL_DEBUG_EVENT = 7, //Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure. } [StructLayout(LayoutKind.Sequential)] private struct DEBUG_EVENT { [MarshalAs(UnmanagedType.I4)] public DebugEventType dwDebugEventCode; public int dwProcessId; public int dwThreadId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte[] bytes; } [DllImport("Kernel32.dll", SetLastError = true)] private static extern bool DebugActiveProcess(int dwProcessId); [DllImport("Kernel32.dll", SetLastError = true)] private static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds); [DllImport("Kernel32.dll", SetLastError = true)] private static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, int dwContinueStatus); [DllImport("Kernel32.dll", SetLastError = true)] private static extern bool IsDebuggerPresent(); [DllImport("Kernel32.dll", SetLastError = true)] private static extern ulong GetLastError(); [DllImport("Kernel32.dll", SetLastError = true)] private static extern bool DebugActiveProcessStop(int dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); // Debugging thread main loop public void debugTarget(object pidObj) { int pid = (int)pidObj; Process.EnterDebugMode(); DEBUG_EVENT evt = new DEBUG_EVENT(); evt.bytes = new byte[1024]; if (!DebugActiveProcess(pid)) return;// Marshal.GetLastWin32Error(); while (true) { // wait for a debug event if (!WaitForDebugEvent(out evt, -1)) return;// Marshal.GetLastWin32Error(); // return DBG_CONTINUE for all events but the exception type int continueFlag = DBG_CONTINUE; if (evt.dwDebugEventCode == DebugEventType.EXCEPTION_DEBUG_EVENT) continueFlag = DBG_EXCEPTION_NOT_HANDLED; // continue running the debugee ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag); while (!_shouldStop) { while (WaitForDebugEvent(out evt, 100)) { ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag); } ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag); } DebugActiveProcessStop(pid); //watchThread = new Thread(dbgWatch.handleEvents); //watchThread.Start(); //while (!watchThread.IsAlive) ; //Thread.Sleep(1); //while (WaitForDebugEvent(out evt, 100)) //{ // ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag); //} //ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag); return;// 0; } } public void RequestStop() { _shouldStop = true; } } public class DebuggerWatcher { Mebugger dbg; Thread watchThread; public int debugTarget(int pid) { dbg = new Mebugger(pid); //int ret = dbg.debugTarget(pid); //if (ret != 0) // return ret; watchThread = new Thread(dbg.debugTarget); watchThread.Start((object)pid); while (!watchThread.IsAlive) ; Thread.Sleep(1); return 0; } public void stopDebug() { dbg.RequestStop(); watchThread.Join(); } } }