步驟解讀
- 先選擇文件
- 讀取文件二進制流
- 從二進制流讀取
DOS頭(DOS_HEADER)
,長度64字節 - 讀取
DOS殼(DOS_STUB)
,DOS頭開始,長度至到dosHeader->e_lfanew偏移量 - 讀取
PE標識(Signature)
,e_lfanew偏移量開始,長度4字節 - 讀取
PE文件頭(FILE_HEADER)
,PE標識開始,長度20字節 - 讀取
PE可選頭(OPTIONAL_HEADER)
,PE文件頭開始,長度peHeader->sizeOfOptionalHeader
直接上代碼
代碼中只解析了重要信息
#include<iostream>
#include<windows.h>using namespace std;BOOL selectFile(char* filePath) {OPENFILENAMEA ofn;char filename[MAX_PATH];ZeroMemory(&ofn, sizeof(ofn));ofn.lStructSize = sizeof(ofn);ofn.hwndOwner = NULL;ofn.lpstrFilter = "ALL Files\0*.*\0";ofn.lpstrFile = filename;ofn.nMaxFile = sizeof(filename);ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;ofn.lpstrFile[0] = '\0';if (GetOpenFileNameA(&ofn) == TRUE) {//MessageBoxA(NULL, filename, "提示", MB_OK);strcpy_s(filePath,MAX_PATH,filename);return TRUE;}return FALSE;
}int main() {char filePath[MAX_PATH];if (selectFile(filePath)) {//打開文件HANDLE hfile = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);//根據文件句柄獲取文件大小DWORD fileSize = GetFileSize(hfile,NULL);//文件流緩沖區char* fileBuffer = new char[fileSize];//實際接收字節數DWORD realRead = 0;//讀取文件if (ReadFile(hfile, fileBuffer, fileSize, &realRead, NULL)) {WORD e_magic = *(WORD*)fileBuffer; //MZ標識DWORD e_lfanew = *(DWORD*)(fileBuffer + 60); //NT頭偏移量printf("e_magic:%04X\n", e_magic);printf("e_lfanew:%08X\n", e_lfanew);printf("\n");DWORD Signatrue = *(DWORD*)(fileBuffer + e_lfanew); //PE標識printf("Siganture:%08X\n", Signatrue);printf("\n");WORD Machine = *(WORD*)(fileBuffer + e_lfanew + 0x04); //運行平臺WORD NumberOfSections = *(WORD*)(fileBuffer + e_lfanew + 0x06); //區段數量DWORD TimeDateStamp = *(DWORD*)(fileBuffer + e_lfanew + 0x08); //區段數量WORD SizeOfOptionHeader = *(WORD*)(fileBuffer + e_lfanew + 0x14); //可選頭大小WORD Characteristics = *(WORD*)(fileBuffer + e_lfanew + 0x16); //特征printf("Machine:%04X\n", Machine);printf("NumberOfSections:%04X\n", NumberOfSections);printf("TimeDateStamp:%04X\n", TimeDateStamp);printf("SizeOfOptionHeader:%04X\n", SizeOfOptionHeader);printf("Characteristics.EXECUTABLE_IMAGE:%d\n", Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE); //是否是可執行文件printf("Characteristics.IMAGE_FILE_LINE_NUMS_STRIPPED:%d\n", Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED); //文件中不包含行號信息。printf("Characteristics.IMAGE_FILE_LOCAL_SYMS_STRIPPED:%d\n", Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED); //文件中不包含局部符號。printf("Characteristics.IMAGE_FILE_32BIT_MACHINE:%d\n", Characteristics & IMAGE_FILE_32BIT_MACHINE); //目標平臺是32位。printf("Characteristics.IMAGE_FILE_DEBUG_STRIPPED:%d\n", Characteristics & IMAGE_FILE_DEBUG_STRIPPED); //調試信息被移除。printf("Characteristics.IMAGE_FILE_SYSTEM:%d\n", Characteristics & IMAGE_FILE_SYSTEM); //文件是系統文件。printf("Characteristics.IMAGE_FILE_DLL:%d\n", Characteristics & IMAGE_FILE_DLL); //文件是dll文件。printf("\n");WORD Magic = *(WORD*)(fileBuffer + e_lfanew + 0x18); //0x10B是32位,0x20B是64位DWORD AddressOfEntryPoint = *(DWORD*)(fileBuffer + e_lfanew + 0x28); //OEP程序入口偏移量DWORD ImageBase = *(DWORD*)(fileBuffer + e_lfanew + 0x34); //程序入口,固定值+偏移量DWORD SectionAlignment = *(DWORD*)(fileBuffer + e_lfanew + 0x38); //內存對齊大小DWORD FileAlignment = *(DWORD*)(fileBuffer + e_lfanew + 0x3C); //文件對齊大小DWORD SizeOfIamge = *(DWORD*)(fileBuffer + e_lfanew + 0x50); //文件在內存中的大小,按SectionAlignment對齊后的大小DWORD SizeOfHeaders = *(DWORD*)(fileBuffer + e_lfanew + 0x54); //DOS,NT,PE,可選PE+區段 各種頭加一塊,按照FileAlignment對齊后的大小DWORD NumberOfRvaAndSizes = *(DWORD*)(fileBuffer + e_lfanew + 0x74); //數據目錄表的個數printf("Magic:%04X\n", Magic);printf("AddressOfEntryPoint:%08X\n", AddressOfEntryPoint);printf("ImageBase:%08X\n", ImageBase);printf("SectionAlignment:%08X\n", SectionAlignment);printf("FileAlignment:%08X\n", FileAlignment);printf("SizeOfIamge:%08X\n", SizeOfIamge);printf("SizeOfHeaders:%08X\n", SizeOfHeaders);printf("NumberOfRvaAndSizes:%08X\n", NumberOfRvaAndSizes);CloseHandle(hfile);}else {int errcode = GetLastError();cout << "文件讀取失敗:"<< errcode << endl;}}else {cout << "文件選擇失敗。" << endl;}
}