C实现PE结构解析
其实就是照着PE结构图抄过来,定义结构体,用结构体指针访问,挨个打印出来。
这里随便用了个植物大战僵尸的PE文件(导出表是用的游戏的dll)。
Loader.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef char BYTE;
typedef short WORD;
typedef int DWORD;
struct IMAGE_RESOURCE_DATA
{
DWORD VirtualAddress;
DWORD Size;
};
struct IMAGE_RESOURCE_DIRECTORY_ENTRY
{
union
{
struct
{
DWORD NameOffset : 31; //目录项名称或者ID
DWORD NameIsString : 1;
};
DWORD Name;
WORD Id;
};
union
{
DWORD OffsetToData;
struct
{
DWORD OffsetToDirectory : 31; //目录项指针,不是rva
DWORD DataIsDirectory : 1;
};
};
};
struct IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
};
struct PIMAGE_IMPORT_BY_NAME
{
WORD Hint;
BYTE Name;
};
struct PIMAGE_THUNK_DATA
{
union
{
BYTE ForwarderString;
DWORD Function;
DWORD Ordinal;
PIMAGE_IMPORT_BY_NAME AddressOfData;
};
};
struct IMAGE_IMPORT_DESCRIPTOR
{
union
{
DWORD Characteristics;
PIMAGE_THUNK_DATA OriginalFirstThunk;
}u;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
PIMAGE_THUNK_DATA FirstThunk;
};
struct IMAGE_DIRECTORY_ENTRY_BASERELOC {
DWORD VirtualAddress;
DWORD Size;
};
struct IMAGE_SECTION_HEADER
{
BYTE Name[8];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
};
struct IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions;
DWORD AddressOfNames;
DWORD AddressOfNameOrdinals;
};
struct IMAGE_DATA_DIRECTORY
{
DWORD VirtualAddress;
DWORD Size;
};
struct IMAGE_DOS_HEADER
{
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
DWORD e_lfanew;
};
struct IMAGE_FILE_HEADER
{
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
};
struct IMAGE_OPTIONAL_HEADER
{
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
};
struct IMAGE_NT_HEADERS
{
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
};
void* OpenFile();
void PrintPEStructs();
void PrintPeHeaders();
int RVAToFOA(int RVA);
int RTF(int Rva);
void ExportTables();
void Relocation();
void ImportTable();
void ResourceTable();
Loader.cpp:
#include "Loader.h"
//打开文件,分配内存,获取指针
void* OpenFile()
{
char arr[] = "D:\\PlantsVsZombies.exe";
FILE* FileOpen = fopen(arr, "rb");
if (!FileOpen)
{
printf("打开文件失败");
return NULL;
}
fseek(FileOpen, 0, SEEK_END);
int FileSize = ftell(FileOpen);
fseek(FileOpen, 0, SEEK_SET);
void* FileBuffer = malloc(FileSize);
if (!FileBuffer)
{
printf("分配内存失败");
return NULL;
}
size_t n = fread(FileBuffer, FileSize, 1, FileOpen);
if (!n)
{
printf("加载到内存失败");
free(FileBuffer);
fclose(FileOpen);
return NULL;
}
fclose(FileOpen);
return FileBuffer;
}
//打印PE头相关信息
char* pBegin = (char*)OpenFile();
IMAGE_DOS_HEADER* DOS_Header = (IMAGE_DOS_HEADER*)pBegin;
int e_lfanew = DOS_Header->e_lfanew;
IMAGE_NT_HEADERS* NT_Header = (IMAGE_NT_HEADERS*)(pBegin + e_lfanew);
IMAGE_DATA_DIRECTORY* datadirectory = (IMAGE_DATA_DIRECTORY*)NT_Header->OptionalHeader.DataDirectory;
WORD SizeOfOptionalHeaders = NT_Header->FileHeader.SizeOfOptionalHeader;
IMAGE_SECTION_HEADER* Sec