首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

PE 可執行檔格式深度解析與修改實戰

     編輯:VC 教學

前言

Windows 9x/NT/2000 以上所有可執行檔(.exe、.dll、.sys 等)均遵循 Microsoft 定義的 PE (Portable Executable) 格式。理解 PE 結構是逆向工程、病毒分析、外掛開發、二進位修補、殼開發等進階技術的基石。本文系統梳理 PE 檔案整體架構、關鍵資料結構與修改實戰要點。

PE 檔案整體架構

+------------------------+
| DOS MZ Header          |  偏移 0x00:DOS 可執行檔標誌 "MZ"
+------------------------+
| DOS Stub               |  實模式下顯示 "This program cannot run in DOS mode"
+------------------------+
| PE Header (IMAGE_NT_HEADERS) |  真正的 PE 資訊起點,DOS Header 0x3C 處指向
+------------------------+
| Section Table          |  區段表(節表),描述各 Section 屬性與位置
+------------------------+
| Section 1 (.text)      |  程式碼區
| Section 2 (.data)      |  初始化資料區
| Section 3 (.rsrc)      |  資源區
| ...                    |
| Section n              |
+------------------------+

關鍵結構體定義

1. DOS Header (IMAGE_DOS_HEADER)


typedef struct _IMAGE_DOS_HEADER {
    WORD  e_magic;      // "MZ" (0x5A4D)
    WORD  e_cblp;
    WORD  e_cp;
    WORD  e_crlc;
    WORD  e_cparhdr;
    WORD  e_minalloc;
    WORD  e_maxalloc;
    WORD  e_ss;
    WORD  e_sp;
    WORD  e_csum;
    WORD  e_ip;
    WORD  e_cs;
    WORD  e_lfarlc;
    WORD  e_ovno;
    WORD  e_res[4];
    WORD  e_oemid;
    WORD  e_oeminfo;
    WORD  e_res2[10];
    LONG  e_lfanew;     // 關鍵:PE Header 相對檔案開頭的偏移 (通常 0x80, 0x100 等)
} IMAGE_DOS_HEADER;

2. PE Header (IMAGE_NT_HEADERS)


typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                    // "PE\0\0" (0x00004550)
    IMAGE_FILE_HEADER FileHeader;       // 實體檔案屬性
    IMAGE_OPTIONAL_HEADER32 OptionalHeader; // 邏輯映像屬性(最重要)
} IMAGE_NT_HEADERS32;

3. File Header (IMAGE_FILE_HEADER)


typedef struct _IMAGE_FILE_HEADER {
    WORD  Machine;              // 0x014c = Intel 386+
    WORD  NumberOfSections;     // 區段數
    DWORD TimeDateStamp;        // 建立時間
    DWORD PointerToSymbolTable; // 除錯符號表
    DWORD NumberOfSymbols;
    WORD  SizeOfOptionalHeader; // OptionalHeader 大小
    WORD  Characteristics;      // 0x0002=EXE, 0x2000=DLL, 0x0001=無重定位等
} IMAGE_FILE_HEADER;

4. Optional Header (IMAGE_OPTIONAL_HEADER32) - 核心重點


typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD  Magic;                       // 0x10b = PE32, 0x20b = PE32+
    BYTE  MajorLinkerVersion;
    BYTE  MinorLinkerVersion;
    DWORD SizeOfCode;                  // 所有代碼區段總大小
    DWORD SizeOfInitializedData;
    DWORD SizeOfUninitializedData;
    DWORD AddressOfEntryPoint;         // 關鍵:程式進入點 RVA
    DWORD BaseOfCode;                  // 代碼區段起始 RVA
    DWORD BaseOfData;                  // 資料區段起始 RVA
    DWORD ImageBase;                   // 建議載入基址 (EXE 常 0x00400000)
    DWORD SectionAlignment;            // 記憶體對齊粒度 (通常 0x1000)
    DWORD FileAlignment;               // 檔案對齊粒度 (通常 0x200)
    WORD  MajorOperatingSystemVersion;
    WORD  MinorOperatingSystemVersion;
    WORD  MajorImageVersion;
    WORD  MinorImageVersion;
    WORD  MajorSubsystemVersion;       // 4.0 以上才有 3D 對話框
    WORD  MinorSubsystemVersion;
    DWORD Win32VersionValue;           // 保留
    DWORD SizeOfImage;                 // 映像在記憶體總大小 (含所有區段)
    DWORD SizeOfHeaders;               // 所有 Header + 區段表大小
    DWORD CheckSum;                    // 校驗和
    WORD  Subsystem;                   // 2=GUI, 3=CUI, 1=Native
    WORD  DllCharacteristics;
    DWORD SizeOfStackReserve;
    DWORD SizeOfStackCommit;
    DWORD SizeOfHeapReserve;
    DWORD SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;         // 固定 16
    IMAGE_DATA_DIRECTORY DataDirectory[16]; // 關鍵目錄表
} IMAGE_OPTIONAL_HEADER32;

