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头信息
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径

融智学视域下的系统性认知增强框架 ——基于文理工三类AI助理赋能HI四阶跃迁路径 一、如何排除50个认知偏差&#xff1a;消除50类偏差的精准矫正系统 1. 技术架构 文科AI&#xff1a; 构建文化语义场&#xff08;Cultural Semantic Field, CSF&#xff09;&#xff0c;通过…

MMDetection环境安装配置

MMDetection 支持在 Linux&#xff0c;Windows 和 macOS 上运行。它需要 Python 3.7 以上&#xff0c;CUDA 9.2 以上和 PyTorch 1.8 及其以上。 MMDetection 至今也一直更新很多个版本了&#xff0c;但是对于最新的pytorch版本仍然不支持&#xff0c;我安装的时候仍然多次遇到m…

如何实现k8s高可用

一、控制平面高可用设计 多主节点部署 • API Server 冗余&#xff1a;部署至少 3 个 Master 节点&#xff0c;每个节点运行独立的 API Server&#xff0c;通过负载均衡器&#xff08;如 Nginx、HAProxy、云厂商 LB&#xff09;对外提供统一入口。 • 选举机制&#xff1a;Sche…

记录心态和工作变化

忙中带闲的工作 其实工作挺忙的, 总是在赶各种功能点. 好巧的是iOS那边因为上架的问题耽搁了一些时间, 从而让Android的进度有了很大的调整空间. 更巧的是后端那边因为对客户端的需求不是很熟悉, 加上Android海外这块的业务他也是第一次接触. 所以需要给他留一些时间把各个环节…

JVM 双亲委派机制

一、从 JDK 到 JVM&#xff1a;Java 运行环境的基石 在 Java 开发领域&#xff0c;JDK&#xff08;Java Development Kit&#xff09;是开发者的核心工具包。它不仅包含了编译 Java 代码的工具&#xff08;如 javac&#xff09;&#xff0c;还内置了 JRE&#xff08;Java Run…

java开发之异常

一 结构 Throwable分为Exception和error Exception分为RuntimeException&#xff08;运行时异常&#xff09;和其他异常 主动抛出运行时异常和非运行时异常的区别 1、throw RuntimeException&#xff08;或运行时异常的子类&#xff09; 编译时不会报错。 2、throw Excepti…

MySQL 中 JOIN 和子查询的区别与使用场景

目录 一、JOIN:表连接1.1 INNER JOIN:内连接1.2 LEFT JOIN:左连接1.3 RIGHT JOIN:右连接1.4 FULL JOIN:全连接二、子查询:嵌套查询2.1 WHERE 子句中的子查询2.2 FROM 子句中的子查询2.3 SELECT 子句中的子查询三、JOIN 和子查询的区别3.1 功能差异3.2 性能差异3.3 使用场…

2025年第三届盘古石杯初赛(智能冰箱,监控部分)

前言 所以去哪里可以取到自己家里的智能家居数据呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; IOT物联网取证 1、分析冰箱&#xff0c;请问智能冰箱的品牌&#xff1f; [答案格式&#xff1a;xiaomi] Panasonic2、请问智能冰箱的型号&#xff1f; [答案格式&#x…

【强化学习】强化学习算法 - 马尔可夫决策过程

文章目录 马尔可夫决策过程 (Markov Decision Process, MDP)1. MDP 原理介绍2. MDP 建模/实现步骤3. MDP 示例&#xff1a;简单网格世界 (Grid World) 马尔可夫决策过程 (Markov Decision Process, MDP) 1. MDP 原理介绍 马尔可夫决策过程 (MDP) 是强化学习 (Reinforcement L…

用户现场不支持路由映射,如何快速将安防监控EasyCVR视频汇聚平台映射到公网?

一、方案背景​ 随着数字化安防与智能交通管理发展&#xff0c;视频监控远程管理需求激增。EasyCVR作为专业视频融合平台&#xff0c;具备多协议接入等核心功能&#xff0c;是智能监控的重要工具。但实际部署中&#xff0c;当EasyCVR处于内网且路由器无法进行端口映射时&#…

