1

My setup:

  • Debugger: Win10 Pro, WinDbg Preview v.1.0.1904.18001
  • Debuggee: Win7 Pro (running in a VM using VMWare Workstation)

I'm trying to follow the SendMessage call from the user space:

enter image description here

Into the kernel, by setting a conditional breakpoint on win32k!NtUserMessageCall:

enter image description here

If we take the declaration of the NtUserMessageCall function:

NTSTATUS NtUserMessageCall(
    HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam,
    ULONG_PTR ResultInfo,
    DWORD dwWndProcType,
    BOOL bAnsi);

The condition for the breakpoint is for uMsg == WM_SYSCOMMAND (or 0x112). I set it as such:

ba e 1 fffff960`00163318 "j (@rdx=0x112) ''; 'gc'"

I can then check that it was set up alright:

enter image description here

But when I then "Go" the OS:

enter image description here

The debuggee OS literally grinds to a halt. I can't do anything. I can see some "life" in there by seeing the clock widget jumping by 20 second intervals but it is impossible to interact with windows or do anything. Note that if I disable the breakpoint above, everything starts working smoothly.

Can someone explain what am I doing wrong there? And how can I make it work?

  • If you can't do anything how you disable the breakpoint? I think you will have to run the OS in sort of virtual machine and debug that.... – Ricardo Jun 18 at 22:31
  • @Ricardo: The debuggee OS is running in a virtual machine. (The first screenshot is from a debuggee. It's showing a user-mode IDA. I added it to show that the execution was a few commands away from entering the kernel mode.) – c00000fd Jun 18 at 22:35
  • make sure you are comparing not assigning with a double == instead of single = use process specifc breakpoint with /p switch (it is a very hot path ) evaluating conditionals is a very intensive work – blabb Jun 19 at 8:22
  • @blabb: hmm, that might be an idea. So how would I get the addr of EPROCESS by PID? – c00000fd Jun 19 at 17:35
1

not sure how you can do it with ida as front end shown below is a pure windbg demo

finding _EPROCESS with name or Cid

1: kd> !process 0 0 explorer.exe
PROCESS ffff8e0c835c9300
    SessionId: 1  Cid: 0fc8    Peb: 00583000  ParentCid: 0f8c
    DirBase: 0a600002  ObjectTable: ffffd58bc24b0d40  HandleCount: 1913.
    Image: explorer.exe

1: kd> !process 0fc8 0
Searching for Process with Cid == fc8
PROCESS ffff8e0c835c9300
    SessionId: 1  Cid: 0fc8    Peb: 00583000  ParentCid: 0f8c
    DirBase: 0a600002  ObjectTable: ffffd58bc24b0d40  HandleCount: 1913.
    Image: explorer.exe

setting an unconditional process specific software bp

1: kd> bp /p ffff8e0c835c9300 win32kfull!NtUserMessageCall
WARNING: Software breakpoints on session addresses can cause bugchecks.
Use hardware execution breakpoints (ba e) if possible.

1: kd> g
Breakpoint 0 hit
win32kfull!NtUserMessageCall:
ffffeae2`57cdc020 48895c2408      mov     qword ptr [rsp+8],rbx

0: kd> ? @$proc
Evaluate expression: -125290582076672 = ffff8e0c`835c9300

0: kd> kb
 # RetAddr            Call Site
00 fffff803`2abdb285  win32kfull!NtUserMessageCall
01 00007ffc`bb641184  nt!KiSystemServiceCopyEnd+0x25
xxxxxxxxxxxxxxxxxxxxxxxxxx

0: kd> r rdx
rdx=0000000000000081

setting a conditional process specific breakpoint

0: kd> bp /p ffff8e0c835c9300 win32kfull!NtUserMessageCall ".if (@rdx != 0x112 ) { gc;}"

WARNING: Software breakpoints on session addresses can cause bugchecks.
Use hardware execution breakpoints (ba e) if possible.
breakpoint 0 redefined

0: kd> bl
     0 e Disable Clear  ffffeae2`57cdc020  win32kfull!NtUserMessageCall ".if (@rdx != 0x112 ) {gc;}"
     Match process data ffff8e0c`835c9300


0: kd> g

win32kfull!NtUserMessageCall:
ffffeae2`57cdc020 48895c2408      mov     qword ptr [rsp+8],rbx

