pe文件二进制解析
c++解析pe文件控制台版本
#include<iostream>
#include<windows.h>
#include<vector>
/*
RVA(相对虚拟地址)与FOA(文件偏移地址)的转换
1.得到 的值:内存地址 - ImageBase
2.判断是否位于PE头中,如果是:FOV = RVA
3.判断RVA位于哪个节:
RVA >= 节.VirtualAddress
RVA <= 节.VirtualAddress + 当前节内存对齐后的大小
差值 = RVA - 节.VirtualAddress
*/
using namespace std;
// 定义一个存放节表数据的结构体
typedef struct SectionTable {
// 在虚拟内存中的地址
DWORD myVirtualAddress;
// 在文件中的偏移
DWORD myPointerToRawData;
}SECTION_TABLE, * PSECTION_TABLE;
// 基本数据结构体
typedef struct BaseData {
ULONGLONG myImageBase;
DWORD mySectionAlignment;
DWORD myFileAlignment;
}BASE_DATA, * PBASE_DATA;
// 表地址结构体
typedef struct TableAddress {
DWORD myVirtualAddress;
DWORD mySize;
}TABLE_ADDRESS, * PTABLE_ADDRESS;
// 创建一个全局的节表数组和表地址数组
vector<SectionTable> g_sectionTable;
vector<TableAddress> g_tableAddress;
// 全局的基本数据
BaseData g_baseData;
// 节的数量
WORD NumberOfSections = 0;
// 文件对齐和内存对齐是否一致
BOOL FILE_EQUALS_MEMORY = TRUE;
// 获取标准pe文件头信息
void getStandardPeHeaderAttribute(IMAGE_FILE_HEADER standardPeHeader);
// 获取扩展pe文件头信息
void getExtendPeHeaderAttribute(IMAGE_OPTIONAL_HEADER extendPeHeader);
// 获取数据目录信息
void getDataDirectoryInfo(const IMAGE_DATA_DIRECTORY* dataDirectory);
// 获取节表信息并把值放入数组中
void getSectionHerader(PIMAGE_SECTION_HEADER sectionHerader, IMAGE_FILE_HEADER standardPeHeader);
// RVA 转 FOA
DWORD rvaToFoa(DWORD address);
// 获取导出表
void getExportsInfo(const char* peFileBuffer);
// 获取导入表
void getImportsInfo(const char* peFileBuffer);
// 获取重定位表
void getRepositionInfo(const char* peFileBuffer);
int main() {
// 判断是否是PE文件
HANDLE hPeFile = CreateFile(L"C://Users//BananaLi//Desktop//mydll.dll",
GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hPeFile != INVALID_HANDLE_VALUE) { // 文件打开成功
// 得到文件大小
DWORD peFileSize = GetFileSize(hPeFile, NULL);
printf("文件大小为:%d 字节\n", peFileSize);
// 读文件
char* peFileBuffer = new char[peFileSize] {0};
if (ReadFile(hPeFile, peFileBuffer, peFileSize, NULL, NULL)) {
// 讲读取到的文件内容转换为IMAGE_DOS_HEADER结构体
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)peFileBuffer;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
cout << "该文件不是PE文件\n";
exit(0);
}
else
{
// 解析头文件
printf("PE文件头:0x%X\n", pDosHeader->e_magic);
printf("PE文件偏移:0x%X\n", pDosHeader->e_lfanew);
// 获取nt头
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(peFileBuffer + pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE){
cout << "该文件不是PE文件\n";
exit(0);
}
else
{
// 获取标准pe头
printf("PE头标识:0x%X\n", pNtHeader->Signature);
IMAGE_FILE_HEADER standardPeHeader = pNtHeader->FileHeader;
printf("标准PE头大小:%lld 字节\n",sizeof(standardPeHeader));
getStandardPeHeaderAttribute(standardPeHeader);
// 获取扩展pe头
IMAGE_OPTIONAL_HEADER extendPeHeader = pNtHeader->OptionalHeader;
printf("扩展PE头大小:%lld 字节\n", sizeof(extendPeHeader));
getExtendPeHeaderAttribute(extendPeHeader);
// 获取节表的数据
PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)(peFileBuffer + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
printf("节表的大小:%d 字节\n", standardPeHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER);
// 获取节表范围数据
getSectionHerader(sectionHeader, standardPeHeader);
// 获取导出表的数据
getExportsInfo(peFileBuffer);
// 获取导入表的数据
getImportsInfo(peFileBuffer);
// 获取重定位表的数据
getRepositionInfo(peFileBuffer);
}
}
}
delete[] peFileBuffer; // 回收
}
else {
cout << "文件打开失败,请检查文件是否存在\n";
}
system("pause");
return 0;
}
void getStandardPeHeaderAttribute(IMAGE_FILE_HEADER standardPeHeader) {
cout << "标准PE头信息如下:\n";
printf("可以运行在什么样的CPU上:0x%X\n", standardPeHeader.Machine);
printf("节的数量:%d\n", standardPeHeader.NumberOfSections);
printf("编译器填写的时间戳:%d\n", standardPeHeader.TimeDateStamp);
printf("调试相关:0x%X\n", standardPeHeader.PointerToSymbolTable);
printf("调试相关:0x%X\n", standardPeHeader.NumberOfSymbols);
printf("可选PE头的大小(32位PE文件:0xE0 , 64位PE文件:0xF0):0x%X\n", standardPeHeader.SizeOfOptionalHeader);
printf("文件属性:0x%X\n", standardPeHeader.Characteristics);
// TODO 后续添加文件属性解析
}
void getExtendPeHeaderAttribute(IMAGE_OPTIONAL_HEADER extendPeHeader) {
cout << "扩展PE头信息如下:\n";
printf("Magic(10B就是32位,20B就是64位的应用程序):0x%X\n", extendPeHeader.Magic);
printf("链接器版本号:0x%X\n", extendPeHeader.MajorLinkerVersion);
printf("链接器版本号:0x%X\n", extendPeHeader.MinorLinkerVersion);
printf("所有代码节的总和(文件对齐后的大小 *编译器填写无实际作用):0x%X\n", extendPeHeader.SizeOfCode);
printf("包含所有已经初始化数据的节的部大小(文件对齐后的大小 *编译器填写无实际作用):0x%X\n", extendPeHeader.SizeOfInitializedData);
printf("包含未初始化数据的节的总大小(文件对齐后的大小 *编译器填写无实际作用):0x%X\n", extendPeHeader.SizeOfUninitializedData);
printf("程序入口(重要):0x%X\n", extendPeHeader.AddressOfEntryPoint);
printf("代码开始的基地(*编译器填写无实际作用):0x%X\n", extendPeHeader.BaseOfCode);
printf("内存镜像基地(重要):0x%llX\n", extendPeHeader.ImageBase);
g_baseData.myImageBase = extendPeHeader.ImageBase;
printf("内存对齐(重要):0x%X\n", extendPeHeader.SectionAlignment);
g_baseData.mySectionAlignment = extendPeHeader.SectionAlignment;
printf("文件对齐(重要):0x%X\n", extendPeHeader.FileAlignment);
g_baseData.myFileAlignment = extendPeHeader.FileAlignment;
printf("标识操作系统版本号(主版本号):0x%X\n", extendPeHeader.MajorOperatingSystemVersion);
printf("标识操作系统版本号(次版本号):0x%X\n", extendPeHeader.MinorOperatingSystemVersion);
printf("PE文件自身的版本号(主版本号):0x%X\n", extendPeHeader.MajorImageVersion);
printf("PE文件自身的版本号(次版本号):0x%X\n", extendPeHeader.MinorImageVersion);
printf("运行所所需子系统版本号(主版本号):0x%X\n", extendPeHeader.MajorSubsystemVersion);
printf("运行所所需子系统版本号(次版本号):0x%X\n", extendPeHeader.MinorSubsystemVersion);
printf("子系统版本的值必须为0:0x%X\n", extendPeHeader.Win32VersionValue);
printf("内存中整个PE文件的映射的尺寸,可比实际的值大,必须是SectionAlignment的整数倍:0x%X\n", extendPeHeader.SizeOfImage);
printf("所有头+节表按照文件对齐后的大小,否则加载会出错:0x%X\n", extendPeHeader.SizeOfHeaders);
printf("核验和,一些系统文件有要求,用来判断文件是否被修改:0x%X\n", extendPeHeader.CheckSum);
printf("子系统 (驱动程序1 图形界面2 控制台,DLL3 ):0x%X\n", extendPeHeader.Subsystem);
printf("文件特性 不是针对DLL文件的:0x%X\n", extendPeHeader.DllCharacteristics);
printf("初始化时保留的栈大小:0x%llX\n", extendPeHeader.SizeOfStackReserve);
printf("初始化时实际提交的大小:0x%llX\n", extendPeHeader.SizeOfStackCommit);
printf("初始化时保留的堆大小:0x%llX\n", extendPeHeader.SizeOfHeapReserve);
printf("初始化时实践提交的大小:0x%llX\n", extendPeHeader.SizeOfHeapCommit);
printf("调试相关:0x%X\n", extendPeHeader.LoaderFlags);
printf("目录项数目:0x%X\n", extendPeHeader.NumberOfRvaAndSizes);
printf("数据目录大小:%lld\n", sizeof(extendPeHeader.DataDirectory));
// TODO DllCharacteristics属性解析
// 判断文件对齐和内存对齐是否一致
if (extendPeHeader.SectionAlignment != extendPeHeader.FileAlignment) FILE_EQUALS_MEMORY = FALSE;
IMAGE_DATA_DIRECTORY *dataDirectory = extendPeHeader.DataDirectory;
// TODO IMAGE_DATA_DIRECTORY属性解析
getDataDirectoryInfo(dataDirectory);
}
void getDataDirectoryInfo(const IMAGE_DATA_DIRECTORY* dataDirectory) {
for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
TableAddress tableAddress;
switch (i)
{
case 0 :printf("1.导出表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 1 :printf("2.导入表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 2 :printf("3.资源表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 3 :printf("4.异常处理表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 4 :printf("5.安全目录:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 5 :printf("6.基址重定位表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 6 :printf("7.调试目录:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 7 :printf("8.架构特定数据:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 8 :printf("9.全局指针表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 9 :printf("10.线程局部存储表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 10 :printf("11.加载配置表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 11 :printf("12.绑定导入表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 12 :printf("13.导入地址表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 13 :printf("14.延迟导入表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 14 :printf("15.COM描符表:\n");
printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);
tableAddress.myVirtualAddress = dataDirectory[i].VirtualAddress;
tableAddress.mySize = dataDirectory[i].Size;
g_tableAddress.push_back(tableAddress);
break;
case 15 :printf("16.保留(目前未使用)\n");
/*printf("VirtualAddress:0x%X\n", dataDirectory[i].VirtualAddress);
printf("VirtualSize:0x%X\n", dataDirectory[i].Size);*/
break;
default:
break;
}
}
/*
一共有十六个IMAGE_DATA_DIRECTORYENDS结构
IMAGE_DIRECTORY_ENTRY_EXPORT 导出表
IMAGE_DIRECTORY_ENTRY_IMPORT 导入表
IMAGE_DIRECTORY_ENTRY_RESOURCE 资源
IMAGE_DIRECTORY_ENTRY_EXCEPTION 异常(具体资料不详)
IMAGE_DIRECTORY_ENTRY_SECURITY 安全(具体资料不详)
IMAGE_DIRECTORY_ENTRY_BASERELOC 重定位表
IMAGE_DIRECTORY_ENTRY_DEBUG 调试信息
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 版权信息
IMAGE_DIRECTORY_ENTRY_GLOBALPTR 具体资料不详
IMAGE_DIRECTORY_ENTRY_TLS Thread Local Storage
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 具体资料不详
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 具体资料不详
IMAGE_DIRECTORY_ENTRY_IAT 导入函数地址表
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 具体资料不详
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 具体资料不详
未使用保留
*/
}
void getSectionHerader(PIMAGE_SECTION_HEADER sectionHerader, IMAGE_FILE_HEADER standardPeHeader) {
cout << "节表信息如下:\n";
// 获取节表的个数
WORD sectionTableNum = standardPeHeader.NumberOfSections;
for (int i = 0; i < sectionTableNum; i++) {
SectionTable mySectionTable;
printf("节表的名称:%s\n", sectionHerader->Name);
printf("节没有对齐时的大小(可以不准确):0x%X\n", sectionHerader->Misc);
printf("在内存中的偏移地址,加上ImageBase才是内存中的真正地址:0x%X\n", sectionHerader->VirtualAddress);
mySectionTable.myVirtualAddress = sectionHerader->VirtualAddress;
printf("节在文件中对齐后的尺寸:0x%X\n", sectionHerader->SizeOfRawData);
printf("节在文件中的偏移:0x%X\n", sectionHerader->PointerToRawData);
mySectionTable.myPointerToRawData = sectionHerader->PointerToRawData;
g_sectionTable.push_back(mySectionTable);
printf("调用相关:0x%X\n", sectionHerader->PointerToRelocations);
printf("调用相关:0x%X\n", sectionHerader->PointerToLinenumbers);
printf("调用相关:0x%X\n", sectionHerader->NumberOfRelocations);
printf("调用相关:0x%X\n", sectionHerader->NumberOfLinenumbers);
printf("节的属性:0x%X\n", sectionHerader->Characteristics);
sectionHerader++; // 每次加一个节表结构体
}
}
// Rva -> FOA
DWORD rvaToFoa(DWORD address) {
for (int i = 0; i < g_sectionTable.size() - 1; i++) {
if (address >= g_sectionTable[i].myVirtualAddress && address < g_sectionTable[i + 1].myVirtualAddress) {
// 节上的偏移
DWORD offsetAddress = address - g_sectionTable[i].myVirtualAddress;
// 节上的偏移加上节在文件的偏移 = 节在文件上的位置
return g_sectionTable[i].myPointerToRawData + offsetAddress;
}
// 判断最后一个节
if (address == g_sectionTable[i + 1].myVirtualAddress) {
// 节上的偏移
DWORD offsetAddress = address - g_sectionTable[i + 1].myVirtualAddress;
// 节上的偏移加上节在文件的偏移 = 节在文件上的位置
return g_sectionTable[i + 1].myPointerToRawData + offsetAddress;
}
}
}
// 获取导出表
void getExportsInfo(const char* peFileBuffer) {
//IMAGE_EXPORT_DIRECTORY exportDirectory;
if (FILE_EQUALS_MEMORY) {
// 文件对齐跟内存对齐一样不需要做处理
}
else {
TableAddress exportAddress = g_tableAddress[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (exportAddress.myVirtualAddress == 0) {
// 当前程序不存在导出表
return;
}
DWORD fileAddress = rvaToFoa(exportAddress.myVirtualAddress);
// 这里指向导出表的结构体
PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(peFileBuffer + fileAddress);
// 获取所有导出的函数个数
DWORD exportCount = exportDirectory->NumberOfFunctions;
// 获取函数名导出的函数个数
DWORD nameCount = exportDirectory->NumberOfNames;
printf("Characteristics(未使用):0x%X\n", exportDirectory->Characteristics);
printf("TimeDateStamp(时间戳):0x%X\n", exportDirectory->TimeDateStamp);
printf("MajorVersion(未使用):0x%X\n", exportDirectory->MajorVersion);
printf("MinorVersion(未使用):0x%X\n", exportDirectory->MinorVersion);
printf("Name(指向该导出表文件名字符串):%s\n", peFileBuffer + rvaToFoa(exportDirectory->Name));
printf("Base(导出函数起始序号):0x%X\n", exportDirectory->Base);
printf("NumberOfFunctions(所有导出函数的个数):%d\n", exportCount);
printf("NumberOfNames(以函数名导出的函数个数):%d\n", nameCount);
printf("AddressOfFunctions(导出函数地址表 重要):0x%X\n", exportDirectory->AddressOfFunctions);
printf("AddressOfNames(导出函数名称表 重要):0x%X\n", exportDirectory->AddressOfNames);
printf("AddressOfNameOrdinals(导出函数序号表 重要):0x%X\n", exportDirectory->AddressOfNameOrdinals);
//printf("AddressOfFunctions地址:0x%X\n", rvaToFoa(exportDirectory->AddressOfFunctions));
//printf("AddressOfNames地址:0x%X\n", rvaToFoa(exportDirectory->AddressOfNames));
//printf("AddressOfNameOrdinals地址:0x%X\n", rvaToFoa(exportDirectory->AddressOfNameOrdinals));
// 读取函数地址表
DWORD addressFuncFoa = rvaToFoa(exportDirectory->AddressOfFunctions);
for (int i = 0; i < exportCount; i++) {
// 打印函数地址
DWORD* tempAddress = (DWORD*)(peFileBuffer + addressFuncFoa);
printf("第%d个函数地址为:0x%X\n", i, rvaToFoa(*(tempAddress + i)));
}
// 读取函数名称表
DWORD nameFuncFoa = rvaToFoa(exportDirectory->AddressOfNames);
for (int i = 0; i < nameCount; i++) {
DWORD* tempName = (DWORD*)(peFileBuffer + nameFuncFoa);
printf("第%d个函数名称为:%s\n", i, peFileBuffer + rvaToFoa(*(tempName + i)));
}
}
}
// 获取导入表
void getImportsInfo(const char* peFileBuffer) {
if (FILE_EQUALS_MEMORY) {
// TODO 文件对齐跟内存对齐一样不需要做处理
}
else {
int importCount = 0;
TableAddress ImportAddress = g_tableAddress[IMAGE_DIRECTORY_ENTRY_IMPORT];
// rva转foa
DWORD fileAddress = rvaToFoa(ImportAddress.myVirtualAddress);
// 这里指向导入表的结构体
PIMAGE_IMPORT_DESCRIPTOR importDirectory = (PIMAGE_IMPORT_DESCRIPTOR)(peFileBuffer + fileAddress);
// 遍历导入表
while (importDirectory->Name != 0) {
int iatCount = 1;
char * dllName = (char*)(peFileBuffer + rvaToFoa(importDirectory->Name));
printf("对应导入表名称:%s\n", dllName);
printf("OriginalFirstThunk对应导入表的INT地址和使用的方法:0x%X\n", rvaToFoa(importDirectory->OriginalFirstThunk));
PIMAGE_THUNK_DATA OriginalFirstThunkIAT = (PIMAGE_THUNK_DATA)(peFileBuffer + rvaToFoa(importDirectory->OriginalFirstThunk));
// reinterpret_cast c++ 推荐使用
//PIMAGE_THUNK_DATA OriginalFirstThunkIAT = reinterpret_cast<PIMAGE_THUNK_DATA>(peFileBuffer + rvaToFoa(importDirectory->OriginalFirstThunk));
// 遍历INT表,有多少个PIMAGE_THUNK_DATA结构体就表示有多少个导入函数
while (OriginalFirstThunkIAT->u1.Ordinal != 0 || OriginalFirstThunkIAT->u1.AddressOfData != 0) {
//printf("%d.%s对应导入表的INT:0x%X\n", iatCount, dllName, OriginalFirstThunkIAT->u1.Ordinal);
// 判断最高位是否为1
if ((OriginalFirstThunkIAT->u1.Ordinal & 0x80000000) != TRUE) {
DWORD IATRav = rvaToFoa(OriginalFirstThunkIAT->u1.Ordinal); // IMAGE_IMPORT_BY_NAME
PIMAGE_IMPORT_BY_NAME dllImport = (PIMAGE_IMPORT_BY_NAME)(peFileBuffer + IATRav);
printf("Hint:%d\n", dllImport->Hint);
printf("Name:%s\n", dllImport->Name);
}
else {
// TODO 最高位为1,解析导出序号,通过通过序号来获取导入函数
}
OriginalFirstThunkIAT++;
iatCount++;
}
//printf("FirstThunk对应导入表的IAT:0x%X\n", rvaToFoa(importDirectory->FirstThunk));
importDirectory++;
importCount++;
}
}
}
// 获取重定位表
void getRepositionInfo(const char* peFileBuffer) {
// 获取重定位表地址
TableAddress repositionAddress = g_tableAddress[IMAGE_DIRECTORY_ENTRY_BASERELOC];
// 得到文件地址
DWORD fileAddress = rvaToFoa(repositionAddress.myVirtualAddress);
// 解析结构体
PIMAGE_BASE_RELOCATION relocationDirectory = (PIMAGE_BASE_RELOCATION)(peFileBuffer + fileAddress);
DWORD size = 0;
while (true) {
// 重新计算重定位表地址
PIMAGE_BASE_RELOCATION relocationDirectory = (PIMAGE_BASE_RELOCATION)(peFileBuffer + fileAddress + size);
if (relocationDirectory->VirtualAddress == 0 && relocationDirectory->SizeOfBlock == 0) {
// 定位表结束
break;
}
// 定位偏移地址位置
WORD* relocation = (WORD*)(peFileBuffer + fileAddress + size + sizeof(IMAGE_BASE_RELOCATION));
// 解析重定位表地址偏移
for (int i = 0; i < (relocationDirectory->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); i++) {
printf("relocation:0x%X \n", *relocation);
// 提取高4位 重定位类型
WORD type = (*relocation >> 12) & 0xF;
// 提取低12位 偏移量
WORD offset = *relocation & 0xFFF;
printf("type:0x%X \n", type);
printf("offset:0x%X \n", offset);
relocation++;
}
printf("VirtualAddress:0x%X \n", relocationDirectory->VirtualAddress);
printf("SizeOfBlock:%d 字节 \n", relocationDirectory->SizeOfBlock);
size += relocationDirectory->SizeOfBlock;
}
}
解析信息
重定位表信息
节表信息
导出方法和导入方法
16张表地址和大小
pe头信息,标准pe头信息,扩展pe头信息