Question

I couldn't find a precise answer so I've decided to ask.

I've been reading the "Inside Windows Debugging" and in the sample it tells me to set a breakpoint on the kernel32!CreateProcessW.

But before that it uses the .symfix debugger command to set the debugger symbols search path to point to the Microsoft online symbols server. When I try to set the breakpoint I get an error that it cannot resolve the function (or something like that). It looks like this.

0:000> bp kernel32!CreateProcessW
Couldn't resolve error at 'kernel32!CreateProcessW'

It's probably because there's no "kernel32!CreateProcessW" in the list below.

0:000> x kernel32!CreateProcess*
76b90cb9 KERNEL32!CreateProcessWithTokenW (void)
76b90d84 KERNEL32!CreateProcessAsUserW (void)
76b90d84 KERNEL32!CreateProcessWithLogonW (void)
76b4e225 KERNEL32!CreateProcessWStub = <no type information>
76b72e04 KERNEL32!CreateProcessInternalAStub = <no type information>
76b72e15 KERNEL32!CreateProcessInternalWStub = <no type information>
76b72de2 KERNEL32!CreateProcessAStub = <no type information>
76b72df3 KERNEL32!CreateProcessAsUserWStub = <no type information>

Everything goes fine if I set the breakpoint to kernel32!CreateProcessWStub but I wondered why I couldn't find and set the breakpoint to the kernel32!CreateProcessW.

This book probably focuses on a reader who's using Windows 7. I'm using Windows 8.1 and thought maybe that kernel32!CreateProcessW got deprecated...

I'm extremely new to this field and apologize if this is a completely stupid question. But thanks for reading it anyway.

Was it helpful?

Solution

CreateProcessW is definitely NOT deprecated. Furthermore, the only documented entry point is still in kernel32.dll, so for all intents and purposes, you should continue calling CreateProcessW through kernel32.dll, and not through kernelbase.dll.

Here is some more details to help understand what you are observing. Windows team often moves code around, and for the last few releases they had strong habit of breaking larger DLL's into smaller ones, which includes kernel32, ole32, user32, gdi32 to name a few. It is not new, Raymond Chen wrote about this in 2006. However the mechanism Raymond describes is based on forwarders, while what you see here with kernel32!CreateProcessW is a stub, i.e. the function that calls kernelbase!CreateProcessW and then returns:

0:014> u kernel32!CreateProcessWStub l14
KERNEL32!CreateProcessWStub:
00007ffd`83cf58a8 4c8bdc          mov     r11,rsp
00007ffd`83cf58ab 4883ec58        sub     rsp,58h
00007ffd`83cf58af 488b8424a8000000 mov     rax,qword ptr [rsp+0A8h]
00007ffd`83cf58b7 498943f0        mov     qword ptr [r11-10h],rax
... skip ...
00007ffd`83cf58f5 ff1555871100    call    qword ptr [KERNEL32!_imp_CreateProcessW (00007ffd`83e0e050)]
00007ffd`83cf58fb 4883c458        add     rsp,58h
00007ffd`83cf58ff c3              ret 

The function called as you can see is kernelbase!CreateProcessW


0:014> ln poi kernel32!_imp_CreateProcessW
(00007ffd`82f92604)   KERNELBASE!CreateProcessW   |  (00007ffd`82f926d0)   KERNELBASE!MakeLocHashNode
Exact matches:
    KERNELBASE!CreateProcessW (no parameter info)

I this case I don't know why Windows folks decided to use a stub rather than a forwarder, to me it seems it would be more efficient to simply forward a call, like most of the other refactoring, was done.

Kernel32.dll in Windows 8.1 still contains export symbol CreateProcessW. Command link /dump /exports prints out all export symbols:

c:\>link /dump /exports c:\Windows\System32\kernel32.dll | findstr CreateProcessW
        220   DB 000058A8 CreateProcessW = CreateProcessWStub

You can use the same command to determine where you should set a breakpoint to. Similarly for forwarded exports:

c:\>link /dump /exports c:\Windows\System32\kernel32.dll | findstr EnterCriticalSection
        298  129          EnterCriticalSection (forwarded to NTDLL.RtlEnterCriticalSection)
       1418  589          TryEnterCriticalSection (forwarded to NTDLL.RtlTryEnterCriticalSection)

The reason why WinDbg cannot resolve symbol kernel32!CreateProcess, is probably just a bug in WinDbg. In this case, the symbols is not part of .PDB file, but contained in a special section in PE image, and apparently WinDbg does not handle that. What is interesting is that if .PDB file is not available, WinDbg is happy to use export table of PE image:

0:014> .sympath .
0:014> .reload
Reloading current modules ....
0:014> x kernel32!CreateProcessW
00007ffd`83cf58a8 <b>KERNEL32!CreateProcessW</b> (no parameter info)

Apparently, WinDbg decides to use either PDB symbols or export symbols, but not both.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top