- May 7, 2013
- 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:
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.
The flags listed for each module are the loader flags.
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.
----------------------------
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