Skip to main content

Deep Dive to Windows, Part 3

In this post, I'd like to explore Loader Data which is part of Process Environment Block ( PEB ). This structure tells us what are the dlls are loaded by the process.

To start with, I've loaded my sample program through WinDbg and all symbol paths are set. Then I've executed following command:

!peb and received following output. (I've trimmed the output) for readability purpose. If we look at the PEB structure below, the highlighted one is important to us. This is basically a NT structure known as _PEB_LDR_DATA.

PEB at 7efde000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            Yes
    ImageBaseAddress:         00400000
    Ldr                       775f0200      <=========_PEB_LDR_DATA at 775f0200
    Ldr.Initialized:          Yes
    Ldr.InInitializationOrderModuleList: 00593288 . 00594308
    Ldr.InLoadOrderModuleList:           005931e8 . 00594018
    Ldr.InMemoryOrderModuleList:         005931f0 . 00594020

Then, executed the command, dt _PEB_LDR_DATA 775f0200. This gives us following information:

ntdll!_PEB_LDR_DATA
   +0x000 Length           : 0x30
   +0x004 Initialized      : 0x1 ''
   +0x008 SsHandle         : (null)
   +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x5931e8 - 0x594018 ]
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x5931f0 - 0x594020 ]
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x593288 - 0x594308 ]

   +0x024 EntryInProgress  : (null)
   +0x028 ShutdownInProgress : 0 ''
   +0x02c ShutdownThreadId : (null)

The highlighted three lines above tells us how Windows OS Loader, loaded Dlls in memory. There are three ways dlls get loaded in memory by Windows OS Loader.

1. InLoadOrderModuleList
2. InMemoryOrderModuleList
3. InInitializationOrderModuleList


Now, I'm interested to know what are the dlls loaded in load order. So I've executed following command:

