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;
找到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:異常處理程式的資料