PE 文件之頭部結構

    把 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

    的,而要由數據目錄表來定位。操作系統

相關文章
相關標籤/搜索