!list -x "dt _LDR_DATA_TABLE_ENTRY" 0x5931e8  and received following list:


ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x593278 - 0x775f020c ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x593280 - 0x775f0214 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase          : 0x00400000 Void
   +0x01c EntryPoint       : 0x00411096 Void
   +0x020 SizeOfImage      : 0x1c000
   +0x024 FullDllName      : _UNICODE_STRING "F:\ForDebugging\Sample_Hello\debug\Sample_Hello.exe"            <========== 'This is our executable'
   +0x02c BaseDllName      : _UNICODE_STRING "Sample_Hello.exe"
   +0x034 Flags            : 0x4000
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f48d8 - 0x775f48d8 ]
   +0x03c SectionPointer   : 0x775f48d8 Void
   +0x040 CheckSum         : 0x775f48d8
   +0x044 TimeDateStamp    : 0x50dc8bed
   +0x044 LoadedImports    : 0x50dc8bed Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x593238 - 0x593238 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x593240 - 0x593240 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x594540 - 0x5941c0 ]
   +0x068 ContextInformation : 0x7752c944 Void
   +0x06c OriginalBase     : 0x400000
   +0x070 LoadTime         : _LARGE_INTEGER 0x0

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x5935f8 - 0x5931e8 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x593600 - 0x5931f0 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x593720 - 0x775f021c ]
   +0x018 DllBase          : 0x774f0000 Void
   +0x01c EntryPoint       : (null)
   +0x020 SizeOfImage      : 0x180000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\SysWOW64\ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x80004004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f48c0 - 0x775f48c0 ]
   +0x03c SectionPointer   : 0x775f48c0 Void
   +0x040 CheckSum         : 0x775f48c0
   +0x044 TimeDateStamp    : 0x4ec49b8f
   +0x044 LoadedImports    : 0x4ec49b8f Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x5932c8 - 0x5932c8 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x5932d0 - 0x5932d0 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x5932d8 - 0x5932d8 ]
   +0x068 ContextInformation : (null)
   +0x06c OriginalBase     : 0x7de70000
   +0x070 LoadTime         : _LARGE_INTEGER 0x0

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x593710 - 0x593278 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x593718 - 0x593280 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x594028 - 0x593720 ]
   +0x018 DllBase          : 0x755c0000 Void
   +0x01c EntryPoint       : 0x755d32b3 Void
   +0x020 SizeOfImage      : 0x110000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\syswow64\kernel32.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "kernel32.dll"
   +0x034 Flags            : 0x80084004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f4880 - 0x775f4880 ]
   +0x03c SectionPointer   : 0x775f4880 Void
   +0x040 CheckSum         : 0x775f4880
   +0x044 TimeDateStamp    : 0x506dbe4f
   +0x044 LoadedImports    : 0x506dbe4f Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x593648 - 0x593648 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x593650 - 0x593650 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x5937c8 - 0x593688 ]
   +0x068 ContextInformation : 0x7752c960 Void
   +0x06c OriginalBase     : 0x7dd60000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cde45b`e4d2de31

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x5942f8 - 0x5935f8 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x594300 - 0x593600 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x593608 - 0x593288 ]
   +0x018 DllBase          : 0x76bb0000 Void
   +0x01c EntryPoint       : 0x76bb74b1 Void
   +0x020 SizeOfImage      : 0x47000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\syswow64\KERNELBASE.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "KERNELBASE.dll"
   +0x034 Flags            : 0x80084004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f48d0 - 0x775f48d0 ]
   +0x03c SectionPointer   : 0x775f48d0 Void
   +0x040 CheckSum         : 0x775f48d0
   +0x044 TimeDateStamp    : 0x506dbe50
   +0x044 LoadedImports    : 0x506dbe50 Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x593760 - 0x593760 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x593768 - 0x593768 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x5937a0 - 0x5937a0 ]
   +0x068 ContextInformation : 0x7752c960 Void
   +0x06c OriginalBase     : 0x7d850000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cde45b`e4da0252

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x594488 - 0x593710 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x594490 - 0x593718 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x775f021c - 0x594498 ]
   +0x018 DllBase          : 0x63ec0000 Void
   +0x01c EntryPoint       : 0x63f41450 Void
   +0x020 SizeOfImage      : 0xfe000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCP80D.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "MSVCP80D.dll"
   +0x034 Flags            : 0x900c4004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f4808 - 0x775f4808 ]
   +0x03c SectionPointer   : 0x775f4808 Void
   +0x040 CheckSum         : 0x775f4808
   +0x044 TimeDateStamp    : 0x4dcddc5b
   +0x044 LoadedImports    : 0x4dcddc5b Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x594348 - 0x594348 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x594350 - 0x594350 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x594198 - 0x594170 ]
   +0x068 ContextInformation : 0x7752c944 Void
   +0x06c OriginalBase     : 0x10480000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cde45b`e4ed0d54

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x594018 - 0x5942f8 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x594020 - 0x594300 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x594308 - 0x594028 ]
   +0x018 DllBase          : 0x63d90000 Void
   +0x01c EntryPoint       : 0x63d92f90 Void
   +0x020 SizeOfImage      : 0x121000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCR80D.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "MSVCR80D.dll"
   +0x034 Flags            : 0x90084004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f48f8 - 0x775f48f8 ]
   +0x03c SectionPointer   : 0x775f48f8 Void
   +0x040 CheckSum         : 0x775f48f8
   +0x044 TimeDateStamp    : 0x4dcddbed
   +0x044 LoadedImports    : 0x4dcddbed Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x5944d8 - 0x5944d8 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x5944e0 - 0x5944e0 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x594148 - 0x594120 ]
   +0x068 ContextInformation : 0x7752c944 Void
   +0x06c OriginalBase     : 0x10200000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cde45b`e4ed0d54

ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x775f020c - 0x594488 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x775f0214 - 0x594490 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x594498 - 0x593608 ]
   +0x018 DllBase          : 0x76a80000 Void
   +0x01c EntryPoint       : 0x76a8a472 Void
   +0x020 SizeOfImage      : 0xac000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\syswow64\msvcrt.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "msvcrt.dll"
   +0x034 Flags            : 0x80084004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x775f48b8 - 0x775f48b8 ]
   +0x03c SectionPointer   : 0x775f48b8 Void
   +0x040 CheckSum         : 0x775f48b8
   +0x044 TimeDateStamp    : 0x4eeaf722
   +0x044 LoadedImports    : 0x4eeaf722 Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x594068 - 0x594068 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x594070 - 0x594070 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x5940f8 - 0x5940a8 ]
   +0x068 ContextInformation : 0x7752c960 Void
   +0x06c OriginalBase     : 0x6ff50000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cde45b`e4ed0d54

Then, I've given lm command and received same list for loaded module (dlls) for the same process.

0:001> lm
start    end        module name
00400000 0041c000   Sample_Hello   (deferred)            
63d90000 63eb1000   MSVCR80D   (deferred)            
63ec0000 63fbe000   MSVCP80D   (deferred)            
755c0000 756d0000   kernel32   (deferred)            
76a80000 76b2c000   msvcrt     (deferred)            
76bb0000 76bf7000   KERNELBASE   (deferred)            
774f0000 77670000   ntdll

More to follow.

Happy Debugging!

Comments

Popular posts from this blog

Reversing char array without splitting the array to tokens

 I was reading about strdup, a C++ function and suddenly an idea came to my mind if this can be leveraged to aid in reversing a character array without splitting the array into words and reconstructing it again by placing spaces and removing trailing spaces. Again, I wanted an array to be passed as a function argument and an array size to be passed implicitly with the array to the function. Assumed, a well-formed char array has been passed into the function. No malformed array checking is done inside the function. So, the function signature and definition are like below: Below is the call from the client code to reverse the array without splitting tokens and reconstructing it. Finally, copy the reversed array to the destination.  For GNU C++, we should use strdup instead _strdup . On run, we get the following output: Demo code

A simple approach to generate Fibonacci series via multi-threading

T his is a very simple approach taken to generate the Fibonacci series through multithreading. Here instead of a function, used a function object. The code is very simple and self-explanatory.  #include <iostream> #include <mutex> #include <thread> class Fib { public:     Fib() : _num0(1), _num1(1) {}     unsigned long operator()(); private:     unsigned long _num0, _num1;     std::mutex mu; }; unsigned long Fib::operator()() {     mu.lock(); // critical section, exclusive access to the below code by locking the mutex     unsigned long  temp = _num0;     _num0 = _num1;     _num1 = temp + _num0;     mu.unlock();     return temp; } int main() {     Fib f;          int i = 0;     unsigned long res = 0, res2= 0, res3 = 0;     std::cout << "Fibonacci series: ";     while (i <= 15) {         std::thread t1([&] { res = f(); }); // Capturing result to respective variable via lambda         std::thread t2([&] { res2 = f(); });         std::thread t3(

Variadic template class to add numbers recursively during compilation

 The idea of having a class to add numbers (variable parameters) during compilation time recursively. Also wanted to restrict types to a single type while sending parameters to class member function. That said, if we mix int, float and double types to add function shall result in compilation error. How do we achieve this. The below is the code which actually helps to achieve this: <code> #include < fmt/format.h > template < typename T> class MyVarSumClass{     private :         T _sum = 0 ;     public :         template < typename ... TRest>         T add(T num, TRest... nums){             static_assert (std::conjunction<std::is_same<TRest, T>...>{}); /* Assert fails                if types are different */             _sum += num;             return add(nums...); // Next parameter packs gets picked recursively         }         // Base case         T add(T num){             _sum += num;             return _sum;         } }; int main() {     My