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.pswp.cn/bicheng/81437.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81437.shtml
英文地址,請注明出處:http://en.pswp.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…