zoukankan      html  css  js  c++  java
  • 遍历导入表(上课代码)

    // 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;
    }
  • 相关阅读:
    Sqlserver 实际开发中表变量的用法
    Python Day 20 面向对象 (面向对象的组合用法,面向对象的三大特性
    Python Day 19 面向对象(初识面向对象)
    Python Day 18 常用模块(模块和包)
    Python Day 17 常用模块(常用模块一 时间模块,random模块,os模块,sys模块,序列化模块)
    Python Day 15 函数(递归函数、二分查找算法)
    Python Day 14 函数(内置函数,匿名函数(lambda表达式))
    Python Day 13 函数(迭代器,生成器,列表推导式,生成器表达式)
    Python Day 11 + Python Day 12 函数(函数名的应用,闭包,装饰器)
    Python Day 10 函数(名称空间,作用域,作用域链,加载顺序等; 函数的嵌套 global,nonlocal)
  • 原文地址:https://www.cnblogs.com/Alyoyojie/p/5329491.html
Copyright © 2011-2022 走看看