把 exe 文件的 PE 文件的頭部結構顯示出來。編程
我沒有按慣例把 IMAGE_DATA_DIRECTORY 放到 IMAGE_OPTIONAL_HEADER 裏面,而是放到了 IMAGE_NT_HEADER 裏面,讓 IMAGE_DATA_DIRECTORY 和 IMAGE_OPTIONAL_HEADER 處於平等地位,由於我以爲這樣比較順眼!可是這會致使 IMAGE_FILE_HEADER 中的 SizeOfOptionalHeader 字段數值不許,須要進行換算。緩存
首先定義幾個數據格式,方便兼容彙編。
安全
/* Typedef.h 數據類型 四彩 2015-11-29 */ #ifndef _TYPEDEF_H #define _TYPEDEF_H #ifndef _STDBOOL_H typedef char BOOL; #define TRUE 1 #define FALSE 0 #endif typedef unsigned char BYTE; // 無符號 1 字節 typedef unsigned short int WORD; // 無符號 2 字節 typedef unsigned int DWORD; // 無符號 4 字節 // 獲得一個 DWORD 的高位 WORD 和低位 WORD #define LWordOfDW(value) ((WORD)((DWORD)(value) & 0xFFFF)) #define HWordOfDW(value) ((WORD)((DWORD)(value) >> 16)) // 獲得一個 WORD 的高位 BYTE 和低位 BYTE #define LByteOfW(value) ((BYTE)((WORD)(value) & 0xFF)) #define HByteOfW(value) ((BYTE)((WORD)(value) >> 8)) // 把兩個 WORD 轉化爲一個 DWORD #define Words2DW(HighWord, LowWord) ((((DWORD)(HighWord)) << 16) + (LowWord)) // 把兩個 BYTE 轉化爲一個 WORD #define Bytes2W(HighByte, LowByte) ((((WORD)(HighByte)) << 8) + (LowByte)) #endif
/* PE.h PE 文件格式 四彩 2015-11-30 */ /* PE 文件的整體結構:(內存地址有低到高) IMAGE_DOS_HEADER(DOS 頭) DOS stub "PE00"(PE 標誌) IMAGE_FILE_HEADER(文件頭) IMAGE_OPTIONAL_HEADER(可選頭) IMAGE_DATA_DIRECTORY(數據塊目錄) IMAGE_SECTION_HEADER(節表) .text節區 .data節區 其它節區 不能被映射的其餘數據 */ /* 虛擬地址:Virtual Address(VA),保護模式下訪問內存所使用的邏輯地址。 裝載基址:Image Base,文件裝入內存的基址。 默認狀況下,EXE 文件的基址爲 0x00400000,DLL 文件的基址爲 0x10000000。 相對虛擬地址:Relative Virtual Address(RVA),在內存中相對於裝載基址的偏移量。 文件偏移地址:File Offset Address(FOA),文件在磁盤上存放時相對於文件開頭的偏移量。 文件偏移地址從文件的第一個字節開始計數,起始值爲 0。 不管是在內存中仍是在磁盤文件中,節都是按基址排列的,並且都要對齊,但對齊值通常不一樣。 映射到內存後,全部頭和節表的偏移位置與大小均沒有變化,而各節基址的偏移位置發生了變化。 無論節是在文件中仍是被加載到內存中,節中數據的位置相對該節的基址是不變的。 在內存中:數據相對節的起始位置的偏移h = 數據的RVA - 節的RVA 在文件中:數據相對節的起始位置的偏移h = 數據的FOA – 節的FOA 一個節中的數據只是屬性相同,並不必定是同一種用途的內容,所以僅依靠節表是沒法肯定和定位 的,而要由數據目錄表來定位。 */ /* IMAGE_DATA_DIRECTORY 直接定義在 IMAGE_NT_HEADER 裏面,而不在 IMAGE_OPTIONAL_HEADER 裏, 這致使 IMAGE_FILE_HEADER 中的 SizeOfOptionalHeader 字段數值失效。 */ #ifndef _PE_H #define _PE_H #include "Typedef.h" // *************************************************************************************** // DOS 頭結構:文件偏移基址 0 // // e_magic 字段預約義值 #define IMAGE_DOS_SIGNATURE 0x5A4D // 即字符 "MZ" typedef struct tag_IMAE_DOS_HEADER { // 偏移 說明 WORD e_magic; // 0x00 DOS 可執行文件標識符(= "MZ") WORD e_cblp; // 0x02 Bytes on last page of file WORD e_cp; // 0x04 Pages in file WORD e_crlc; // 0x06 Relocations WORD e_cparhdr; // 0x08 Size of header in paragraphs WORD e_minalloc; // 0x0A Minimum extra paragraphs needed WORD e_maxalloc; // 0x0C Maximum extra paragraphs needed WORD e_ss; // 0x0E Initial (relative) SS value WORD e_sp; // 0x10 Initial SP value WORD e_csum; // 0x12 Checksum WORD e_ip; // 0x14 Initial IP value WORD e_cs; // 0x16 Initial (relative) CS value WORD e_lfarlc; // 0x18 File address of relocation table WORD e_ovno; // 0x1A Overlay number WORD e_res[4]; // 0x1C Reserved words WORD e_oemid; // 0x24 OEM identifier (for e_oeminfo) WORD e_oeminfo; // 0x26 OEM information; e_oemid specific WORD e_res2[10]; // 0x28 Reserved words DWORD e_lfanew; // 0x3C PE 簽名的文件偏移地址 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; // ======================================================================================= // *************************************************************************************** // NT 頭結構:文件偏移地址 = IMAGE_DOS_HEADER.e_lfanew // // NT 頭結構 —— File 頭結構 // // Machine 字段預約義值: Value Meaning #define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // x86 #define IMAGE_FILE_MACHINE_AMD64 0x8664 // x64 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel Itanium /* Characteristics 是一個標誌的集合 位 預約義值 含義 0 IMAGE_FILE_RELOCS_STRIPPED 文件中沒有重定向信息。在可執行文件中沒有使用。 可執行文件用基址重定向目錄表來表示重定向信息。 1 IMAGE_FILE_EXECUTABLE_IMAGE 可執行文件。 2 IMAGE_FILE_LINE_NUMS_STRIPPED 沒有行數信息。在可執行文件中沒有使用。 3 IMAGE_FILE_LOCAL_SYMS_STRIPPED 沒有局部符號信息。在可執行文件中沒有使用。 4 IMAGE_FILE_AGGRESIVE_WS_TRIM 已無效。 5 IMAGE_FILE_LARGE_ADDRESS_AWARE 應用程序能夠處理超過 2 GB 的地址。 6 未使用 7 IMAGE_FILE_BYTES_REVERSED_LO 已無效。 8 IMAGE_FILE_32BIT_MACHINE 但願機器爲32位機。這個值永遠爲 1。 9 IMAGE_FILE_DEBUG_STRIPPED 沒有調試信息。在可執行文件中沒有使用。 10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 該程序不能運行於可移動介質中(如軟驅或CD)。 11 IMAGE_FILE_NET_RUN_FROM_SWAP 程序不能在網上運行。(必須拷貝到內存中執行) 12 IMAGE_FILE_SYSTEM 系統文件,如驅動程序。在可執行文件中沒有使用。 13 IMAGE_FILE_DLL 動態連接庫(DLL)。 14 IMAGE_FILE_UP_SYSTEM_ONLY 不能運行於多處理器系統中。 15 IMAGE_FILE_BYTES_REVERSED_HI 已無效。 */ // Characteristics 字段預約義值 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 #define IMAGE_FILE_32BIT_MACHINE 0x0100 #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 #define IMAGE_FILE_SYSTEM 0x1000 #define IMAGE_FILE_DLL 0x2000 #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 typedef struct tag_IMAGE_FILE_HEADER { WORD Machine; // 0x04 運行所要求的 CPU 類型。 WORD NumberOfSections; // 0x06 節數。 DWORD TimeDateStamp; // 0x08 文件建立日期和時間 DWORD PointerToSymbolTable; // 0x0C 指向符號表(用於調試) DWORD NumberOfSymbols; // 0x10 符號表中符號個數(用於調試) WORD SizeOfOptionalHeader; // 0x14 IMAGE_OPTIONAL_HEADER 結構大小(無效) WORD Characteristics; // 0x16 屬性 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; // --------------------------------------------------------------------------------------- // NT 頭結構 —— NT 可選頭結構 // /* 數據目錄表各項的含義 索引 預約義值 對應的數據塊 0 IMAGE_DIRECTORY_ENTRY_EXPORT 導出函數表,主要用於 DLL 中的導出函數 1 IMAGE_DIRECTORY_ENTRY_IMPORT 導入函數表,使用外部函數的數據表 2 IMAGE_DIRECTORY_ENTRY_RESOURCE 資源數據表 3 IMAGE_DIRECTORY_ENTRY_EXCEPTION 異常處理表(具體資料不詳) 4 IMAGE_DIRECTORY_ENTRY_SECURITY 安全處理數據表(具體資料不詳) 5 IMAGE_DIRECTORY_ENTRY_BASERELOC 重定位信息表,通常和 DLL 相關 6 IMAGE_DIRECTORY_ENTRY_DEBUG 調試信息表 7 IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 版權信息表 8 IMAGE_DIRECTORY_ENTRY_GLOBALPTR 機器值(MIPS GP)(具體資料不詳) 9 IMAGE_DIRECTORY_ENTRY_TLS 線程信息本地存儲表 10 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 裝配信息表(具體資料不詳) 11 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 輸入函數綁定信息表(具體資料不詳) 12 IMAGE_DIRECTORY_ENTRY_IAT 導入函數地址表(與 ImportTable 對應, 由 Loader 填寫的輸入函數地址) 13 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 延遲裝入的函數信息表(具體資料不詳) 14 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 公用組件信息表(具體資料不詳) 15 未使用 */ typedef struct tag_IMAGE_OPTIONAL_HEADER { // 偏移 說明 // Standard fields. WORD Magic; // 0x18 標誌字(Win32 下老是 0x010B) BYTE MajorLinkerVersion; // 0x1A 連接程序的主版本號 BYTE MinorLinkerVersion; // 0x1B 連接程序的次版本號 DWORD SizeOfCode; // 0x1C 全部含代碼的節的總大小 DWORD SizeOfInitializedData; // 0x20 全部含已初始化數據的節的總大小 DWORD SizeOfUninitializedData; // 0x24 全部含未初始化數據的節的大小 DWORD AddressOfEntryPoint; // 0x28 程序執行入口地址(RVA) DWORD BaseOfCode; // 0x2C 代碼的區塊的起始地址(RVA) DWORD BaseOfData; // 0x30 數據的區塊的起始地址(RVA) // NT additional fields. DWORD ImageBase; // 0x34 首選裝載基址 DWORD SectionAlignment; // 0x38 內存中節的對齊單位(32 位下爲 4K) DWORD FileAlignment; // 0x3C 磁盤文件中節的對齊單位(一個扇區大小) WORD MajorOperatingSystemVersion; // 0x40 要求操做系統最低版本號的主版本號 WORD MinorOperatingSystemVersion; // 0x42 要求操做系統最低版本號的副版本號 WORD MajorImageVersion; // 0x44 可運行於操做系統的主版本號 WORD MinorImageVersion; // 0x46 可運行於操做系統的次版本號 WORD MajorSubsystemVersion; // 0x48 要求最低子系統版本的主版本號 WORD MinorSubsystemVersion; // 0x4A 要求最低子系統版本的次版本號 DWORD Win32VersionValue; // 0x4C 不明。通常爲 0 。 DWORD SizeOfImage; // 0x50 裝入內存後的總大小 DWORD SizeOfHeaders; // 0x54 全部頭 + 節表的總大小 DWORD CheckSum; // 0x58 校檢和 WORD Subsystem; // 0x5C 可執行文件指望的界面子系統 WORD DllCharacteristics; // 0x5E DllMain() 函數什麼時候被調用,默認爲 0 DWORD SizeOfStackReserve; // 0x60 初始化時的棧大小 DWORD SizeOfStackCommit; // 0x64 初始化時實際提交的棧大小 DWORD SizeOfHeapReserve; // 0x68 初始化時保留的堆大小 DWORD SizeOfHeapCommit; // 0x6C 初始化時實際提交的堆大小 DWORD LoaderFlags; // 0x70 與調試有關,默認爲 0 DWORD NumberOfRvaAndSizes; // 0x74 數據目錄表的項數 } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; // --------------------------------------------------------------------------------------- // NT 頭結構 —— 數據目錄結構 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 // 數據目錄表的項數一直是 16 typedef struct tag_IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; // 數據的基址(RVA) DWORD Size; // 數據的長度 } IMAGE_DATA_DIRECTORY; // --------------------------------------------------------------------------------------- // NT 頭結構 // // Signature 字段預約義值 #define IMAGE_NT_SIGNATURE 0x00004550 // 即字符"PE00" typedef struct tag_IMAGE_NT_HEADERS { // 偏移 說明 DWORD Signature; // 0x00 PE 文件簽名(= "PE00") IMAGE_FILE_HEADER FileHeader; // 0x04 文件頭結構 IMAGE_OPTIONAL_HEADER OptionalHeader; // 0x18 可選 NT 頭結構 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 0x78 數據目錄表 } IMAGE_NT_HEADER, *PIMAGE_NT_HEADER; // ======================================================================================= // *************************************************************************************** // 節表:文件偏移地址 = IMAGE_DOS_HEADER.e_lfanew + sizeof(IMAGE_NT_HEADER) // 項數由 IMAGE_NT_HEADER 中的 FileHeader.NumberOfSections 指定 // // 節(區塊)頭結構 #define IMAGE_SIZEOF_SHORT_NAME 8 // Name 字段最長 8 字節 // Characteristics 字段預約義值 #define IMAGE_SCN_CNT_CODE 0x20 // 包含代碼 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 // 包含已初始化數據 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 // 包含未初始化數據 #define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 // 數據在進程開始後將被丟棄 #define IMAGE_SCN_MEM_NOT_CACHED 0x4000000 // 數據不通過緩存 #define IMAGE_SCN_MEM_NOT_PAGED 0x8000000 // 數據不被交換出內存 #define IMAGE_SCN_MEM_SHARED 0x10000000 // 數據可共享 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 // 可執行 #define IMAGE_SCN_MEM_READ 0x40000000 // 可讀 #define IMAGE_SCN_MEM_WRITE 0x80000000 // 可寫 typedef struct tag_IMAGE_SECTION_HEADER { // 偏移 說明 BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 0x00 節表名稱(僅供編程參考) union // 0x08 通常是取後一個,即節的真實長度 { DWORD PhysicalAddress; // 物理地址 DWORD VirtualSize; // 真實長度(沒有進行對齊處理前的實際大小) } Misc; DWORD VirtualAddress; // 0x0C 裝載到內存的基址(內存對齊後的 RVA) DWORD SizeOfRawData; // 0x10 在文件中的大小(在磁盤中對齊後的大小) DWORD PointerToRawData; // 0x14 在文件中的偏移量(從文件頭開始算起) DWORD PointerToRelocations; // 0x18 重定位的偏移(在 OBJ 文件中供調試用) DWORD PointerToLinenumbers; // 0x1C 行號表的偏移(同上) WORD NumberOfRelocations; // 0x20 重定位項的數目(同上) WORD NumberOfLinenumbers; // 0x22 行號表中行號的數目(同上) DWORD Characteristics; // 0x24 節的屬性(如可讀、可寫、可執行等) } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; // ======================================================================================= #endif
/* PEF.c 顯示 PE 文件格式信息 四彩 2015-11-30 */ #include <stdio.h> #include <stdlib.h> #include "PE.h" // 顯示 IMAGE_DOS_HEADER 信息 void PrintDosHeader(IMAGE_DOS_HEADER DosHeader) { int i; printf("e_magic : %c%c\n", LByteOfW(DosHeader.e_magic), HByteOfW(DosHeader.e_magic)); printf("e_cblp : 0x%04X\n", DosHeader.e_cblp); printf("e_cp : 0x%04X\n", DosHeader.e_cp); printf("e_crlc : 0x%04X\n", DosHeader.e_crlc); printf("e_cparhdr : 0x%04X\n", DosHeader.e_cparhdr); printf("e_minalloc : 0x%04X\n", DosHeader.e_minalloc); printf("e_maxalloc : 0x%04X\n", DosHeader.e_maxalloc); printf("e_ss : 0x%04X\n", DosHeader.e_ss); printf("e_sp : 0x%04X\n", DosHeader.e_sp); printf("e_csum : 0x%04X\n", DosHeader.e_csum); printf("e_ip : 0x%04X\n", DosHeader.e_ip); printf("e_cs : 0x%04X\n", DosHeader.e_cs); printf("e_lfarlc : 0x%04X\n", DosHeader.e_lfarlc); printf("e_ovno : 0x%04X\n", DosHeader.e_ovno); printf("e_res : "); for(i = 0; i < 4; i++) printf("0x%X, ", DosHeader.e_res[i]); printf("\ne_oemid : 0x%04X\n", DosHeader.e_oemid); printf("e_oeminfo : 0x%04X\n", DosHeader.e_oeminfo); printf("e_res2 : "); for(i = 0; i < 10; i++) printf("0x%X, ", DosHeader.e_res2[i]); printf("\ne_lfanew : 0x%04X\n", DosHeader.e_lfanew); } // 顯示 IMAGE_FILE_HEADER 信息 void PrintFileHeader(IMAGE_FILE_HEADER FileHeader) { printf("Machine : 0x%04X\n", FileHeader.Machine); printf("NumberOfSections : 0x%04X\n", FileHeader.NumberOfSections); printf("TimeDateStamp : 0x%08X\n", FileHeader.TimeDateStamp); printf("PointerToSymbolTable : 0x%08X\n", FileHeader.PointerToSymbolTable); printf("NumberOfSymbols : 0x%08X\n", FileHeader.NumberOfSymbols); printf("SizeOfOptionalHeader : 0x%04X\n", FileHeader.SizeOfOptionalHeader); printf("Characteristics : 0x%04X\n", FileHeader.Characteristics); } // 顯示 IMAGE_OPTIONAL_HEADER 信息 void PrintOptionalHeader(IMAGE_OPTIONAL_HEADER OptHeader) { // Standard fields. printf("Magic : 0x%04X\n", OptHeader.Magic); printf("MajorLinkerVersion : 0x%02X\n", OptHeader.MajorLinkerVersion); printf("MinorLinkerVersion : 0x%02X\n", OptHeader.MinorLinkerVersion); printf("SizeOfCode : 0x%08X\n", OptHeader.SizeOfCode); printf("SizeOfInitializedData : 0x%08X\n", OptHeader.SizeOfInitializedData); printf("SizeOfUninitializedData : 0x%08X\n", OptHeader.SizeOfUninitializedData); printf("AddressOfEntryPoint : 0x%08X\n", OptHeader.AddressOfEntryPoint); printf("BaseOfCode : 0x%08X\n", OptHeader.BaseOfCode); printf("BaseOfData : 0x%08X\n", OptHeader.BaseOfData); // NT additional fields. printf("ImageBase : 0x%08X\n", OptHeader.ImageBase); printf("SectionAlignment : 0x%08X\n", OptHeader.SectionAlignment); printf("FileAlignmen : 0x%08X\n", OptHeader.FileAlignment); printf("MajorOperatingSystemVersion : 0x%04X\n", OptHeader.MajorOperatingSystemVersion); printf("MinorOperatingSystemVersion : 0x%04X\n", OptHeader.MinorOperatingSystemVersion); printf("MajorImageVersion : 0x%04X\n", OptHeader.MajorImageVersion); printf("MinorImageVersion : 0x%04X\n", OptHeader.MinorImageVersion); printf("MajorSubsystemVersion : 0x%04X\n", OptHeader.MajorSubsystemVersion); printf("MinorSubsystemVersion : 0x%04X\n", OptHeader.MinorSubsystemVersion); printf("Win32VersionValue : 0x%08X\n", OptHeader.Win32VersionValue); printf("SizeOfImage : 0x%08X\n", OptHeader.SizeOfImage); printf("SizeOfHeaders : 0x%08X\n", OptHeader.SizeOfHeaders); printf("CheckSum : 0x%08X\n", OptHeader.CheckSum); printf("Subsystem : 0x%04X\n", OptHeader.Subsystem); printf("DllCharacteristics : 0x%04X\n", OptHeader.DllCharacteristics); printf("SizeOfStackReserve : 0x%08X\n", OptHeader.SizeOfStackReserve); printf("SizeOfStackCommit : 0x%08X\n", OptHeader.SizeOfStackCommit); printf("SizeOfHeapReserve : 0x%08X\n", OptHeader.SizeOfHeapCommit); printf("SizeOfHeapCommit : 0x%08X\n", OptHeader.SizeOfHeapCommit); printf("LoaderFlags : 0x%08X\n", OptHeader.LoaderFlags); printf("NumberOfRvaAndSizes : 0x%08X\n", OptHeader.NumberOfRvaAndSizes); } // 顯示 IMAGE_DATA_DIRECTORY 信息 void PrintDataDircrory(IMAGE_DATA_DIRECTORY DataDirectory) { printf(" 0x%08X 0x%08X", DataDirectory.VirtualAddress, DataDirectory.Size); } // 顯示 IMAGE_SECTION_HEADER 信息 void PrintSectionHeader(IMAGE_SECTION_HEADER SectionHeader) { printf("Name : %s\n", SectionHeader.Name); printf("Misc.VirtualSize : 0x%08X\n", SectionHeader.Misc.VirtualSize); printf("VirtualAddress : 0x%08X\n", SectionHeader.VirtualAddress); printf("SizeOfRawData : 0x%08X\n", SectionHeader.SizeOfRawData); printf("PointerToRawData : 0x%08X\n", SectionHeader.PointerToRawData); printf("PointerToRelocations : 0x%08X\n", SectionHeader.PointerToRelocations); printf("PointerToLinenumbers : 0x%08X\n", SectionHeader.PointerToLinenumbers); printf("NumberOfRelocations : 0x%04X\n", SectionHeader.NumberOfRelocations); printf("NumberOfLinenumbers : 0x%04X\n", SectionHeader.NumberOfLinenumbers); printf("Characteristics : 0x%08X\n", SectionHeader.Characteristics); } int main(int argc, char **argv) { int i; FILE *fp; IMAGE_DOS_HEADER DosHeader; IMAGE_NT_HEADER NtHeader; IMAGE_SECTION_HEADER SectionHeader; if(argc != 2) { printf("Usage : %s exeFileName\n", argv[0]); return 0; } fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Error : open file\n"); return -1; } // 顯示 IMAGE_DOS_HEADER 信息 fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, fp); if(DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { printf("Error : NOT DOS file\n"); fclose(fp); return -1; } printf("IMAGE_DOS_HEADER :\n"); PrintDosHeader(DosHeader); // 顯示 IMAGE_NT_HEADER 信息 fseek(fp, DosHeader.e_lfanew, SEEK_SET); fread(&NtHeader, sizeof(IMAGE_NT_HEADER), 1, fp); if(NtHeader.Signature != IMAGE_NT_SIGNATURE) { printf("Error : NOT PE file\n"); fclose(fp); return 0; } printf("\nIMAGE_NT_HEADER :\n"); // Signature printf("Signature : %c%c%d%d\n", // 低低高高 LByteOfW(LWordOfDW(NtHeader.Signature)), HByteOfW(LWordOfDW(NtHeader.Signature)), LByteOfW(HWordOfDW(NtHeader.Signature)), HByteOfW(HWordOfDW(NtHeader.Signature))); printf("\nIMAGE_FILE_HEADER :\n"); // IMAGE_FILE_HEADER PrintFileHeader(NtHeader.FileHeader); printf("\nIMAGE_OPTIONAL_HEADER :\n"); // IMAGE_OPTIONAL_HEADER PrintOptionalHeader(NtHeader.OptionalHeader); printf("\nIMAGE_DATA_DIRECTORY : "); // 遍歷所有 IMAGE_DATA_DIRECTORY printf("\n NO. VirtualAddress Size"); for(i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { if(NtHeader.DataDirectory[i].Size != 0) { printf("\n %2d", i); PrintDataDircrory(NtHeader.DataDirectory[i]); } } // 遍歷顯示所有 IMAGE_SECTION_HEADER 信息 printf("\n\nIMAGE_SECTION_HEADER :"); for(i = 0; i < NtHeader.FileHeader.NumberOfSections; i++) { printf("\nSECTION_HEADER : NO.%02d\n", i); fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, fp); PrintSectionHeader(SectionHeader); } fclose(fp); return 0; }
本程序的顯示結果:ide
IMAGE_DOS_HEADER : e_magic : MZ e_cblp : 0x0090 e_cp : 0x0003 e_crlc : 0x0000 e_cparhdr : 0x0004 e_minalloc : 0x0000 e_maxalloc : 0xFFFF e_ss : 0x0000 e_sp : 0x00B8 e_csum : 0x0000 e_ip : 0x0000 e_cs : 0x0000 e_lfarlc : 0x0040 e_ovno : 0x0000 e_res : 0x0, 0x0, 0x0, 0x0, e_oemid : 0x0000 e_oeminfo : 0x0000 e_res2 : 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, e_lfanew : 0x0080 IMAGE_NT_HEADERS : Signature : PE00 IMAGE_FILE_HEADER : Machine : 0x014C NumberOfSections : 0x000D TimeDateStamp : 0x565C3D10 PointerToSymbolTable : 0x00006A00 NumberOfSymbols : 0x0000047D SizeOfOptionalHeader : 0x00E0 Characteristics : 0x0107 IMAGE_OPTIONAL_HEADER : Magic : 0x010B MajorLinkerVersion : 0x02 MinorLinkerVersion : 0x19 SizeOfCode : 0x00002400 SizeOfInitializedData : 0x00005000 SizeOfUninitializedData : 0x00000600 AddressOfEntryPoint : 0x000014E0 BaseOfCode : 0x00001000 BaseOfData : 0x00004000 ImageBase : 0x00400000 SectionAlignment : 0x00001000 FileAlignmen : 0x00000200 MajorOperatingSystemVersion : 0x0004 MinorOperatingSystemVersion : 0x0000 MajorImageVersion : 0x0001 MinorImageVersion : 0x0000 MajorSubsystemVersion : 0x0004 MinorSubsystemVersion : 0x0000 Win32VersionValue : 0x00000000 SizeOfImage : 0x00011000 SizeOfHeaders : 0x00000400 CheckSum : 0x0001C911 Subsystem : 0x0003 DllCharacteristics : 0x0000 SizeOfStackReserve : 0x00200000 SizeOfStackCommit : 0x00001000 SizeOfHeapReserve : 0x00001000 SizeOfHeapCommit : 0x00001000 LoaderFlags : 0x00000000 NumberOfRvaAndSizes : 0x00000010 IMAGE_DATA_DIRECTORY : NO. VirtualAddress Size 1 0x00009000 0x00000640 9 0x0000B004 0x00000018 12 0x00009124 0x000000E8 IMAGE_SECTION_HEADER : SECTION_HEADER : NO.00 Name : .text Misc.VirtualSize : 0x00002274 VirtualAddress : 0x00001000 SizeOfRawData : 0x00002400 PointerToRawData : 0x00000400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x60500060 SECTION_HEADER : NO.01 Name : .data Misc.VirtualSize : 0x00000038 VirtualAddress : 0x00004000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00002800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.02 Name : .rdata Misc.VirtualSize : 0x0000138C VirtualAddress : 0x00005000 SizeOfRawData : 0x00001400 PointerToRawData : 0x00002A00 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x40300040 SECTION_HEADER : NO.03 Name : /4 Misc.VirtualSize : 0x00000970 VirtualAddress : 0x00007000 SizeOfRawData : 0x00000A00 PointerToRawData : 0x00003E00 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x40300040 SECTION_HEADER : NO.04 Name : .bss Misc.VirtualSize : 0x00000444 VirtualAddress : 0x00008000 SizeOfRawData : 0x00000000 PointerToRawData : 0x00000000 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0700080 SECTION_HEADER : NO.05 Name : .idata Misc.VirtualSize : 0x00000640 VirtualAddress : 0x00009000 SizeOfRawData : 0x00000800 PointerToRawData : 0x00004800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.06 Name : .CRT Misc.VirtualSize : 0x00000034 VirtualAddress : 0x0000A000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005000 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.07 Name : .tls Misc.VirtualSize : 0x00000020 VirtualAddress : 0x0000B000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005200 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.08 Name : /14 Misc.VirtualSize : 0x00000038 VirtualAddress : 0x0000C000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42400040 SECTION_HEADER : NO.09 Name : /29 Misc.VirtualSize : 0x00000DE7 VirtualAddress : 0x0000D000 SizeOfRawData : 0x00000E00 PointerToRawData : 0x00005600 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.10 Name : /41 Misc.VirtualSize : 0x00000089 VirtualAddress : 0x0000E000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.11 Name : /55 Misc.VirtualSize : 0x00000129 VirtualAddress : 0x0000F000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006600 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.12 Name : /67 Misc.VirtualSize : 0x00000038 VirtualAddress : 0x00010000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42300040
如今就是有個疑問:數據目錄結構(IMAGE_DATA_DIRECTORY)到底幹什麼用的?和節表(IMAGE_SECTION_HEADER)有什麼聯繫?函數
答:一個節中的數據只是屬性相同,並不必定是同一種用途的內容,所以僅依靠節表是沒法肯定和定位spa
的,而要由數據目錄表來定位。操作系統