好吧,这可能不是最好的方法,但它确实有效。 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
or !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