private void HandleCreateThread(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.CreateThread; if ((uint)DebugEvent.dwProcessId != DebugInstance.MainProcess.ProcessID) { throw new Exception("Handling event for unknown process"); } var Process = DebugInstance.FindProcess((uint)DebugEvent.dwProcessId); if (Process == null) { throw new Exception("Unable to create tread with untracked process id"); } var Thread = new DebuggerThread(Process); Thread.Handle = DebugInfo.hThread; Thread.ThreadID = NativeMethods.GetThreadId(Thread.Handle); Thread.StartAddress = DebugInfo.lpStartAddress; Thread.ThreadBase = DebugInfo.lpThreadLocalBase; foreach (IDebuggerThreadEvents Event in ThreadEvents) { Event.OnThreadCreate(Thread); } }
private void HandleOutputDebugString(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.DebugString; string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1); Parallel.ForEach(OutputEvents, Event => Event.OnDebugOutput(debugString)); }
private void HandleOutputDebugString(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.DebugString; string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1); foreach (IDebuggerOutputEvents Event in OutputEvents) { Event.OnDebugOutput(debugString); } }
private void HandleCreateProcess(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.CreateProcessInfo; var Process = new DebuggerProcess(); Process.Core = true; Process.Handle = DebugInfo.hProcess; Process.ProcessID = WinLowLevel.GetProcessId(Process.Handle); Process.Path = ResolveProcessPath(DebugInfo.hFile); // Skip over allocated Xbox memory Process.ImageBase = DebugInfo.lpBaseOfImage + VM_PLACEHOLDER_SIZE; var MainThread = new DebuggerThread(Process); MainThread.Handle = DebugInfo.hThread; MainThread.ThreadID = NativeMethods.GetThreadId(DebugInfo.hThread); MainThread.ThreadBase = DebugInfo.lpThreadLocalBase; // Setup as the main thread // TODO Check that we need to treat this as a special case Process.MainThread = MainThread; DebugInstance = new DebuggerInstance(Process); RegisterEventInterfaces(DebugInstance); foreach (IDebuggerProcessEvents Event in ProcessEvents) { Event.OnProcessCreate(Process); } foreach (IDebuggerThreadEvents Event in ThreadEvents) { Event.OnThreadCreate(MainThread); } var XboxModule = new DebuggerModule(); XboxModule.Path = Target; XboxModule.ImageBase = DebugInfo.lpBaseOfImage; XboxModule.Core = true; foreach (IDebuggerModuleEvents Event in ModuleEvents) { Event.OnModuleLoaded(XboxModule); } }
private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.UnloadDll; if ((uint)DebugEvent.dwProcessId != DebugInstance.MainProcess.ProcessID) { throw new Exception("Handling event for unknown process"); } var TargetModule = DebugInstance.MainProcess.Modules.Find(Module => Module.ImageBase == DebugInfo.lpBaseOfDll); if (TargetModule != null) { Parallel.ForEach(ModuleEvents, Event => Event.OnModuleUnloaded(TargetModule)); } }
private void HandleLoadDll(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.LoadDll; if ((uint)DebugEvent.dwProcessId != DebugInstance.MainProcess.ProcessID) { throw new Exception("Handling event for unknown process"); } var Module = new DebuggerModule(); Module.Path = ResolveProcessPath(DebugInfo.hFile); Module.ImageBase = DebugInfo.lpBaseOfDll; Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(Module)); }
private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.ExitProcess; if ((uint)DebugEvent.dwProcessId != DebugInstance.MainProcess.ProcessID) { throw new Exception("Handling event for unknown process"); } var TargetProcess = DebugInstance.FindProcess((uint)DebugEvent.dwProcessId); uint ExitCode = DebugInfo.dwExitCode; if (TargetProcess != null) { Parallel.ForEach(ProcessEvents, Event => Event.OnProcessExit(TargetProcess, ExitCode)); } }
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.ExitThread; if ((uint)DebugEvent.dwProcessId != DebugInstance.MainProcess.ProcessID) { throw new Exception("Handling event for unknown process"); } var TargetThread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (TargetThread != null) { uint ExitCode = DebugInfo.dwExitCode; Parallel.ForEach(ThreadEvents, Event => Event.OnThreadExit(TargetThread, ExitCode)); } }
public void RunThreaded() { WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT(); ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugStart(); } // Loop until told to stop while (bContinue == true) { // Pause until a debug event notification happens bContinue = WinDebug.NativeMethods.WaitForDebugEvent(out DbgEvt, VsChromium.Core.Win32.Constants.INFINITE); switch (DbgEvt.dwDebugEventCode) { case WinDebug.DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT: HandleException(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.CREATE_THREAD_DEBUG_EVENT: HandleCreateThread(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT: HandleCreateProcess(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.EXIT_THREAD_DEBUG_EVENT: HandleExitThread(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT: HandleExitProcess(DbgEvt); // XX Temporary bContinue = false; break; case WinDebug.DEBUG_EVENT_CODE.LOAD_DLL_DEBUG_EVENT: HandleLoadDll(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.UNLOAD_DLL_DEBUG_EVENT: HandleUnloadDll(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT: HandleOutputDebugString(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.RIP_EVENT: // TODO: Handle break; } // TODO: Stop doing this once we raise an exception WinDebug.NativeMethods.ContinueDebugEvent(DbgEvt.dwProcessId, DbgEvt.dwThreadId, ContinueStatus); ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; } State = RunState.Ended; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugEnd(); } }
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.Exception; switch ((ExceptionCode)DebugInfo.ExceptionRecord.ExceptionCode) { case ExceptionCode.AccessViolation: { // Ignore all access violation errors. // This will fallback to the debugee (Cxbx) and the exception handling routine. // Should they be unsupported, the debugger "OVERRIDE_EXCEPTION" message is thrown // which means the exception is usually fatal ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED; } break; case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); bool Handled = false; foreach (IDebuggerExceptionEvents Event in ExceptionEvents) { Handled |= Event.OnAccessViolation(Thread, Query.ExceptionCode, Query.ExceptionAddress); } // Write the reponse to memory Thread.OwningProcess.WriteMemory(Query.ReponseAddr, Handled); } } break; case (ExceptionCode)DebuggerMessages.ReportType.HLECACHE_FILE: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetHLECacheReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); SetupHLECacheProvider(Report.FileName); } } break; case (ExceptionCode)DebuggerMessages.ReportType.KERNEL_PATCH: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetKernelPatchReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); KernelSymbolProvider.AddKernelSymbolFromMessage(Report); } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_OPENED: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileOpenedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileOpened(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_READ: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileReadReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileRead(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_WRITE: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileWriteReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileWrite(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_CLOSED: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileClosedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); if (Report != null) { foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileClosed(Report); } } } } break; case (ExceptionCode)DebuggerMessages.ReportType.DEBUGGER_INIT: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetDebuggerInitReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); InitParams = Report; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugTitleLoaded(InitParams.Title); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.MS_VC_EXCEPTION: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetMSVCThreadName(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); if (Report != null) { // Resolve the ThreadId of an invalid ID to the current thread name if (Report.ThreadId == uint.MaxValue) { Report.ThreadId = (uint)DebugEvent.dwThreadId; } var ResolvedThread = DebugInstance.MainProcess.FindThread(Report.ThreadId); if (ResolvedThread != null) { // Update the resolved thread name ResolvedThread.DebugName = Report.Name; foreach (IDebuggerThreadEvents Event in ThreadEvents) { Event.OnThreadNamed(Thread); } } } } } break; case ExceptionCode.Breakpoint: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { uint BpAddr = (uint)DebugInfo.ExceptionRecord.ExceptionAddress; uint BpCode = DebugInfo.ExceptionRecord.ExceptionCode; bool FirstChance = (DebugInfo.dwFirstChance != 0); bpStall.Reset(); foreach (IDebuggerExceptionEvents Event in ExceptionEvents) { Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance); } bpStall.WaitOne(); } } break; case ExceptionCode.SingleStep: // TODO Handle break; default: ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED; break; } }
public static extern bool WaitForDebugEvent(out DEBUG_EVENT debugEvent, uint timeout);