1: kd> ? @$proc
Evaluate expression: -125290582076672 = ffff8e0c`835c9300

1: kd> r rdx
rdx=0000000000000112

call stack for break

1: kd> kb
 # RetAddr             Call Site
00 fffff803`2abdb285   win32kfull!NtUserMessageCall
01 00007ffc`bb641184   nt!KiSystemServiceCopyEnd+0x25
02 00007ffc`bb8b9d60   win32u!NtUserMessageCall+0x14
03 00007ffc`bb8b98d2   USER32!RealDefWindowProcWorker+0x150
04 00007ffc`b8aeea12   USER32!RealDefWindowProcW+0x52
05 00007ffc`b8aeeaf2   UxTheme!DoMsgDefault+0x2e [es\uxtheme\handlers.cpp @ 550] 
06 00007ffc`b8ae8626   UxTheme!OnDwpSysCommand+0x32 [es\uxtheme\nctheme.cpp @ 7566] 
07 00007ffc`b8ae7641   UxTheme!_ThemeDefWindowProc+0x4c6 [emes\uxtheme\sethook.cpp @ 1067] 
08 00007ffc`bb8b9ad4   UxTheme!ThemeDefWindowProcW+0x11 [hemes\uxtheme\sethook.cpp @ 1109] 
09 00007ffc`a339bd0c   USER32!DefWindowProcW+0x1c4
0a 00007ffc`a33b0f2e   v_WndProc+0xac
0b 00007ffc`bb8bca66   s_WndProc+0x6e
0c 00007ffc`bb8bc78c   USER32!UserCallWinProcCheckWow+0x266
0d 00007ffc`bb8cfa83   USER32!DispatchClientMessage+0x9c
0e 00007ffc`be5322c4   USER32!_fnDWORD+0x33
0f 00007ffc`bb641184   ntdll!KiUserCallbackDispatcherContinue
10 00007ffc`bb8b9d60   win32u!NtUserMessageCall+0x14
11 00007ffc`bb8b98d2   USER32!RealDefWindowProcWorker+0x150
12 00007ffc`b8aeea12   USER32!RealDefWindowProcW+0x52
13 00007ffc`b8aeebb4   UxTheme!DoMsgDefault+0x2e [hemes\uxtheme\handlers.cpp @ 550] 
14 00007ffc`b8ae8626   UxTheme!OnDwpNcLButtonDown+0xa4 [hemes\uxtheme\nctheme.cpp @ 7157] 
15 00007ffc`b8ae7641   UxTheme!_ThemeDefWindowProc+0x4c6 [\themes\uxtheme\sethook.cpp @ 1067] 
16 00007ffc`bb8b9ad4   UxTheme!ThemeDefWindowProcW+0x11 [l\themes\uxtheme\sethook.cpp @ 1109] 
17 00007ffc`a339bd0c   USER32!DefWindowProcW+0x1c4
18 00007ffc`a33b0f2e   v_WndProc+0xac
19 00007ffc`bb8bca66   s_WndProc+0x6e
1a 00007ffc`bb8bc582   USER32!UserCallWinProcCheckWow+0x266
1b 00007ffc`a33a48a3   USER32!DispatchMessageWorker+0x1b2
1c 00007ffc`a33a47a9   FrameMessagePump+0xe3
1d 00007ffc`a33a46f6   explorerframe!BrowserThreadProc+0x85
1e 00007ffc`a33a5a12   explorerframe!BrowserNewThreadProc+0x3a
1f 00007ffc`a33b70c2  InternalResumeRT+0x12
20 00007ffc`babdb3ec  Run+0xb2
21 00007ffc`babdb0a5  TT_Run+0x3c
22 00007ffc`babdaf85  ThreadProc+0xdd
23 00007ffc`bc9ac315  s_ThreadProc+0x35
24 00007ffc`bb6d7e94   shcore!_WrapperThreadProc+0xf5
25 00007ffc`be4f7ad1   KERNEL32!BaseThreadInitThunk+0x14
26 00000000`00000000   ntdll!RtlUserThreadStart+0x21

