如何进行混合 user-mode/kernel-mode 调试?

How to do hybrid user-mode/kernel-mode debugging?

基本上,我有一个调用 kernel32.CreateProcessA() 的用户模式程序,它在内部调用 kernel32.CreateProcessInternalW()。在这个函数中,我对 ntdll.NtCreateSection() 内部发生的事情很感兴趣,它试图将可执行文件映射到虚拟内存中。进入这个函数后,程序迅速将内核调用设置为 EAX=0x32 并执行 SYSENTER 指令。

显然我无法在用户模式调试器中看到调用门之外的东西。我有一点调试内核模式驱动程序的经验,所以我在 VMWare window 中加载了 XP SP3 的副本,并使用 VirtualKD 将管道连接到 WinDbg(我恰好在 运行ning 里面开发协会)。连接内核调试器后,我将我的用户模式 ​​EXE 程序和 PDB 复制到虚拟机上,但我有点不知道如何在我的用户模式程序中正确设置初始断点。我不想拦截对等效 ntdll.ZwCreateSection() 的所有调用,我认为它位于调用门的另一侧。理想情况下,既然我正在使用内核调试器,我想进入用户模式代码并逐步通过该调用门,但我不知道第一步是什么。

我进行了一些谷歌搜索,并通过在

中设置 "ntsd -d" 值接近
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\myprocess.exe

当我启动我的进程时,这会导致内核调试器中断,但我似乎无法在我需要向 IDA 发出 .breakin 命令以进入 WinDbg 提示符后设置任何断点。我一直在关注这个 guide ,在这里我使用 !process 找到我的进程然后切换到上下文,并重新加载符号但是我在我的进程中设置断点或前进到初始断点设置时遇到问题 "ntsd -d"。在收到无法解析断点并添加延迟断点的消息后,如果有任何意义,我似乎无法在不清除断点的情况下将 "into" 推进到进程。这是我第一次休息时所处位置的堆栈:

ChildEBP RetAddr  
b2b55ccc 8060e302 nt!RtlpBreakWithStatusInstruction
b2b55d44 8053d638 nt!NtSystemDebugControl+0x128
b2b55d44 7c90e4f4 nt!KiFastCallEntry+0xf8
0007b270 7c90de3c ntdll!KiFastSystemCallRet
0007b274 6d5f5ca6 ntdll!ZwSystemDebugControl+0xc
0007bd48 6d5f6102 dbgeng!DotCommand+0xd0d
0007de8c 6d5f7077 dbgeng!ProcessCommands+0x318
0007dec4 6d5bec6c dbgeng!ProcessCommandsAndCatch+0x1a
0007eedc 6d5bed4d dbgeng!Execute+0x113
0007ef0c 010052ce dbgeng!DebugClient::Execute+0x63
0007ff3c 010069fb ntsd!MainLoop+0x1ec
0007ff44 01006b31 ntsd!main+0x10e
0007ffc0 7c817067 ntsd!mainCRTStartup+0x125
0007fff0 00000000 kernel32!BaseProcessStart+0x23

老实说,我不确定我的 PDB 是否正在加载,但我怀疑这可能不是我的直接问题;我的模块面板只显示内核驱动模块,不显示用户模式模块。当我过去进行驱动程序调试时,我可以在此窗格中看到我的驱动程序图像以及符号是否已加载,所以我不确定用户模式图像会发生什么。 没有图像,我真的不能指望调试器解决任何断点。

我意识到我可能会完全错误地解决这个问题,但我没有找到如何进行 user-mode/kernel-mode 混合调试的运气。有没有人可以指出正确的方向,以便我可以从特定的用户模式进程进入这个内核模式函数?或者,至少设置一个适当的内核模式断点,以便它仅作为我特定的用户模式进程的结果被触发?

