PE 学习之路 —— 区块表
1. 前述
在 NT 頭結束后,緊接著就是區塊表,區塊表包含每個塊在映象中的信息,分別指向不同的區塊實體。
2. 區塊表
區塊表是一個 IMAGE_SECTION_HEADER 結構數組,這個結構包含區塊的信息,比如位置、長度、屬性等,區塊的數目是由 NT 頭中的文件頭里的?NumberOfSections?給出。以下為 `IMAGE_SECTION_HEADER` 結構:
在上述圖中,有兩個字段比較重要,分別為 `VirtualAddress`、`PointerToRawData`,這兩個字段用于將相對虛擬地址或虛擬地址轉換為文件偏移地址,以下為 RVA 轉 FOA 函數:
DWORD RVAtoFOA(DWORD dwRva) {// 獲取區段表的數量DWORD dwCounts = g_NtHeader->FileHeader.NumberOfSections;// 獲取區段表數組的首元素auto Sections = IMAGE_FIRST_SECTION(g_NtHeader);// 遍歷所有的區段表找到符合要求的區段for (DWORD i = 0; i < dwCounts; ++i){// 要求:RVA >= 區段的首地址 并且 RVA < 區段的結尾的地址if (dwRva >= Sections[i].VirtualAddress &&(Sections[i].VirtualAddress + Sections[i].SizeOfRawData)){// FOA = VA - ImageBase - (所在區段的 RVA - 所在區段的 FOA)// FOA = RVA - 所在區段的 RVA + 所在區段的 FOAreturn dwRva - Sections[i].VirtualAddress + Sections[i].PointerToRawData;}}// 如果找不到就返回 -1return -1; }計算公式為:`FOA = VA - ImageBase - (所在區段的 RVA - 所在區段的 FOA)` 或 `FOA = RVA - 所在區段的 RVA + 所在區段的 FOA`。在上述代碼中,有一個為 `IMAGE_FIRST_SECTION`,我們來看下它的定義,如下:
其實 `IMAGE_FIRST_SECTION` 為一個宏,它主要由三部分相加組成,作用是獲取到第一個區段的首地址,參數為 NT 頭。你可以把這個首地址理解成數組名,數組的首地址。在獲取到了地址后,下面的 for 循環遍歷所有的區段表找到符合要求的區段。這三部分內容具體如下:
- IMAGE_NT_HEADERS 的起始地址
- IMAGE_OPTIONAL_HEADER32 (PE 擴展頭)在 IMAGE_NT_HEADERS 中的偏移
- IMAGE_OPTIONAL_HEADER32 的大小
?其中后兩個加起來的大小恰好就是 IMAGE_NT_HEADERS 的大小,再跟第一個相加就得到區段表的地址了。看到這你可以會問,為什么不直接加上 `IMAGE_NT_HEADERS` 的大小呢?因為 `IMAGE_OPTIONAL_HEADER32` 大小不固定,32 位下該值為 0x00E0H,64 位下該值為 0x00F0H,并且用戶還可以自定義其大小。
?3. 額外說明
擴展頭大小是由文件頭中 `SizeOfOptionalHeader` 字段給出,`FIELD_OFFSET` 這個是給出 `OptionalHeader` 在 `IMAGE_NT_HEADERS` 結構中的偏移,如下:
(本小節完)
轉載于:https://www.cnblogs.com/importthis/p/10192523.html
總結
以上是生活随笔為你收集整理的PE 学习之路 —— 区块表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 粘包问题
- 下一篇: 区块链跨链领域新突破!