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

XOR (Exclusive OR) for branchless coding

The following example shows the array reversing using the  XOR operator . No need to take any additional variable to reverse the array.   int main(int argc, _TCHAR* argv[]) { char str[] = "I AM STUDENT"; int length = strlen(str); for(int i = 0; i < ((length/2)); i++) { str[i] ^= str[length - (1+i)]; str[length - (1+i)] ^= str[i]; str[i] ^= str[length - (1+i)]; } cout << str << endl; return 0; } The above example is one of the uses of XOR but XOR comes in handy when we can do branchless coding  methods like butterfly switch etc. Sometimes this is very effective in speeding up the execution.  Let's see one of the uses of XOR in branchless coding. I am taking a simple example of Y = | X |.  Yes, I am generating abs of a supplied number. So, my function signature/definition in C++ looks like below: int absoluteBranch( int x) {     if (x < 0 ) {         return -x;     }     else {         retur

Power of Two

  I n this post will be discussing how to calculate if a number is a power of two or not. As an example, 8 is a power of two but the number 10 is not. There are many ways we can solve this. First , we will take an approach which is simple and iterative. In this case, we will calculate the power of two one by one and check with the supplied number. The below code illustrates it. bool isPowerofTwo(unsigned num) { auto y = 1; while (0 != y) { if (num == y) return true; if (num < y) return false; y <<= 1; } return false; } Second , assuming, the number is a 32-bit number, this is also an iterative solution. In this scenario, iterating all bits and counting the set bits. Any number which is a power of 2 will have only one bit set and the rest will be zeros. As an example, 8 in binary representation is 1000. Using this observation, we can implement an iterative solution. bool isPowerofTwo(unsigned num) { auto one_count = 0; for (auto index = 0; index < 32;