Search code examples
c++pointersdllportable-executable

Crash while accessing any member of the PE's PIMAGE_EXPORT_DIRECTORY structure


I'm trying to get the RVA of a function in kernel32.dll and I got the offset for the export directory and added it with my file_map. However when I try to do anything with any of the members of the PIMAGE_EXPORT_DIRECTORY structure, my program crashes. I can't even check whether or not it's a nullptr without it crashing. Here is my code:

#include "Sample.h" //Just contains other headers
#include <dbghelp.h>
#include <imagehlp.h>

int main()
{
    char kernel_path[MAX_PATH];

    //PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)GetModuleHandle("kernel32.dll");
    //if(pDos_hdr == NULL){printf("Invalid header: %d", (int)GetLastError());}

    if(GetModuleFileName(GetModuleHandle("kernel32.dll"), kernel_path, MAX_PATH) == 0)
    {
        printf("GetModuleFileName failed: %d", (int)GetLastError());
        return 1;
    }

    HANDLE hFile = CreateFile(kernel_path, GENERIC_READ, FILE_SHARE_READ,
       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
    if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: 
       %d", (int)GetLastError());return 1;}

    HANDLE kernel_map = CreateFileMapping(hFile, NULL, 
       PAGE_READONLY|SEC_IMAGE, 0, 256, "KernelMap");

    LPVOID file_map = MapViewOfFile(kernel_map, FILE_MAP_READ, 0, 0, 0);
    if(file_map == 0){printf("Error getting mapped view: %d",
      (int)GetLastError());return 1;}

    PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)file_map;
    if(pDos_hdr->e_magic == IMAGE_DOS_SIGNATURE){printf("Has MZ signature\n");}

    PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)((char*)file_map+pDos_hdr->e_lfanew);
    if(pNt_hdr->Signature == 0x4550){printf("Has PE signature\n");}

    IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader;
    IMAGE_DATA_DIRECTORY exp_entry = 
       opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)
        (((char*)file_map)+exp_entry.VirtualAddress);

    // Crashing Code --->
    void **func_table = (void**)((char*)file_map+pExp_dir->AddressOfFunctions);

    return 0;
}

Solution

  • From msdn, CreateFileMapping:: dwMaximumSizeLow [in] -

    The low-order DWORD of the maximum size of the file mapping object. If this parameter and dwMaximumSizeHigh are 0 (zero), the maximum size of the file mapping object is equal to the current size of the file that hFile identifies.

    You haven't mapped the full size of the file to the current process's virtual memory. This is because you have limited (256) the dwMaximumSizeLow parameter of the CreateFileMapping function. You can verify that by calling VirtualQuery.

    HANDLE kernel_map = CreateFileMapping(hFile, NULL, 
    PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap"); // 5th Param = 0