如何使用visual studio调试子进程?

时间:2018-02-02 07:25:33

标签: windows visual-studio debugging visual-c++

我想调试一个由进程A启动的进程B,当我附加进程B时出错,我无法在主函数上中断。进程B启动时是否有自动中断的方法?

2 个答案:

答案 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附加到已在运行的流程。因此,如果此过程启动新进程 - 它将不会被调试。

我们可以通过NoDebugInheritNtQueryInformationProcess 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()的第一条语句处中断。