解析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\n", pFileHeader->Machine);
        printf("区段数量:%x\n", pFileHeader->NumberOfSections);


        //2.2找到扩展头、
        PIMAGE_OPTIONAL_HEADER pOptionHeader =
            &pNt->OptionalHeader;
        printf("入口点:%x\n", pOptionHeader->AddressOfEntryPoint);
        printf("加载基址:%x\n", pOptionHeader->ImageBase);
        printf("文件对齐:%x\n", pOptionHeader->FileAlignment);
        printf("内存对齐:%x\n", pOptionHeader->SectionAlignment);
        //.......

        //2.3找到数据目录表
        PIMAGE_DATA_DIRECTORY  pDataDir = pOptionHeader->DataDirectory;
        printf("导出表的地址是:%x     ",pDataDir[0].VirtualAddress);//导出表的RVA
        printf("导出表的大小是:%x\n",pDataDir[0].Size);                   //导出表这个数据的大小
        printf("导入表的地址是:%x     ", pDataDir[1].VirtualAddress);//导入表的RVA
        printf("导入表的大小是:%x\n", 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\n",
                 pSection->Name, pSection->VirtualAddress, pSection->Misc.VirtualSize,
                 pSection->PointerToRawData, pSection->SizeOfRawData);
             pSection++;
         }
         DWORD Offect = RvaToOffect(0x2010, pBuf);
         printf("%x", Offect);
    }

    return 0;
}

 

转载于:https://www.cnblogs.com/Alyoyojie/p/5329316.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值