EXE или DLL Базовый адрес образа

Есть ли способ в C++/ Windows, чтобы получить базовый адрес образа EXE /DLL? Спасибо:)

6 ответов

Решение

Если вы загружаете бинарный файл в свой собственный процесс, вы можете использовать GetModuleHandle. Он возвращает HMODULE, но это то же самое, что HINSTANCE и базовый адрес.

Если вы хотите знать, какой базовый адрес предпочитает двоичный файл, вам следует прочитать PE-заголовок. Смотрите здесь и ищите поле ImageBase в IMAGE_OPTIONAL_HEADER.

Редактировать: GetModuleHandle(NULL) вернет базовый адрес (хотя указанный тип HMODULE) для текущего процесса.

Я обнаружил, что наиболее удобный и точный способ получить базовый адрес модуля (и размер изображения в памяти) - через 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;
    // ...
}

Если вы проверяете файл DLL или EXE на диске, используйте утилиту dumpbin. Он установлен в Visual Studio или SDK.

Пример вывода дампа / заголовков:

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

Если вы хотите получить свой собственный адрес ImageBase из DLL/EXE, то как насчет этого:

#include <winnt.h>

EXTERN_C IMAGE_DOS_HEADER __ImageBase;

Если вы хотите перечислить все модули процесса, вы также можете использовать 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);
}

Немного хакерский, но это тоже работает:

https://ntopcode.wordpress.com/2018/02/26/anatomy-of-the-process-environment-block-peb-windows-internals/

Не забудьте включить Windows.h а также winternl.h

И когда я открываю его в VMMap:

(адрес на этот раз другой из-за ASLR)

Для.dll еще никто не упомянул этот метод: http://sandsprite.com/CodeStuff/Understanding_the_Peb_Loader_Data_List.html

Посмотрите на структуры в kd и получите правильные смещения для вашей системы, хотя они редко меняются в разных версиях Windows.

Это только как GetModuleHandle все равно реализовано. Он призываетBasepGetModuleHandleExW а функциональность реализована в RtlPcToFileHeader.

Найдите ниже код, чтобы найти базовый адрес изображения в 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;
}
Другие вопросы по тегам