2.4 PE結構:節表詳細解析

来源:https://www.cnblogs.com/LyShark/archive/2023/09/05/17679067.html
-Advertisement-
Play Games

節表(Section Table)是Windows PE/COFF格式的可執行文件中一個非常重要的數據結構,它記錄了各個代碼段、數據段、資源段、重定向表等在文件中的位置和大小信息,是操作系統載入文件時根據節表來進行各個段的映射和初始化的重要依據。節表中的每個記錄則被稱為`IMAGE_SECTION_... ...


節表(Section Table)是Windows PE/COFF格式的可執行文件中一個非常重要的數據結構,它記錄了各個代碼段、數據段、資源段、重定向表等在文件中的位置和大小信息,是操作系統載入文件時根據節表來進行各個段的映射和初始化的重要依據。節表中的每個記錄則被稱為IMAGE_SECTION_HEADER,它記錄了一個段的各種屬性信息和在文件中的位置和大小等信息,一個文件可以由多個IMAGE_SECTION_HEADER構成。

在執行PE文件的時候,Windows 並不在一開始就將整個文件讀入記憶體,PE裝載器在裝載的時候僅僅建立好虛擬地址和PE文件之間的映射關係,只有真正執行到某個記憶體頁中的指令或者訪問頁中的數據時,這個頁面才會被從磁碟提交到記憶體中,這種機制極大的節約了記憶體資源,使文件的裝入速度和文件的大小沒有太多的關係。

Windows 裝載器在裝載DOS部分PE文件頭部分和節表部分時不進行任何處理,而在裝載節區的時候會根據節的不同屬性做不同的處理,一般需要處理以下幾個方面的內容:

節區的屬性: 節是相同屬性的數據的組合,當節被裝入記憶體的時候,同一個節對應的記憶體頁面將被賦予相同的頁屬性,Windows系統對記憶體屬性的設置是以頁為單位進行的,所以節在記憶體中的對其單位必須至少是一個頁的大小,對於X86來說這個值是4KB(1000h),而對於X64來說這個值是8KB(2000h),磁碟中存儲的程式並不會對齊4KB,而只有被PE載入器載入記憶體的時候,PE裝載器才會自動的補齊4KB對其的零頭數據。

節區的偏移: 節的起始地址在磁碟文件中是按照IMAGE_OPTIONAL_HEADER結構的FileAhgnment欄位的值對齊的,而被載入到記憶體中時是按照同一結構中的SectionAlignment欄位的值對齊的,兩者的值可能不同,所以一個節被裝入記憶體後相對於文件頭的偏移和在磁碟文件中的偏移可能是不同的。

節區的尺寸: 由於磁碟映像和記憶體映像的對齊單位不同,磁碟中的映像在裝入記憶體後會自動的進行長度擴展,而對於未初始化的數據段(.data?)來說,則沒有必要為它在磁碟文件中預留空間,只要可執行文件裝入記憶體後動態的為其分配空間即可,所以包含未初始化數據的節在磁碟中長度被定義為0,只有在運行後PE載入器才會動態的為他們開闢空間。

不進行映射的節: 有些節中包含的數據僅僅是在裝入的時候用到,當文件裝載完畢時,他們不會被遞交到物理記憶體中,例如重定位節,該節的數據對於文件的執行代碼來說是透明的,他只供Windows裝載器使用,可執行代碼根本不會訪問他們,所以這些節存在於磁碟文件中,不會被映射到記憶體中。

一般來說,當一個PE文件被編譯生成時則預設會存在.text,.data等基本節表,而每一個節表都是由一個IMAGE_SECTION_HEADER結構排列而成,每個結構都用來描述一個節,節表總被存放在緊接在PE文件頭的地方,也即是從PE文件頭開始偏移為00f8h的位置,針對每一個節中的定義可查看節表結構體的定義;

typedef struct _IMAGE_SECTION_HEADER
{
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;           // 節區尺寸
    } Misc;
    DWORD   VirtualAddress;                // 節區RVA
    DWORD   SizeOfRawData;                 // 在文件中對齊後的尺寸
    DWORD   PointerToRawData;              // 在文件中的偏移
    DWORD   PointerToRelocations;          // 在OBJ文件中使用
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;               // 節區屬性欄位
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

針對IMAGE_SECTION_HEADER中各個欄位的詳細解析:

  • Name:段名,是一個8位元組的ASCII字元串,不足8位元組用0補齊。

  • VirtualSize:虛擬大小,標識在記憶體中占用的大小,請勿與PhysicalSize(物理大小)混淆。

  • VirtualAddress:虛擬地址,標識在記憶體中對應段頭的地址,與實際載入的位置有關。

  • SizeOfRawData:物理大小,標識在PE文件中該段的占用大小,不足以文件對齊單位則會進行填充。

  • PointerToRawData:物理地址,標識該段在文件中的偏移位置。

  • PointerToRelocations:重定向表的偏移位置。

  • PointerToLinenumbers:行號表的偏移位置。

  • NumberOfRelocations:重定向表數量。

  • NumberOfLinenumbers:行號表數量。

  • Characteristics:標識該段的各種屬性信息,包括下列常用屬性:

    • IMAGE_SCN_MEM_READ:可讀;
    • IMAGE_SCN_MEM_WRITE:可寫;
    • IMAGE_SCN_MEM_EXECUTE:可執行;
    • IMAGE_SCN_CNT_CODE:代碼段;
    • IMAGE_SCN_CNT_INITIALIZED_DATA:已初始化數據段;
    • IMAGE_SCN_CNT_UNINITIALIZED_DATA:未初始化數據段;
    • IMAGE_SCN_LNK_INFO:包含附加信息。

與數據目錄表的枚舉方式基本一致,數據目錄表的枚舉也不會太難,讀者只需要通過NtHeader->FileHeader.NumberOfSections獲取到當前有多少個節,並通過迴圈的方式依次得到這些節中的指針,並將該指針轉換為PIMAGE_SECTION_HEADER結構,依次迴圈輸出即可得到;

int main(int argc, char * argv[])
{
    BOOL PE = IsPeFile(OpenPeFile("c://pe/x86.exe"), 0);

    if (PE == TRUE)
    {
        printf("編號\t 節區名稱\t虛擬偏移\t虛擬大小\t實際偏移\t實際大小\t節區屬性\n");

        for (DWORD each = 0; each < NtHeader->FileHeader.NumberOfSections; each++, pSection++)
        {
            printf("%d\t %-9s\t 0x%.8X \t 0x%.8X \t 0x%.8X \t 0x%.8X \t 0x%.8X \n",
                each + 1, pSection->Name, pSection->VirtualAddress, pSection->Misc.VirtualSize,
                pSection->PointerToRawData, pSection->SizeOfRawData, pSection->Characteristics);
        }
    }
    else
    {
        printf("非標準程式 \n");
    }

    system("pause");
    return 0;
}

運行上述程式,即可輸出當前程式中存在的節表信息,輸出效果如下圖所示;

文章作者:lyshark (王瑞)
文章出處:https://www.cnblogs.com/LyShark/p/17679067.html
本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 類型介面 Go不是面向對象的語言,在go里通過不同的結構體實現同一組公共介面這種組合的形式實現多態,類似C++的類和虛函數 定義類型介面(Interface Definition): 使用 type 關鍵字定義介面,指定介面的方法簽名。 方法簽名由方法的名稱、參數列表和返回值組成,但不包含方法體。 ...
  • ## 教程簡介 Spring框架是一個開放源代碼的J2EE應用程式框架,由Rod Johnson發起,是針對bean的生命周期進行管理的輕量級容器(lightweight container)。 Spring解決了開發者在J2EE開發中遇到的許多常見的問題,提供了功能強大IOC、AOP及Web MV ...
  • # Python文件的基礎操作(2) - 二進位模式下讀寫操作 - 練習 - 控制文件內指針(游標)的移動 - 文件的修改 - 函數的介紹 ## 練習 ```python # 小練習: 編寫拷貝工具 1. 讓用戶輸入被拷貝的文件路徑(源文件路徑) 2. 輸入即將要拷貝的文件路徑(目標文件路徑) 3. ...
  • `@Autowired` 是 Spring Framework 中用於自動註入依賴的註解,通常情況下可以正常工作,但有一些情況下可能無法獲取到 bean 對象: 1. **Bean未定義或未掃描到**:如果要註入的 bean 沒有在 Spring 上下文中定義或者沒有被正確掃描到,`@Autowir ...
  • PEP703是未來去除GIL的計劃,當然現在提案還在繼續修改,但大致方向確定了。 對於實現細節我沒啥興趣多說,挑幾個我比較在意的點講講。 ## 儘量少依賴原子操作的引用計數 沒了GIL之後會出現兩個以上的線程同時操作同一個Python對象的情況,首先要解決的是引用計數的計算不能出岔子,否則整個記憶體管 ...
  • 享元模式在主流的標準里是放到結構大類下的,但是我感覺這個模式的最終作用也是為了獲取一個類,所以我將其劃分到創建大類下。 # What is Flyweight Pattern Flyweight 是指輕量級的。 享元模式旨在支持大量細粒度的對象共用,以減少記憶體消耗。該模式通過共用相似對象的部分狀態, ...
  •  **多個word 文檔 轉化成 PDF 文件, 最後合併成一個PDF文件** ``` import os from win32com import client from PyPDF2 import PdfMerger # 使用PdfMerger def wordToPdf(folder): # ...
  • 2021年上半年,擼了個rust cli開發的框架,基本上把交互模式,子命令提示這些cli該有的常用功能做進去了。項目地址:[https://github.com/jiashiwen/interactcli-rs。](https://github.com/jiashiwen/interactcli- ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...