C++ EXE 或 DLL 图像基地址
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4298331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
EXE or DLL Image base address
提问by Idov
Is there a way in C++/windows to get the exe/DLL image base address? thanks :)
在 C++/windows 中有没有办法获取 exe/DLL 映像基址?谢谢 :)
回答by Lars Truijens
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.
如果您将二进制文件加载到您自己的进程中,您可以使用GetModuleHandle。它返回一个 HMODULE,但这与 HINSTANCE 和基地址相同。
If you want to know what base address the binary prefers you should read the PE header. See hereand look for the ImageBase field in IMAGE_OPTIONAL_HEADER.
如果您想知道二进制文件喜欢哪个基地址,您应该阅读 PE 标头。请参阅此处并在 IMAGE_OPTIONAL_HEADER 中查找 ImageBase 字段。
Edit: GetModuleHandle(NULL) will return the base address (altough the specified type is HMODULE) for the current process.
编辑:GetModuleHandle(NULL) 将返回当前进程的基地址(尽管指定的类型是 HMODULE)。
回答by shf301
If you are examining an DLL or EXE file on disk, use the dumpbinutility. It in installed with Visual Studio or the SDK.
如果您正在检查磁盘上的 DLL 或 EXE 文件,请使用dumpbin实用程序。它与 Visual Studio 或 SDK 一起安装。
Example Output of dumpbin /headers:
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
回答by Arty OneSoul
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):
我发现获取模块基地址(和内存中图像大小)的最方便和准确的方法是通过 GetModuleInformation(包括 psapi.h,链接到 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;
// ...
}
回答by Christopher Oezbek
If you want to get your own ImageBase Address from inside a DLL/EXE then how about this:
如果您想从 DLL/EXE 中获取自己的 ImageBase 地址,那么如何:
#include <winnt.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
回答by Mi-La
If you want to enumerate all process's modules, you can also use CreateToolhelp32Snapshot:
如果要枚举所有进程的模块,还可以使用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);
}
回答by Nishikant Mokashi
Find below code to find Image Base Address in CPP :
查找以下代码以在 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;
}
回答by Lewis Kelsey
A bit hacky but this works too:
有点hacky,但这也有效:
https://ntopcode.wordpress.com/2018/02/26/anatomy-of-the-process-environment-block-peb-windows-internals/
https://ntopcode.wordpress.com/2018/02/26/anatomy-of-the-process-environment-block-peb-windows-internals/
Make sure to include Windows.h
and winternl.h
确保包括Windows.h
和winternl.h
And when I open it up in VMMap:
(address is different this time because of ASLR)
(因为ASLR,这次地址不同)
For .dlls, nobody has mentioned this method yet: http://sandsprite.com/CodeStuff/Understanding_the_Peb_Loader_Data_List.html
对于 .dll,还没有人提到这个方法: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.
查看 kd 中的结构并为您的系统获取正确的偏移量,尽管它很少在 Windows 版本之间发生变化。
This is only how GetModuleHandle
is implemented anyway. It calls BasepGetModuleHandleExW
and the functionality is implemented in RtlPcToFileHeader
.
GetModuleHandle
无论如何,这只是如何实施。它调用BasepGetModuleHandleExW
并且功能在RtlPcToFileHeader
.