EXE或DLL映像基址

时间:2010-11-28 18:39:28

标签: c++ windows portable-executable base-address

在C ++ / windows中是否有办法获取exe / DLL映像基址? 谢谢:))

7 个答案:

答案 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)

有点黑,但这也可行:

enter image description here 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") } })

当我在VMMap中打开它时: enter image description here

(这次由于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位指针。无论哪种类型的转换都将对程序集输出产生相同的效果-仅有助于代码级的概念清晰性和编译器警告。