예제 #1
0
        public bool HandlePageGuardViolationEvent(DEBUG_EVENT debugEvent, out DebuggerAction nextAction)
        {
            // Memory breakpoints are implemented using page guards. We need to check if the page guard
            // violation originated from a breakpoint or not, and pause or continue execution when appropriate.

            const int ExceptionInformationReadWrite = 0;
            const int ExceptionInformationAddress   = 1;

            var info    = debugEvent.InterpretDebugInfoAs <EXCEPTION_DEBUG_INFO>();
            var process = _session.GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);

            if (info.ExceptionRecord.NumberParameters >= 2)
            {
                bool   isWrite = info.ExceptionRecord.ExceptionInformation[ExceptionInformationReadWrite] == 1;
                IntPtr address = (IntPtr)info.ExceptionRecord.ExceptionInformation[ExceptionInformationAddress];

                var pageGuard = process.GetContainingPageGuard(address);
                if (pageGuard != null)
                {
                    // Restore page guard after continuing.
                    _pageGuardsToRestore.Add(pageGuard);

                    if (pageGuard.Breakpoints.TryGetValue(address, out var breakpoint) &&
                        (breakpoint.BreakOnRead == !isWrite || breakpoint.BreakOnWrite == isWrite))
                    {
                        // Violation originated from a breakpoint.
                        var eventArgs = new BreakpointEventArgs(thread, breakpoint)
                        {
                            NextAction = DebuggerAction.Stop
                        };

                        breakpoint.HandleBreakpointEvent(eventArgs);
                        OnBreakpointHit(eventArgs);
                        nextAction = eventArgs.NextAction;
                    }
                    else
                    {
                        // Violation did not originate from a breakpoint.
                        _isRestoringFromGuard = true;
                        PrepareContextForSingleStep(thread);
                        nextAction = DebuggerAction.Continue;
                    }

                    return(true);
                }
            }


            nextAction = DebuggerAction.ContinueWithException;
            return(false);
        }
예제 #2
0
        private DebuggerAction HandleExitProcessDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <EXIT_PROCESS_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);

            process.ExitCode = (int)info.dwExitCode;

            var eventArgs = new DebuggeeProcessEventArgs(process);

            OnProcessTerminated(eventArgs);

            _processes.Remove((int)debugEvent.dwProcessId);
            return(eventArgs.NextAction);
        }
예제 #3
0
        private DebuggerAction HandleExitThreadDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <EXIT_THREAD_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);

            thread.ExitCode = (int)info.dwExitCode;

            var eventArgs = new DebuggeeThreadEventArgs(thread);

            OnThreadTerminated(eventArgs);

            process.RemoveThread(thread);
            return(eventArgs.NextAction);
        }
예제 #4
0
        private DebuggerAction HandleCreateThreadDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <CREATE_THREAD_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);

            var thread = new DebuggeeThread(process, info.hThread, (int)debugEvent.dwThreadId, info.lpStartAddress);

            process.AddThread(thread);

            var eventArgs = new DebuggeeThreadEventArgs(thread);

            OnThreadStarted(eventArgs);

            return(eventArgs.NextAction);
        }
예제 #5
0
        private DebuggerAction HandleOutputStringDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <OUTPUT_DEBUG_STRING_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);

            var eventArgs = new DebuggeeOutputStringEventArgs(thread,
                                                              process.ReadString(
                                                                  info.lpDebugStringData,
                                                                  info.nDebugStringLength,
                                                                  info.fUnicode == 0));

            OnOutputStringSent(eventArgs);

            return(eventArgs.NextAction);
        }
예제 #6
0
        private DebuggerAction HandleCreateProcessDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <CREATE_PROCESS_DEBUG_INFO>();
            var process = GetOrCreateProcess(info.hProcess, (int)debugEvent.dwProcessId);

            process.BaseAddress = info.lpBaseOfImage;

            // Create process event also spawns a new thread.
            _currentThread = new DebuggeeThread(process, info.hThread, (int)debugEvent.dwThreadId, info.lpStartAddress);
            process.AddThread(_currentThread);

            var eventArgs = new DebuggeeProcessEventArgs(process);

            OnProcessStarted(eventArgs);

            return(eventArgs.NextAction);
        }
예제 #7
0
        private DebuggerAction HandleExceptionDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <EXCEPTION_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);

            var  nextAction = DebuggerAction.Stop;
            bool handled    = false;

            switch (info.ExceptionRecord.ExceptionCode)
            {
            case ExceptionCode.EXCEPTION_BREAKPOINT:
            {
                handled = _executionController.HandleBreakpointEvent(debugEvent, out nextAction);
                break;
            }

            case ExceptionCode.EXCEPTION_SINGLE_STEP:
            {
                handled = _executionController.HandleStepEvent(debugEvent, out nextAction);
                break;
            }

            case ExceptionCode.EXCEPTION_GUARD_PAGE:
            {
                handled = _executionController.HandlePageGuardViolationEvent(debugEvent, out nextAction);
                break;
            }
            }

            if (!handled)
            {
                // Forward exception to debugger.
                var eventArgs = new DebuggeeExceptionEventArgs(thread,
                                                               new DebuggeeException((uint)info.ExceptionRecord.ExceptionCode,
                                                                                     info.ExceptionRecord.ExceptionCode.ToString(),
                                                                                     info.dwFirstChance == 1,
                                                                                     info.ExceptionRecord.ExceptionFlags == 0));
                OnExceptionOccurred(eventArgs);
                nextAction = eventArgs.NextAction;
            }

            return(nextAction);
        }
예제 #8
0
        private DebuggerAction HandleUnloadDllDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <UNLOAD_DLL_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);
            var library = process.GetLibraryByBase(info.lpBaseOfDll);

            if (library != null)
            {
                process.RemoveLibrary(library);

                var eventArgs = new DebuggeeLibraryEventArgs(thread, library);
                OnLibraryUnloaded(eventArgs);

                return(eventArgs.NextAction);
            }

            return(DebuggerAction.Continue);
        }
예제 #9
0
        private DebuggerAction HandleLoadDllDebugEvent(DEBUG_EVENT debugEvent)
        {
            var info    = debugEvent.InterpretDebugInfoAs <LOAD_DLL_DEBUG_INFO>();
            var process = GetProcessById((int)debugEvent.dwProcessId);
            var thread  = process.GetThreadById((int)debugEvent.dwThreadId);

            // LOAD_DLL_DEBUG_INFO.lpImageName is a char** or a wchar_t**, which can be null.
            string name = null;

            try
            {
                if (info.lpImageName != IntPtr.Zero)
                {
                    var buffer = new byte[8];
                    process.ReadMemory(info.lpImageName, buffer, 0, IntPtr.Size);
                    var ptr = new IntPtr(BitConverter.ToInt64(buffer, 0));

                    if (ptr != IntPtr.Zero)
                    {
                        name = process.ReadZeroTerminatedString(ptr, info.fUnicode == 0);
                    }
                }
            }
            catch (Win32Exception)
            {
                // Reading failed, possibly due to an invalid pointer address. Set to no name instead.
                name = null;
            }

            var library = new DebuggeeLibrary(process, name, info.lpBaseOfDll);

            process.AddLibrary(library);

            var eventArgs = new DebuggeeLibraryEventArgs(thread, library);

            OnLibraryLoaded(eventArgs);

            return(eventArgs.NextAction);
        }