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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:04:03  来源:igfitidea点击:

EXE or DLL Image base address

c++windowsportable-executablebase-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,但这也有效:

enter image description herehttps://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.hand winternl.h

确保包括Windows.hwinternl.h

And when I open it up in VMMap: enter image description here

当我在 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 GetModuleHandleis implemented anyway. It calls BasepGetModuleHandleExWand the functionality is implemented in RtlPcToFileHeader.

GetModuleHandle无论如何,这只是如何实施。它调用BasepGetModuleHandleExW并且功能在RtlPcToFileHeader.