pazdinho_
pazdinho_

Reputation: 45

Why does WinDbg show different function origin than MSDN?

I've been debugging a program where I had to set a breakpoint on CreateProcessAsUserW function. The Microsoft Docs for this function (https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw) state that the function is located (exported) from Advapi32.dll. But WinDbg "states" that the function in located in KernelBase.dll, as far as I correctly understand these results (coming from WinDbg):

0:000> dt advapi32!CreateProc*
0:000> dt kernelbase!CreateProcessAsUser*
00007ffc504da520  KERNELBASE!CreateProcessAsUserA
00007ffc504da550  KERNELBASE!CreateProcessAsUserW

Why is that, why are the results different since both sources are trustworthy?

Upvotes: 0

Views: 158

Answers (2)

blabb
blabb

Reputation: 9007

both kernelbase.dll and advapi32.dll exports the Function CreateProcessAsuserA/W

C:\Windows\System32>dumpbin /exports KernelBase.dll | find /I "AsU"
        216   D0 001BEA00 CreateProcessAsUserA
        217   D1 001BEA40 CreateProcessAsUserW
        222   D6 001AEA00 CreatePseudoConsoleAsUser

C:\Windows\System32>dumpbin /exports advapi32.dll | find /I "AsU"
       1140   8A 00034190 CreateProcessAsUserA
       1141   8B 00020560 CreateProcessAsUserW

under kernelbase the exported function Address is a place holder for lots of redirected function with a not implemented ErrorReturn

0:000> x KernelBase!CreateProcessAsUserW
00000001`80096ab0 KernelBase!CreateProcessAsUserW (void)

0:000> uf KernelBase!CreateProcessAsUserW
KernelBase!IsServerVersionOrAbove:

00000001`80096ab0 4883ec28        sub     rsp,28h
00000001`80096ab4 b97f000000      mov     ecx,7Fh
00000001`80096ab9 48ff1580c41200  call    qword ptr [KernelBase!_imp_RtlSetLastWin32Error (00000001`801c2f40)]
00000001`80096ac0 0f1f440000      nop     dword ptr [rax+rax]
00000001`80096ac5 33c0            xor     eax,eax
00000001`80096ac7 4883c428        add     rsp,28h
00000001`80096acb c3              ret


0:000> ln KernelBase!CreateProcessAsUserW
(00000001`80096ab0)   KernelBase!IsServerVersionOrAbove   |  (00000001`80096ae0)   KernelBase!LsaIExtractTargetInfo
Exact matches:
    KernelBase!GetUrlCacheConfigInfoA (void)
    KernelBase!FwIsValidPorts (void)
    KernelBase!AbortPrinter (void)
    KernelBase!RangeMapCreate (void)
    KernelBase!IsThreadDesktopComposited (void)
    KernelBase!ASN1utctime_cmp (void)
    KernelBase!SetWindowCompositionAttribute (void) 
    XXXXXXXXXXXXXXXXXXXXXXcut off XXXXXXXXXXXXXXX

the actual implementation also is done at kernelbase.dll at a different Address (non exported)

0:000> x KernelBase!CreateProcessA*
00000001`80096ab0 KernelBase!CreateProcessAsUserA (void)
00000001`80096ab0 KernelBase!CreateProcessAsUserW (void)  <<<<<<< as above
00000001`8010bf50 KernelBase!CreateProcessAsUserA (CreateProcessAsUserA)
00000001`800071c0 KernelBase!CreateProcessA (CreateProcessA)
00000001`80006360 KernelBase!CreateProcessAsUserW (CreateProcessAsUserW) <<<<<<< actual implementation 

0:000> uf 00000001`80006360
KernelBase!CreateProcessAsUserW:
00000001`80006360 4c8bdc          mov     r11,rsp
00000001`80006363 4883ec68        sub     rsp,68h
00000001`80006367 498363f000      and     qword ptr [r11-10h],0
00000001`8000636c 488b8424c0000000 mov     rax,qword ptr [rsp+0C0h]
00000001`80006374 498943e8        mov     qword ptr [r11-18h],rax
00000001`80006378 488b8424b8000000 mov     rax,qword ptr [rsp+0B8h]
00000001`80006380 498943e0        mov     qword ptr [r11-20h],rax
00000001`80006384 488b8424b0000000 mov     rax,qword ptr [rsp+0B0h]
00000001`8000638c 498943d8        mov     qword ptr [r11-28h],rax
00000001`80006390 488b8424a8000000 mov     rax,qword ptr [rsp+0A8h]
00000001`80006398 498943d0        mov     qword ptr [r11-30h],rax
00000001`8000639c 8b8424a0000000  mov     eax,dword ptr [rsp+0A0h]
00000001`800063a3 89442430        mov     dword ptr [rsp+30h],eax
00000001`800063a7 8b842498000000  mov     eax,dword ptr [rsp+98h]
00000001`800063ae 89442428        mov     dword ptr [rsp+28h],eax
00000001`800063b2 488b842490000000 mov     rax,qword ptr [rsp+90h]
00000001`800063ba 498943b8        mov     qword ptr [r11-48h],rax
00000001`800063be e8cd1a0000      call    KernelBase!CreateProcessInternalW (00000001`80007e90)
00000001`800063c3 4883c468        add     rsp,68h
00000001`800063c7 c3              ret

there is no symbol match for this address which is pointed by advapi32.dll

0:000> ln 00000001`80006360
(00000001`80006360)   KernelBase!CreateProcessAsUserW   |  (00000001`800063d0)   KernelBase!Wow64SetThreadDefaultGuestMachine
Exact matches:
0:000>

0:000> uf /c advapi32!CreateProcessAsUserWStub
advapi32!CreateProcessAsUserWStub (00007ffb`d89d7cc0)
  advapi32!CreateProcessAsUserWStub+0x59 (00007ffb`d89d7d19):
    call to KERNELBASE!CreateProcessAsUserW (00007ffb`d6d96360)
0:000> u 00007ffb`d89d7d19 l2
advapi32!CreateProcessAsUserWStub+0x59:
00007ffb`d89d7d19 48ff1598120600  call    qword ptr [advapi32!_imp_CreateProcessAsUserW (00007ffb`d8a38fb8)]
00007ffb`d89d7d20 0f1f440000      nop     dword ptr [rax+rax]
0:000> dps 00007ffb`d8a38fb8 l1
00007ffb`d8a38fb8  00007ffb`d6d96360 KERNELBASE!CreateProcessAsUserW
0:000>

Upvotes: 1

Anders
Anders

Reputation: 101726

When WinDbg has symbols for a module it unfortunately ignores forwarded function exports from the PE exports section.

If you start another WinDbg instance without correct symbols for advapi32 you can do bp advapi32!CreateProcessAsUserW etc. This is not a great solution of course.

Just knowing that this happens is usually enough. When you fail to find a function, look in kernelbase (kernel32, advapi32), ntdll (kernel32, user32) or shcore (shlwapi, shell32) instead...

Upvotes: 1

Related Questions