Pages

Monday, May 18, 2015

[C/C++] From GetModuleHandleW to LdrGetDllHandle

Code snippet:

#include <windows.h>
#include <stdio.h>

int WINAPI iWinMain() {
#ifdef _WIN64
    LPWSTR captionMsg = L"64-bit Application";
#else
    LPWSTR captionMsg = L"32-bit Application";
#endif

    HMODULE moduleHandle;
    WCHAR mainMsg[MAX_PATH] = {0};

    moduleHandle = GetModuleHandleW(L"kernel32.dll");

    _snwprintf(
        mainMsg,
        MAX_PATH,
        L"kernel32.dll ImageBaseAddress: 0x%p",
        moduleHandle);

    MessageBoxW(
        NULL,
        mainMsg,
        captionMsg,
        MB_ICONINFORMATION);

    return 0;
}
Inside the Debugger:
Push     ebp
Mov      ebp, esp
sub      esp, 208h
xor      eax, eax
push     206h            ; Size
push     eax             ; Val
mov      [ebp+Text], ax
lea      eax, [ebp+Dst]
push     eax             ; Dst
call     memset
add      esp, 0Ch
push     0               ; lpModuleName
call     GetModuleHandleW
push     eax
push     offset Format   ; "kernel32.dll"...
lea      eax, [ebp+Text]
push     104h            ; Count
push     eax             ; Dest
call     _snwprintf
add      esp, 10h
push     40h             ; uType
push     offset Caption  ; "32-bit Application"
lea      eax, [ebp+Text]
push     eax             ; lpText
push     0               ; hWnd
call     MessageBoxW
xor      eax, eax
leave
retn
Case when GetModuleHandleW handle NULL parameter: I observed than if we pass "NULL" as parameter the function doesn't call any other function and retrieve the ImageBaseAddress directly from the information stored in the current PEB (Process Environment Block)
GetModuleHandleW(NULL);
mov      edi, edi
push     ebp
mov      ebp, esp
cmp      dword ptr [ebp+8], 0
jz       loc_75668DD6
Check the parameter and redirection to the PEB if the parameter is equal to NULL.
75668DD6 moveax, large fs:18h
75668DDC moveax, [eax+30h]
75668DDF moveax, [eax+8] ImageBaseAddress

typedefstruct _PEB
{
 /* 0x0000 */ BOOLEAN InheritedAddressSpace;
 /* 0x0001 */ BOOLEAN ReadImageFileExecOptions;
 /* 0x0002 */ BOOLEAN BeingDebugged;
 /* 0x0003 */ BOOLEAN Spare;
 /* 0x0004 */ HANDLE Mutant;
 /* 0x0008 */ PVOID ImageBaseAddress;
 /* 0x000C */ PPEB_LDR_DATA LoaderData;
......
......
Case when GetModuleHandleW handle a valid parameter:
GetModuleHandleW(L"kernel32.dll");
Calling native function
ntdll!LdrGetDllHandle
Rewriting the Code snippet:
#include <windows.h>
#include <stdio.h>

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

extern "C" {
    VOID
    WINAPI
    RtlInitUnicodeString (
        PUNICODE_STRING DestinationString,
        PCWSTR SourceString);

    NTSTATUS
    WINAPI
    LdrGetDllHandle(
        ULONG,
        ULONG,
        const UNICODE_STRING*,
        HMODULE*);
}

int WINAPI iWinMain() {
#ifdef _WIN64
    LPWSTR captionMsg = L"64-bit Application";
#else
    LPWSTR captionMsg = L"32-bit Application";
#endif

    HMODULE moduleHandle;
    WCHAR mainMsg[MAX_PATH] = {0};

    UNICODE_STRING moduleName;
    RtlInitUnicodeString(&moduleName, L"kernel32.dll");
    LdrGetDllHandle(NULL, NULL, &moduleName, &moduleHandle);

    _snwprintf(
        mainMsg,
        MAX_PATH,
        L"kernel32.dll ImageBaseAddress: 0x%p",
        moduleHandle);

    MessageBoxW(
        NULL,
        mainMsg,
        captionMsg,
        MB_ICONINFORMATION);

    return 0;
}
The final Code snippet:
#include <windows.h>
#include <stdio.h>

#define NATIVE

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

extern "C" {
    VOID
    WINAPI
    RtlInitUnicodeString (
        PUNICODE_STRING DestinationString,
        PCWSTR SourceString);

    NTSTATUS
    WINAPI
    LdrGetDllHandle(
        ULONG,
        ULONG,
        const UNICODE_STRING*,
        HMODULE*);
}

int WINAPI iWinMain() {
#ifdef _WIN64
    LPWSTR captionMsg = L"64-bit Application";
#else
    LPWSTR captionMsg = L"32-bit Application";
#endif

    HMODULE moduleHandle;
    WCHAR mainMsg[MAX_PATH] = {0};

#ifdef NATIVE
    UNICODE_STRING moduleName;
    RtlInitUnicodeString(&moduleName, L"kernel32.dll");
    LdrGetDllHandle(NULL, NULL, &moduleName, &moduleHandle);
#else
    moduleHandle = GetModuleHandleW(L"kernel32.dll");
#endif
    _snwprintf(
        mainMsg,
        MAX_PATH,
        L"kernel32.dll ImageBaseAddress: 0x%p",
        moduleHandle);

    MessageBoxW(
        NULL,
        mainMsg,
        captionMsg,
        MB_ICONINFORMATION);

    return 0;
}
 
Source:
http://www.mediafire.com/download/uj0wprstq9q9jpu/ImageBaseAddress.rar