首先,我們先用之前學過的一點知識在二進制文件中手動翻找區塊表,這樣做的好處是可以使你很快的對PE結構牢記於心。學來的東西就是能用的東西,不能用的理論是空談,是瞎扯。
(具體過程演示大夥可參考小甲魚的視頻教程:《解密系列》系統篇.第五講)
這裏我們經過千辛萬苦終於找到了我們的區塊表了(當然將來我會教大家寫一個自己的工具,讓工具去找,現在讓大家自己動手是爲了增強感覺!),現在我們聯繫上一章節提到的區塊表的結構對各個成員進行詳細的分析:
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 節表名稱,如“.text”
//IMAGE_SIZEOF_SHORT_NAME=8
union
{
DWORD PhysicalAddress; // 物理地址
DWORD VirtualSize; // 真實長度,這兩個值是一個聯合結構,可以使用其中的任何一個,一
// 般是取後一個
} Misc;
DWORD VirtualAddress; // 節區的 RVA 地址
DWORD SizeOfRawData; // 在文件中對齊後的尺寸
DWORD PointerToRawData; // 在文件中的偏移量
DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; // 行號表的偏移(供調試使用地)
WORD NumberOfRelocations; // 在OBJ文件中使用,重定位項數目
WORD NumberOfLinenumbers; // 行號表中行號的數目
DWORD Characteristics; // 節屬性如可讀,可寫,可執行等 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;Name:區塊名。這是一個由8位的ASCII 碼名,用來定義區塊的名稱。多數區塊名都習慣性以一個“.”作爲開頭(例如:.text),這個“.” 實際上是不是必須的。值得我們注意的是,如果區塊名超過 8 個字節,則沒有最後的終止標誌“NULL” 字節。並且前邊帶有一個“$” 的區塊名字會從連接器那裏得到特殊的待遇,前邊帶有“$” 的相同名字的區塊在載入時候將會被合併,在合併之後的區塊中,他們是按照“$” 後邊的字符的字母順序進行合併的。
另外小甲魚童鞋要跟大家囉嗦一下的是:每個區塊的名稱都是唯一的,不能有同名的兩個區塊。但事實上節的名稱不代表任何含義,他的存在僅僅是爲了正規統一編程的時候方便程序員查看方便而設置的一個標記而已。所以將包含代碼的區塊命名爲“.Data” 或者說將包含數據的區塊命名爲“.Code” 都是合法的。
因此,小甲魚建議大家:當我們要從PE 文件中讀取需要的區塊時候,不能以區塊的名稱作爲定位的標準和依據,正確的方法是按照 IMAGE_OPTIONAL_HEADER32 結構中的數據目錄字段結合進行定位。
Virtual Size:對錶對應的區塊的大小,這是區塊的數據在沒有進行對齊處理前的實際大小。
Virtual Address:該區塊裝載到內存中的RVA 地址。這個地址是按照內存頁來對齊的,因此它的數值總是 SectionAlignment 的值的整數倍。在Microsoft 工具中,第一個快的默認 RVA 總爲1000h。在OBJ 中,該字段沒有意義地,並被設爲0。
SizeOfRawData:該區塊在磁盤中所佔的大小。在可執行文件中,該字段是已經被FileAlignment 潛規則處理過的長度。
PointerToRawData:該區塊在磁盤中的偏移。這個數值是從文件頭開始算起的偏移量哦。
PointerToRelocations:這哥們在EXE文件中沒有意義,在OBJ 文件中,表示本區塊重定位信息的偏移值。(在OBJ 文件中如果不是零,它會指向一個IMAGE_RELOCATION 結構的數組)
PointerToLinenumbers:行號表在文件中的偏移值,文件的調試信息,於我們沒用,雞肋。
NumberOfRelocations:這哥們在EXE文件中也沒有意義,在OBJ 文件中,是本區塊在重定位表中的重定位數目來着。
NumberOfLinenumbers:該區塊在行號表中的行號數目,雞肋。
Characteristics:該區塊的屬性。該字段是按位來指出區塊的屬性(如代碼/數據/可讀/可寫等)的標誌。
小甲魚以下給大家列舉出最常用的一些屬性值:
具體內容可以參考MSDN在線文檔:http://msdn.microsoft.com/en-us/library/ms680341%28v=vs.85%29.aspx
|
The section contains executable code. 包含代碼,常與 0x10000000一起設置。 |
|
The section contains initialized data. 該區塊包含以初始化的數據。 |
|
The section contains uninitialized data. 該區塊包含未初始化的數據。 |
|
The section can be discarded as needed. 該區塊可被丟棄,因爲當它一旦被裝入後, 進程就不在需要它了,典型的如重定位區塊。 |
|
The section can be shared in memory. 該區塊爲共享區塊。 |
|
The section can be executed as code. 該區塊可以執行。通常當0x00000020被設置 時候,該標誌也被設置。 |
|
The section can be read. 該區塊可讀,可執行文件中的區塊總是設置該 標誌。 |
|
The section can be written to. 該區塊可寫。 |