Search code examples
c++windowspointerstypesportable-executable

Find the name of the Imported DLLs using PE Headers


A Few days back I have started with Windows System Programming using c++. Hence, thought of building a utility to grab the PE Headers of an exe file. And now I am stuck with the Image_Import_descriptor structure.

What I want is to get the names of the DLL files(modules) imported by the exe. And below is the code I am using to get those names:

        DWORD Image_Import_Descriptor_addr = (DWORD)ntHeader + (DWORD)sizeof(ntHeader->FileHeader) + (DWORD)ntHeader->FileHeader.SizeOfOptionalHeader + (DWORD)ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
        importImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)Image_Import_Descriptor_addr;

To get the RVA of the name:

        DWORD name = importImageDescriptor->Name;
        printf("\n\n\n\t\t (((Module Name)): %X", name);

Gives an output: 4778B00

Hope untill now everything was fine technically.

However, my motive is to print the DLL names(like kernel32.dll). Can anyone help me out how to get the names of the DLL ?

My workarounds:

            LPCSTR snames = (LPCSTR)name;          
            printf("\n\n\n\t\t (((Module Name)): %s", *snames);

But this is giving me an error: Access Violation

I am getting confused with the pointers and Datatype conversions. A help is much appreciated.


Solution

  • Got the technique from 'ired' security blogs. Below is the working code.

    HANDLE h_File = CreateFile(L"testing.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if (!h_File) {
        printf("\nERROR : Could not open the file specified\n");
    }
    
    //Mapping Given EXE file to Memory
    HANDLE hMapObject = CreateFileMapping(h_File, NULL, PAGE_READONLY, 0, 0, NULL);
    LPVOID basepointer = (char*)MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0);
    
    //PIMAGE_DOS_HEADER dos_header;        
    PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)basepointer;
    printf("Magic number - %X\n", dos_header->e_magic); 
    
    printf("DOS HEADER: IMAGE NT HEADER offset(Relative Address) - %X\n", dos_header->e_lfanew);  //DOS header working fine...
    
    //PIMAGE_NT_HEADERS ntHeader;         
    PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)((DWORD)basepointer + dos_header->e_lfanew);
    printf("NT HEADER: Signature %x\n", nt_header->Signature);
    
    PIMAGE_FILE_HEADER file_header = (PIMAGE_FILE_HEADER)((DWORD)basepointer + dos_header->e_lfanew + sizeof(nt_header->Signature));
    printf("FILE HEADER: Machine %x\n", file_header->Machine);
    
    PIMAGE_OPTIONAL_HEADER optional_header = (PIMAGE_OPTIONAL_HEADER)((DWORD)basepointer + dos_header->e_lfanew + sizeof(nt_header->Signature) + sizeof(nt_header->FileHeader));
    printf("OPTIONAL HEADER: Image Base %x\n", optional_header->ImageBase);
    
    PIMAGE_SECTION_HEADER section_header = (PIMAGE_SECTION_HEADER)((DWORD)basepointer + dos_header->e_lfanew + sizeof(nt_header->Signature) + sizeof(nt_header->FileHeader) + sizeof(nt_header->OptionalHeader));
    DWORD numberofsections = file_header->NumberOfSections;
    printf("Section Header: Number of Sections %x\n", file_header->NumberOfSections);
    
    
        
    for (int j = 0; j < optional_header->NumberOfRvaAndSizes;j++) {
        printf("Data Directory: Virtual Address: %x\t\n", optional_header->DataDirectory[j].VirtualAddress);
    }
    
    DWORD RVAimport_directory = nt_header->OptionalHeader.DataDirectory[1].VirtualAddress;
    //printf("RVAimport_directory %x", RVAimport_directory);
    
    PIMAGE_SECTION_HEADER import_section = {};
    for (int i = 1; i <= numberofsections; i++, section_header++) {
        printf("Section Header: Section Name %s\n", section_header->Name);
    
        if (RVAimport_directory >= section_header->VirtualAddress && RVAimport_directory < section_header->VirtualAddress + section_header->Misc.VirtualSize) {
    
            import_section = section_header;
        }
        //section_header += (DWORD)sizeof(PIMAGE_SECTION_HEADER);
    }
    
    DWORD import_table_offset = (DWORD)basepointer + import_section->PointerToRawData;
    //imageBaseAddress + pointerToRawDataOfTheSectionContainingRVAofInterest + (RVAofInterest - SectionContainingRVAofInterest.VirtualAddress
    
    importImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(import_table_offset + (nt_header->OptionalHeader.DataDirectory[1].VirtualAddress - import_section->VirtualAddress));
    
    //DLL Imports
    for (;importImageDescriptor->Name != 0 ; importImageDescriptor++) {
        DWORD Imported_DLL = import_table_offset + (importImageDescriptor->Name - import_section->VirtualAddress);
        printf("Imported DLLs: %s\n", Imported_DLL);