更新: 我在调试的OS(我碰巧使用OllyDbg)上的用户模式调试器中加载了我的模块(碰巧被命名为runlist.exe)。一旦我在用户模式断点处暂停,仅来自 SYSENTER 的几条指令,我就使用内核调试器暂停了 OS。然后我设置流程上下文。 WinDbg命令window内容如下:

WINDBG>!process 0 0 runlist.exe

PROCESS 820645a8  SessionId: 0  Cid: 01b4    Peb: 7ffd7000  ParentCid: 02b0
    DirBase: 089c02e0  ObjectTable: e1671bb0  HandleCount:   8.
    Image: runlist.exe

WINDBG>.process /i /r /p 820645a8
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
WINDBG>g
This command cannot be passed to the WinDbg plugin directly, please use IDA Debugger menu to achieve the same result.
Break instruction exception - code 80000003 (first chance)
WINDBG>.reload /user
Loading User Symbols
....
Caching 'Modules'... ok
WINDBG>lmu
start    end        module name
00400000 00405000   runlist  C (no symbols)           
7c340000 7c396000   MSVCR71    (private pdb symbols)  g:\symcache\msvcr71.pdb0C79175C1942C099C9BC4ED019C6092\msvcr71.pdb
7c800000 7c8f6000   kernel32   (pdb symbols)          e:\windows\symbols\dll\kernel32.pdb
7c900000 7c9af000   ntdll      (pdb symbols)          e:\windows\symbols\dll\ntdll.pdb
WINDBG>bp 0x7c90d16a
WINDBG>bl
 0 e 7c90d16a     0001 (0001) ntdll!ZwCreateSection+0xa

虽然我无法使用“.reload”加载进程的符号(PDB 在同一目录中 - 可能需要将其复制到我的符号目录),但我关心的断点无论如何都在 ntdll 中所以我将它设置在地址 0x7C90D16A 上,调试器将其识别为在 ntdll.ZwCreateSection() 内。对我来说奇怪的是,在用户模式代码中,该地址解析为 ntdll.NtCreateSection(),但无论哪种方式,该断点距离我的用户模式中断点只有 2 条指令。当我恢复机器时,我的意图是 "run" 用户模式调试进程,这将触发内核模式断点 2 指令。内核断点从未被击中,应用程序在该点之后恢复。但是,我可以在 ntdll!ZwCreateSection() 上设置一个断点,但是当恢复 OS 时,断点会被其他进程反复击中,阻止我返回到用户模式调试器,因此我可以 "run"它只在我自己的进程中到那个位置。

更新 合并@conio提供的提示,以下步骤对我有用:

1> 附加内核调试器和引导目标 OS 后,暂停 OS 并应用一些配置选项:

!gflag +ksl         //allow sxe to report user-mode module load events under kernel debugger
sxe ld myproc.exe   //cause kernel debugger break upon process load
.sympath+ <path>    //path to HOST machine's user-mode app's symbols

2> 运行 调试器恢复目标 OS

3> 在目标上,运行 我们要调试的 EXE

4> 内核调试器应该中断;现在输入以下命令切换到用户模式上下文:

!process 0 0 myproc.exe                 //get address of EProcess structure (first number on 1st line after "PROCESS")
.process /i /r /p <eprocess*>           //set kernel debugger to process context
g                                       //continue execution to allow the context switch; debugger will break after switch complete
.reload /user                           //reload user symbols
lmu                                     //ensure you have symbols although not really necessary in my particular case

5> 现在因为我已经知道 ntdll.NtCreateSection() 的用户模式端发生了什么,我只是继续为该函数的内核模式端设置一个断点,但指定我希望断点仅在我的流程上下文中出现。这样就不会触发断点 OS wide:

bu /p <eprocess*> nt!NtCreateSection        //set breakpoint in kernel side of function
g                                           //run to break

6> 如果一切按计划进行,断点将在 NtCreateSection() 的内核模式端唤醒调试器。感谢所有回复和提示!

使用 ntsd -d 并开始使用 kd 连接从目标调试 executabke 您可以将 kd 用作用户模式调试器以及内核调试器 多次阅读文档 第一次这样做并不容易,但要多次尝试你应该掌握它阅读关于 .breakin 等

