如何在 C 中读取导入目录表

How to read Import Directory Table in C(如何在 C 中读取导入目录表)

本文介绍了如何在 C 中读取导入目录表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用 C++ 构建一个 PE 查看器,如果我尝试在导入目录表中输出库的名称,它似乎会崩溃.我似乎没有得到程序使用的 DLL 的正确指针.

I'm trying to build a PE viewer in C++ and it seems to crash if i try to output the names of the libraries in the Import Directory Table. It seems that I am not getting the correct pointers for the DLLs that are used by the program.

HANDLE handle = CreateFile("messagebox.exe",GENERIC_READ,0,0,OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL,0);
DWORD size = GetFileSize(handle,NULL);
PVOID virtualpointer = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE);
state = ReadFile(handle,virtualpointer,size,&byteread,NULL);
CloseHandle(handle);
PIMAGE_NT_HEADERS ntheaders = PIMAGE_NT_HEADERS(PCHAR(vpointer) + 
                                     PIMAGE_DOS_HEADER(vpointer)->e_lfanew);
handle = GetCurrentProcess();
DWORD EntryAddr = ntheaders->OptionalHeader.ImageBase + 
                       ntheaders->OptionalHeader.AddressOfEntryPoint;

DWORD importdir = 
       (DWORD) &(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);

DWORD va = (DWORD)(ntheaders->OptionalHeader.ImageBase) + 
                     ((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress;
LPSTR libname[128];
int i =0;
while(((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name)
{
       // get DLL name
       libname[i] = (LPSTR)(nt->OptionalHeader.ImageBase + 
                         ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name);
       i++;
}

推荐答案

要读取导入目录表中库的名称,您可以执行以下操作:

To read the names of the libraries in the Import Directory Table, you can do the following:

  1. 获取文件的内存映射基地址.
  2. 获取指向 IMAGE_NT_HEADERS 的指针 结构.
  3. 获取指向 IMAGE_SECTION_HEADER 结构.

DataDirectory 是 OptionalHeader 的最后 128 个字节,它又是 PE 标头的最后一个成员 IMAGE_NT_HEADERS.该结构有 2 个成员,其中包含数据结构的位置和大小.
如果要查找有关dll名称的信息,首先要从Data Directory中找到Import Directory的RVA(Relative Virtual Address),在原始部分数据,现在您有一个 IMAGE_IMPORT_DESCRIPTOR 数组.通过检查 Name 字段指向的字符串,获取与映射图像相关的数组成员.

DataDirectory is the final 128 bytes of OptionalHeader, which in turn is the final member of the PE header IMAGE_NT_HEADERS. The structure has 2 members which contain the location and size of the data structure.
If you want to look up information about the dll names, you first find the RVA (Relative Virtual Address) of the Import Directory from the Data Directory, find that address in the raw section data and now you have an array of IMAGE_IMPORT_DESCRIPTOR. Get the member of this array that relates to mapped image by inspecting the strings pointed to by the Name fields.

我不会描述可移植可执行文件格式的结构,但您可以查看以下链接:
深入了解 PE
微软系统杂志

I will not describe structure of Portable Executable File Format, but you can look at the following links:
Peering Inside the PE
Microsoft Systems Journal

您的代码中的某些变量未声明,这令人困惑,但坚持使用您的骨架代码,我编写了它,以便它满足您的问题.

Some variables in your code are not declared and this is confusing, but sticking to your skeleton code I wrote it so that it meets to your question.

DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt);
int _tmain(int argc, _TCHAR* argv[])
{
LPCWSTR fNmae=L"C:\Windows\system32\notepad.exe";
HANDLE handle=CreateFile(fNmae/*"messagebox.exe"*/, GENERIC_READ, 0, 0, OPEN_EXISTING,  FILE_ATTRIBUTE_NORMAL, 0);
DWORD byteread,size=GetFileSize(handle, NULL);
PVOID virtualpointer=VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
ReadFile(handle, virtualpointer, size, &byteread, NULL);
CloseHandle(handle);
// Get pointer to NT header
PIMAGE_NT_HEADERS           ntheaders=(PIMAGE_NT_HEADERS)(PCHAR(virtualpointer) + PIMAGE_DOS_HEADER(virtualpointer)-> e_lfanew);   
PIMAGE_SECTION_HEADER       pSech=IMAGE_FIRST_SECTION(ntheaders);//Pointer to first section header
PIMAGE_IMPORT_DESCRIPTOR    pImportDescriptor; //Pointer to import descriptor 
__try
{
    if(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0)/*if size of the table is 0 - Import Table does not exist */
    {
        pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer +
                            Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,pSech,ntheaders));
        LPSTR libname[256];
        size_t i=0;
        // Walk until you reached an empty IMAGE_IMPORT_DESCRIPTOR
        while(pImportDescriptor->Name != NULL)
        {
            printf("Library Name   :");
            //Get the name of each DLL
            libname[i]=(PCHAR)((DWORD_PTR)virtualpointer + Rva2Offset(pImportDescriptor->Name,pSech,ntheaders));
            printf("%s
", libname[i]);
            pImportDescriptor++; //advance to next IMAGE_IMPORT_DESCRIPTOR
            i++;

        }

    }
    else
    {
        printf("No Import Table!
");
        return 1;
    }
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
    if(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
    {
        printf("Exception: EXCEPTION_ACCESS_VIOLATION
");
        return 1;
    }

}
if(virtualpointer)
    VirtualFree(virtualpointer, size, MEM_DECOMMIT);

return 0;
}
 /*Convert Virtual Address to File Offset */
DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt)
{
    size_t i = 0;
    PIMAGE_SECTION_HEADER pSeh;
    if(rva == 0)
    {
            return (rva);
    }
    pSeh = psh;
    for(i = 0; i < pnt->FileHeader.NumberOfSections; i++)
    {
            if(rva >= pSeh->VirtualAddress && rva < pSeh->VirtualAddress +
               pSeh->Misc.VirtualSize)
            {
                    break;
            }
            pSeh++;
    }
    return (rva - pSeh->VirtualAddress + pSeh->PointerToRawData);
} 

这篇关于如何在 C 中读取导入目录表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何在 C 中读取导入目录表

基础教程推荐