• 遍历导入表(上课代码)


    // 02 遍历导入表.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <windows.h>
    //************************************
    // Method:    IsPeFile
    // FullName:  IsPeFile
    // Access:    public 
    // Returns:   bool   成功失败
    // Qualifier:
    // Parameter: TCHAR * szPath  路径
    //************************************
    bool  IsPeFile(TCHAR* szPath)
    {
        BOOL bSuccess = TRUE;
        //1 将PE文件读取到内存
        HANDLE hFile = CreateFile(
            szPath,
            GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL
            , NULL
            );
        DWORD dwSize = GetFileSize(hFile, NULL);
        DWORD dwRubbish = 0;
        unsigned char * pBuf = new unsigned char[dwSize];
        ReadFile(hFile, pBuf, dwSize, &dwRubbish, NULL);
        //2 判断是否是PE文件
        PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pBuf;
        if (pDos->e_magic != IMAGE_DOS_SIGNATURE)
        {
            bSuccess = FALSE;
            goto Error;
    
        }
        PIMAGE_NT_HEADERS  pNt = (PIMAGE_NT_HEADERS)(pBuf + pDos->e_lfanew);
        if (pNt->Signature != IMAGE_NT_SIGNATURE)
        {
            bSuccess = FALSE;
            goto Error;
        }
    
    Error:
    
        if (pBuf != NULL)
        {
            delete[]pBuf;
        }
        if (hFile != INVALID_HANDLE_VALUE)
        {
            CloseHandle(hFile);
        }
        return bSuccess;
    }
    
    //************************************
    // Method:    RvaToOffect
    // FullName:  RvaToOffect
    // Access:    public 
    // Returns:   DWORD
    // Qualifier: 将RVA转换为Offect
    // Parameter: DWORD rva    要转换的RVA
    // Parameter: unsigned char * pFile   存储pe文件内容的缓冲区
    //************************************
    DWORD RvaToOffect(DWORD rva, unsigned char* pFile)
    {
        //1 找到NT头
        PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pFile;
        PIMAGE_NT_HEADERS  pNt = (PIMAGE_NT_HEADERS)(pFile + pDos->e_lfanew);
        //2 找到数据目录表
        PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
        //3 判断要转换的位置是不是PE头部
        if (rva < pSection->VirtualAddress)
        {
            return rva;
        }
        //4 在数据目录表中遍历,进行计算
        for (int i = 0; i < pNt->FileHeader.NumberOfSections; i++)
        {
            if (
                (rva >= pSection->VirtualAddress) &&
                (rva <= pSection->VirtualAddress + pSection->Misc.VirtualSize)
                )
            {
                return rva - pSection->VirtualAddress + pSection->PointerToRawData;
            }
            pSection++;
        }
        return -1;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        //1 将PE文件读取到内存
        HANDLE hFile = CreateFile(
            L"D:\Test.exe",
            GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL
            , NULL
            );
        DWORD dwSize = GetFileSize(hFile, NULL);
        DWORD dwRubbish = 0;
        unsigned char * pBuf = new unsigned char[dwSize];
        ReadFile(hFile, pBuf, dwSize, &dwRubbish, NULL);
        //2 找到dos头
        PIMAGE_DOS_HEADER  pDos = PIMAGE_DOS_HEADER(pBuf);
        //3 找到nt头
        PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pBuf + pDos->e_lfanew);
        //4 找到扩展头
        PIMAGE_OPTIONAL_HEADER pOption = &(pNt->OptionalHeader);
        //5 找到数据目录表
        PIMAGE_DATA_DIRECTORY  pDataDirectory = pOption->DataDirectory;
        //6 找到导入表的数据目录
        PIMAGE_DATA_DIRECTORY pExportDirectory = (pDataDirectory + 1);
        
        //7解析导入表的数据目录
        DWORD dwImportOffect = 
            RvaToOffect(pExportDirectory->VirtualAddress, pBuf);
        PIMAGE_IMPORT_DESCRIPTOR pImport = 
            (PIMAGE_IMPORT_DESCRIPTOR)(dwImportOffect + pBuf);
        //8 解析导入表
        while (pImport->OriginalFirstThunk != 0)
        {
            //8.1通过INT的RVA得到INT在文件中的位置
            PIMAGE_THUNK_DATA32  pInt = 
            (PIMAGE_THUNK_DATA32)(RvaToOffect(pImport->OriginalFirstThunk, pBuf) + pBuf);
            char* pDllName = (char*)(RvaToOffect(pImport->Name,pBuf)+pBuf);
            printf("%s
    ", pDllName);
            while (pInt->u1.Ordinal!=0)
            {
                //8.2得到位置之后,判断一下最高位是不是1
                if ((pInt->u1.Ordinal & 80000000)>>31 != 1)
                {
                    //8.2.1如果不是1的话,说明它既有名称也有序号,需要使用PIMAGE_IMPORT_BY_NAME  AddressOfData去解析
                    PIMAGE_IMPORT_BY_NAME pNameAndOrder = (PIMAGE_IMPORT_BY_NAME)
                        (RvaToOffect(pInt->u1.AddressOfData, pBuf) + pBuf);
                    printf("   序号为:%x",pNameAndOrder->Hint);
                    printf("   名称为:%s
    ",pNameAndOrder->Name);
                }
            
                else
                {
                    //8.2.2如果是1的话,说明它没有名称只有序号,直接使用DWORD Ordinal得到序号
                    printf("   序号为:%x
    ", pInt->u1.Ordinal & 0x7FFFFFFF);
                }
                
                pInt++;
    
            }
            pImport++;
        }
    
    
        return 0;
    }
  • 相关阅读:
    如何向MyEclipse项目的文件夹中添加JSP页面?
    MyEclipse中如何安装插件(以Subclipse为例)[转]
    s:textarea中的文本内容在什么时候才能被赋值给Action中的属性?
    由 s:hidden 引起的文本框内容不能传到 struts的Action中
    centos6分区与格式化数据盘、挂载磁盘的方法
    node实现后台权限管理系统
    在ERP软件行业项目应该怎么做?
    中小公司的Java工程师应该如何逆袭冲进BAT?
    Adminer轻量级MySQL管理工具,替代phpMyAdmin
    远程桌面连接失败了,提示身份验证错误,要求的函数不受支持
  • 原文地址:https://www.cnblogs.com/Alyoyojie/p/5329491.html
Copyright © 2020-2023  润新知