在C ++ / windows中是否有办法获取exe / DLL映像基址? 谢谢:))
答案 0 :(得分:16)
如果您将二进制文件加载到您自己的进程中,则可以使用GetModuleHandle。它返回一个HMODULE,但那是the same as HINSTANCE and the base address。
如果您想知道二进制文件更喜欢哪个基址,您应该读取PE头。请参阅here并在IMAGE_OPTIONAL_HEADER中查找ImageBase字段。
编辑:GetModuleHandle(NULL)将返回当前进程的基地址(尽管指定的类型为HMODULE)。
答案 1 :(得分:6)
如果要检查磁盘上的DLL或EXE文件,请使用dumpbin实用程序。它与Visual Studio或SDK一起安装。
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
答案 2 :(得分:3)
我发现获取模块基址(和内存中图像大小)的最方便和准确的方法是通过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;
// ...
}
答案 3 :(得分:3)
如果你想从DLL / EXE中获取自己的ImageBase地址,那么这个怎么样:
#include <winnt.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
答案 4 :(得分:2)
如果要枚举所有流程的模块,还可以使用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);
}
答案 5 :(得分:0)
查找以下代码以在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;
}
答案 6 :(得分:0)
有点黑,但这也可行:
https://ntopcode.wordpress.com/2018/02/26/anatomy-of-the-process-environment-block-peb-windows-internals/
确保包含 <div id="wrapper">
<div class="characters">
<div class="container">
<div class="row">
<div class="col box-1" data-isChar="false" data-char="1">
<h4 class="character-name">Tom karaktär</h4>
<footer class="character-info">
<p>Skapa en ny karaktär</p>
</footer>
<div class="buttons">
<button id="play-char" class="btn btn-success" data-target="#locationSelect">SPELA</button>
<button id="delete" class="btn btn-danger">RADERA</button>
</div>
</div>
<div class="col box-2" data-isChar="false" data-char="2">
<h4 class="character-name">Tom karaktär</h4>
<footer class="character-buttons">
<p class="character-info">Skapa en ny karaktär</p>
</footer>
<div class="buttons">
<button id="play-char" class="btn btn-success" data-target="#locationSelect">SPELA</button>
<button id="delete" class="btn btn-danger">RADERA</button>
</div>
</div>
<div class="col box-3" data-isChar="false" data-char="3">
<h4 class="character-name">Tom karaktär</h4>
<footer class="character-info">
<p>Skapa en ny karaktär</p>
</footer>
<div class="buttons">
<button id="play-char" class="btn btn-success" data-target="#locationSelect">SPELA</button>
<button id="delete" class="btn btn-danger">RADERA</button>
</div>
</div>
</div>
</div>
</div>
</div>
和 $(".buttons #play-char").click(function() {
if ($(".col").attr("data-isChar") === "false") {
$(this).attr("data-target", "#createModal")
$("#createModal").modal("show")
} else {
$("#locationSelect").modal("show")
}
})
(这次由于ASLR而地址不同)
对于.dll,尚无人提及此方法:http://sandsprite.com/CodeStuff/Understanding_the_Peb_Loader_Data_List.html
查看kd中的结构并为您的系统获取正确的偏移量,尽管它在Windows版本中很少更改。
这仅是如何实现GetModuleHandle
的方式。它调用Windows.h
,并在winternl.h
中实现该功能。如果参数为NULL,则返回BasepGetModuleHandleExW
,否则它将使用PEB中其下方的RtlPcToFileHeader
成员来解析地址空间中列表加载的dll,如sandsprite链接所示
模块句柄只是转换为return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
的地址,而Ldr
就是HMODULE
就是HINSTANCE
就是{{1指向空白的64位指针。无论哪种类型的转换都将对程序集输出产生相同的效果-仅有助于代码级的概念清晰性和编译器警告。