1. 程式人生 > >PE檔案格式學習(六):異常表

PE檔案格式學習(六):異常表

1.概述

x86系統採用動態的方式構建SEH結構,相比而言x64系統下采用靜態的方式處理SEH結構,它儲存在PE檔案中,通常在.pdata區段。因此本文的例子採用x64編譯過的程式。

異常表在資源表的後面。

2.異常表解析

資料目錄表的第四個元素指向異常表,RVA指向的是一個IMAGE_IA64_RUNTIME_FUNCTION_ENTRY的結構體,本例的RVA是0xA000(也就是.pdata段的起始位置),轉換成offset是0x7a00。它的結構體是:

typedef struct_IMAGE_IA64_RUNTIME_FUNCTION_ENTRY {

   DWORD BeginAddress;   //與SEH相關程式碼的起始偏移地址

   DWORD EndAddress;      //與SEH相關程式碼的末尾偏移地址

   DWORD UnwindInfoAddress;//指向描述上面兩個欄位之間程式碼異常資訊的UNWIND_INFO

} IMAGE_IA64_RUNTIME_FUNCTION_ENTRY,*PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY;

IMAGE_IA64_RUNTIME_FUNCTION_ENTRY

找到0x7a00處,根據這個結構體可以分別找到這三個欄位的值。

BeginAddress RVA:0x00001020
EndAddress RVA:0x00001063
UnwindInfoAddress RVA:0x00007fd0

轉換為offset:

BeginAddress:0x420
EndAddress:0x463
UnwindInfoAddress:0x71d0

0x420-0x463沒什麼好說的,是異常處理函式的內容,UnwindInfoAddress指向的位置是用來描述BeginAddress與EndAddress之間的程式碼異常屬性資訊的UNWIND_INFO。UNWIND_INFO也叫作異常展開資訊,此結構用來描述堆疊指標的記錄屬性與暫存器中儲存的地址屬性,它的結構體如下:

struct _UNWIND_INFO {

   UBYTE Version:3;        
   UBYTE Flags:5; 
   UBYTE SizeOfProlog;        
   UBYTE CountOfCodes;   
   UBYTE FrameRegister:4;
   UBYTE FrameOffset:4;
   UNWIND_CODE UnwindCode[1];
   union {
        // If (Flags & UNW_FLAG_EHANDLER)
       OPTIONAL ULONG ExceptionHandler;//異常/終止函式的映像相對地址指標
       // Else if (Flags & UNW_FLAG_CHAININFO)
       OPTIONAL ULONG FunctionEntry;//展開資訊鏈的映像相對地址指標
   };
   // If (Flags & UNW_FLAG_EHANDLER)
   ULONG ExceptionData[1];//異常處理程式的資料
} UNWIND_INFO, *PUNWIND_INFO;

Version:異常展開資訊的版本號,一般為0x001

Flags:共有四種標誌:
    1.當它為0x0的時候表示UNW_FLAG_NHANDLER,沒有異常處理函式。
    2.當它為0x1的時候表示UNW_FLAG_EHANDLER,有異常處理函式。
    3.當它為0x2的時候表示UNW_FLAG_UHANDLER,有系統預設的處理函式。
    4.當它為0x4的時候表示UNW_FLAG_CHAININFO,表示FunctionEntry指向的是前一個RUNTIME_FUNCTION的RAV。

SizeOfProlog:函式起始部分位元組的長度

CountOfCodes:UNWIND_INFO結構包含的UNWIND_CODE結構數

FrameRegister:暫存器幀指標,為0則指定函式不使用框架

FrameOffset:若上面欄位不為0,表示函式偏移

UnwindCode:指定永久性暫存器與RSP的陣列專案數

ExceptionHandler:異常控制代碼

FunctionEntry:展開資訊鏈(函式)的映像相對地址指標(如果設定了UNW_FLAG_CHAININFO標識)

ExceptionData:異常處理程式的資料