MODBUS RTU调试助手使用方法详解

一、软件简介 485调试助手是一款常用的串口通信调试工具&#xff0c;专门用于RS-485总线设备的测试、调试和通信监控。它支持多种串口参数设置&#xff0c;提供数据收发功能&#xff0c;是工业现场调试的必备工具之一。 二、软件安装与启动 1. 系统要求 Windows 7/10/11操作…

ECMAScript 2018(ES2018):异步编程与正则表达式的深度进化

1.版本背景与发布 发布时间&#xff1a;2018年6月&#xff0c;由ECMA International正式发布&#xff0c;标准编号为ECMA-262 9th Edition。历史意义&#xff1a;作为ES6之后的第三次年度更新&#xff0c;ES2018聚焦于异步编程、正则表达式和对象操作的标准化&#xff0c;推动…

【C语言】链接与编译(编译环境 )

前言&#xff1a; 在前面讲解文件操作&#xff0c;了解了文件的类别&#xff0c;文件的打开与关闭&#xff0c;字符读写函数&#xff0c; 字符串读写函数&#xff0c;格式化输入输出函数 在C语言编程中&#xff0c;编译与链接是将源代码转化为可执行程序的关键步骤。为了详细…

Java视频流RTMP/RTSP协议解析与实战代码

在Java中实现视频直播的输入流处理&#xff0c;通常需要结合网络编程、多媒体处理库以及流媒体协议&#xff08;如RTMP、HLS、RTSP等&#xff09;。以下是实现视频直播输入流的关键步骤和技术要点&#xff1a; 1. 视频直播输入流的核心组件 网络输入流&#xff1a;通过Socket或…

系分论文《论系统需求分析方法及应用》

系统分析师论文范文系列 【摘要】 2022年6月&#xff0c;我作为系统分析师参与了某金融机构“智能信贷风控系统”的建设项目。该系统旨在通过对业务流程的数字化重构&#xff0c;优化信贷审批效率并降低风险。项目涉及信贷申请、资质审核、风险评估、额度审批等核心流程&#x…

stack和queue简单模拟实现

stackreverse_iteratorqueuepriority_queue仿函数具体代码 stack Stacks are a type of container adaptor, specifically designed to operate in a LIFO context (last-in first-out), where elements are inserted and extracted only from one end of the container. 上述描…

Linux内核可配置的参数

sysctl -a 命令会列出当前Linux内核所有可配置的参数及其当前值。这些参数允许你在系统运行时动态地调整内核的行为&#xff0c;而无需重新编译内核或重启系统。 内容非常多&#xff0c;因为内核有很多可调的方面。我们可以把它们大致分为几个主要类别&#xff1a; kernel.*: …

【背包dp-----分组背包】------(标准的分组背包【可以不装满的 最大价值】)

通天之分组背包 题目链接 题目描述 自 01 01 01 背包问世之后&#xff0c;小 A 对此深感兴趣。一天&#xff0c;小 A 去远游&#xff0c;却发现他的背包不同于 01 01 01 背包&#xff0c;他的物品大致可分为 k k k 组&#xff0c;每组中的物品相互冲突&#xff0c;现在&a…

操作系统:os概述

操作系统&#xff1a;OS概述 程序、进程与线程无极二级目录三级目录 程序、进程与线程 指令执行需要那些条件&#xff1f;CPU内存 需要数据和 无极 二级目录 三级目录

RAG文本分块

不论是向量化模型还是大语言模型&#xff0c;都存在输入长度的限制。对于超过限制的文本&#xff0c;模型会进行截断&#xff0c;造成语义缺失。分块可以确保每个文本片段都在模型的处理范围内&#xff0c;避免重要信息的丢失。 文本分块的核心原则 高质量分块的核心原则是&a…