如何在C中读取导入目录表 [英] How to read Import Directory Table in C

查看:115
本文介绍了如何在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名称的信息,请首先找到以下内容的RVA(相对虚拟地址):从数据目录中的导入目录,在原始节数据中找到该地址,现在您有了一个 IMAGE_IMPORT_DESCRIPTOR 。通过检查名称字段所指向的字符串,获取与映射图像有关的数组成员。

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.

I不会描述可移植可执行文件格式的结构,但是您可以查看以下链接:

在PE内凝视

Microsoft Systems Journal

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\n", libname[i]);
            pImportDescriptor++; //advance to next IMAGE_IMPORT_DESCRIPTOR
            i++;

        }

    }
    else
    {
        printf("No Import Table!\n");
        return 1;
    }
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
    if(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
    {
        printf("Exception: EXCEPTION_ACCESS_VIOLATION\n");
        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中读取导入目录表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