Windows PE第6章 栈与重定位表
第六章?棧與重定位表
? ? 本章主要介紹棧和代碼重定位。站和重定位表兩者并沒有必然的聯(lián)系,但都和代碼有關(guān)。棧描述的是代碼運行過程中,操作系統(tǒng)為調(diào)度程序之間相互調(diào)用關(guān)系,或臨時存放操作數(shù)而設(shè)置的一種數(shù)據(jù)結(jié)構(gòu)。重定位表則是在一個PE中的代碼被加載到任意一個內(nèi)存地址時,用來描述相關(guān)操作數(shù)地址變化規(guī)律的數(shù)據(jù)結(jié)構(gòu)。通過重定位技術(shù),代碼運行在內(nèi)存中的任意位置時,可以避免因操作數(shù)的定位錯誤而導(dǎo)致失敗。
6.1棧
? ? 前面基本概念直接過...
? ? 程序在運行的時候會為系統(tǒng)分配一塊內(nèi)存區(qū)域作為棧,由棧選擇子SS和棧定指針(esp)來確定當(dāng)前棧的大小,CPU則直接操作EBP來存取數(shù)據(jù)。
內(nèi)存中棧結(jié)構(gòu)如下:
?
? ? 壓棧時根據(jù)壓入的數(shù)據(jù)類型的字節(jié)大小,將ESP減少相應(yīng)的字節(jié)數(shù),如壓入一個雙子,則ESP-4。
? ? 相反出棧的時候是esp增加相應(yīng)的字節(jié)數(shù),如彈出一個雙字,則esp+4。
6.1.1??棧的應(yīng)用場合
(1)保存臨時的值
?Push?eax
?......
?Pop?eax
?
(2)保存程序現(xiàn)場
?CALL?_subPrg
? ? 當(dāng)指令執(zhí)行時,會將緊跟在CALL指令后面的下一條指令地址壓入棧,以便于程序在調(diào)用完以后,能正確放回到主程序繼續(xù)運行<shell?code?常用>。
(3)
? ? 傳遞函數(shù)參數(shù)
?看下面的MessageBox調(diào)用反匯編
?
下面是壓棧以后的示意圖。
? ? 當(dāng)子程序結(jié)束以后,會調(diào)用ret指令返回,eip隨之被彈出。為了平衡棧,需要調(diào)用者使用如下語句將傳入的參數(shù)一一彈出:
Add?esp,0010h??;4個整型
(4)存放過程中的局部變量
進(jìn)入一個過程后,會定義很多局部變量,而局部變量的存放處也是棧。為局部變量在棧中申請的內(nèi)存區(qū)域成為緩沖區(qū)。當(dāng)過程結(jié)束以后,局部變量將從棧中刪除,恢復(fù)到進(jìn)入過程最初狀態(tài)。也就是說,局部變量在過程結(jié)束以后就自動被釋放了,原因是CPU調(diào)整了棧的棧頂指針esp。
6.1.3??棧溢出
? ? 所謂棧溢出,是指由于程序沒有考慮棧中定義的局部數(shù)據(jù)塊的大小,而向該數(shù)據(jù)塊寫入了過多的數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)越界,覆蓋了棧中的已存在的其他數(shù)據(jù)的技術(shù)。這里可以shellcode,細(xì)節(jié)不說了,之前單獨總結(jié)過這里。后面都是基本定義,直接跳過,直接看重定位。
6.2??代碼重定位
? ? 代碼重定位是把可執(zhí)行代碼從內(nèi)存的一個地方移動到另一個地方去,保證該部分代碼還能正常執(zhí)行的一種技術(shù)。用于補丁和病毒程序開發(fā)。
6.2.1??重定位的提出
? ? 可執(zhí)行代碼從內(nèi)存的一個地方移動到另一個地方,所有的字節(jié)均保持不變;如果代碼指令中的某些操作數(shù)不跟隨著地址發(fā)生改變,勢必會導(dǎo)致程序運行出錯。這里的某些操作是指那些使用了絕對地址定位的程序指令中的操作數(shù)。如下:
????從上面可以看出,全局變量訪問直接采用了絕對地址。如果直接把這部分機器碼拷貝到另一個位置,直接執(zhí)行會出問題的,因為需要我們重新給代碼定位才可以。
6.2.2??實現(xiàn)重定位的方法
先看書上的姿勢:
???是這樣的,大體就是用相對偏移來算的,然后下面給了特長一段來解釋這個,看了半天有點暈,我自己大體猜了下,然后用C++還原了這個場景。
C++代碼(就直接拿上面用過的那個例子):
然后看下反匯編:
? ? 注意被圈上的那一行,后面那個***ds:[00104F18h]是直接用的映地址寫的,每次編譯都是隨機的,我看上面書上的意思是可以根據(jù)棧彈出來的位置,也就是函數(shù)里面的某個位置來偏移過去,于是我們可以驗證下,直接還是看上面紅色框的部分,注意這兩個值:
?
前面是代碼地址,后面是全局變量地址,我在想,這兩個差是不是固定的,于是就奪取了幾組,發(fā)現(xiàn)差真的是固定的。
00C815D4??mov?????????eax,dword?ptr?ds:[00C94F18h]??13944
000515D4??mov?????????eax,dword?ptr?ds:[00064F18h]??13944
000F15D4??mov?????????eax,dword?ptr?ds:[00104F18h]??13944
? ? so應(yīng)該大體知道啥姿勢了,于是模擬一發(fā):
? ? 先計算下偏移量:
? ? 得到如下結(jié)果:
pFunAddMark?=?0x001a15c0?{TEST_CPP_.exe!wmain(int,?wchar_t?*?*)}
pnNumber?=?0x001b4f18?{TEST_CPP_.exe!int?g_nNumber}?{1111}
? ? 然后字節(jié)嘗試測試一發(fā):
? ? 這樣看來結(jié)果沒啥問題,如果我沒理解錯書上的那一坨匯編的話,應(yīng)該就是這么個意思,如果理解有誤希望大家留言提醒我,一起學(xué)習(xí)。
6.3??PE頭文件中的重定位表
? ? 重定位信息是在編譯的時候,由編譯器生成并被保留在可執(zhí)行文件中。當(dāng)程序執(zhí)行前,操作系統(tǒng)會根據(jù)這些重定位信息對代碼予以修正,復(fù)雜的操作由編譯器和操作系統(tǒng)代替程序完成。程序被裝入內(nèi)存時,其基址是由字段IMAGE——OPTIONAL_HEADER32.imageBase決定的:
但是,如果當(dāng)裝載時該位置已經(jīng)被別的程序使用,那么操作系統(tǒng)就有權(quán)重新選擇一個基地址。這時候就需要對所有的重定位信息進(jìn)行修正,而修正的依據(jù)就是PE中的重定位表。
6.3.1??重定位表定義
重定位表為數(shù)據(jù)目錄中注冊的數(shù)據(jù)類型之一,其描述信息處于數(shù)據(jù)目錄項的第6個目錄項中:
通過上面,得到信息:
重定位表所在地址RVA=0x00018000
重定位表數(shù)據(jù)大小????=0x000010C4
結(jié)合這個:
說明存在了.reloc段。
然后根據(jù)RVA計算FOA:
FOA?=?0x12C00
6.3.2??重定位表項IMAGE_BASE_RELOCATION
? ? 與導(dǎo)入表類似,重定位表指針指向的位置是一個數(shù)組,而不像導(dǎo)出表一樣只有一個結(jié)構(gòu)。這個數(shù)組中的每一項都是如下結(jié)構(gòu):
IMAGE_BASE_RELOCATION?STRUCT
??VirtualAddress??dd?????;重定位內(nèi)存頁的起始RVA
??SizeOfBlock????dd?????;重定位塊的長度
IMAGE_BASE_RELOCATION?ENDS
? ? 解釋下這兩項:
? ? MAGE_BASE_RELOCATION.VirtualAddress
? ? +0000h,雙字。重定位塊RVA.由于直接尋址指令較多,所以在一些PE文件中,存在大量的需要修正的重定位地址。按照常規(guī)計算,每個地址占4字節(jié),如果有n個重定位項,那么需要總的空間為4*n字節(jié)。重新審視直接尋址中的地址發(fā)現(xiàn),在一頁中的所有地址只需要12位(因為Win32頁面大小為10000h,也就是4096字節(jié),即2的12次方)。
? ? 而這12位只需要用兩個字就能表達(dá)出來。如果有n個重定位項,則只需要2*n個地址+4字節(jié)頁面起始RVA+4字節(jié)的本業(yè)的重定位項長度。將以上兩種情況的表達(dá)式:
Sum0=4*n
Sum1=2*n+4+4
? ? 很明顯,當(dāng)有大量的重定位地址時,Sum0遠(yuǎn)大于Sum1。事實上,為了節(jié)約存儲空間,重定位表的存儲方式選擇第二種方式。字段IMAGE_BASE_RELOCATION.VirtualAddress就是表達(dá)式Sum1中的第一個4,也就是頁面起始RVA。
IMAGE_BASE_RELOCATION.SizeOfBlock
+0004h,雙字。重定位塊中重定位表項長度。該字段是表達(dá)式Sum1里的第二個4.
? ? 數(shù)組和數(shù)組之間并不是相鄰的。比如頁面1的IMAGE_BASE_RELOCATION后并不是頁面2的IMAGE_BASE_RELOCATION,而是頁面1的所有重定位表項;每個項大小為一個字,每個字的高四位被用來說明此重定位的類型,剩下的十二位才是需要重定位的數(shù)據(jù)在頁面中的地址。高四位含義如下:
? ?在實際的PE文件中,我們只能看到0和3這兩種情況,也就是說要么是對其用的,要么是需要全部修正的。
6.3.3??重定位表的結(jié)構(gòu)
?
?
總結(jié)
以上是生活随笔為你收集整理的Windows PE第6章 栈与重定位表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TLS实现代码段加密
- 下一篇: java信息管理系统总结_java实现科