0

I'm trying to figure out why adding to the path AddDllDirectory() instead of exiting the process PATH won't let me load a dll that is used in VBA functions. So I want to know what the third parameter of LoadLibraryExW() is.

First problem is I have symbols loading correctly. My symbol server cache is full of pdb files. However, there are no symbols for kernelbase.dll are found.

Process monitor shows the stack traces but not he symbols.

I set a breakpoint for kernelbase!LoadLibraryExW in WinDbgPreview, but I'm not sure how to read the stack trace. In this example is one of those hex values supposed to be the third parameter? Or is that from the registers when I want stacks?

 # Child-SP          RetAddr               : Args to Child                                                           : Call Site
00 00000051`184fe648 00007ffe`e30b5ae5     : 00007ffe`e3431380 00000000`00000060 00000051`184feac0 00000000`00000008 : KERNELBASE!LoadLibraryExW
01 00000051`184fe650 00007ffe`e30b5a45     : 00000051`184fe704 1103aa3e`00000001 00000000`00000008 00000000`00000007 : mso20win32client!Ordinal104+0x295
02 00000051`184fe690 00007ffe`e3090bb1     : 000001df`179f4860 00000000`02000000 00000000`00000008 00000000`00000000 : mso20win32client!Ordinal104+0x1f5
03 00000051`184fe6d0 00007ffe`e3091c11     : 00000051`184feb10 000001df`179f4860 00000000`00000000 00000051`184feaf0 : mso20win32client!Ordinal67+0x1f71
04 00000051`184fea50 00007ffe`d808e62a     : 000001df`179f4860 00007ffe`d9c34730 000001df`17f7b1c0 00000000`00000000 : mso20win32client!Ordinal1818+0x8c1
05 00000051`184fead0 00007ffe`d808f3c3     : 000001df`179f4860 00007ffe`d9c34730 000001df`17f7b1c0 00007ffe`d9c33a10 : mso!Ordinal2534+0x51a
06 00000051`184feb10 00007ffe`d808f347     : 000001df`182fb2c0 000001df`00000001 000001df`182fb2c0 00000000`00000000 : mso!Ordinal2534+0x12b3
07 00000051`184feb50 00007ffe`d8153c24     : 000001df`182fb2c0 00000000`00000000 000001df`17f7b1c0 000001df`17f7b1c0 : mso!Ordinal2534+0x1237
08 00000051`184feb80 00007ffe`d80b1c8e     : 00000051`184ff290 00000000`0001d4c0 000001df`17ed3700 00000051`184ff360 : mso!Ordinal1436+0x16b4
09 00000051`184ff0d0 00007ffe`d80b1925     : 000001df`12529600 00000000`00000000 000001df`17ca9430 000001df`12529600 : mso!Ordinal921+0xe6e
0a 00000051`184ff340 00007ffe`e2fe3c3c     : 00000051`184ff488 00000051`184ff440 00000000`00000000 00000000`00000000 : mso!Ordinal921+0xb05
0b 00000051`184ff3d0 00007ffe`e2fe413b     : 000001df`01849818 00000000`00000000 000001df`01849800 00000000`00000144 : mso20win32client!Ordinal1756+0xbc
0c 00000051`184ff460 00007ffe`e2fe3c3c     : 000001df`11d96b90 000001df`17823c68 000001df`17ca9430 00007fff`88aa7551 : mso20win32client!Ordinal1756+0x5bb
0d 00000051`184ff4f0 00007ffe`e311741d     : 000001df`1284a6a0 00000000`00000000 00000051`184ff790 00000000`00000000 : mso20win32client!Ordinal1756+0xbc
0e 00000051`184ff580 00007ffe`e3050e6e     : 000001df`1284a6a0 00000000`00000000 000001df`1284a601 000001df`01a18f80 : mso20win32client!Ordinal1700+0x28d
0f 00000051`184ff5b0 00007ffe`e3051ed5     : 00000051`184ff710 000001df`1284a6a0 000001df`01a18f80 000001df`1284a6a0 : mso20win32client!Ordinal347+0x23e
10 00000051`184ff610 00007ffe`e305c2d6     : 000001df`017c9470 00000000`00000000 000001df`017c9470 00000000`00000000 : mso20win32client!Ordinal1966+0x6e5
11 00000051`184ff770 00007fff`873854e0     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : mso20win32client!Ordinal2633+0x686
12 00000051`184ff7e0 00007fff`88a8485b     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x10
13 00000051`184ff810 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2b

Is there a way to get kernlbase.pdb? Is it available for older versions of windows? Is there a WinDbg command I can get to read the parameters?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Justin Dearing
  • 14,270
  • 22
  • 88
  • 161
  • 4
    On x64, the first four parameters are in registers. `rcx`, `rdx`, `r8`, and `r9`. So the third parameter is in `r8`. More generally, to debug DLL loading issues, you can turn on [loader snaps](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/show-loader-snaps). – Raymond Chen Nov 20 '21 at 05:22
  • You can use the [`kp`](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/k--kb--kc--kd--kp--kp--kv--display-stack-backtrace-) command once you've loaded symbols. [Symbols for Windows debugging](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/symbols) explains how to do that. – IInspectable Nov 20 '21 at 08:21
  • @IInspectable symbols are l downloading and oading. SPECIFICALLY kernelbase.pdb is not downloading. The directory is full of other symbols. – Justin Dearing Nov 20 '21 at 20:27
  • @RaymondChen: OT: [here you say that it's possible to reserve all memory below 4 GB](https://devblogs.microsoft.com/oldnewthing/20161014-00/?p=94515). How? The link to "the earlier discussion" is dead. I want to [do that again](https://stackoverflow.com/questions/58958744/force-heap-allocations-above-4-gb) – Thomas Weller Nov 22 '21 at 16:48
  • 1
    @ThomasWeller iirc it is /HIGHENTROPYVA linker switch – blabb Nov 22 '21 at 18:46
  • 1
    @ThomasWeller You just do it. Use `VirtualQuery` to walk through the address space and `VirtualAlloc` to reserve every block below 4GB that is marked as free. – Raymond Chen Nov 22 '21 at 18:52
  • 1
    not dead use the date marker and scour in the footer of the redirect to find [earlier discussion](https://devblogs.microsoft.com/oldnewthing/20150709-00/?p=45181) as i recall it has discussion on highentroyva – blabb Nov 22 '21 at 18:57
  • @RaymondChen: thanks for the method name. That'll help. Never used VirtualQuery before. – Thomas Weller Nov 22 '21 at 19:56
  • @blabb: Thanks for the link – Thomas Weller Nov 22 '21 at 19:57
  • @RaymondChen Ok that is useful, and now I have KernelBase.pdb in my symbol cache, – Justin Dearing Nov 25 '21 at 06:01

1 Answers1

0

This was meant to be a comment but it grew so answering

sometimes you have half downloaded or aborted downloads of pdb in such cases it may be evident that the symbol file is not being downloaded

the aborted downloads have .error extension

check if you have such file and remove them to redownload pdbs properly.

   f:\symbols>set _NT_
    _NT_SYMBOL_PATH=srv*f:\symbols*https://msdl.microsoft.com/download/symbols
    
    f:\symbols>dir /s /b *.error
    f:\symbols\windows.ui.xaml.pdb\7349BE8DF456ACFBEE7774E6197449541\downloadDA83A900E9B74A20B6A95465B35021C5.error

if your platform is x64 as already commented
the first four parameters are passed via rcx,rdx,r8, and r9 on windows

a breakon LoadLibraryExW on an arbitrary binary

0:000> k4
Child-SP          RetAddr           Call Site
000000a4`6013eda8 00007ffb`f5df62f1 KERNELBASE!LoadLibraryExW
000000a4`6013edb0 00007ffb`f5df6449 ucrtbase!try_get_function+0xa9
000000a4`6013ee00 00007ffb`f5df5e80 ucrtbase!_vcrt_FlsAlloc+0x25
000000a4`6013ee30 00007ffb`f5df5cb9 ucrtbase!_vcrt_initialize_ptd+0x10
0:000> r rcx,rdx,r8,r9
rcx=00007ffbf5e778a0 rdx=0000000000000000 r8=0000000000000800 r9=00007ffbf5e75a70
0:000> du @rcx
00007ffb`f5e778a0  "api-ms-win-core-fibers-l1-1-1"
0:000> ? @r8
Evaluate expression: 2048 = 00000000`00000800
0:000> .shell -ci ".echo looking for 0x800" pss LOAD_.*0x00000800 "c:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um\libloaderapi.h"
c:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um\libloaderapi.h:409:#define LOAD_LIBRARY_SEARCH_SYSTEM32        0x00000800
.shell: Process exited
0:000>  

EDIT

The LoadLibrary Api Takes its input sting in a variety of formats

  1. bare names like kernel,
  2. names with extension like kernel.dll
  3. relative and absolute paths
  4. lower and upper cases like foo.dll and BAR.DLL

so it is a pita to string compare with builtin script and $spat operator

try writing a javascript like below to ease the pain (tested once only)

/// <reference path="JSProvider.d.ts" />
"use strict";
var prevlibs =[];
function libname() {    
    var addr = host.currentThread.Registers.User.rcx;
    var libstr = host.memory.readWideString(addr).toLowerCase()
    var cond = libstr.includes("imm32.dll");
    if (cond) {
        host.diagnostics.debugLog("breaking\n");
    }
    else {
        prevlibs.push(libstr);
        host.namespace.Debugger.Utility.Control.ExecuteCommand("gc");
    }
    return prevlibs;
}

usage and result as follows imm32 is taken to show case and abs path input

0:000> .scriptload f:\wdscr\libname.js
JavaScript script successfully loaded from 'f:\wdscr\libname.js'
0:000> bp KERNELBASE!LoadLibraryExW "dx @$scriptContents.libname()"
0:000> g
KERNELBASE!LoadLibraryExW:
00007ffb`f60ee840 4055            push    rbp
0:000> du @rcx
0000006d`3f56e8f0  "C:\WINDOWS\system32\IMM32.DLL"
0:000> dx @$scriptContents.libname()
breaking
@$scriptContents.libname() : api-ms-win-core-synch-l1-2-0,api-ms-win-core-fibers-l1-1-1,api-ms-win-core-fibers-l1-1-1,api-ms-win-core-synch-l1-2-0,api-ms-win-core-localization-l1-2-1,kernel32,api-ms-win-core-string-l1-1-0,api-ms-win-core-datetime-l1-1-1,api-ms-win-core-localization-obsolete-l1-2-0,api-ms-win-core-file-l1-2-1.dll,api-ms-win-eventing-provider-l1-1-0.dll,ole32.dll
    length           : 0xc
    [0x0]            : api-ms-win-core-synch-l1-2-0
    [0x1]            : api-ms-win-core-fibers-l1-1-1
    [0x2]            : api-ms-win-core-fibers-l1-1-1
    [0x3]            : api-ms-win-core-synch-l1-2-0
    [0x4]            : api-ms-win-core-localization-l1-2-1
    [0x5]            : kernel32
    [0x6]            : api-ms-win-core-string-l1-1-0
    [0x7]            : api-ms-win-core-datetime-l1-1-1
    [0x8]            : api-ms-win-core-localization-obsolete-l1-2-0
    [0x9]            : api-ms-win-core-file-l1-2-1.dll
    [0xa]            : api-ms-win-eventing-provider-l1-1-0.dll
    [0xb]            : ole32.dll
0:000>  
blabb
  • 8,674
  • 1
  • 18
  • 27
  • so first of all, it seems the symbol has been added. There was no error file in the cache, but today it downloaded. Before I did do a noisy load and saw it tried to download the file and didn't get it. The only piece I need now is to figure out string comparisons for a conditional breakpoint. – Justin Dearing Nov 25 '21 at 06:27
  • @jus Try getting a [Time Travel Debugging](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-overview) trace. The tooling provides a rich query language that allows to more quickly navigate to the point of interest. – IInspectable Nov 26 '21 at 11:12
  • added a demo for your comment take a look – blabb Nov 26 '21 at 17:16