Is there a way in C++/windows to get the exe/DLL image base address? thanks :)
If you load the binary into your own process you can use GetModuleHandle. It returns a HMODULE, but that is the same as HINSTANCE and the base address.
If you want to know what base address the binary prefers you should read the PE header. See here and look for the ImageBase field in IMAGE_OPTIONAL_HEADER.
Edit: GetModuleHandle(NULL) will return the base address (altough the specified type is HMODULE) for the current process.
If you are examining an DLL or EXE file on disk, use the dumpbin utility. It in installed with Visual Studio or the SDK.
Example Output of dumpbin /headers:
FILE HEADER VALUES
14C machine (i386)
6 number of sections
306F7A22 time date stamp Sun Oct 01 22:35:30 1995
0 file pointer to symbol table
1D1 number of symbols
E0 size of optional header
302 characteristics
Executable
32 bit word machine
Debug information stripped
OPTIONAL HEADER VALUES
10B magic #
2.60 linker version
1E00 size of code
1E00 size of initialized data
0 size of uninitialized data
1144 address of entry point
1000 base of code
3000 base of data
----- new -----
**2BB0000 image base** <--- This is what you are looking for
1000 section alignment
200 file alignment
3 subsystem (Windows CUI)
4.00 operating system version
4.00 image version
3.50 subsystem version
8000 size of image
400 size of headers
62C8 checksum
100000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 [ 0] address [size] of Export Directory
5000 [ 3C] address [size] of Import Directory
6000 [ 394] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
7000 [ 21C] address [size] of Base Relocation Directory
3030 [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
0 [ 0] address [size] of Load Configuration Directory
268 [ 44] address [size] of Bound Import Directory
50A0 [ 64] address [size] of Import Address Table Directory
0 [ 0] address [size] of Reserved Directory
0 [ 0] address [size] of Reserved Directory
0 [ 0] address [size] of Reserved Directory
SECTION HEADER #1
.text name
1D24 virtual size
1000 virtual address
1E00 size of raw data
400 file pointer to raw data
0 file pointer to relocation table
3C20 file pointer to line numbers
0 number of relocations
37E number of line numbers
60000020 flags
Code
(no align specified)
Execute Read
I found that the most convenient and accurate way to get module's base address (and in-memory image size) is through GetModuleInformation (include psapi.h, link to psapi.lib):
MODULEINFO module_info; memset(&module_info, 0, sizeof(module_info));
if (GetModuleInformation(GetCurrentProcess(), hModule, &module_info, sizeof(module_info))) {
DWORD module_size = module_info.SizeOfImage;
BYTE * module_ptr = (BYTE*)module_info.lpBaseOfDll;
// ...
}
If you want to get your own ImageBase Address from inside a DLL/EXE then how about this:
#include <winnt.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
If you want to enumerate all process's modules, you can also use CreateToolhelp32Snapshot:
#include <windows.h>
#include <tlhelp32.h>
std::vector<std::pair<std::string, uint32_t> > base_addresses;
// take a snapshot of all modules in the specified process
HANDLE snaphot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
if (snaphot_handle != INVALID_HANDLE_VALUE)
{
// first module
MODULEENTRY32 mod_entry;
mod_entry.dwSize = sizeof(mod_entry);
if (Module32First(snaphot_handle, &mod_entry))
{
// iterate through the module list of the process
do
{
base_addresses.push_back(
std::make_pair(mod_entry.szModule,
static_cast<uint32_t>(mod_entry.modBaseAddr));
} while (Module32Next(snaphot_handle, &mod_entry));
}
CloseHandle(snaphot_handle);
}
Find below code to find Image Base Address in CPP :
#include<windows.h>
#include<iostream>
int main()
{
LPCSTR fileName="inputFile.exe";
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS peHeader;
PIMAGE_SECTION_HEADER sectionHeader;
hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE)
{
std::cout<<"\n CreateFile failed \n";
return 1;
}
hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(hFileMapping==0)
{
std::cout<<"\n CreateFileMapping failed \n";
CloseHandle(hFile);
return 1;
}
lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);
if(lpFileBase==0)
{
std::cout<<"\n MapViewOfFile failed \n";
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 1;
}
dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;
if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
{
std::cout<<"\n DOS Signature (MZ) Matched \n";
peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
if(peHeader->Signature==IMAGE_NT_SIGNATURE)
{
std::cout<<"\n PE Signature (PE) Matched \n";
//once found valid exe or dll
std::cout<<"\n Image Base : "<<std::hex<<peHeader->OptionalHeader.ImageBase;
}
else
{
return 1;
}
}
else
{
return 1;
}
return 0;
}
A bit hacky but this works too:
https://ntopcode.wordpress.com/2018/02/26/anatomy-of-the-process-environment-block-peb-windows-internals/
Make sure to include windows.h
, which ends up including the definition of NtCurrentTeb
in winnt.h
, as well as macros and typedefs that winnt.h
needs, and make sure to include winternl.h
for struct _TEB
type definition.
And when I open it up in VMMap:
(address is different this time because of ASLR)
For .dlls, nobody has mentioned this method yet: http://sandsprite.com/CodeStuff/Understanding_the_Peb_Loader_Data_List.html
Look at the structures in kd and get the right offsets for your system, although it rarely changes across windows versions.
This is only how GetModuleHandle
is implemented anyway. It calls BasepGetModuleHandleExW
and the functionality is implemented in RtlPcToFileHeader
. If the parameter is NULL
then it returns return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
, otherwise it will use the Ldr
member below it in the PEB to parse the list loaded dlls in the address space as shown in the sandsprite link.
As can be seen, the image base address is also the first module in the initialisation order linked list.
The module handle is just the address cast to a HMODULE
, which is just a HINSTANCE
which is a HANDLE
which is a PVOID
which is a void*
64 bit pointer to a void. Casting as either will have the same effect on the assembly output -- it only aids code level conceptual clarity and compiler warnings, and makes the implementation of the handle transparent to the programmer; they just need to pass the handle to the API functions and not worry about whether it is an index into the handle entries pointed to the handle table pointed to by the struct _EPROCESS
, a 64-bit raw address or a pseudohandle.
You can view this in kd
by getting a process ID using Process Explorer and then performing (i.e. if it is pid 16416
, different process to previous example):
lkd> ? 0n16416 //convert denary to hex (output not shown in this example)
lkd> !process 0x4020 //display eprocess for pid (or you can use !process 0n16416 without having to convert to hex) (output not shown in this example)
lkd> .process /P 0xfffffa802edb1a80 //supply eprocess address acquired from the output of the !process command the current; sets current context to the context of that process (output not shown in this example)
lkd> !peb //display the PEB of for the current process context
PEB at 000007fffffd3000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: No
ImageBaseAddress: 00000000ff0c0000
Ldr 000000007794d640
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 0000000000343cd0 . 00000000003b3950
Ldr.InLoadOrderModuleList: 0000000000343bc0 . 00000000003b3930
Ldr.InMemoryOrderModuleList: 0000000000343bd0 . 00000000003b3940
Base TimeStamp Module
ff0c0000 559ea8be Jul 09 18:00:46 2015 C:\Windows\system32\NOTEPAD.EXE
77820000 595fa942 Jul 07 16:31:14 2017 C:\Windows\SYSTEM32\ntdll.dll
77700000 595fa987 Jul 07 16:32:23 2017 C:\Windows\system32\kernel32.dll
7fefd700000 595fa988 Jul 07 16:32:24 2017 C:\Windows\system32\KERNELBASE.dll
7fefed00000 595fa8e2 Jul 07 16:29:38 2017 C:\Windows\system32\ADVAPI32.dll
7feffa90000 4eeb033f Dec 16 08:37:19 2011 C:\Windows\system32\msvcrt.dll
7feff780000 55636728 May 25 19:17:12 2015 C:\Windows\SYSTEM32\sechost.dll
7fefd9a0000 595fa8ec Jul 07 16:29:48 2017 C:\Windows\system32\RPCRT4.dll
7feff100000 5915fd6c May 12 19:22:36 2017 C:\Windows\system32\GDI32.dll
77600000 5824a140 Nov 10 16:33:04 2016 C:\Windows\system32\USER32.dll
7fefee10000 5915fd82 May 12 19:22:58 2017 C:\Windows\system32\LPK.dll
7fefdad0000 5915fd8f May 12 19:23:11 2017 C:\Windows\system32\USP10.dll
7fefde20000 4ce7c635 Nov 20 12:59:33 2010 C:\Windows\system32\COMDLG32.dll
7fefee20000 4ce7c9ab Nov 20 13:14:19 2010 C:\Windows\system32\SHLWAPI.dll
7fefcff0000 553a8775 Apr 24 19:12:05 2015 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0
7fefdec0000 591331f3 May 10 16:29:55 2017 C:\Windows\system32\SHELL32.dll
7fefa1d0000 4ce7ca38 Nov 20 13:16:40 2010 C:\Windows\system32\WINSPOOL.DRV
7fefdba0000 58f4e14a Apr 17 16:37:46 2017 C:\Windows\system32\ole32.dll
7feff190000 58f4e14e Apr 17 16:37:50 2017 C:\Windows\system32\OLEAUT32.dll
7fefd500000 4a5be082 Jul 14 02:33:54 2009 C:\Windows\system32\VERSION.dll
7fefede0000 4a5bdf40 Jul 14 02:28:32 2009 C:\Windows\system32\IMM32.DLL
7feff980000 57fd0632 Oct 11 16:33:06 2016 C:\Windows\system32\MSCTF.dll
7fefd510000 5b046e43 May 22 20:23:47 2018 C:\Windows\system32\nvinitx.dll
75190000 57f433c5 Oct 04 23:57:09 2016 C:\Program Files\NVIDIA Corporation\CoProcManager\detoured.dll
7fefa4e0000 5b047092 May 22 20:33:38 2018 C:\Program Files\NVIDIA Corporation\CoProcManager\nvd3d9wrapx.dll
7feff7a0000 4ce7c9a2 Nov 20 13:14:10 2010 C:\Windows\system32\SETUPAPI.dll
7fefd8e0000 4ce7c55c Nov 20 12:55:56 2010 C:\Windows\system32\CFGMGR32.dll
7fefd6e0000 4a5bdee1 Jul 14 02:26:57 2009 C:\Windows\system32\DEVOBJ.dll
7fefa4b0000 5b04708d May 22 20:33:33 2018 C:\Program Files\NVIDIA Corporation\CoProcManager\nvdxgiwrapx.dll
7fefd2b0000 5a147c83 Nov 21 19:20:35 2017 C:\Windows\system32\guard64.dll
7fefd290000 5879cba2 Jan 14 06:56:34 2017 C:\Windows\system32\api-ms-win-core-synch-l1-2-0.DLL
7fefcf80000 4a5bdeff Jul 14 02:27:27 2009 C:\Windows\system32\fltlib.dll
7fefd430000 595fa9c6 Jul 07 16:33:26 2017 C:\Windows\system32\CRYPTBASE.dll
7fefb4c0000 4a5be093 Jul 14 02:34:11 2009 C:\Windows\system32\uxtheme.dll
7fefb090000 559eb4fe Jul 09 18:53:02 2015 C:\Windows\system32\dwmapi.dll
SubSystemData: 0000000000000000
ProcessHeap: 0000000000340000
ProcessParameters: 0000000000342a50
CurrentDirectory: 'C:\Program Files (x86)\IntelSWTools\VTune Amplifier XE 2016\'
WindowTitle: 'C:\Users\lewis\Desktop\support.txt - Shortcut.lnk'
ImageFile: 'C:\Windows\system32\NOTEPAD.EXE'
DllPath: 'C:\Windows\system32;C:\Windows\system32;C:\Windows\system;C:\Windows;.;C:\Program Files (x86)\IntelSWTools\VTune Amplifier XE 2016\bin32;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Performance Tools;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\Hostx64\x64;C:\Program Files\ImageMagick-7.0.10-Q16-HDRI;C:\Users\lewis\Desktop\IDA_Pro_v6.8_and_Hex-Rays_Decompiler_(ARM,x64,x86)\;C:\Program Files\Java\jdk-9\bin;C:\Program Files\ImageMagick-7.0.10-Q16-HDRI;C:\Program Files\Debugging Tools for Windows (x64)\;C:\Windows\system32;C:\Windows\system32\ffmpeg\bin;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files (x86)\QuickTime\QTSystem\;C:\texlive\2017\bin\win32;C:\adb;C:\Users\lewis\AppData\Local\Programs\Python\Python36-32\;C:\Users\lewis\AppData\Local\Programs\Python\Python36-32\Scripts;C:\Users\lewis\Desktop\New folder (2)\sqlmapproject-sqlmap-6402d2e;C:\Program Files\PuTTY\;C:\Program Files\Java\jdk-9\bin;;C:\Users\lewis\AppData\Local\Programs\hyper\resources\bin'
Environment: 00000000003c7ff0
=C:=C:\Users\lewis\Desktop
=ExitCode=00000000
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\lewis\AppData\Roaming
CLASSPATH=.;C:\Program Files\Java\jdk-9\lib
CommonProgramFiles=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=QWERTYUIOP
ComSpec=C:\Windows\system32\cmd.exe
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Users\lewis
JAVA_HOME=C:\Program Files\Java\jdk-9
JDK_HOME=C:\Program Files\Java\jdk-9
LOCALAPPDATA=C:\Users\lewis\AppData\Local
LOGONSERVER=\\QWERTYUIOP
NUMBER_OF_PROCESSORS=8
NVIDIAWHITELISTED=0x01
ORIGINAL_XDG_CURRENT_DESKTOP=undefined
OS=Windows_NT
Path=C:\Program Files (x86)\IntelSWTools\VTune Amplifier XE 2016\bin32;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Performance Tools;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\Hostx64\x64;C:\Program Files\ImageMagick-7.0.10-Q16-HDRI;C:\Users\lewis\Desktop\IDA_Pro_v6.8_and_Hex-Rays_Decompiler_(ARM,x64,x86)\;C:\Program Files\Java\jdk-9\bin;C:\Program Files\ImageMagick-7.0.10-Q16-HDRI;C:\Program Files\Debugging Tools for Windows (x64)\;C:\Windows\system32;C:\Windows\system32\ffmpeg\bin;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files (x86)\QuickTime\QTSystem\;C:\texlive\2017\bin\win32;C:\adb;C:\Users\lewis\AppData\Local\Programs\Python\Python36-32\;C:\Users\lewis\AppData\Local\Programs\Python\Python36-32\Scripts;C:\Users\lewis\Desktop\New folder (2)\sqlmapproject-sqlmap-6402d2e;C:\Program Files\PuTTY\;C:\Program Files\Java\jdk-9\bin;;C:\Users\lewis\AppData\Local\Programs\hyper\resources\bin
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 158 Stepping 9, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=9e09
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PROMPT=$P$G
PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
PT7HOME=C:\Program Files\Cisco Packet Tracer 7.0
PUBLIC=C:\Users\Public
PYTHON_HOME=C:\Users\lewis\AppData\Local\Programs\Python\Python36-32
QTJAVA=C:\Program Files (x86)\QuickTime\QTSystem\QTJava.zip
SESSIONNAME=Console
SHIM_MCCOMPAT=0x810000001
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=D:\System\Temp
TMP=D:\System\Temp
USERDOMAIN=QWERTYUIOP
USERNAME=lewis
USERPROFILE=C:\Users\lewis
VBOX_MSI_INSTALL_PATH=C:\Program Files\Oracle\VirtualBox\
VTUNE_AMPLIFIER_XE_2016_DIR=C:\Program Files (x86)\IntelSWTools\VTune Amplifier XE 2016\
windir=C:\Windows
windows_tracing_flags=3
_NT_SYMBOL_PATH=srv*c:\symbols*http://msdl.microsoft.com/download/symbols
LANG=en_GB.UTF-8
TERM=xterm-256color
COLORTERM=truecolor
TERM_PROGRAM=Hyper
TERM_PROGRAM_VERSION=3.1.0-canary.4
To get kernel module bases you can use the .reload
command followed by lm
, which will also show the user bases for the current process context that was set by .process
if the PEB is mapped in when the snapshot is taken (in the case of livekd
) or at that time (in the case of kd -kl
local debugging).
.reload
searches for modules in the PEB in the current process context if the PEB is mapped in in to learn their names, bases and lengths and also traverses PsLoadedModuleList
to get the kernel module names, bases and lengths, but unloads / does not load symbols for any of the modules except for essential ones, and it loads fewer or more of the essential .pdb
s depending on whether the .pdb
is cached locally or whether it needs to download from the symbol server (either to a cache or its own cache in sym\
if you don't have one specified). You have to load symbols with ld *
or .reload /f
and make sure .sympath
is srv*C:\localcache\*https://https://msdl.microsoft.com/download/symbols
. When the PEB is not mapped in, you'll have to use VMMap / Process Explorer to get the base addresses and lengths of the modules. If the PEB isn't mapped in .reload kernel32
will not work because it wont be able to find the module, but .reload kernel32.dll 775c0000,11f000
will work if you tell it where it is by supplying the base and address acquired from Process Explorer. Supplying an address for a module also loads symbols to be used with it starting at that address, regardless of the /f
setting. lm
shows all the modules found, the address, address of the first page after the final page allocation, name and whether symbols have been loaded for them in the debugger.
© 2022 - 2024 — McMap. All rights reserved.