在PE中添加,刪除SECTION
這兩天空閑,自己寫了個添加,刪除SECTION的程式,發現裡面的技巧很多,需要注意的地方也很多,現把心得寫上,希望能給正在學習PE檔案的朋友提供方便。
關於PE的格式,PE的基本知識,請參看其他相關文章。
添加SECTION
添加SECTION的前提是在最後一個SECTION與第一個區塊之間有足夠的空間)添加一個新SECTION 40位元組。通常情況下,是有40位元組的空間的,但是如果沒有就需要想辦法騰出40位元組空間來。
通常有2種方法騰空間
重新編排PE頭
通常IMAGE_DOS_HEADER 和 IMAGE_NT_HEADER不是緊挨著,中間有一些其他資料,比如DOS佔位程式,這些資料基本上沒用,可以將NT頭以及SECTION資料前移覆蓋這些資料達到擴充PE頭空餘空間添加新SECTION。
IMAGE_DOS_HEADER 的e_flanew 指向NT頭相對於檔案頭的位移,將NT頭前移,只需修改e_flanew的值即可。
優點:相對於擴充PE頭,不需要修改所有SECTION的PointerToRawData指向,不用移動所有區塊。
缺點:騰出來的尺寸只能加入有限的新SECTION.
擴充PE頭
這種方法通常將SizeOfHeader的尺寸擴大檔案對齊位元組,0x200位元組,然後把所有SECTION的PointerToRawData值得加上0x200位元組,然後再將所有區塊資料向後移動0x200位元組。當然SizeOfHeader 也需要加0x200位元組。
優點:使用這種方法可以實現無限的添加新SECTION。
缺點:需要改動的地方比較多。
注意綁定輸入表
有了空間不一定就能添加新SECTION,還需要查看綁定輸入表,綁定輸入表和其他節表不同,綁定輸入表緊挨著最後的一個SECTION存放,綁定輸入表而且必須在PE頭區內,由IMAGE_DATA_DIRECTORY[11]來指向。
我手上的PE編輯工具,LoardPE,PETools,StudPE都忽視了這個問題,添加SECTION後都覆蓋了綁定輸入表資料,而且也沒有IMAGE_DATA_DIRECTORY[11],導致添加節區後PE檔案不能運行。
如果不想保留綁定輸入,那麼添加SECTION的時候直接把IMAGE_DATA_DIRECTORY[11]內的資料置0.
如果想保留綁定輸入表,那麼就先把綁定資料拷貝出來,添加完SECTION再把資料複製到這個SECTION的後面,然後修改IMAGE_DATA_DIRECTORY[11]的指向就可以。
IMAGE_SECTION_HEADER 結構內容
Name 新區塊的名字,注意不能超過8位元組大小。
VirtualAddress 虛擬位址;這個地址就是PE檔案裝載後,這個區塊所在的記憶體位址。地址必須是"記憶體頁對齊",必須緊挨著上一個區塊。計算公式就是上一個區 塊的VirtualAddress + VirtualSize 記憶體頁對齊後的值。
VirtualSize 區塊內資料的實際大小;通過資料的實際大小,就可以計算出檔案對齊後的資料大小。
SizeOfRawData 區塊資料檔案對齊後的資料大小。根據VirtualSize計算可計算出檔案對齊後的尺寸。
PointerToRawData 區塊相對於檔案頭的檔案位移, 在檔案中兩區塊資料之間不必緊挨著,但起始地址必須是"檔案對齊"的。
Characteristics 區塊的屬性,可根據添加區塊的實際目的設定屬性,拿不準就設定E0000060代表可讀,可寫,可執行,包含代碼,包含初始化資料。
添加SECTION後還需要添加這個SCTION的區塊資料,首先需要把檔案尺寸擴大,擴大的尺寸就是區塊資料檔案對齊後的大小。
最後將IMAGE_OPTIONAL_HEADER32的SizeOfImage 加上新區塊資料的VirtualAddress。
將IMAGE_FILE_HEADER 的NumberOfSection 加 1。
刪除SECTION
刪除一個SECTION,需要考慮的比較多;
刪除SECTION不能根據名稱刪除,應該根據序號刪除,因為允許存在同名的Section。
如果刪除的Section位於中間位置,後面Section的PointerToRawData檔案位移可以向上移動,但是VirtualAddress虛擬位址就不能簡單的向上移動了,因為如果某個節區的VA發生變化,那麼這個節區裡的所有RVA也會發生變化,而要修複這些RVA工作量就太大了。處理辦法就是,把要刪除的這個Section的上一個Section的VirtualSize擴大,也就是加上要刪除的這個Section的VirtualSize,這樣,後面的所有Section的VirtualAddress不變,只修正PointerToRawData就可以。當然SizeOfImage也就不用調整了,PE映像大小沒變,只改變了PE檔案大小。
如果刪除的是最後一個Section,那麼刪除後將SizeOfImage減小就可以,不存在VA問題。
如果刪除的Section和IMAGE_NT_HEADER的DATA_DIRECTORY有關,比如重定位表,TLS表,那麼必須要清除資料目錄的VirtualAddress,和VirtualSize。
最後,如果有綁定資料,需要在檔案中上移一個IMAGE_SECTION_HEADER尺寸,然後修正資料目錄表的指向。