天天看點

PE 檔案中.reloc節 删除記錄

PE檔案是windows 下的一種可移植執行體,其設計目的使用來解決跨平台問題(但實際上隻是在windows下使用)。通常在windows下使用的.exe .dll .sys等檔案都是PE檔案,符合PE檔案格式規範,有其自身的格式。不熟悉的朋友也可以網上查找相關資料。

PE檔案的.reloc 節 即是使用了PE重定位技術。PE加載到程序虛拟位址時,會加載到PE中的IMAGE_OPTIONAL_HEADER結構體中ImageBase(DWORD)字段所訓示的位置,一般.exe檔案為4000000H,而.dll 檔案為1000000H。但是一個PE依賴的DLL多數情況下不止一個!寫一個簡單的C程式,可能調用了kernel32.dll和User.dll等系統元件。而若先将kernel32.dll加載到1000000H的位置,User.dll 再加載到這個位置就會覆寫,是以加載器作了DLL重定位,将User.dll加載到其他位置,防止發生沖突。

win7與vista之前沒有引入ASLR安全機制,是以.exe檔案在加載後位置都是固定在ImageBase處。

windowsPE重定位操作基本步驟:

1、查找PE代碼中寫死的位置;

2、做相關運算,若位址值為x,ImageBase - x 進行Virtual Address 到 Relative Virtual Address 的運算,最後再加上實際加載的位址。

因為一般的.exe程式中reloc節幾乎對運作無影響,可以直接删除(但dll和系統驅動好像都是必須的)。下面記錄删除過程:

工具:任意一中PE檢視器和十六進制編輯器(本文使用HexEdit和PETool)。材料: explorer.exe(我在XP下找的explorer,本想用notepad,最後發現它沒有reloc節)。

1、删除.reloc節資料;

  找到reloc節的資料,檢視SectionHeader字段:

PE 檔案中.reloc節 删除記錄

explorer沒有壓縮也,直接定位SectionHeader就可以,先查找IMAGE_DOS_HEADER中的e_lfanew(假設為 x )字段,得到IMAGE_NT_HEADER的RAW(檔案偏移),定位到FileHeader中,得到SizeOfOptionalHeader(= e0h),定位IMAGE_OPTIONAL_HEADER的RAW(x + 14h,14h為FileHeader的長度)。定位SecionHeader位置,使用IMAGE_OPTIONAL_HEADER偏移加上其大小即可。之後可以看到節區名稱:

PE 檔案中.reloc節 删除記錄

上圖看到了.reloc節,此後就可以得到節區的資訊,主要的資訊為:SizeOfRawData, VirtualSize, VirtualAddress, PointerToRawData,上面使用的PE工具都列出來了,要是不想自己定位,依賴工具吧!

通過PointerToRawData字段得到檔案中.reloc節的偏移量:EB600H;又得到其在檔案中的長度SizeOfRawData:3800H,于是定位到此處,把所有内容用0填充就可以了,PE中稱為(NULL-Padding)。

2、删除SectionHeader結構;

将剛才找到的SectionHeader節也用NULL-Padding。一個節頭是IMAGE_SECTION_HEADER結構,聲明在<winnt.h>中。其長度為28H。

3、删除IDT中的Base Relocation Table;

IMAGE_OPTIONAL_HEADER中的最後一個字段,DataDirectory,其中第六個元素即是reloc節表的IMAGE_DATA_DIRECTORY。每一個IMAGE_DATA_DIRECTORY長度為8bytes,偏移其起始位置28H即可找到,将他們全部修改為0。下圖箭頭所指位置為DataDirectory起始位置,選中部分既是第六個元素,第一個雙字為VirtualAddress, 第二個雙字為VirtualSize。

PE 檔案中.reloc節 删除記錄

4、修改FileHeader中的NumberOfSection;

IMAGE_FILE_HEADER中的NumberOfSection記錄了PE檔案中節區總數目。其位置通過NT偏移量+6h即可,其在IMAGE_FILE_HEADER第二個字的位置。具體可參見其聲明,在<winnt.h>檔案。将它減去1,。注意位元組序,我計算機是IA32架構的,使用的是小端位元組序。下圖中第一個雙字(50h 45h 00h 00h)為NT的Signature字段,後面緊接的字(4ch 01h)為IMAGE_FILE_HEADER.Machine字段,之後即為我們需要的NumberOfSection,其值為0x0004(小端位元組序),改為0x0003(03h 00h)。

PE 檔案中.reloc節 删除記錄

5、修改OptionalHeader中的ImageSize;

最後一步,目前的ImageSize值為F1000H,而reloc節加載到記憶體後長度為374cH,此處要使用SectionAligment的值(1000h),即每個節區的最小長度,長度為1000h的整數倍。是以此處減去4000h(374cH,向上取整)。即F1000H-4000H,同理注意位元組序。

至此删除工作完成,存檔後執行正常!說明檔案沒有問題,修改正确。

剛才也試了試用系統元件Kernel32.dll,修改後替換了系統的dll,但并沒有報錯,可能是因為記憶體中已經加載了此元件,目前沒有再加載的必要,是以系統運作正常。我在公共機房上的網,要是重新開機後系統不能還原這些元件,可能很多程式都會受影響。

繼續閱讀