public ContextManager(String name, Logger loggerInstance, Specifics specificsInstance, Func<ContextManager, int, Win32Imports.ContextX64, bool, ContextTracer.TraceReturn> breakPointCallBack, ImportResolver importResolver) { LoggerInstance = loggerInstance; BreakPointCallBack = breakPointCallBack; _importResolver = importResolver; setDebugPrivilege(); CurrentProcess = DebugProcessUtils.GetFirstProcessByName(name); foreach (ProcessThread thread in CurrentProcess.Threads) { loggerInstance.WriteLine($"main thread: {thread.Id}"); break; } SpecificsInstance = specificsInstance; Console.WriteLine("debugger"); Console.WriteLine("pid: " + CurrentProcess.Id); #if RestartEachTime // Attach to the process we provided the thread as an argument if (!Win32Imports.DebugActiveProcess(CurrentProcess.Id)) { throw new Win32Exception(); } if (!Win32Imports.DebugSetProcessKillOnExit(false)) { throw new Win32Exception(); } ClearEvents(); }
public List<ThreadData> GetContexts() { // Attach to the process we provided the thread as an argument #if RestartEachTime #if UseDebugger if (!Win32Imports.DebugActiveProcess(CurrentProcess.Id)) { throw new Win32Exception(); } if (!Win32Imports.DebugSetProcessKillOnExit(false)) { throw new Win32Exception(); } #endif #endif var retval = new List<ThreadData>(); //CONTEXT_X64 context = new CONTEXT_X64(); Win32Imports.ContextX64 context = new Win32Imports.ContextX64(); foreach (ProcessThread thread in CurrentProcess.Threads) { uint iThreadId = (uint)thread.Id; getRip(iThreadId, ref context, GetRipAction.ActionGetContext); //Console.WriteLine($"Rip: {Rip}"); retval.Add(new ThreadData() { ThreadId = iThreadId, Rip = context.Rip }); //Console.WriteLine($"thread id: {iThreadId}"); //Console.WriteLine($"RIP: {context.Rip}"); } #if RestartEachTime #if UseDebugger if (!Win32Imports.DebugActiveProcessStop(CurrentProcess.Id)) { throw new Win32Exception(); } #endif #endif return retval; }
// remember to set targetAddress before using this function public List<ThreadData> TestBreak() { #if RestartEachTime #if UseDebugger // Attach to the process we provided the thread as an argument if (!Win32Imports.DebugActiveProcess(CurrentProcess.Id)) { throw new Win32Exception(); } if (!Win32Imports.DebugSetProcessKillOnExit(false)) { throw new Win32Exception(); } #endif #endif var retval = new List<ThreadData>(); var context = new Win32Imports.ContextX64(); //Console.WriteLine("TestBreak"); if (!CheckBreakPointActive()) { //Console.WriteLine("adding breakpoints: " + breakPoints.Keys.Count); foreach (var breakPoint in BreakPoints.Keys) { var shouldEnable = BreakPoints[breakPoint].ShouldEnable; //Console.WriteLine($"enumerating breakPoint: 0x{breakPoint}, shouldEnable: {shouldEnable}"); if (shouldEnable) { var msg = BreakPoints[breakPoint].Description; Console.WriteLine($"installing continuation breakpoint at {breakPoint:X}: {msg}"); LoggerInstance.WriteLine($"installing continuation breakpoint at {breakPoint:X}: {msg}"); /* if (!Specifics.useDebugger) { LoggerInstance.WriteLine("Suspending all threads"); foreach (ProcessThread thread2 in process.Threads) { getRip((uint)thread2.Id, ref context, ACTION_SUSPEND); } }*/ try { #if UseHardwareBreakPoints foreach (ProcessThread thread in CurrentProcess.Threads) { InstallHardwareBreakPoint((uint) thread.Id, breakPoint); } #else InstallBreakPoint(breakPoint); #endif } catch (Exception e) { Console.WriteLine($"Exception: {e.Message}"); Console.WriteLine(e.StackTrace); LoggerInstance.WriteLine($"Exception: {e.Message}"); LoggerInstance.WriteLine(e.StackTrace); } } else { Console.WriteLine("stale breakpoint" + BreakPoints[breakPoint].Description); } } } foreach (ProcessThread thread in CurrentProcess.Threads) { uint iThreadId = (uint)thread.Id; #if UseDebugger var traceInterval = Specifics.TraceInterval; var waitInterval = Specifics.WaitInterval; var sw = new Stopwatch(); sw.Start(); // trace program. slows down program a lot var done = false; foreach (ProcessThread thread2 in CurrentProcess.Threads) { //Console.WriteLine("reinstalling CloseHandle breakpoint"); InstallHardwareBreakPoint((uint)thread2.Id, BreakPoints.First(kv => kv.Value.Description.Equals(CloseHandleDescription)).Key); } while (sw.ElapsedMilliseconds <= traceInterval) { getRip(iThreadId, ref context, GetRipAction.ActionGetContext); var breakAddress = context.Rip; if (BreakPoints.ContainsKey(breakAddress) && BreakPoints[breakAddress].IsActive) { LoggerInstance.WriteLine("setting initial trace"); setTrace(iThreadId); } if (ResumeBreak()) { done = true; break; } } sw.Stop(); if (!done) { sw = new Stopwatch(); sw.Start(); // give program time to run without debugging while (sw.ElapsedMilliseconds <= waitInterval) { ResumeBreak(false); } sw.Stop(); } #else var sw = new Stopwatch(); sw.Start(); //getRip(iThreadId, ref context, ACTION_RESUME); while (sw.ElapsedMilliseconds <= Specifics.loopWaitInterval) { foreach (ProcessThread thread2 in CurrentProcess.Threads) { uint iThreadId2 = (uint)thread2.Id; getRip(iThreadId2, ref context, ActionGetContext); var breakAddress = context.Rip; if (BreakPoints.ContainsKey(breakAddress) && BreakPoints[breakAddress].IsActive) { LoggerInstance.WriteLine($"match at {breakAddress:X} for thread {iThreadId2}"); setTrace((uint)iThreadId2, true); UninstallBreakPoint(breakAddress); _lastBreakAddress = breakAddress; CurrentInfo.LastContext = context; CurrentInfo.LastContextReady = true; // trace BreakPointCallBack(this, (int)iThreadId2, context, true); } } } //getRip(iThreadId, ref context, ACTION_SUSPEND); sw.Stop(); #endif // XXX: ONLY FIRST THREAD /*if (Specifics.useDebugger) { break; }*/ break; } /* if (!Specifics.useDebugger) { foreach (var address in originalCode.Keys) { if (activeBreakPoints[address]) { RemoveBreakPoint(address); } } if (!Specifics.useDebugger) { LoggerInstance.WriteLine("Resuming all threads"); foreach (ProcessThread thread2 in process.Threads) { getRip((uint)thread2.Id, ref context, ACTION_RESUME); } } }*/ //ResumeBreak(address); //Thread.Sleep(5000); #if RestartEachTime #if UseDebugger if (!Win32Imports.DebugActiveProcessStop(CurrentProcess.Id)) { throw new Win32Exception(); } #endif #endif return retval; }
public static void TraceIt(Process process, ulong patchSite, Logger logger, bool debug, Action <Process, ulong, Logger> installTracer) { if (debug) { if (!Win32Imports.DebugActiveProcess(process.Id)) { throw new Win32Exception(); } if (!Win32Imports.DebugSetProcessKillOnExit(false)) { throw new Win32Exception(); } } foreach (ProcessThread thread in process.Threads) { var threadId = thread.Id; var context = new Win32Imports.ContextX64(); ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionSuspend); } Console.WriteLine("installing tracer"); installTracer(process, patchSite, logger); var mainThread = 0; foreach (ProcessThread thread in process.Threads) { var threadId = thread.Id; var context = new Win32Imports.ContextX64(); var breakAddress = ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionGetContext); var diff = new BigInteger(breakAddress) - new BigInteger(patchSite); diff = diff < 0 ? -diff : diff; if (diff < 1000) { mainThread = threadId; logger.WriteLine($"thread {threadId} setting Rip to patch site: {patchSite:X}"); ContextManager.setRip((uint)threadId, false, patchSite); if (debug) { ContextManager.setTrace((uint)threadId, false); } } ContextManager.getRip((uint)threadId, ref context, ContextManager.GetRipAction.ActionResume); } /*if (!Win32Imports.DebugBreakProcess(process.Id)) { * throw new Win32Exception(); * }*/ if (debug) { Dictionary <int, OldState> oldThreadState = new Dictionary <int, OldState>(); try { while (true) { Win32Imports.DebugEvent evt; if (Win32Imports.WaitForDebugEvent(out evt, -1)) { Console.WriteLine($"debug event {evt.dwDebugEventCode}"); var continueCode = Win32Imports.DbgContinue; if (evt.dwDebugEventCode == Win32Imports.DebugEventType.ExceptionDebugEvent && evt.dwThreadId == mainThread) { var exceptionAddress = (ulong)evt.Exception.ExceptionRecord.ExceptionAddress.ToInt64(); var context = new Win32Imports.ContextX64(); var breakAddress = ContextManager.getRip((uint)evt.dwThreadId, ref context, ContextManager.GetRipAction.ActionGetContext); var code = evt.Exception.ExceptionRecord.ExceptionCode; Console.WriteLine($"thread {evt.dwThreadId} break at 0x{exceptionAddress:X} code {code}, 0x{breakAddress:X}"); ContextManager.setTrace((uint)evt.dwThreadId); var instr = AssemblyUtil.Disassemble(process, exceptionAddress); var asm = AssemblyUtil.FormatInstruction(instr); var strContext = oldThreadState.ContainsKey(evt.dwThreadId) ? AssemblyUtil.FormatContextDiff(context, oldThreadState[evt.dwThreadId].Context, oldThreadState[evt.dwThreadId].Instruction) : AssemblyUtil.FormatContext(context); logger.WriteLine($"thread {evt.dwThreadId} break at 0x{exceptionAddress:X}, 0x{breakAddress:X} code {code}: {asm}, regs-1: {strContext}"); oldThreadState[evt.dwThreadId] = new OldState { Context = context, Instruction = instr }; if (code == Win32Imports.ExceptionCodeStatus.ExceptionAccessViolation) { continueCode = Win32Imports.DbgExceptionNotHandled; } } if (!Win32Imports.ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueCode)) { throw new Win32Exception(); } } } } finally { if (!Win32Imports.DebugActiveProcessStop(process.Id)) { throw new Win32Exception(); } } } }