【问题标题】:How do I debug a process that starts at boot time?如何调试在启动时启动的进程?
【发布时间】:2014-08-10 18:22:39
【问题描述】:

我正在尝试在启动时启动的 Windows 服务中设置断点。由于我的不幸错误,该服务强制机器进入重新启动循环:这意味着我无法进入可以部署修复程序的稳定状态,显然我无法尝试调试服务在更方便的时间。

我可以在内核模式下使用windbg。当服务达到wmain 函数时,我非常想中断,但我遇到了问题。

到目前为止,我发现使用以下命令可以在加载图像时停止:

!gflag +ksl
sxe ld MyServiceExecutable.exe

问题是一旦中断,我发现自己处于一个空进程中,显然我无法在其中设置断点。 bm MyServiceExecutable!wmain 说它找不到符号并且断点将被“延迟”,但实际上它从未设置或到达。在KERNEL32!BaseThreadInitThunk 上设置断点似乎在所有正在运行的进程中或多或少地随机工作,到目前为止我没有太多运气停止我的服务。

【问题讨论】:

  • 你不能简单地从命令行启动进程并在那里调试(如果你设计它以这种方式工作)。阻止启动通常意味着 ServiceInit 永远不会返回,这应该很容易调试。
  • @AloisKraus,在这个特定的例子中,我确切地知道错误是什么以及如何修复它,问题是机器无法进入我可以部署修复的状态。基本上,我的选择是“以你的方式进入功能状态”或“擦除机器”。
  • 如果启动挂起,您不能强制蓝屏并调试创建的内存转储吗? msdn.microsoft.com/en-us/library/windows/hardware/…
  • @AloisKraus,在内核模式下使用 WinDbg 暂停系统是最简单的事情,只需按 Ctrl+Break 即可。我不是试图诊断问题,而是试图在不擦拭机器的情况下解决问题。
  • !gflag 显然不是 !gflags。

标签: windows windbg boot


【解决方案1】:

好的,这可能不是最好的方法,但它确实有效。 MSFT,如果我在做一些愚蠢的事情,请纠正我!

第一部分很好:

kd> !gflag +ksl
    New NtGlobalFlag contents: 0x00440000
        ksl - Enable loading of kernel debugger symbols
        ece - Enable close exception
kd> sxe ld MyServiceExecutable.exe
kd> g

在内核模式下,sxe ld 将仅在第一次加载可执行文件时停止。

当调试器再次停止时,我们处于新创建的进程中。我们不再需要 gflag:

kd> !gflag -ksl
    New NtGlobalFlag contents: 0x00400000
        ece - Enable close exception

虽然我们需要EPROCESS 指针。我们可以通过.process!process -1 0 得到它,但它已经在$proc 伪寄存器中:

kd> r $proc
    $proc=0011223344556677
kd> .process
    Implicit process is now 00112233`44556677

从这一点开始,可以在nt 符号上设置断点,所以让我们使用NtMapViewOfSection,因为它会为每个加载的 dll 调用。

kd> bp /p @$proc nt!NtMapViewOfSection
kd> g

应该在下一站加载ntdll(如果它在堆栈上,请检查kn,如果需要,请.reload /user),因此您可以在RtlUserThreadStart上设置断点。此外,我们正在覆盖断点 0,因为我们不再需要在 NtMapViewOfSection 上中断(这会很麻烦)。

kd> bp0 /p @$proc ntdll!RtlUserThreadStart
kd> g

在第一个用户线程启动时,所有符号都应该已加载,因此您可以随意设置断点。

kd> .reload /user
kd> bp /p @$proc MyServiceExecutable!wmain
kd> g

【讨论】:

  • 您可以使用bu 设置未解决的断点,这将允许您在尚未加载的模块上设置断点,您可以将以上所有内容放在一个脚本中,这会简化一些事情
  • @EdChum,根据我的阅读,bm 断点的行为与bu 相同,而我对这些不太走运——可能是因为我错过了@987654341 @在我的第一次尝试中?也就是说,既然我解决了我的问题,你就会明白我并不急于再试一次:)
  • 只有符号可以匹配才成立,如果模块没有加载则没有符号匹配,bm允许你在多个匹配上设置多个断点,我可以理解不想去再次通过这个!
  • 这对我有用!可执行文件通过运行!process -1 0 显示,但未显示在!process 0 0 中。 -1 是指某种最近加载的可执行文件吗?
【解决方案2】:

使用 MS 描述的调试 winlogon 的技术,该技术涉及串联使用内核模式和用户模式调试器。请参阅“Windows 调试工具”下载附带的 debugger.chm 文件中的“调试 WinLogon”。

【讨论】:

  • “要将调试器附加到 WinLogon,您必须通过注册表,以便从启动时开始调试进程,”我做不到。
  • @zneak,你可以设置reg keybefore重启机器,重启后进程会进入调试器。它应该对您有用,并且以这种方式调试用户模式进程是一种更强大的方法,因为您将基本上处于 WinDbg 中,所有普通用户模式扩展都按预期工作。在您使用普通 KD 的方法中,工作起来更加困难,尤其是在某些进程内存被调出的情况下。
  • @SevaTitov,这里是交易:服务阻止机器启动。它卡在重启循环中。这就是我的问题中所说的“服务阻塞了启动过程,所以我不能在更方便的时候调试它,也不能修改它”。
  • @zneak,能不能开机进入安全模式(windows logo出现前按F8),修改注册表,然后正常开机?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2014-11-09
  • 2017-08-07
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
相关资源
最近更新 更多