编辑以添加使用 ntsd -d

的演示

设置

1 ) a vm running winxp sp3 and windbg version 6.12 installed in it    
2 ) _NT_SYMBOL_PATH in vm is set to z:\   
3 ) z:\ is a mapped network drive that points to e:\symbols in host   
4 ) host running win 7 sp2    
5 ) host windbg 10.0010586      

在 ntsd 下的 vm 中启动应用程序并将其重定向到 kd

在 vm 中打开命令提示符导航到 windbg 安装目录并发出 ntsd -s -d calc -s is to disable lazy symbol loading

0:000> version
version
Windows XP Version 2600 (Service Pack 3) UP Free x86 compatible
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 5.1.2600.5512 (xpsp.080413-2111)
Machine Name:
Debug session time: Thu Mar 16 16:44:29.222 2017 
System Uptime: 0 days 0:10:12.941
Process Uptime: 0 days 0:01:40.980
  Kernel time: 0 days 0:00:01.632
  User time: 0 days 0:00:00.040
Live user mode: <Local>

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

command line: 'ntsd -s -d calc'  Debugger Process 0xA8 
dbgeng:  image 6.12.0002.633, built Tue Feb 02 01:38:31 2010
[path C:\Documents and Settings\admin\Desktop\Debugging Tools for Windows (x86)\dbgeng.dll]

windbg 在 SystemBreakPoint 上中断,调试提示为 Input:\>
lm 显示符号是从 z:\

加载的
CommandLine: calc
Symbol search path is: z:\
Executable search path is: 
ModLoad: 01000000 0101f000   calc.exe
xxxxx
ntdll!DbgBreakPoint:
7c90120e cc              int     3
0:000> lm
lm
start    end        module name
01000000 0101f000   calc       (pdb symbols)          z:\calc.pdbB7D84101\calc.pdb
77c10000 77c68000   msvcrt     (export symbols)       C:\WINDOWS\system32\msvcrt.dll

执行到 AddressOfEntryPoint

0:000> g @$exentry
g @$exentry

calc!WinMainCRTStartup:
01012475 6a70            push    70h

同时在用户模式和内核模式设置断点

0:000> bp ntdll!ZwCreateSection  <--- user mode bp notice prompt 0:000
bp ntdll!ZwCreateSection


0:000> .breakin  <<---- transferring to kd mode 
.breakin
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
804e3592 cc              int     3


kd> !process 0 0 calc.exe   <<----- looking for our process of interest
Failed to get VAD root
PROCESS ffae2020  SessionId: 0  Cid: 0410    Peb: 7ffde000  ParentCid: 00a8
    DirBase: 04d87000  ObjectTable: e1bd5238  HandleCount:  26.
    Image: calc.exe

kd> bp /p ffae2020 nt!NtCreateSection  << setting a kernel mode bp    
on counterpart that matches with our process of interest notice prompt kd> 


kd> g  <<<---- return to user mode  after setting a breakpoint
0:000> g   <<<<<---------  executing in user mode 
g

现在 calc 进程在 vm 的用户模式下 运行 单击 help about(这将触发 Loadlib 并且需要一个 Section,因此我们将在内核调试器中中断我们的用户模式 ​​bp)

Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d160 esp=0007f22c ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!NtCreateSection:
7c90d160 b832000000      mov     eax,32h

现在我们可以愉快地使用 t 跟踪而不是 p 或 g 或任何其他执行命令

0:000> t
t
eax=00000032 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d165 esp=0007f22c ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwCreateSection+0x5:
7c90d165 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
0:000> 

eax=00000032 ebx=00000000 ecx=00000001 edx=7ffe0300 esi=0007f368 edi=00000000
eip=7c90d16a esp=0007f22c ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwCreateSection+0xa:
7c90d16a ff12    call dword ptr [edx] ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c90e4f0)}
0:000> 

eax=00000032 ebx=00000000 ecx=00000001 edx=7ffe0300 esi=0007f368 edi=00000000
eip=7c90e4f0 esp=0007f228 ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall:
7c90e4f0 8bd4            mov     edx,esp
0:000> 

eax=00000032 ebx=00000000 ecx=00000001 edx=0007f228 esi=0007f368 edi=00000000
eip=7c90e4f2 esp=0007f228 ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCall+0x2:
7c90e4f2 0f34            sysenter
0:000> 

Breakpoint 1 hit
nt!NtCreateSection:
805652b3 6a2c            push    2Ch

在内核的 bp 中时。重新加载并查看堆栈跟踪

第二个堆栈跟踪与第一个相同,但具有更正的符号 Shell32.dll(虚拟机无法访问互联网,因此第一次失败 所以我从 vm 中拖放了那个特定的 dll,并使用 windbg -z shell32.dll 和 .reload 从主机中获取了它的 sumbols(因为主机中的 downstore 是网络映射到 vm 中的第二个跟踪正确加载 pdb 并提供正确的堆栈无警告跟踪

kd> kb
 # ChildEBP RetAddr  Args to Child              
00 f8bb1d40 804de7ec 0007f368 0000000f 00000000 nt!NtCreateSection
01 f8bb1d40 7c90e4f4 0007f368 0000000f 00000000 nt!KiFastCallEntry+0xf8
02 0007f224 7c90d16c 7c91c993 0007f368 0000000f ntdll!KiFastSystemCallRet
03 0007f228 7c91c993 0007f368 0000000f 00000000 ntdll!NtCreateSection+0xc
04 0007f2a8 7c91c64a 0007f340 00000790 0007f300 ntdll!LdrpCreateDllSection+0x92
05 0007f388 7c91624a 000add00 0007f414 0007f93c ntdll!LdrpMapDll+0x28f
06 0007f648 7c9164b3 00000000 000add00 0007f93c ntdll!LdrpLoadDll+0x1e9
07 0007f8f0 7c801bbd 000add00 0007f93c 0007f91c ntdll!LdrLoadDll+0x230
08 0007f958 7c801d72 7ffddc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
09 0007f96c 7ca625a3 7ca625ac 00000000 00000000 kernel32!LoadLibraryExA+0x1f
WARNING: Stack unwind information not available. Following frames may be wrong.
0a 0007f990 010057b8 000700ac 000a7c84 00000000 SHELL32!SHCreateQueryCancelAutoPlayMoniker+0x2062d
0b 0007fbc4 010041ac 0000012e 00000111 01006118 calc!MenuFunctions+0x15d
0c 0007fcb4 01004329 0000012e 00000111 01006118 calc!RealProcessCommands+0x1b61
0d 0007fcdc 01006521 0000012e 0007fd6c 01006118 calc!ProcessCommands+0x2d
0e 0007fd04 7e418734 000700ac 00000111 0000012e calc!CalcWndProc+0x409
0f 0007fd30 7e418816 01006118 000700ac 00000111 USER32!InternalCallWinProc+0x28
10 0007fd98 7e4189cd 00000000 01006118 000700ac USER32!UserCallWinProcCheckWow+0x150
11 0007fdf8 7e418a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x306
12 0007fe08 010021a7 0007fee8 7c80b731 000a1ee4 USER32!DispatchMessageW+0xf
13 0007ff1c 010125e9 000a7738 00000055 000a7738 calc!WinMain+0x256
14 0007ffc0 7c817067 00000000 00000000 7ffde000 calc!WinMainCRTStartup+0x174
15 0007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23

没有警告的 STACKtrace

Breakpoint 0 hit
nt!NtCreateSection:
805652b3 6a2c            push    2Ch
kd> kb
 # ChildEBP RetAddr  Args to Child              
00 f8aa0d40 804de7ec 0007f368 0000000f 00000000 nt!NtCreateSection
01 f8aa0d40 7c90e4f4 0007f368 0000000f 00000000 nt!KiFastCallEntry+0xf8
02 0007f224 7c90d16c 7c91c993 0007f368 0000000f ntdll!KiFastSystemCallRet
03 0007f228 7c91c993 0007f368 0000000f 00000000 ntdll!NtCreateSection+0xc
04 0007f2a8 7c91c64a 0007f340 00000790 0007f300 ntdll!LdrpCreateDllSection+0x92
05 0007f388 7c91624a 000add00 0007f414 0007f93c ntdll!LdrpMapDll+0x28f
06 0007f648 7c9164b3 00000000 000add00 0007f93c ntdll!LdrpLoadDll+0x1e9
07 0007f8f0 7c801bbd 000add00 0007f93c 0007f91c ntdll!LdrLoadDll+0x230
08 0007f958 7c801d72 7ffdfc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
09 0007f96c 7ca625a3 7ca625ac 00000000 00000000 kernel32!LoadLibraryExA+0x1f
0a 0007f97c 7ca62e8e 003800dd 000a7c84 00000000 SHELL32!GetXPSP1ResModuleHandle+0x16
0b 0007f990 010057b8 000900ac 000a7c84 00000000 SHELL32!ShellAboutW+0x1f
0c 0007fbc4 010041ac 0000012e 00000111 01006118 calc!MenuFunctions+0x15d
0d 0007fcb4 01004329 0000012e 00000111 01006118 calc!RealProcessCommands+0x1b61
0e 0007fcdc 01006521 0000012e 0007fd6c 01006118 calc!ProcessCommands+0x2d
0f 0007fd04 7e418734 000900ac 00000111 0000012e calc!CalcWndProc+0x409
10 0007fd30 7e418816 01006118 000900ac 00000111 USER32!InternalCallWinProc+0x28
11 0007fd98 7e4189cd 00000000 01006118 000900ac USER32!UserCallWinProcCheckWow+0x150
12 0007fdf8 7e418a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x306
13 0007fe08 010021a7 0007fee8 7c80b731 000a1ee4 USER32!DispatchMessageW+0xf
14 0007ff1c 010125e9 000a7738 00000055 000a7738 calc!WinMain+0x256
15 0007ffc0 7c817067 00000000 00000000 7ffda000 calc!WinMainCRTStartup+0x174
16 0007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23

将参数转储到 NtCreateSection

kd> dds @esp l8
f8bb1d44  804de7ec nt!KiFastCallEntry+0xf8
f8bb1d48  0007f368
f8bb1d4c  0000000f
f8bb1d50  00000000
f8bb1d54  00000000
f8bb1d58  00000010
f8bb1d5c  01000000 calc!_imp__RegOpenKeyExA <PERF> (calc+0x0)
f8bb1d60  00000790

我们知道第七个参数是HANDLE according to prototype of DDI

    NTSTATUS ZwCreateSection(
      _Out_    PHANDLE            SectionHandle,
      _In_     ACCESS_MASK        DesiredAccess,
      _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
      _In_opt_ PLARGE_INTEGER     MaximumSize,
      _In_     ULONG              SectionPageProtection,
      _In_     ULONG              AllocationAttributes,
      _In_opt_ HANDLE             FileHandle
    );

kd> !handle 790

Failed to get VAD root
PROCESS ffae2020  SessionId: 0  Cid: 0410    Peb: 7ffde000  ParentCid: 00a8
    DirBase: 04d87000  ObjectTable: e1bd5238  HandleCount:  29.
    Image: calc.exe

Handle table at e1bd5238 with 29 entries in use

0790: Object: 8124b028  GrantedAccess: 00100020 Entry: e1032f20
Object: 8124b028  Type: (8127b900) File
    ObjectHeader: 8124b010 (old version)
        HandleCount: 1  PointerCount: 1
        Directory Object: 00000000  Name: \WINDOWS\system32\xpsp1res.dll {HarddiskVolume1}

return 从内核模式回到用户模式并检查新的Section Handle

kd> g
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d16c esp=0007f22c ebp=0007f2a8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!ZwCreateSection+0xc:
7c90d16c c21c00          ret     1Ch

在用户模式下检查return HANDLE 的值

0:000> dd 7f368 l1
dd 7f368 l1
0007f368  0000078c
0:000> !handle 78c
!handle 78c
Handle 78c
  Type          Section
0:000> !handle 78c f
!handle 78c f
Handle 78c
  Type          Section
  Attributes    0
  GrantedAccess 0xf:
         None
         Query,MapWrite,MapRead,MapExecute
  HandleCount   2
  PointerCount  3
  Name          <none>
  Object Specific Information
    Section base address 0
    Section attributes 0x1800000
    Section max size 0x2f000
0:000> 

如果不满意,我们可以恢复到 kd 设置进程上下文并在内核模式下检查 returned 句柄

kd> !handle 78c f

Failed to get VAD root
PROCESS ffae2020  SessionId: 0  Cid: 0410    Peb: 7ffde000  ParentCid: 00a8
    DirBase: 04d87000  ObjectTable: e1bd5238  HandleCount:  30.
    Image: calc.exe

Handle table at e1bd5238 with 30 entries in use

078c: Object: e1088f30  GrantedAccess: 0000000f Entry: e1032f18
Object: e1088f30  Type: (8128b900) Section
    ObjectHeader: e1088f18 (old version)
        HandleCount: 1  PointerCount: 1

现在如果你继续执行你可以在 windbg 中看到加载的库 dbgprint 和在 vm 中的关于对话框:)

kd> g
0:000> g
g
ModLoad: 10000000 1002f000   C:\WINDOWS\system32\xpsp1res.dll

有两种方法可以将用户模式调试与内核模式调试结合起来,您会混淆和混淆它们。

您尝试的方法是使用内核模式调试器调试内核模式代码,使用用户模式调试器(ntsd)调试用户模式代码,并控制用户模式debugger 运行 从内核调试器在目标机器上。这就是 ntsd-d 标志所做的。此方法在 MSDN 的 Controlling the User-Mode Debugger from the Kernel Debugger 页面及其子页面中进行了描述。

它的作用(或多或少)是将 ntsd 输入和输出重定向到内核调试器。模块窗格——作为 WinDbg 中 windows 的其余部分——属于内核调试器。您与用户模式调试器的唯一交互是通过内核调试器创建的隧道,您只能通过命令 window 访问它。这记录在 -d 标志的文档中:

-d

        Passes control of this debugger to the kernel debugger. If you are debugging CSRSS, this control redirection always is active, even if -d is not specified. (This option cannot be used during remote debugging -- use -ddefer instead.) See Controlling the User-Mode Debugger from the Kernel Debugger for details. This option cannot be used in conjunction with either the -ddefer option or the -noio option.

        Note  If you use WinDbg as the kernel debugger, many of the familiar features of WinDbg are not available in this scenario. For example, you cannot use the Locals window, the Disassembly window, or the Call Stack window, and you cannot step through source code. This is because WinDbg is only acting as a viewer for the debugger (NTSD or CDB) running on the target computer.

第二种方法,也就是您在link中使用的方法,是使用内核调试器来调试内核模式代码和用户模式代码。没有用户模式调试器。没有ntsd。你说你遵循了指南,但实际上你没有。如果有,就不会有任何 ntsd.

我建议你使用这种方法开始,并且在你使用用户模式调试器之后,只有当你发现你需要时(因为你想使用用户模式扩展,例如)。

为了让内核调试器与用户模式模块一起工作,您必须启用 Enable loading of kernel debugger symbols GlobalFlag。使用 !gflag +ksl 来做到这一点。

完成后,使用 sxe ld:runlist 中断进程加载,设置断点(可能使用 /p 选项)并根据需要进行调试。

只需这样做,而不是所有 ntsd 混乱。