pe文件二进制解析(用c/c++解析一个二进制pe文件)
pe文件二进制解析
c++解析pe文件控制台版本
#include<iostream>
#include<windows.h>
#include<vector>/*RVA(相对虚拟地址)与FOA(文件偏移地址)的转换1.得到 的值:内存地址 - ImageBase2.判断是否位于PE头中,如果是:FOV = RVA3.判断RVA位于哪个节:RVA >= 节.VirtualAddressRVA <= 节.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 StorageIMAGE_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转foaDWORD 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);// 判断最高位是否为1if ((OriginalFirstThunkIAT->u1.Ordinal & 0x80000000) != TRUE) {DWORD IATRav = rvaToFoa(OriginalFirstThunkIAT->u1.Ordinal); // IMAGE_IMPORT_BY_NAMEPIMAGE_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头信息