#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 retnCase 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_75668DD6Check 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!LdrGetDllHandleRewriting 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