/// <summary> /// See <see cref="StepIn"/>. /// If there's a call as next instruction, it'll be skipped. /// </summary> public void StepOver(DebugThread th) { var code = APIIntermediate.ReadArray <byte>(th.OwnerProcess.Handle, th.CurrentInstruction, DisAsm86.MaximumInstructionLength); int instructionLength = 0; var instrType = DisAsm86.GetInstructionType(code, false, out instructionLength); /* * If there's a call, set a breakpoint right after the call to skip the called subroutine */ if (instrType == InstructionType.Call) { var bpAddr = IntPtr.Add(th.CurrentInstruction, instructionLength); var tempBreakPoint = Breakpoints.ByAddress(bpAddr); bool keepBpAfterStepComplete = false; if (keepBpAfterStepComplete = tempBreakPoint == null) { tempBreakPoint = Breakpoints.CreateBreakpoint(bpAddr); } th.ContinueDebugging(); Debuggee.WaitForDebugEvent(); if (!keepBpAfterStepComplete) { Breakpoints.Remove(tempBreakPoint); } } else { StepIn(th); } }
/// <summary> /// Removes the breakpoint from the code /// </summary> public void Disable() { if (enabled) { APIIntermediate.RemoveInterrupt(Owner.Handle, Address, originalInstruction); } enabled = false; }
/// <summary> /// Inserts the breakpoint into the code /// </summary> public void Enable() { if (!enabled) { APIIntermediate.SetInterrupt(Owner.Handle, Address, out originalInstruction); enabled = true; temporarilyDisabled = false; } }
void BuildCallStack() { callstack.Clear(); var ebp = lastReadCtxt.ebp; const int MaxFrames = 128; var proc = Thread.OwnerProcess; var p = proc.Handle; callstack.Add(new Stackframe(new IntPtr(ebp), new IntPtr(lastReadCtxt.eip))); do { // The return address is stored at ebp+1 var returnTo = APIIntermediate.Read <uint>(p, new IntPtr(ebp + 4)); ebp = APIIntermediate.Read <uint>(p, new IntPtr(ebp)); if (ebp == 0 || returnTo == ebp) { break; } callstack.Add(new Stackframe(new IntPtr(ebp), new IntPtr(returnTo))); }while (callstack.Count < MaxFrames); string file = ""; ushort line = 0; Console.WriteLine("------------------------\r\nCall stack begin:\r\n------------------------"); foreach (var sf in callstack) { Console.Write("0x" + sf.CodeAddress.ToString("X8")); if (proc.MainModule.ContainsSymbolData && proc.MainModule.ModuleMetaInfo.TryDetermineCodeLocation((uint)sf.CodeAddress.ToInt32(), out file, out line)) { Console.WriteLine(" @ " + file + ":" + line); } else { Console.WriteLine(); } } }
/// <summary> /// Executes until the currently executed method's point of return has been reached. /// </summary> public void StepOut(DebugThread th) { var returnPtr = APIIntermediate.Read <IntPtr>(th.OwnerProcess.Handle, new IntPtr(th.Context.lastReadCtxt.ebp + 4)); var tempBreakPoint = Breakpoints.ByAddress(returnPtr); bool keepBpAfterStepComplete = false; if (keepBpAfterStepComplete = tempBreakPoint == null) { tempBreakPoint = Breakpoints.CreateBreakpoint(returnPtr); } th.ContinueDebugging(); Debuggee.WaitForDebugEvent(); if (!keepBpAfterStepComplete) { Breakpoints.Remove(tempBreakPoint); } }
public DebugProcess(Debuggee dbg, Win32.CREATE_PROCESS_DEBUG_INFO info, uint id, uint threadId) { this.Debuggee = dbg; Handle = info.hProcess; Id = id == 0 ? API.GetProcessId(Handle) : id; var moduleFile = APIIntermediate.GetModulePath(Handle, info.lpBaseOfImage, info.hFile); // Deduce main module MainModule = new DebugProcessModule(info.lpBaseOfImage, moduleFile, ExecutableMetaInfo.ExtractFrom(moduleFile)); RegModule(MainModule); // Create main thread MainThread = new DebugThread(this, info.hThread, threadId == 0 ? API.GetThreadId(info.hThread) : threadId, info.lpStartAddress, info.lpThreadLocalBase); RegThread(MainThread); }
void HandleDebugEvent(DebugEventData de) { var p = ProcessById(de.dwProcessId); var th = CurrentThread = p.ThreadById(de.dwThreadId); switch (de.dwDebugEventCode) { case DebugEventCode.EXCEPTION_DEBUG_EVENT: HandleException(th, de.Exception); break; case DebugEventCode.CREATE_PROCESS_DEBUG_EVENT: var cpi = de.CreateProcessInfo; if (MainProcess != null && de.dwProcessId == MainProcess.Id) { API.CloseHandle(cpi.hProcess); API.CloseHandle(cpi.hThread); API.CloseHandle(cpi.hFile); foreach (var l in DDebugger.EventListeners) { l.OnCreateProcess(MainProcess); } break; } // After a new process was created (also occurs after initial WaitForDebugEvent()!!), p = new DebugProcess(this, cpi, de.dwProcessId, de.dwThreadId); API.CloseHandle(cpi.hFile); // enlist it processes.Add(p); // and call the listeners foreach (var l in DDebugger.EventListeners) { l.OnCreateProcess(p); } break; case DebugEventCode.CREATE_THREAD_DEBUG_EVENT: p = ProcessById(de.dwProcessId); // Create new thread wrapper th = CurrentThread = new DebugThread(p, de.CreateThread.hThread, de.dwThreadId, de.CreateThread.lpStartAddress, de.CreateThread.lpThreadLocalBase); // Register it to main process p.RegThread(th); // Call listeners foreach (var l in DDebugger.EventListeners) { l.OnCreateThread(th); } break; case DebugEventCode.EXIT_PROCESS_DEBUG_EVENT: foreach (var l in DDebugger.EventListeners) { l.OnProcessExit(p, de.ExitProcess.dwExitCode); } processes.Remove(p); p.Dispose(); break; case DebugEventCode.EXIT_THREAD_DEBUG_EVENT: foreach (var l in DDebugger.EventListeners) { l.OnThreadExit(th, de.ExitThread.dwExitCode); } p.RemThread(th); th.Dispose(); break; case DebugEventCode.LOAD_DLL_DEBUG_EVENT: var loadParam = de.LoadDll; var modName = APIIntermediate.GetModulePath(p.Handle, loadParam.lpBaseOfDll, loadParam.hFile); API.CloseHandle(loadParam.hFile); var mod = new DebugProcessModule(loadParam.lpBaseOfDll, modName, ExecutableMetaInfo.ExtractFrom(modName)); p.RegModule(mod); foreach (var l in DDebugger.EventListeners) { l.OnModuleLoaded(p, mod); } break; case DebugEventCode.UNLOAD_DLL_DEBUG_EVENT: mod = p.ModuleByBase(de.UnloadDll.lpBaseOfDll); foreach (var l in DDebugger.EventListeners) { l.OnModuleUnloaded(p, mod); } p.RemModule(mod); break; case DebugEventCode.OUTPUT_DEBUG_STRING_EVENT: var message = APIIntermediate.ReadString(p.Handle, de.DebugString.lpDebugStringData, de.DebugString.fUnicode == 0 ? Encoding.ASCII : Encoding.Unicode, (int)de.DebugString.nDebugStringLength); foreach (var l in DDebugger.EventListeners) { l.OnDebugOutput(th, message); } break; } }
internal DebugEventData WaitForDebugEventInternal(uint timeOut) { lastDebugEvent.ApplyFrom(APIIntermediate.WaitForDebugEvent(timeOut)); return(lastDebugEvent); }