使用 PE 标头查找导入的 DLL 的名称

问题描述

几天前,我开始使用 C++ 进行 Windows 系统编程。因此,考虑构建一个实用程序来获取 exe 文件的 PE 标头。 现在我坚持使用 Image_Import_descriptor 结构。

我想要的是获取exe导入的DLL文件(模块)的名称。下面是我用来获取这些名称代码

        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;

获取名称的 RVA:

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

给出输出4778B00

希望直到现在一切在技术上都很好。

然而,我的动机是打印 DLL 名称(如 kernel32.dll)。 谁能帮助我如何获取 DLL 的名称

我的解决方法

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

但这给了我一个错误访问冲突

我对指针和数据类型转换感到困惑。非常感谢您的帮助。

解决方法

从 'ired' 安全博客中获得技术。以下是工作代码。

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,PAGE_READONLY,NULL);
LPVOID basepointer = (char*)MapViewOfFile(hMapObject,FILE_MAP_READ,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);