我想调试一个由进程A启动的进程B,当我附加进程B时出错,我无法在主函数上中断。进程B启动时是否有自动中断的方法?
答案 0 :(得分:1)
遗憾的是没有使用visual-studio。在第一个和主要 - 这个调试器不能一次调试几个进程。它只能调试一个进程。如果你调试进程 A 并且它开始处理 B - 这个调试器根本无法调试新进程 B 。
通常在我们调试进程 A 时 - 存在DebugPort
对象附加到进程。 (EPROCESS.DebugPort
)也在EPROCESS
对象中存在NoDebugInherit
标志。当进程 A 启动新进程 B - 系统执行下一步(伪代码)时:
if (Process->DebugPort && !Process->NoDebugInherit)
AttachDebugPortToNewProcess(Process->DebugPort);
如果 A 在调试器下并且NoDebugInherit
标志未设置 - 新进程 B 也附加到同一DebugPort
(相同的调试器)。< / p>
如何设置NoDebugInherit
?
如果我们通过CreateProcess
api启动流程 - 如果我们将DEBUG_ONLY_THIS_PROCESS
NoDebugInherit
设置为true。如果我们使用DEBUG_PROCESS
而不使用 DEBUG_ONLY_THIS_PROCESS
- NoDebugInherit
设置为false - 那么新流程创建的所有子流程也将被调试。
如果我们通过设置为true的DebugActiveProcess
NoDebugInherit
附加到已在运行的流程。因此,如果此过程启动新进程 - 它将不会被调试。
我们可以通过NoDebugInherit
和NtQueryInformationProcess
NtSetInformationProcess
ProcessDebugFlags
查询并设置此PROCESSINFOCLASS
(在< EM> NTDDK.H )。有了这个,我们可以随时通过下一个代码查询和更改ProcessDebugFlags
:
// from WRK\WRK-v1.2\public\sdk\inc\ntpsapi.h
//
// Define process debug flags
//
#define PROCESS_DEBUG_INHERIT 0x00000001
NTSTATUS SetDebugInherit(HANDLE hProcess, BOOLEAN bInherit)
{
ULONG DebugFlags;
// hProcess must have PROCESS_QUERY_INFORMATION access
NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessDebugFlags, &DebugFlags, sizeof(DebugFlags), 0);
if (0 <= status)
{
bInherit ? DebugFlags |= PROCESS_DEBUG_INHERIT : DebugFlags &= ~PROCESS_DEBUG_INHERIT;
// hProcess must have PROCESS_SET_INFORMATION access
status = NtSetInformationProcess(hProcess, ProcessDebugFlags, &DebugFlags, sizeof(DebugFlags));
}
return status;
}
如果返回 MSVS 或 WinDbg - 它始终使用DEBUG_ONLY_THIS_PROCESS
启动新进程。即使我们自己将NoDebugInherit
设置为false并启动新进程 - 无论如何,如果我们使用 MSVS ,新进程将不会被调试甚至不运行。如果 WinDbg 一次尝试正式的调试2(和更多)进程,但也不能这样做。你需要有更好的调试器,它可以在并发中调试多个进程。
另一种可能性在进程 A 中的CreateProcessInternalW
中设置断点并在其命中之后 - 将断点设置为NtResumeThread
(这必须是临时断点 - 在{{之后1}}只打了)。当CreateProcessInternalW
命中时 - 新进程NtResumeThread
已经启动(处于挂起状态)。此时,您可以运行 MSVS 或 WinDbg 的新实例并附加到该实例。但是这里也可能存在问题,因为大多数调试器( MSVS 和 WinDbg )都使用B
。这个api在调用DebugActiveProcess
之后需要并且足以开始调试过程,由于某种原因在目标进程(NtDebugActiveProcess
)中创建(DbgUiIssueRemoteBreakin
)新线程。结果,新进程开始在此线程上执行。在xp中,这会导致进程初始化失败。在现代窗口中 - 这通常是有效的,但无论如何都会影响流程执行 - 主流程线程不会首先进入。
如果 B 是你的过程 - 所以你可以修改它代码,你总是可以做下一步,你想要附加/中断调试器:
DbgUiRemoteBreakin
或者如果你能展示gui:
while (!IsDebuggerPresent()) Sleep(1000);
__debugbreak();
答案 1 :(得分:0)
当您手动附加到进程B时,它必须已经运行了一段时间。
使用插件“ Microsoft Child Process Debugging Power Tool”,VS可以在子进程启动时自动附加到子进程,并且您可以在main()
的第一条语句处中断。