there isn't any special reason to use software bp it comes by rote

how to do multiple conditions

1: kd> bp win32kfull!NtUserMessageCall ".if ( ( @rdx != 410 ) & ( @rcx != 20498 ) ) { r rdx,rcx; gc }"
WARNING: Software breakpoints on session addresses can cause bugchecks.
Use hardware execution breakpoints (ba e) if possible.
breakpoint 0 redefined
1: kd> g
rdx=0000000000000084 rcx=0000000000010404
rdx=0000000000000084 rcx=000000000001046e
rdx=0000000000000084 rcx=0000000000010404
rdx=0000000000000020 rcx=0000000000010470
rdx=0000000000000020 rcx=000000000001046e
rdx=0000000000000020 rcx=00000000000104a6
rdx=0000000000000020 rcx=000000000001048e
rdx=0000000000000020 rcx=0000000000060480
rdx=0000000000000020 rcx=0000000000010446
rdx=0000000000000020 rcx=0000000000010404
rdx=0000000000000407 rcx=000000000001047c
rdx=0000000000000084 rcx=0000000000010404
rdx=000000000000004e rcx=0000000000010492
win32kfull!NtUserMessageCall:
ffffeae2`57cdc020 48895c2408      mov     qword ptr [rsp+8],rbx
1: kd> r rdx,rcx
rdx=0000000000000407 rcx=0000000000020498

demo for bitwise versus logical operators and why logical operator needs to be evaluated as c++

0:000> $$ display rdx and rcx register
0:000> r rdx, rcx
rdx=0000000000000000 rcx=00007ffd7a57fc04
0:000> $$ evaluating logical operator as C++ expression
0:000> ?? @rdx && @rcx
bool false
0:000> $$ evaluating logical operator as masm expression (will fail)
0:000> ? @rdx && @rcx
Numeric expression missing from '& @rcx'
0:000> $$ evaluating bitwise operator as masm expression 
0:000> ? @rdx & @rcx
Evaluate expression: 0 = 00000000`00000000
0:000> $$ evaluating bitwise operator as c++ expression 
0:000> ?? @rdx & @rcx
unsigned int64 0
  • Thanks. Two quick questions. 1) Why are you using software breakpoint instead of a hardware one? and 2) if I want to set up an AND condition, when I did ba e 1 /p ffffe001ab2c4180 fffff96000218ac0 ".if (@rdx != 0x112 || @rcx != 0x103cc) {gc;}"` it triggered the breakpoint but not when I expected. RDX was not 0x112 and RCX was not 0x103cc. Is there another syntax for the OR/AND operator? – c00000fd Jun 19 at 20:46
  • no special reason what are you trying bitwise OR (|) or logical OR (||) anyway I added an edit take a look – blabb Jun 19 at 21:14
  • I'm sorry, but what does if( @rdx != 410 ) & ( @rcx != 20498 ) do? If the & means AND then it's as if you wrote if(true). Also can you explain what's the purpose of r rdx,rcx part? As for the software bp it may cause BSOD if the memory is not paged yet. That's why I asked. – c00000fd Jun 19 at 22:02
  • & is bitwise && is logical & is masm operator && is c++ operator so if your default expression evaluator is masm && will err and break you need to enclose the condition with a @@c++ qualifier that is why i asked what are you trying – blabb Jun 19 at 22:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.