该程序用与对PE文件的头文件以及数据目录表进行分析,并输出各个数据目录表以及头文件的关键字段
运行环境
Microsoft Visual Studio Professional 2017 Windows10
项目格式
头文件 Entry.h
#pragma once
#include <stdio.h>
#include <Windows.h>
//计算数据目录表起始位置到文件头的偏移
DWORD RvaToOffset(DWORD dwRva, char *buffer);
//解析导入表的函数
void ImportTable(char * buffer);
//解析导出表的函数
void ExportTable(char * buffer);
//解析TLS表的函数
void TLSTable(char* buffer);
//解析延迟导入表的函数
void DelayImportTable(char *buffer);
//解析重定位表的函数
void RelocTable(char *buffer);
//解析资源表的函数
void ResourceTable(char *buffer);
//解析其他表(以Debug表为例)
void DataTable(char *buffer);
源文件 Entry.cpp
在执行前需要修改分析的PE文件的路径,执行时可以选择调试以及一个一个的功能调试,便于分析.
#include "Entry.h"
int main()
{
//文件读取
FILE * pFile = NULL;
char * buffer;
int nFileLength = 0;
pFile = fopen("D:\\Program Files\\Edrawsoft\\Edraw MindMaster(简体中文)\\MindMaster.exe", "rb");
//pFile = fopen("D:\\Program Files\\Edrawsoft\\Edraw MindMaster(简体中文)\\MindMaster.exe", "rb");
//D:\\Program Files\\Edrawsoft\\Edraw MindMaster(简体中文)\\MindMaster.exe
fseek(pFile, 0, SEEK_END);
nFileLength = ftell(pFile);
rewind(pFile);
int imageLength = nFileLength * sizeof(char) + 1;
buffer = (char *)malloc(imageLength);
memset(buffer, 0, nFileLength * sizeof(char) + 1);
fread(buffer, 1, imageLength, pFile);
//MS-DOS头解析
PIMAGE_DOS_HEADER ReadDosHeader;
ReadDosHeader = (PIMAGE_DOS_HEADER)buffer;
printf("MS-DOS Info:\n");
printf("MZ标志位:%x\n", ReadDosHeader->e_magic);
printf("PE头偏移:%x\n", ReadDosHeader->e_lfanew);
printf("==================================================================\n");
printf("PE Header Info:\n");
PIMAGE_NT_HEADERS32 ReadNTHeaders;
//PE头解析
ReadNTHeaders = (PIMAGE_NT_HEADERS32)(buffer + ReadDosHeader->e_lfanew);
//PE头标志
printf("PE标志位:%x\n", ReadNTHeaders->Signature);
//标准PE头字段
printf("运行平台:%x\n", ReadNTHeaders->FileHeader.Machine);
//扩展PE头字段
printf("ImageBase:%x\n", ReadNTHeaders->OptionalHeader.ImageBase);
printf("==================================================================\n");
printf("Section Header Info:\n");
//区段解析遍历
PIMAGE_SECTION_HEADER ReadSectionHeader = IMAGE_FIRST_SECTION(ReadNTHeaders);
PIMAGE_FILE_HEADER pFileHeader = &ReadNTHeaders->FileHeader;
for (int i = 0; i < pFileHeader->NumberOfSections; i++)
{
printf("Name(区段名称):%s\n", ReadSectionHeader[i].Name);
printf("VOffset(起始的相对虚拟地址):%08X\n", ReadSectionHeader[i].VirtualAddress);
printf("VSize(区段大小):%08X\n", ReadSectionHeader[i].SizeOfRawData);
printf("ROffset(文件偏移):%08X\n", ReadSectionHeader[i].PointerToRawData);
printf("RSize(文件中区段大小):%08X\n", ReadSectionHeader[i].Misc.VirtualSize);
printf("标记(区段的属性):%08X\n\n", ReadSectionHeader[i].Characteristics);
}
printf("==================================================================\n");
//分析函数
//ImportTable(buffer);
//ExportTable(buffer);
//TLSTable(buffer);
//DelayImportTable(buffer);
//RelocTable(buffer);
//ResourceTable(buffer);
//DataTable(buffer);
free(buffer);
return 0;
}
//dwRva是某个数据目录表的VirtualAddress
//buffer是读取到的PE文件缓冲区
DWORD RvaToOffset(DWORD dwRva, char * buffer)// 计算偏移的函数,将RVA转化成偏移
{
//解析Dos头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE头
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//区段表
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
//判断是否落在了头部当中
if (dwRva