You can set kernel breakpoints per process using the bp /p
command (doc):
/p EProcess (Kernel-mode only) Specifies a process that is associated
with this breakpoint. EProcess should be the actual address of the
EPROCESS structure, not the PID. The breakpoint is triggered only if
it is encountered in the context of this process.
To get the EPROCESS
structure (which represents a process object in kernel land), you can issue the !process
command:
Example with notepad:
0: kd> !process 0 0 notepad.exe
PROCESS ffffbe8e593d3080
SessionId: 14 Cid: 74bc Peb: 2d7c91c000 ParentCid: 8a94
DirBase: a2faeb002 ObjectTable: ffffa981f4ce3a40 HandleCount: 246.
Image: notepad.exe
The hexadecimal number right at the top of the output (ffffbe8e593d3080
above) is the address of the EPROCESS structure. If you have more than one process with the same name, you can discriminate between them using the Cid
(otherwise known a PID, Process identifier).
Setting a BP:
0: kd> bp /p ffffbe8e593d3080 nt!ZwCreateEvent
Debugging a userland process in kernel mode is sometimes a bit contrived. I'd suggest to debug your process using windbg in user mode and setting a breakpoint at the user / kernel boundary (that is, in ntdll.dll
), simply:
0:004> bp ntdll!ZwCreateEvent
Note that in this case (from a user-mode debugger) you're setting a breakpoint in the function that performs the syscall (transitioning to kernel mode):
0:004> u ntdll!ZwCreateEvent
ntdll!NtCreateEvent:
00007ffa`d1d8d950 4c8bd1 mov r10,rcx
00007ffa`d1d8d953 b848000000 mov eax,48h
00007ffa`d1d8d958 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffa`d1d8d960 7503 jne ntdll!NtCreateEvent+0x15 (00007ffa`d1d8d965)
00007ffa`d1d8d962 0f05 syscall
00007ffa`d1d8d964 c3 ret
Obviously, you won't be able to step in kernel mode from there.