Finding .dlls for a Process with WinDbg

x BlueRobot

Administrator
Staff member
Joined
May 7, 2013
Posts
10,400
You can find .dlls relatively easy with WinDbg, the extensions demonstrated in this tutorial, can be hit and miss depending upon the dump file your using and the process context your attempting to view. An easier method would be to dump the IAT of a process using another tool like PeStudio or Dependency Walker.

----------------------------

The most efficient method is to use the !dlls extension in WinDbg. The !dlls extension feeds directly into the _PEB_LDR_DATA structure. We can dump the _PEB_LDR_DATA using the dt command. Alternatively, you can use the !peb extension which gives the same information but in a slightly different format.

The PEB_LDR_DATA is part of the _PEB structure:

Code:
0: kd> [COLOR=#008000]dt nt!_PEB -y Ldr[/COLOR]
   [COLOR=#ff0000]+0x018[/COLOR] Ldr : Ptr64 _PEB_LDR_DATA

Code:
0: kd> [COLOR=#008000]dt nt!_PEB_LDR_DATA[/COLOR]
   +0x000 Length           : Uint4B
   +0x004 Initialized      : UChar
   +0x008 SsHandle         : Ptr64 Void
  [COLOR=#ff0000] +0x010 InLoadOrderModuleList : _LIST_ENTRY 
   +0x020 InMemoryOrderModuleList : _LIST_ENTRY
   +0x030 InInitializationOrderModuleList : _LIST_ENTRY[/COLOR]
   +0x040 EntryInProgress  : Ptr64 Void
   +0x048 ShutdownInProgress : UChar
   +0x050 ShutdownThreadId : Ptr64 Void

The InLoadOrderModuleList, InMemoryOrderModuleList and InInitializationOrderModuleList are all doubly-linked lists which contain the same information; the .dlls imported and loaded by that process.

Each of the lists contains pointers to the LDR_DATA_TABLE_ENTRY structure which represents the loaded .dll.

Code:
0: kd> [COLOR=#008000]dt nt!_LDR_DATA_TABLE_ENTRY[/COLOR]
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x010 InMemoryOrderLinks : _LIST_ENTRY
   +0x020 InInitializationOrderLinks : _LIST_ENTRY
   +0x020 InProgressLinks  : _LIST_ENTRY
   +0x030 DllBase          : Ptr64 Void
   +0x038 EntryPoint       : Ptr64 Void
   +0x040 SizeOfImage      : Uint4B
   +0x048 FullDllName      : _UNICODE_STRING
   +0x058 BaseDllName      : _UNICODE_STRING
   +0x068 FlagGroup        : [4] UChar
   +0x068 Flags            : Uint4B

[snip]

Code:
0:036> [COLOR=#008000]!dlls[/COLOR]
This is Pre-Win8 without the loader DAG.

0x002a2ba8: C:\Program Files\Pale Moon\palemoon.exe
      Base   0x01300000  EntryPoint  0x01302783  Size        0x0004a000
      Flags  0x00004000  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_ENTRY_PROCESSED

0x002a2c28: C:\Windows\SYSTEM32\ntdll.dll
      Base   0x76ff0000  EntryPoint  0x00000000  Size        0x00141000
      Flags  0x00004004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED

0x002a2f20: C:\Windows\system32\kernel32.dll
      Base   0x76450000  EntryPoint  0x7649ce1f  Size        0x000d4000
      Flags  0x00084004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED
             LDRP_PROCESS_ATTACH_CALLED

0x002a3008: C:\Windows\system32\KERNELBASE.dll
      Base   0x750f0000  EntryPoint  0x750f7e10  Size        0x0004b000
      Flags  0x00084004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED
             LDRP_PROCESS_ATTACH_CALLED

0x002a3780: C:\Windows\system32\USER32.dll
      Base   0x75310000  EntryPoint  0x7532d711  Size        0x000c9000
      Flags  0x000c4004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED
             LDRP_DONT_CALL_FOR_THREADS
             LDRP_PROCESS_ATTACH_CALLED

0x002a3860: C:\Windows\system32\GDI32.dll
      Base   0x771f0000  EntryPoint  0x771f9c09  Size        0x0004e000
      Flags  0x000c4004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED
             LDRP_DONT_CALL_FOR_THREADS
             LDRP_PROCESS_ATTACH_CALLED

0x002a3980: C:\Windows\system32\LPK.dll
      Base   0x77150000  EntryPoint  0x7715136c  Size        0x0000a000
      Flags  0x000c4004  LoadCount   0x0000ffff  TlsIndex    0x00000000
             LDRP_IMAGE_DLL
             LDRP_ENTRY_PROCESSED
             LDRP_DONT_CALL_FOR_THREADS
             LDRP_PROCESS_ATTACH_CALLED

The flags listed for each module are the loader flags.

Code:
#define LDRP_STATIC_LINK                0x00000002
#define LDRP_IMAGE_DLL                  0x00000004
#define LDRP_LOAD_IN_PROGRESS           0x00001000
#define LDRP_UNLOAD_IN_PROGRESS         0x00002000
#define LDRP_ENTRY_PROCESSED            0x00004000
#define LDRP_ENTRY_INSERTED             0x00008000
#define LDRP_CURRENT_LOAD               0x00010000
#define LDRP_FAILED_BUILTIN_LOAD        0x00020000
#define LDRP_DONT_CALL_FOR_THREADS      0x00040000
#define LDRP_PROCESS_ATTACH_CALLED      0x00080000
#define LDRP_DEBUG_SYMBOLS_LOADED       0x00100000
#define LDRP_IMAGE_NOT_AT_BASE          0x00200000
#define LDRP_COR_IMAGE                  0x00400000
#define LDRP_COR_OWNS_UNMAP             0x00800000
#define LDRP_SYSTEM_MAPPED              0x01000000
#define LDRP_IMAGE_VERIFYING            0x02000000
#define LDRP_DRIVER_DEPENDENT_DLL       0x04000000
#define LDRP_ENTRY_NATIVE               0x08000000
#define LDRP_REDIRECTED                 0x10000000
#define LDRP_NON_PAGED_DEBUG_INFO       0x20000000
#define LDRP_MM_LOADED                  0x40000000
#define LDRP_COMPAT_DATABASE_PROCESSED  0x80000000[FONT=verdana]
[/FONT]



Why not use lm?


The lm command dumps all the modules which have been loaded globally, it doesn't consider the current process context, unless you explictly tell it to. To load the module list for a specific process context, then you must change the process context with .process and then use the .reload command to ensure that WinDbg has loaded the corrected User-Mode module list, and then use the lmu command to dump the User-Mode list.

Code:
.process <Address>
.reload /user
lmu
 
Wouldn't that only apply to user mode processes?
Given that most Kernel processes use the EPROCESS, and subsequently, the KPROCESS data structure.
 
_PEB is defined inside of _EPROCESS structure.

Code:
0: kd> [COLOR=#008000]dt nt!_EPROCESS -y Peb[/COLOR]
   [COLOR=#ff0000]+0x3e8[/COLOR] Peb : Ptr64 _PEB

You can still use !peb with Kernel-Mode processes. The !dlls extension still applies if you can get it to work properly. I had to attach to a live process and then execute it from there. It would be useful for investigating User-Mode from a Full Memory Dump.
 
Of course...
The EPROCESS data structure applies to all processes, even user mode ones. Although it is located in the system address space, kernel mode.
But the PEB is an exception, which contains user mode specific information, and thus resides in the process address space.
 

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top