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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...