public DebuggerEventArgs( IntPtr processHandle, byte[] faultingInstructions, string instructionHash, DEBUG_EVENT debugEvent, ProcessMemory memory #if FULL_DBG , BreakpointManager breakpoints, HookManager hooks #endif ) { ProcessHandle = processHandle; FaultingInstructions = faultingInstructions; InstructionHash = instructionHash; DebugEvent = debugEvent; Memory = memory; #if FULL_DBG Breakpoints = breakpoints; Hooks = hooks; #endif }
public void ProcessDebugEvents() { IsStarted = true; var debugEvent = new DEBUG_EVENT(); while (!_killProcesses && IsStarted && Processes.Count != 0) { if (!Kernel32.WaitForDebugEvent(ref debugEvent, 200)) { var error = Marshal.GetLastWin32Error(); //if (error == 121 || _killProcesses) /*if (_killProcesses) * { * KillCore(); * break; * } * else */if (error != 121) { throw new Win32Exception(error); } if (Timeout > 0 && (DateTime.Now - StartTime).TotalMilliseconds > Timeout) { Kill(); return; } continue; } Process p = null; LockProcesses(() => { if (_processTable.ContainsKey(debugEvent.dwProcessId)) { p = _processTable[debugEvent.dwProcessId]; } }); byte[] buffer = null; var hash = "[NO HASH]"; switch (debugEvent.dwDebugEventCode) { case DebugEventType.CREATE_PROCESS_DEBUG_EVENT: if (p != null) { var mem = new ProcessMemory(p.Handle); lock (_readers) { _readers.Add(p.Handle, mem); } #if FULL_DBG if (!_hookManagers.ContainsKey(p.Handle)) { _hookManagers.Add(p.Handle, new HookManager(mem)); _breakpointManagers.Add(p.Handle, new BreakpointManager(mem)); } #endif } lock (_loaderBreakpointTable) { if (!_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Add(debugEvent.dwProcessId, false); } } LockProcesses(() => { AddProcess(debugEvent.dwProcessId); p = _processTable[debugEvent.dwProcessId]; }); Kernel32.CloseHandle(debugEvent.CreateProcessInfo.hFile); break; case DebugEventType.EXIT_PROCESS_DEBUG_EVENT: lock (_loaderBreakpointTable) { if (_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Remove(debugEvent.dwProcessId); } } LockProcesses(() => RemoveProcess(debugEvent.dwProcessId)); if (p != null) { lock (_readers) { try { // Swallow exceptions caused by accessing Process.Handle after // process has exited. _readers.Remove(p.Handle); } catch { } } } break; case DebugEventType.LOAD_DLL_DEBUG_EVENT: Kernel32.CloseHandle(debugEvent.LoadDll.hFile); break; case DebugEventType.EXCEPTION_DEBUG_EVENT: lock (_loaderBreakpointTable) { if (debugEvent.Exception.ExceptionRecord.ExceptionCode == ExceptionCode.EXCEPTION_BREAKPOINT) { if (!_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Add(debugEvent.dwProcessId, false); } if (!_loaderBreakpointTable[debugEvent.dwProcessId]) { _loaderBreakpointTable[debugEvent.dwProcessId] = true; debugEvent.ContinueUnhandled(); continue; } } } if (p != null) { if (HashException) { hash = GetExceptionHash(p, debugEvent); } if (ReadFaultingInstructions) { buffer = new byte[32]; var exPtr = IntPtr.Zero; try { exPtr = (IntPtr)debugEvent.Exception.ExceptionRecord.ExceptionAddress; } catch (OverflowException) { } if (Kernel32.ReadProcessMemory( p.Handle, exPtr, buffer, new IntPtr(buffer.Length), out var bytesRead)) { if (bytesRead < buffer.Length) { Array.Resize(ref buffer, bytesRead); } } else { buffer = null; } //hash = CreateInstructionHash(buffer.Take(HashSize)); } } //elser //{ // throw new InvalidOperationException(); //} break; } if (DebugEventReceived != null) { IntPtr handle; try { handle = p != null ? p.Handle : IntPtr.Zero; } catch { handle = IntPtr.Zero; } #if FULL_DBG if (!_breakpointManagers.TryGetValue(handle, out var breakpoints)) { _breakpointManagers.Add(handle, breakpoints = new BreakpointManager(GetMemory(handle))); } if (!_hookManagers.TryGetValue(handle, out var hooks)) { _hookManagers.Add(handle, hooks = new HookManager(GetMemory(handle))); } #endif DebugEventReceived(this, new DebuggerEventArgs( handle, buffer, hash, debugEvent, GetMemory(handle) #if FULL_DBG , breakpoints, hooks #endif )); } if (Timeout > 0 && (DateTime.Now - StartTime).TotalMilliseconds > Timeout) { Kill(); return; } } //KillCore(); }