5. Data Directory (IMAGE_DATA_DIRECTORY) - 16 個預定義目錄

索引常數用途
0IMAGE_DIRECTORY_ENTRY_EXPORT匯出表
1IMAGE_DIRECTORY_ENTRY_IMPORT匯入表 (IAT)
2IMAGE_DIRECTORY_ENTRY_RESOURCE資源表 (.rsrc)
3IMAGE_DIRECTORY_ENTRY_EXCEPTION例外處理表
4IMAGE_DIRECTORY_ENTRY_SECURITY安全性憑證
5IMAGE_DIRECTORY_ENTRY_BASERELOC基址重定位表
6IMAGE_DIRECTORY_ENTRY_DEBUG除錯資訊
7IMAGE_DIRECTORY_ENTRY_ARCHITECTURE架構專用
8IMAGE_DIRECTORY_ENTRY_GLOBALPTR全域指標
9IMAGE_DIRECTORY_ENTRY_TLS執行緒區域儲存
10IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG載入配置
11IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT綁定匯入表
12IMAGE_DIRECTORY_ENTRY_IAT匯入地址表
13IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT延遲匯入表
14IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR.NET 元資料 (CLR Header)
15保留-

6. Section Header (IMAGE_SECTION_HEADER) - 區段表項


typedef struct _IMAGE_SECTION_HEADER {
    BYTE  Name[8];          // 區段名 (如 ".text", ".data", ".rsrc")
    DWORD VirtualSize;      // 區段在記憶體大小
    DWORD VirtualAddress;   // 區段 RVA (相對 ImageBase)
    DWORD SizeOfRawData;    // 區段在檔案大小 (對齊 FileAlignment)
    DWORD PointerToRawData; // 區段在檔案偏移
    DWORD PointerToRelocations;
    DWORD PointerToLinenumbers;
    WORD  NumberOfRelocations;
    WORD  NumberOfLinenumbers;
    DWORD Characteristics;  // 0x60000020 = 代碼/可讀/可執行 等
} IMAGE_SECTION_HEADER;

RVA vs FOA 轉換核心公式

RVA (Relative Virtual Address):相對映像基址的虛擬位址(載入記憶體後)。
FOA (File Offset Address):檔案中的實際位移。


// RVA -> FOA
DWORD RvaToFoa(DWORD rva, PIMAGE_SECTION_HEADER sections, int count)
{
    for (int i = 0; i < count; i++)
    {
        DWORD start = sections[i].VirtualAddress;
        DWORD end   = start + sections[i].VirtualSize;
        if (rva >= start && rva < end)
        {
            return sections[i].PointerToRawData + (rva - start);
        }
    }
    return 0; // 不在任何區段
}

// FOA -> RVA
DWORD FoaToRva(DWORD foa, PIMAGE_SECTION_HEADER sections, int count)
{
    for (int i = 0; i < count; i++)
    {
        DWORD start = sections[i].PointerToRawData;
        DWORD end   = start + sections[i].SizeOfRawData;
        if (foa >= start && foa < end)
        {
            return sections[i].VirtualAddress + (foa - start);
        }
    }
    return 0;
}

常見修改實戰場景

場景修改目標關鍵步驟
修改程式進入點OptionalHeader.AddressOfEntryPoint設為新代碼區段 RVA,注意堆疊平衡
新增區段 (加殼/外掛)Section Table 新增 IMAGE_SECTION_HEADER調整 NumberOfSections、SizeOfImage、對齊計算、寫入資料
修改匯入表 (IAT Hook)DataDirectory[1] 匯入表定位目標 DLL/函式,修改 IAT 項指向自訂函式
資源替換/新增.rsrc 區段 + Resource Directory Tree解析資源目錄樹,插入/替換葉節點,調整 SizeOfRawData
去除殼/解壓Entry Point、區段屬性、重定位表找到 OEP,修復 IAT、重定位、區段屬性 (MEM_WRITE→MEM_READ)
修改 SubsystemOptionalHeader.Subsystem2(GUI)↔3(CUI) 切換控制台視窗顯示

工具鏈推薦

  • 靜態分析:CFF Explorer、PE-bear、LordPE、PEview
  • 動態分析:x64dbg、OllyDbg、IDA Pro
  • 程式庫:libpeconv、pe-parse、Windows SDK (ImageHlp.h)
  • 腳本自動化:Python + pefile、LIEF

法律與道德提醒

PE 修改技術屬雙面刃:

  • ✅ 合法用途:相容性修補、安全性研究、效能優化、外掛開發、惡意軟體分析。
  • ❌ 非法用途:破解授權、植入後門、繞過防護、製作病毒/木馬、侵犯智慧財產權。

請嚴格遵守當地法律法規,僅在授權範圍內進行二進位分析與修改。

掌握 PE 格式細節,即擁有了「透視 Windows 可執行檔本質」的 X 光眼,是系統級開發與安全研究的核心內功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved