示例#1
0
        /// <summary>
        /// Waits for a debug event from any of the processes in the wait set.
        /// </summary>
        /// <param name="timeout">timeout in milliseconds to wait. If 0, checks for a debug event and returns immediately</param>
        /// <returns>Null if no event is available</returns>
        /// <remarks>Debug events should be continued by calling ContinueEvent. The debuggee is completely stopped when a
        /// debug event is dispatched and until it is continued.</remarks>
        public NativeEvent WaitForDebugEvent(int timeout)
        {
            EnsureIsOnWin32EventThread();
            bool fHasEvent;

            if (IntPtr.Size == sizeof(Int32))
            {
                DebugEvent32 event32 = new DebugEvent32();
                fHasEvent = NativeMethods.WaitForDebugEvent32(ref event32, timeout);
                if (fHasEvent)
                {
                    return(NativeEvent.Build(this, ref event32.header, ref event32.union));
                }
            }
            else
            {
                DebugEvent64 event64 = new DebugEvent64();
                fHasEvent = NativeMethods.WaitForDebugEvent64(ref event64, timeout);
                if (fHasEvent)
                {
                    return(NativeEvent.Build(this, ref event64.header, ref event64.union));
                }
            }

            // Not having an event could be a timeout, or it could be a real failure.
            // Empirically, timeout produces GetLastError()=121 (ERROR_SEM_TIMEOUT), but MSDN doesn't spec that, so
            // we don't want to rely on it. So if we don't have an event, just return NULL and
            // don't try to probe any further.
            return(null);
        }
            private static bool WaitForDebugEvent(ref dynamic debugEvent32Or64, int dwMilliseconds)
            {
                bool is64BitProcess = (IntPtr.Size == 8);

                if (is64BitProcess)
                {
                    var debugEvent64 = new DebugEvent64();
                    if (!NativeDebuggingMethods.WaitForDebugEvent64(ref debugEvent64, dwMilliseconds))
                    {
                        return(false);
                    }
                    debugEvent32Or64 = debugEvent64;
                }
                else
                {
                    var debugEvent32 = new DebugEvent32();
                    if (!NativeDebuggingMethods.WaitForDebugEvent32(ref debugEvent32, dwMilliseconds))
                    {
                        return(false);
                    }
                    debugEvent32Or64 = debugEvent32;
                }
                return(true);
            }
示例#3
0
        public void DebugThread(string executable)
        {
            var lpStartupInfo        = new STARTUPINFO();
            var lpProcessInformation = new PROCESS_INFORMATION();

            if (!NativeMethods.CreateProcess(executable, "",
                                             IntPtr.Zero, IntPtr.Zero, false,
                                             NativeMethods.CreateProcessFlags.DEBUG_PROCESS |
                                             NativeMethods.CreateProcessFlags.DEBUG_ONLY_THIS_PROCESS,
                                             IntPtr.Zero, null, lpStartupInfo,
                                             lpProcessInformation))
            {
                Console.WriteLine($"FAIL with {Marshal.GetLastWin32Error()}");
            }

            var process = Process.GetProcessById(lpProcessInformation.dwProcessId);

            ProcessContext context = null;

            var loop = true;

            while (loop)
            {
                var debugEvent = new DebugEvent64();
                NativeMethods.WaitForDebugEvent64(ref debugEvent, -1);

                try
                {
                    switch (debugEvent.header.dwDebugEventCode)
                    {
                    case NativeDebugEventCode.None:
                        break;

                    case NativeDebugEventCode.EXCEPTION_DEBUG_EVENT:
                        switch (debugEvent.union.Exception.ExceptionRecord.ExceptionCode)
                        {
                        case ExceptionCode.STATUS_BREAKPOINT:
                            OnProcessBreakpoint(new ProcessBreakpointEventArgs(context, lpProcessInformation.hProcess, debugEvent.header.dwProcessId, debugEvent.header.dwThreadId));
                            break;
                        }
                        break;

                    case NativeDebugEventCode.CREATE_THREAD_DEBUG_EVENT:
                        break;

                    case NativeDebugEventCode.CREATE_PROCESS_DEBUG_EVENT:
                    {
                        context = new ProcessContext(process);
                        OnProcessCreated(new ProcessCreatedEventArgs(context, lpProcessInformation.hProcess, debugEvent.header.dwProcessId, debugEvent.header.dwThreadId));
                        break;
                    }

                    case NativeDebugEventCode.EXIT_THREAD_DEBUG_EVENT:
                        break;

                    case NativeDebugEventCode.EXIT_PROCESS_DEBUG_EVENT:
                    {
                        loop = false;
                        break;
                    }

                    case NativeDebugEventCode.LOAD_DLL_DEBUG_EVENT:
                    {
                        var    loadDllDebugInfo = debugEvent.union.LoadDll;
                        string value            = null;
                        if (loadDllDebugInfo.lpImageName != IntPtr.Zero)
                        {
                            var intPtr = context.Memory[loadDllDebugInfo.lpImageName, false].Read <IntPtr>();
                            if (intPtr != IntPtr.Zero)
                            {
                                value = context.Memory[intPtr, false]
                                        .ReadString(loadDllDebugInfo.fUnicode != 0 ? Encoding.Unicode : Encoding.ASCII);
                            }
                        }

                        OnProcessModuleLoad(new ProcessModuleLoadEventArgs(context, lpProcessInformation.hProcess, debugEvent.header.dwProcessId, debugEvent.header.dwThreadId)
                            {
                                Name = value
                            });

                        break;
                    }

                    case NativeDebugEventCode.UNLOAD_DLL_DEBUG_EVENT:
                        break;

                    case NativeDebugEventCode.OUTPUT_DEBUG_STRING_EVENT:
                    {
                        var outputDebugStringInfo = debugEvent.union.OutputDebugString;

                        var value = context.Memory[outputDebugStringInfo.lpDebugStringData, false]
                                    .ReadString(outputDebugStringInfo.fUnicode != 0 ? Encoding.Unicode : Encoding.ASCII);

                        OnProcessDebugOutput(new ProcessDebugOutputEventArgs(context, lpProcessInformation.hProcess, debugEvent.header.dwProcessId, debugEvent.header.dwThreadId)
                            {
                                Value = value
                            });
                        break;
                    }

                    case NativeDebugEventCode.RIP_EVENT:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                catch (Exception e)
                {
                    OnDebugException(new DebugExceptionEventArgs(context, lpProcessInformation.hProcess, debugEvent.header.dwProcessId, debugEvent.header.dwThreadId)
                    {
                        Exception = e
                    });

                    NativeMethods.ContinueDebugEvent(debugEvent.header.dwProcessId, debugEvent.header.dwThreadId,
                                                     NativeMethods.ContinueStatus.DBG_EXCEPTION_NOT_HANDLED);

                    continue;
                }

                NativeMethods.ContinueDebugEvent(debugEvent.header.dwProcessId, debugEvent.header.dwThreadId,
                                                 NativeMethods.ContinueStatus.DBG_CONTINUE);
            }
        }