小甲魚PE詳解之基址重定位詳解(PE詳解10)

小甲魚PE詳解之基址重定位詳解(PE詳解10)

這一節對於講來研究病毒原理的研究影響比較大,大家務必要深入理解~
但是吧,咱的權威教材看雪的《加密與解密》在這一節的講解上實在不給力,很多初學者看得雲裏霧裏的。大家意見一致啵 ?!

爲了讓大家能夠更容易的接受,小甲魚決定通過自問 - 自答循環漸進的模式給大家講解基址重定位的原理和應用。



問題一:什麼是基址重定位?

答:
重定位就是你本來這個程序理論上要佔據這個地址,但是由於某種原因,這個地址現在不能讓你霸佔,你必須轉移到別的地址,這就需要基址重定位。打個比方:例如你現在計劃在某某地方建一棟樓,但是有一天你收到上邊的通知,這個地方政府臨時要徵用建公廁,所以這時候你就沒轍,得去別的地方建啦~


問題二:爲什麼需要基址重定位?


答:其實這個問題看起來跟前邊的有點重複不是? 但是有些朋友可能會這麼說,小甲魚老溼你的言論是可以,但是放在程序中,小甲魚你上節課不是還說每個程序都讓Windows 欺騙了嗎 —— 每個程序覺得自己都完全佔有 4GB的內存空間,何來地址被別的程序佔據了呢?!

首先,能夠提出問題的朋友都是
值得表揚和鼓勵的

但是,上節課我們談了什麼內容呢 ? 談了導出表,爲什麼會出現導出表呢 ? 正是因爲有DLL 這類破壞別人家庭幸福的“小三”的存在~

我們之前談過,動態鏈接庫它自己是沒有佔據任何似有空間的,都是寄生在應用程序的私有空間裏邊。那寄生在別人家裏,睡在哪裏就肯定不是
小三說了算啦,肯定要由主人決定不是? 所以,在小三的眼裏,不用說,肯定永遠都睡在大房,但客觀事實告訴我們,經常只能住臥室~(有點扯遠了,其實小甲魚想說的是,基址重定位就是這麼被需求的^_^)


問題三:我們需要對程序中的哪些語句(指令)進行基址重定位呢?

答:請先看下圖




這是上節課我們用到的動態鏈接庫 Counter.dll 文件,對其用W32Dasm 進行反彙編的截圖。我們分析下,有哪些語句是需要我們來進行基址重定位的呢 ?(溫馨提示:以下內容涉及一些彙編基礎和windows基礎,不懂的朋友可以參照視頻教程。因爲一般說話比打字容易,信息量也比較大~)

答案是 ——但凡涉及到直接尋址的指令都需要進行重定位處理!( 那什麼是直接尋址? 咱在零基礎入門學習彙編裏邊講得很清楚啦,只要在機器碼中看到有地址的,那就叫直接尋址……那有沒有間接的? 肯定哈,間接的就是地址被間接的保存起來,例如存放在寄存器eax, 然後通過訪問寄存器來獲取地址,那就叫間接 )

那麼我們再過頭來看下圖片,一眼就能掃出以下指令需要對其進行重定位:

:10001026 FF0500300010            inc dword ptr [10003000]
:1000102C FF3500300010            push dword ptr [10003000]
:1000103D A100300010                mov eax, dword ptr [10003000]
:10001049 FF0D00300010            dec dword ptr [10003000]
:1000104F FF3500300010            push dword ptr [10003000]
:10001060 A100300010                mov eax, dword ptr [10003000]
:1000106A FF2500200010            Jmp dword ptr [10002000]


那有些朋友可能會問了,類似於“:10001038 E8CFFFFFFF        call 1000100C”的指令,爲什麼後邊顯示的是call + 地址,而機器碼卻不包含地址信息呢? CPU神了? 莫非地址信息被加密了?

其實不是的,學過彙編的朋友不知道還記不記得,小甲魚在講call 原理的時候用了大部分時間在談幾種跳轉,其中經常遇到的就是“地址+偏移”的形式。那這就能有個說得通的解釋了:CFFFFFFFh 事實上就是一個偏移地址,記得咱這是little-edition,轉換過來就是FFFF FFCFh,也就是等於-31h。那麼1000103Dh - 31h == 1000100Ch,Perfect! ^_^



問題四:系統對一條指令進行重定位需要哪些信息?

答:
我們還是拿上邊那張圖片來說事兒,我們說了上邊的那些指令需要重定位,現在就假設重定位後的基地址由原來的10000000h 變爲 20000000h了,那麼類似這樣的語句:
inc dword ptr [10003000] 應該改成 inc dword ptr [20003000]

注意,重定位的算法我們可以總結爲:將直接尋址指令中的雙字地址加上模塊的實際裝入地址與模塊建議裝入地址之差。

從上邊的信息中我們看到,需要進行重定位需要三個因素:

1. 需要修正的地址(10003000h)
2. 建議裝入的地址(10003000h)
3. 實際裝入的地址(20003000h)


問題五:這些信息哪些應該被保存在重定位表中?

聰明的我們可以發現:
1. 建議裝入的地址在PE 文件頭中已經定義了
2. 實際裝入的地址在沒有被裝載器裝入我們根本無從得知,也就是說這事天不知地不知我們不知只有裝載器知道……

因此,我們可以得到的結論是:
PE 文件的重定位表(Base Relocation Table)中保存的就是文件中所有需要進行重定位修正的代碼的地址。


基址重定位結構表

IMAGE_BASE_RELOCATION STRUC

 VirtualAddress        DWORD        ?  ; 重定位數據開始的RVA 地址
 SizeOfBlock           DWORD        ?  ; 重定位塊得長度
 TypeOffset            WORD          ?  ;  重定項位數組

IMAGE_BASE_RELOCATION  ENDS

VirtualAddress 是 Base Relocation Table 的位置它是一個 RVA 值;
SizeOfBlock 是 Base Relocation Table 的大小

TypeOffset 是一個數組,數組每項大小爲兩個字節(16位),它由高 4位和低 12位組成,高 4位代表重定位類型,低 12位是重定位地址,它與 VirtualAddress 相加即是指向PE 映像中需要修改的那個代碼的地址。

IMAGE_REL_BASED_ABSOLUTE           (0) 使塊按照32位對齊,位置爲0。
IMAGE_REL_BASED_HIGH                    (1) 高16位必須應用於偏移量所指高字16位。
IMAGE_REL_BASED_LOW                     (2) 低16位必須應用於偏移量所指低字16位。
IMAGE_REL_BASED_HIGHLOW            (3) 全部32位應用於所有32位。
IMAGE_REL_BASED_HIGHADJ             (4) 需要32位,高16位位於偏移量,低16位位於下一個偏移量數組元素,組合爲一個帶符號數,加上32位的一個數,然後加上8000然後把高16位保存在偏移量的16位域內。
IMAGE_REL_BASED_MIPS_JMPADDR  (5)  Unknown
IMAGE_REL_BASED_SECTION             (6)  Unknown
IMAGE_REL_BASED_REL32                   (7)  Unknown




輸出表結構實例分析(具體過程將在視頻中演示,這裏不囉嗦啦~)

工具:PEinfo.exe, UltraEdit, W32DasmV10.0
解剖對象:Counter.dll

發佈了19 篇原創文章 · 獲贊 14 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章