/// <summary> /// Starts the characterbuilder and modifies the in-memory representation of LOADED_FILE to /// support unencrypted data. /// </summary> /// <param name="patchFile"></param> public static void StartProcessAndPatchMemory() { Log.Debug("About to start loading character builder."); //// start character builder NativePipeline np = new NativePipeline(); Log.Debug("Creating process and attaching debugger"); NativeDbgProcess proc = np.CreateProcessDebug(EXECUTABLE, EXECUTABLE_ARGS); while (true) { Log.Debug("Waiting for next event"); NativeEvent ne = np.WaitForDebugEventInfinite(); Log.Debug(ne.ToString()); ne.Process.HandleIfLoaderBreakpoint(ne); if (ne.EventCode == NativeDebugEventCode.LOAD_DLL_DEBUG_EVENT) { DllBaseNativeEvent ev = (DllBaseNativeEvent)ne; if (ev.Module.Name.Contains(LOADED_FILE)) { patchMemory(ev, (uint)proc.Id); np.ContinueEvent(ne); np.Detach(proc); break; } } np.ContinueEvent(ne); } }
NativeDbgProcess CreateNew(int processId) { NativeDbgProcess process = new NativeDbgProcess(processId); m_processes[processId] = process; return(process); }
/// <summary> /// Stop debugging the specified process (detach) /// </summary> /// <param name="process">process to detach from</param> /// <remarks>After detaching, the process is removed from the caches and can not be accessed. If detaching at a debug /// event, do not call Continue on the event. </remarks> public void Detach(NativeDbgProcess process) { if (process == null) { throw new ArgumentNullException("process"); } EnsureIsOnWin32EventThread(); int pid = process.Id; bool fDetachOk = NativeMethods.DebugActiveProcessStop((uint)pid); if (!fDetachOk) { int err = Marshal.GetLastWin32Error(); throw new InvalidOperationException("Failed to detach to process " + pid + "error=" + err); } RemoveProcess(pid); }
/// <summary> /// Continue a debug event previously gotten by WaitForDebugEvent /// </summary> /// <param name="nativeEvent"></param> /// <remarks>Can't continue a debug event if we just detached from the process</remarks> public void ContinueEvent(NativeEvent nativeEvent) { if (nativeEvent == null) { throw new ArgumentNullException("nativeEvent"); } if (nativeEvent.ContinueStatus == NativeMethods.ContinueStatus.CONTINUED) { throw new ArgumentException("event was already continued", "nativeEvent"); } if (nativeEvent.Pipeline != this) { throw new ArgumentException("event does not belong to this pipeline"); } EnsureIsOnWin32EventThread(); // Verify that the process for this event is still connected to our pipeline. // The lookup will throw if the process detached or was terminated. NativeDbgProcess proc = nativeEvent.Process; Debug.Assert(proc.Id == nativeEvent.ProcessId); nativeEvent.DoCleanupForContinue(); bool fContinueOk = NativeMethods.ContinueDebugEvent((uint)nativeEvent.ProcessId, (uint)nativeEvent.ThreadId, nativeEvent.ContinueStatus); if (!fContinueOk) { int err = Marshal.GetLastWin32Error(); throw new InvalidOperationException("Continue failed on process " + nativeEvent.ProcessId + " error=" + err); } // Mark as continued so that we don't accidentally continue again. nativeEvent.ContinueStatus = NativeMethods.ContinueStatus.CONTINUED; }
public void DebugEventHandler() { NativePipeline dbg = new NativePipeline(); NativeDbgProcess process = dbg.Attach(_pid); _attached = true; // Tell the process it is ready to resume try { _process.PyProcess.on_handle_first_bp(); } catch (Exception ex) { Console.WriteLine(string.Format("ERROR: Python class 'Process' {0} failed when executing 'on_handle_first_bp()':", _process.GetName())); Console.WriteLine(ex.ToString()); // attempt to continue anyways } // Initialize the printing variables DateTime numEvents_lastPrintTime = DateTime.Now; Hashtable numEventsByTarget = new Hashtable(0x1000); _breakpointInfo = new Hashtable(10); bool printReport = false; bool processReady = false; bool loaderBreakpointReceived = false; bool wx86BreakpointReceived = false; while (_processingEvents) { if (DateTime.Now.Subtract(numEvents_lastPrintTime).TotalSeconds >= 1) { // Print the number of events in the last second if (printReport && numEventsByTarget.Count > 0) { PrintReport(numEventsByTarget); } numEvents_lastPrintTime = DateTime.Now; numEventsByTarget.Clear(); } // Check to see if the process has loaded if (!processReady) { processReady = HandleProcessReady(wx86BreakpointReceived); } NativeEvent e = dbg.WaitForDebugEvent(100); // Check to see if the process has loaded if (!processReady) { processReady = HandleProcessReady(wx86BreakpointReceived); } if (_keepOnExit && dbg.KillOnExit) { dbg.KillOnExit = false; } if (e != null) { //Console.WriteLine(e.ToString()); e.Process.HandleIfLoaderBreakpoint(e, ref loaderBreakpointReceived); switch (e.EventCode) { case NativeDebugEventCode.EXCEPTION_DEBUG_EVENT: HandleNativeDebugEvent((ExceptionNativeEvent)e, ref numEventsByTarget, ref wx86BreakpointReceived); break; case NativeDebugEventCode.LOAD_DLL_DEBUG_EVENT: // Start of the process, ntdll.dll and kernel32.dll should now be loaded. Trigger a Process.HandleProcessLoaded() event. if (_process.PyProcess.print_debugger_messages) { Console.WriteLine(e.ToString()); } //Console.WriteLine(((LoadDllNativeEvent)e).Module.Name ); _process.HandleModuleLoaded((LoadDllNativeEvent)e); break; case NativeDebugEventCode.EXIT_PROCESS_DEBUG_EVENT: // Process crashed, send Process.ProcessTerminated() event and finish. if (printReport && numEventsByTarget.Count > 0) { PrintReport(numEventsByTarget); } _process.HandleProcessTerminated(); dbg.Dispose(); _attached = false; return; default: break; } // Resume event dbg.ContinueEvent(e); } } // Detach dbg.KillOnExit = false; _attached = false; }