• 解析PE头(上课代码)


    // 02 解析PE头.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "windows.h"
    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;
    }
    
    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[])
    {
        BOOL bSuccess = IsPeFile(L"D:\Test.exe");
        if (bSuccess == TRUE)
        {
            //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 找到NT头
            PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pBuf;
            PIMAGE_NT_HEADERS  pNt = (PIMAGE_NT_HEADERS)(pBuf + pDos->e_lfanew);
            //2.1 找到文件头
            PIMAGE_FILE_HEADER  pFileHeader = &pNt->FileHeader;
            printf("运行平台:%x
    ", pFileHeader->Machine);
            printf("区段数量:%x
    ", pFileHeader->NumberOfSections);
    
    
            //2.2找到扩展头、
            PIMAGE_OPTIONAL_HEADER pOptionHeader =
                &pNt->OptionalHeader;
            printf("入口点:%x
    ", pOptionHeader->AddressOfEntryPoint);
            printf("加载基址:%x
    ", pOptionHeader->ImageBase);
            printf("文件对齐:%x
    ", pOptionHeader->FileAlignment);
            printf("内存对齐:%x
    ", pOptionHeader->SectionAlignment);
            //.......
    
            //2.3找到数据目录表
            PIMAGE_DATA_DIRECTORY  pDataDir = pOptionHeader->DataDirectory;
            printf("导出表的地址是:%x     ",pDataDir[0].VirtualAddress);//导出表的RVA
            printf("导出表的大小是:%x
    ",pDataDir[0].Size);                   //导出表这个数据的大小
            printf("导入表的地址是:%x     ", pDataDir[1].VirtualAddress);//导入表的RVA
            printf("导入表的大小是:%x
    ", pDataDir[1].Size);                   //导入表这个数据的大小
            pDataDir[2];//资源
            pDataDir[3];//异常
            pDataDir[4];//安全结构
            pDataDir[5];//重定位
            pDataDir[6];//调试信息
            //.......
    
    
            //2.4找到区段表
             PIMAGE_SECTION_HEADER pSection =   IMAGE_FIRST_SECTION(pNt);
             for (int i = 0; i < pFileHeader->NumberOfSections;i++)
             {
                 printf("区段名:%s  ,起始RVA:%x,在映像中的大小:%x,起始Offect%x,在文件中的大小%x
    ",
                     pSection->Name, pSection->VirtualAddress, pSection->Misc.VirtualSize,
                     pSection->PointerToRawData, pSection->SizeOfRawData);
                 pSection++;
             }
             DWORD Offect = RvaToOffect(0x2010, pBuf);
             printf("%x", Offect);
        }
    
        return 0;
    }
  • 相关阅读:
    初识Vulkan
    网络相关系列之中的一个:Android中使用HttpClient发送HTTP请求
    Hello,Android
    熊猫猪新系统測试之四:Ubuntu 14.04
    iOS OC08,09_内存管理
    XML总结
    【Scala-ML】怎样利用Scala构建并行机器学习系统
    在vs2010中编译log4cxx-0.10.0具体方法(从下载、编译、解决错误具体介绍)
    UI_UITableView_搭建
    Angular 4 子路由
  • 原文地址:https://www.cnblogs.com/Alyoyojie/p/5329316.html
Copyright © 2020-2023  润新知