如何调试在启动时启动的进程? [英] How do I debug a process that starts at boot time?
问题描述
我试图在Windows服务中设置一个在启动时启动的断点.由于不幸的错误,该服务迫使计算机进入重新启动循环:这意味着我无法进入可以部署修补程序的稳定状态,而且显然我无法尝试调试该服务在更方便的时间.
I am trying to set a breakpoint into a Windows service that starts at boot time. Because of an unfortunate mistake on my end, the service forces the machine into a reboot loop: this means that I can't get to a stable state from which I could deploy a fix, and obviously I can't try to debug the service at a more convenient time.
我可以在内核模式下使用windbg.我非常想在服务命中wmain
功能时中断,但是我遇到了问题.
I can use windbg in kernel mode. I'd very much like to break when the service hits the wmain
function, but I'm having issues with that.
到目前为止,我发现可以使用以下命令在加载图像时停止:
Up to now, I found that I can stop when the image is loaded by using the following commands:
!gflag +ksl
sxe ld MyServiceExecutable.exe
问题在于,一旦中断,我发现自己陷入了一个空白进程,显然我无法设置断点. bm MyServiceExecutable!wmain
表示找不到符号,并且断点将推迟",但是实际上从未设置或到达该断点.在KERNEL32!BaseThreadInitThunk
上设置断点似乎在所有正在运行的进程中或多或少地随机起作用,到目前为止,我没有很多运气可以停止服务.
The problem is that once it breaks, I find myself in an empty process, in which I am apparently unable to set breakpoints. bm MyServiceExecutable!wmain
says that it can't find the symbol and that the breakpoint will be "deferred", but it is effectively never set or reached. Setting a breakpoint on KERNEL32!BaseThreadInitThunk
seems to work more or less at random across all the processes running and I didn't have a lot of luck with it to stop in my service so far.
推荐答案
好的,这可能不是最好的方法,但它确实有效. MSFT,如果我做一些愚蠢的事情,请纠正我!
Alright, this might not the best way to do it, but it worked. MSFTs, please correct me if I'm doing something dumb!
第一部分很好:
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
将首次停止加载可执行文件.
In kernel mode, sxe ld
will stop the first time the executable is loaded only.
当调试器再次停止时,我们位于新创建的进程中.我们不再需要gflag了:
When the debugger stops again, we're inside the freshly created process. We don't need the gflag anymore:
kd> !gflag -ksl
New NtGlobalFlag contents: 0x00400000
ece - Enable close exception
尽管我们将需要EPROCESS
指针.我们可以用.process
或!process -1 0
来获得它,但是它已经在$proc
伪寄存器中:
Though we're going to need the EPROCESS
pointer. We can get it with .process
or !process -1 0
, but it is already in the $proc
pseudo-register:
kd> r $proc
$proc=0011223344556677
kd> .process
Implicit process is now 00112233`44556677
从这一点开始,可以在nt
符号上设置断点,所以我们在每个加载的dll调用NtMapViewOfSection
时使用它.
From this point it's possible to set breakpoints on nt
symbols, so let's use NtMapViewOfSection
as it's called for each dll loaded.
kd> bp /p @$proc nt!NtMapViewOfSection
kd> g
在下一个停止处,应加载ntdll(如果在堆栈中,请在kn
中进行检查,如果需要,请在.reload /user
中进行检查),以便可以在RtlUserThreadStart
上设置断点.另外,我们将覆盖断点0,因为既然我们不再需要在NtMapViewOfSection
上中断(这将是一个麻烦).
On the next stop ntdll should be loaded (check with kn
if it's on the stack, .reload /user
if necessary), so you can set a breakpoint on RtlUserThreadStart
. Also, we are overwriting breakpoint 0, because since we don't need to break on NtMapViewOfSection
anymore(it would just be a nuisance).
kd> bp0 /p @$proc ntdll!RtlUserThreadStart
kd> g
所有符号都应该在第一个用户线程启动时已加载,因此您可以随意在任意位置设置断点.
All symbols should have been loaded by the time the first user thread starts, so you're free to set your breakpoint wherever you want.
kd> .reload /user
kd> bp /p @$proc MyServiceExecutable!wmain
kd> g
这篇关于如何调试在启动时启动的进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!