使用ollydbg從零開始cracking第三十三章神馬是iat如何修復_第1頁
使用ollydbg從零開始cracking第三十三章神馬是iat如何修復_第2頁
使用ollydbg從零開始cracking第三十三章神馬是iat如何修復_第3頁
使用ollydbg從零開始cracking第三十三章神馬是iat如何修復_第4頁
使用ollydbg從零開始cracking第三十三章神馬是iat如何修復_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

在介紹如何修復IAT之前,我們首先來介紹一下IAT的相關(guān)基本概念,本章的實驗對象依然是Cruehead的CrackMe。首先我們來定位該程序的IAT位于何處,然后再來看看對其加了UPX的殼后,IAT又位于何處。什么是我們知道每個API函數(shù)在對應(yīng)的進程空間中都有其相應(yīng)的地址,例如:我們用OD加載Cruehead的CrackMe,在命令欄中輸入大家可以看到在我的機器上,MeageBoxA這個AI函數(shù)的地址為77504E,如果大家在自己的機器上面定位到這個地址的話,可能有部分人的機器上該地址對應(yīng)的還是MeageBoxA的地址,而另外一部分人的機器上該地址對應(yīng)的就不是MeageBoxA的地址了,這取決于大家機器的操作系統(tǒng)版本,以及打補丁的情況。眾所周知,操作系統(tǒng)動態(tài)庫版本的更新,其包含的I函數(shù)地址通常也會改變。比如User32我們就拿Cuehead的CackMe中的MeageoxA這個PI函數(shù)來說吧,其地址為77504E,在我的機器上運行的很好,那些跟作系統(tǒng)版本以及e32dll版本相同的童鞋的機器上該程序運行可能也很正常,但是如果在操作系統(tǒng)版本或者e32dll的版本跟我的不同童鞋的機器上運行,可能就會出錯。為了解決以上兼容問題,操作系統(tǒng)就必須提供一些措施來確保該CackMe可以在其他版本的indos操作系統(tǒng),以及LL版本下也能正常運行。這時IAT(ImportAddressTable:輸入函數(shù)地址表)就應(yīng)運而生大家不要覺得其名字很霸氣,就會問是不是很難?其實不然。接下來我們一起來探討一下如何在脫殼過程中定位IAT我們現(xiàn)在通過在反匯編窗口中單擊鼠標右鍵選擇-Searchfor-Allintermodularcalls來看看主模塊中調(diào)用了哪些模塊以及API函數(shù)這里我們可以看到有幾處調(diào)用了MessageBoxA,我們在第一個MessageBoxA調(diào)用處雙擊鼠標左鍵反匯編窗口就會馬上定位到該調(diào)用處,OD提示窗口中顯示其實際調(diào)用的是4013A處的MPER32MeageBox,這里用尖括號括起來了,說明這里是直接調(diào)用,而非間接調(diào)用。這里其實CALL40143A,顯示為CALL<JMP&USER32MessageBoxA>大家可能會覺得不太直觀。這里我們Debuggingoptions菜單項:Disasm頁中的Showsysmbolicaddresses選項被勾選上了,如果我們?nèi)サ粼搶?將不會顯示函數(shù)地址我們可以看到右邊的注釋窗口中同樣顯示了API函數(shù)的參數(shù)以及函數(shù)名稱,比剛剛顯示符號地址看起來更直觀,一眼就可以看出CALLSearchfor-Allintermodularcalls窗口中顯示如下我們可以看到這里有三處通過CALL40143A調(diào)用MessageBoxA,我們定位到40143A處看看是什么這里我們可以看到是一個間接跳轉(zhuǎn)。JMP這里我們再次勾選上顯示符號地址的選項,可以更加直觀的看出其調(diào)用的API函數(shù)這里有意思的地方就來了,我們看到MP4031C4031C這個內(nèi)存單元中保存的數(shù)值才是MeageBoxA真正的地址)。我們還可以看到很多類似的間接MP。這就是為了解決各操作系統(tǒng)之間的兼容問題而設(shè)計的,當程序需要調(diào)用某API函數(shù)的時候,都是通過一個間接跳轉(zhuǎn)來調(diào)用的,讀取某個地址中保存的API函數(shù)地址,然后調(diào)用之。我們現(xiàn)在在數(shù)據(jù)窗口中定位到4031AC地址處,看看該內(nèi)存單元中存放的是什這里我們可以看到,4031C中保存的是77504E,這一片區(qū)域包含了該程序調(diào)用的所有AI函數(shù)的地址,這塊區(qū)域我們稱之為T導入函數(shù)地址表這里就是解決不同版本操作系統(tǒng)間調(diào)用I兼容問題的關(guān)鍵所在,該程序在不同版本操作系統(tǒng)上都是調(diào)用間接跳轉(zhuǎn)到IAT表中,在IAT中到真正的API函數(shù)地址,然后調(diào)用之,所以說只需要將不同系統(tǒng)中的API函數(shù)地址填充IAT中,這樣就可以確保不同版本系統(tǒng)調(diào)用的都是正確的API函數(shù)。有些人可能會問,4031AC這個地址在不同機器上也可能會不同的吧呵呵,這個問題提的非常好,我們一起來看看操作系統(tǒng)將正確的API函數(shù)地址填充到IAT中的具體原理,大家就會明白了這里我們4031AC中保存的內(nèi)容,單擊鼠標右鍵選擇-Viewexecutablefile,就能看到4031AC這個虛擬地址對應(yīng)于可執(zhí)行文件我們可以看到在可執(zhí)行文件對應(yīng)文件偏移處中的內(nèi)容為60330000,當程序運行起來的時候,0FAC這個文件偏移對應(yīng)的虛擬地址處就會被填EA04D577,也就是說該CrackMe進程空間中的4031AC地址處會被填入正確的API函數(shù)地址。有這么神奇indos操作系統(tǒng)當可執(zhí)行文件被加載到進程所在內(nèi)存空間中時,會將正確的I函數(shù)地址填充到T中,這里就是4031C中被填入了MeageBoxA的地址,其他T項也會被填入對應(yīng)的I函數(shù)地址。其作系統(tǒng)并沒有大家想象得的那么神奇,我們看到0FAC文件偏移處的值3360,該數(shù)值其實是RVA(相對虛擬地址),其指向?qū)?yīng)的API函數(shù)名稱。這里3360加上映像基址即403360,我們定位到403360處,看看是什么這里我們可以看到指向的是MeageBoxA這個字符串,也就是說操作系統(tǒng)可以根據(jù)這個指針,定位到相應(yīng)的AI函數(shù)名稱,然后通過調(diào)用etocddes獲取對應(yīng)I函數(shù)的地址,然后將該地址填充到T中,覆蓋原來的3360,IT中被填充了正確的AI函數(shù)地址。如果我們換一臺機器,定位到4031C處可能會看到里面存放著不同的地址。JMP這樣就能夠調(diào)用MeageBoxA了,大家可能會覺得這個過程很復雜,其實填充T的過程都是操作系統(tǒng)幫我們完成的,在程序開始執(zhí)行前,T已經(jīng)被填入了正確的I函數(shù)地址。也就是說,為了確保操作系統(tǒng)將正API函數(shù)地址填充到IAT中,應(yīng)該滿足一下幾點要求:1:可執(zhí)行文件各IAT項所在的文件偏移處必須是一個指針,指向一個字符串。2:該字符串為API函數(shù)的名稱如果這兩項滿足,就可以確保程序在啟動時,操作系統(tǒng)會將正確的I函數(shù)地址填充到T中后面會詳細介紹操作系統(tǒng)是如何填充T的。假如,我們當前位于被加殼程序的EP處,我們接下來可以將程序dup出來,但是在dup之前須修復,為什么要修復T呢?難道殼將T破壞了嗎?對,的確是這樣,殼壓根不需要原程序的,因為被加殼程序首先會執(zhí)行例程,T中所需要的PI的名稱指針,然后定位到PI函數(shù)地址,將其填入到T中,這個時候,T中已經(jīng)被填充了正確的PI函數(shù)地址,對應(yīng)的I函數(shù)名稱的字符串已經(jīng)不需要了,可以清除掉。大部分的殼會將PI函數(shù)名稱對應(yīng)的字符串以密文的形式保存到某個地址處,讓Cacker們不能那么容易找到它們。下面我們來看看CackMeX這個程序,在dup之前我們需要修復T。我們定位到4031AC處-原程序MessageBoxA地址的存放處是空的,那么403360指向的字符串呢也是空的,我們跟到EP處,再來看看這幾個地址處有沒有內(nèi)容,我們知道原程序在運行之前,T必須被填充上正確的AI函數(shù)地址。JMP如果此時IAT還是空的話,那么程序運行起來就會出錯,我們現(xiàn)在定位到OEP我們在這個JMPOEP指令處設(shè)置一個斷點,運行起來,接著來看看我們可以看到殼的例程已經(jīng)將正確的API函數(shù)地址填充到原程序的T中,如果這個時候程序dup出來的話,運行會出錯,因為dup出來的程序啟動所必須的數(shù)據(jù)是不完整的。我們現(xiàn)在來看看各個API函數(shù)名稱,定位到403360處,會發(fā)現(xiàn)是空的現(xiàn)在我們dump出來看看,dump出來的原程序代碼肯定是正確的,但是程序仍然無法正常運行,因為缺少數(shù)據(jù),操作系統(tǒng)無法Dump的話我們需要用到一個工具,名字叫做LordPE(PS:大家應(yīng)該用的很多吧)我們運行LordPE,定位到需要dumpCRACKMEUPX所在的進程,當前該進程處于OEP處選中CRACKMEUPX所在的進程我們單擊鼠標右鍵選擇-activedumpengine-InliDump-Select!。接著選擇dumpfulldump出來的程序命名為dumpedexe。如果我們直接運行dumpedexe的話會發(fā)現(xiàn)無法啟動,嘗試用OD加載dumpedexe,OD會報錯,我們來看看日志窗口中的錯誤信息這里我們機器上提示錯誤發(fā)現(xiàn)在7C929913地址處,我們定位到該地址(大家可以根據(jù)自己機器上顯示的錯誤地址自行定位)這里我們可以給這一行設(shè)置一個硬件執(zhí)行斷點或者INT3斷點,即當斷在這一行時看看錯誤發(fā)生之前是什么狀況我們運行起來,會發(fā)現(xiàn)沒有斷在這一行,這是因為勾選了忽略異常選項的緣故,這里我們?nèi)サ艉雎援惓_x項的對勾,重新運行起來斷了下來,我們可以看到該錯誤是在到達點之前產(chǎn)生的,所以dumpedexe無法正常運行,我們現(xiàn)在來看看IAT的情況我們可以看到當前雖然在我的機器上API函數(shù)的地址被填I(lǐng)AT中,但是想要正常運行在其他機器上的話,必須要指向各個API函數(shù)名稱字符串的指針,這樣才是確保操作系統(tǒng)能夠通過GetProcAddress獲取到正確的API函數(shù)地址并填充到IAT中。這里該dumpedexe缺少這些指向API函數(shù)名稱字符串的指針,所以運行的時候會發(fā)生錯誤。這里大家不要嘗試先dump出來,然后再恢復各個API函數(shù)的名稱字符串以及其指針,如果這樣手工修復的話,是一件極其的工作,你需要將4031AC地址處的內(nèi)容修改為MessageBoxA這個字符串的指針,IAT中的其他項也要進行相應(yīng)的處理。比較明智的做法是,dump出來之前就將IAT修復了我們知道dump出來的代碼肯定是正確的,我們定位到401000處看一看我們看到API函數(shù)的調(diào)用處,40135C地址處應(yīng)該是調(diào)用的MessageBoxA我們定位到40143A處,這里依然是通過一個間接跳轉(zhuǎn)這些間接跳轉(zhuǎn)是無法正常運行的因為在正常情況,操作系統(tǒng)必須知道指向各個API函數(shù)名稱字符串的指針,然后通過GetProcAddress定位到各個API函數(shù)正確的地址并填充到IAT中,這樣這些間接跳轉(zhuǎn)才能起作用。下面我們來看看未加殼程序的IAT。我們用OD加載CrueheadCrackMe我們來定位該CrackMePE結(jié)構(gòu)中一些重要字段。首先在數(shù)據(jù)窗口中定位400000地址處單擊鼠標右鍵選擇-Special-PEheader切換到PE頭的顯示模往下拉我們可以看到PE頭的偏移為100PE頭位于400100地址處繼續(xù)往下拉,我們可以看到IT(導入表)的指針,這里大家不要將其跟IAT搞了IT=IAT=輸入函數(shù)地址我們知道當程序啟動之前操作系統(tǒng)會將API函數(shù)的地址填充到IAT中,那么IT(導入表)又是怎么一回事呢?首先我們定位到導入表,該導入表偏移值為3000(即虛擬地址為403000),長度為670(十六進制),403670為導入表的結(jié)尾。我們一起來看一看。這就是導入表了,我們來介紹一下導入表的結(jié)構(gòu)吧我們選中的這20個字節(jié)是導入表的描述符結(jié)構(gòu)。的叫法為IMAGE_IMPORT_DESCRIPTOR。每組為20個字節(jié),IMAGE_IMPORT_DESCRIPTOR包含了一個的字符串指針,該指針指向了某個的動態(tài)庫名稱字符串。我們來看個例子這里IMAGE_IMPORT_DESCRIPTOR簡稱為IID。這里選中的部分為導入表中的第一個IID。其中5個DWORD字段的 時間 鏈表的前一個結(jié) 指向DLL名稱的指itThunk 指向的鏈表定義了針對ae1這個動態(tài)庫引入的所有導入函數(shù)前三個字段不是很重要,對于我們Cacker來說,我們只對第4,5字段感。正如大家所看到的,第4個字段為指向DLL名稱字符串的指針,我們來看看403290處是哪個DLL的名稱這里我們可以看到是USER32DLL,5個字段指向了USER32DLL對應(yīng)IAT項的起始地址,403184這里就是IAT了,導入表的結(jié)束地址為403670。導入表中的每個IID項指明了DLL的名稱以及其對應(yīng)IAT項的起始地址。緊湊大量實驗表明,T并不一定位于在導入表中。T可以位于程序中任何具有寫權(quán)限的地方,只要當可執(zhí)行程序運行起來時,操作系統(tǒng)可以定位到這些ID項,然后根據(jù)T中標明的I函數(shù)名稱獲取到函數(shù)地址即可。下面我們來總結(jié)一下操作系統(tǒng)填充T的具體步驟:1:定位導入2:解析第一個IID項,根據(jù)IID中的第4個字段定位DLL的名3:根據(jù)IID項的第5個字段DLL對應(yīng)的IAT項的起始地4:根據(jù)IAT中的指針定位到相應(yīng)API函數(shù)名稱字符5:通過GetProcAddress獲取API函數(shù)的地址并填充到IAT6:當定位到的IAT項為零的時候表示該DLL的API函數(shù)地址獲取完畢了,接著繼續(xù)解析第二個IID,重復上面的步驟。定位導入定位到導入表的起始根據(jù)第一個IID項中的第段得到DLL名稱字符串的指針,這里指向的是USER32根據(jù)第五個字段的內(nèi)容定位到IAT項的起始地址,這里是403184,我們定位到該地址處這里我們可以看到已經(jīng)被填充了正確的AI函數(shù)的地址,跟我們dup出來的結(jié)果一樣,我們再來看看相應(yīng)的可執(zhí)行文件偏移處的內(nèi)容是什么。這里我們可以看到第一個API函數(shù)的名稱位于4032CC地址處,我們定位到該地址處第一個API函數(shù)是KillTimer,我們在OD中看到的KillTimer的地址是操作系統(tǒng)調(diào)用GetProcAddress獲取到的這里我們可以看到KillTimer的地址為77D18C42。該地址將被填充到IAT相應(yīng)單元中去覆蓋原來的值這里是IAT中的第一元我們再來看下一個元素,向后偏移4就是,來看一看該API函數(shù)名稱字符串的指針是多少定位到可執(zhí)行文件的相應(yīng)偏移

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論