版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
外掛編寫必備工具2——OllyDBG(OD)入門系列1OllyDBG入門系列(一)-認(rèn)識OllyDBG一、OllyDBG的安裝與配置OllyDBG1.10版的發(fā)布版本是個ZIP壓縮包,只要解壓到一個目錄下,運行OllyDBG.exe就可以了。漢化版的發(fā)布版本是個RAR壓縮包,同樣只需解壓到一個目錄下運行OllyDBG.exe即可:OllyDBG中各個窗口的功能如上圖。簡單解釋一下各個窗口的功能,更詳細(xì)的內(nèi)容可以參考TT小組翻譯的中文幫助:反匯編窗口:顯示被調(diào)試程序的反匯編代碼,標(biāo)題欄上的地址、HEX數(shù)據(jù)、反匯編、注釋可以通過在窗口中右擊出現(xiàn)的菜單界面選項->隱藏標(biāo)題或顯示標(biāo)題來進(jìn)行切換是否顯示。用鼠標(biāo)左鍵點擊注釋標(biāo)簽可以切換注釋顯示的方式。寄存器窗口:顯示當(dāng)前所選線程的CPU寄存器內(nèi)容。同樣點擊標(biāo)簽寄存器(FPU)可以切換顯示寄存器的方式。信息窗口:顯示反匯編窗口中選中的第一個命令的參數(shù)及一些跳轉(zhuǎn)目標(biāo)地址、字串等。數(shù)據(jù)窗口:顯示內(nèi)存或文件的內(nèi)容。右鍵菜單可用于切換顯示方式。堆棧窗口:顯示當(dāng)前線程的堆棧。要調(diào)整上面各個窗口的大小的話,只需左鍵按住邊框拖動,等調(diào)整好了,重新啟動一下OllyDBG就可以生效了。啟動后我們要把插件及UDD的目錄配置為絕對路徑,點擊菜單上的選項->界面,將會出來一個界面選項的對話框,我們點擊其中的目錄標(biāo)簽:因為我這里是把OllyDBG解壓在F:\OllyDBG目錄下,所以相應(yīng)的UDD目錄及插件目錄按圖上配置。還有一個常用到的標(biāo)簽就是上圖后面那個字體,在這里你可以更改OllyDBG中顯示的字體。上圖中其它的選項可以保留為默認(rèn),若有需要也可以自己修改。修改完以后點擊確定,彈出一個對話框,說我們更改了插件路徑,要重新啟動OllyDBG。在這個對話框上點確定,重新啟動一下OllyDBG,我們再到界面選項中看一下,會發(fā)現(xiàn)我們原先設(shè)置好的路徑都已保存了。有人可能知道插件的作用,但對那個UDD目錄不清楚。我這簡單解釋一下:這個UDD目錄的作用是保存你調(diào)試的工作。比如你調(diào)試一個軟件,設(shè)置了斷點,添加了注釋,一次沒做完,這時OllyDBG就會把你所做的工作保存到這個UDD目錄,以便你下次調(diào)試時可以繼續(xù)以前的工作。如果不設(shè)置這個UDD目錄,OllyDBG默認(rèn)是在其安裝目錄下保存這些后綴名為udd的文件,時間長了就會顯的很亂,所以還是建議專門設(shè)置一個目錄來保存這些文件。另外一個重要的選項就是調(diào)試選項,可通過菜單選項->調(diào)試設(shè)置來配置:新手一般不需更改這里的選項,默認(rèn)已配置好,可以直接使用。建議在對OllyDBG已比較熟的情況下再來進(jìn)行配置。上面那個異常標(biāo)簽中的選項經(jīng)常會在脫殼中用到,建議在有一定調(diào)試基礎(chǔ)后學(xué)脫殼時再配置這里。除了直接啟動OllyDBG來調(diào)試外,我們還可以把OllyDBG添加到資源管理器右鍵菜單,這樣我們就可以直接在.exe及.dll文件上點右鍵選擇“用Ollydbg打開”菜單來進(jìn)行調(diào)試。要把OllyDBG添加到資源管理器右鍵菜單,只需點菜單選項->添加到瀏覽器,將會出現(xiàn)一個對話框,先點擊“添加Ollydbg到系統(tǒng)資源管理器菜單”,再點擊“完成”按鈕即可。要從右鍵菜單中刪除也很簡單,還是這個對話框,點擊“從系統(tǒng)資源管理器菜單刪除Ollydbg”,再點擊“完成”就行了。OllyDBG支持插件功能,插件的安裝也很簡單,只要把下載的插件(一般是個DLL文件)復(fù)制到OllyDBG安裝目錄下的PLUGIN目錄中就可以了,OllyDBG啟動時會自動識別。要注意的是OllyDBG1.10對插件的個數(shù)有限制,最多不能超過32個,否則會出錯。建議插件不要添加的太多。到這里基本配置就完成了,OllyDBG把所有配置都放在安裝目錄下的ollydbg.ini文件中。二、基本調(diào)試方法OllyDBG有三種方式來載入程序進(jìn)行調(diào)試,一種是點擊菜單文件->打開(快捷鍵是F3)來打開一個可執(zhí)行文件進(jìn)行調(diào)試,另一種是點擊菜單文件->附加來附加到一個已運行的進(jìn)程上進(jìn)行調(diào)試。注意這里要附加的程序必須已運行。第三種就是用右鍵菜單來載入程序(不知這種算不算)。一般情況下我們選第一種方式。比如我們選擇一個test.exe來調(diào)試,通過菜單文件->打開來載入這個程序,OllyDBG中顯示的內(nèi)容將會是這樣:調(diào)試中我們經(jīng)常要用到的快捷鍵有這些:外掛編寫必備工具2——OllyDBG(OD)入門系列2OllyDBG入門系列(二)-字串參考上一篇是使用入門,現(xiàn)在我們開始正式進(jìn)入破解。今天的目標(biāo)程序是看雪兄《加密與解密》第一版附帶光盤中的鏡像打包中的CFFCrackme#3,采用用戶名/序列號保護(hù)方式。原版加了個UPX的殼。剛開始學(xué)破解先不涉及殼的問題,我們主要是熟悉用OllyDBG來破解的一般方法。我這里把殼脫掉來分析,附件是脫殼后的文件,直接就可以拿來用。先說一下一般軟件破解的流程:拿到一個軟件先別接著馬上用OllyDBG調(diào)試,先運行一下,有幫助文檔的最好先看一下幫助,熟悉一下軟件的使用方法,再看看注冊的方式。如果是序列號方式可以先輸個假的來試一下,看看有什么反應(yīng),也給我們破解留下一些有用的線索。如果沒有輸入注冊碼的地方,要考慮一下是不是讀取注冊表或Key文件(一般稱keyfile,就是程序讀取一個文件中的內(nèi)容來判斷是否注冊),這些可以用其它工具來輔助分析。如果這些都不是,原程序只是一個功能不全的試用版,那要注冊為正式版本就要自己來寫代碼完善了。有點跑題了,呵呵。獲得程序的一些基本信息后,還要用查殼的工具來查一下程序是否加了殼,若沒殼的話看看程序是什么編譯器編的,如VC、Delphi、VB等。這樣的查殼工具有PEiD和FI。有殼的話我們要盡量脫了殼后再來用OllyDBG調(diào)試,特殊情況下也可帶殼調(diào)試。下面進(jìn)入正題:我們先來運行一下這個crackme(用PEiD檢測顯示是Delphi編的),界面如圖:這個crackme已經(jīng)把用戶名和注冊碼都輸好了,省得我們動手^_^。我們在那個“Registernow!”按鈕上點擊一下,將會跳出一個對話框:好了,今天我們就從這個錯誤對話框中顯示的“WrongSerial,tryagain!”來入手。啟動OllyDBG,選擇菜單文件->打開載入CrackMe3.exe文件,我們會停在這里:我們在反匯編窗口中右擊,出來一個菜單,我們在查找->所有參考文本字串上左鍵點擊:當(dāng)然如果用上面那個超級字串參考+插件會更方便。但我們的目標(biāo)是熟悉OllyDBG的一些操作,我就盡量使用OllyDBG自帶的功能,少用插件。好了,現(xiàn)在出來另一個對話框,我們在這個對話框里右擊,選擇“查找文本”菜單項,輸入“WrongSerial,tryagain!”的開頭單詞“Wrong”(注意這里查找內(nèi)容要區(qū)分大小寫)來查找,找到一處:在我們找到的字串上右擊,再在出來的菜單上點擊“反匯編窗口中跟隨”,我們來到這里:見上圖,為了看看是否還有其他的參考,可以通過選擇右鍵菜單查找參考->立即數(shù),會出來一個對話框:分別雙擊上面標(biāo)出的兩個地址,我們會來到對應(yīng)的位置:00440F79|.BA8C104400MOVEDX,CrackMe3.0044108C;ASCII"WrongSerial,tryagain!"00440F7E|.A1442C4400MOVEAX,DWORDPTRDS:[442C44]00440F83|.8B00MOVEAX,DWORDPTRDS:[EAX]00440F85|.E8DEC0FFFFCALLCrackMe3.0043D06800440F8A|.EB1800440F8C|>6A00JMPSHORTCrackMe3.00440FA4PUSH000440F8E|.B980104400MOVECX,CrackMe3.0044108000440F93|.BA8C104400MOVEDX,CrackMe3.0044108C;ASCII"WrongSerial,tryagain!";ASCII"Beggaroff!"00440F98|.A1442C4400MOVEAX,DWORDPTRDS:[442C44]00440F9D|.8B00MOVEAX,DWORDPTRDS:[EAX]00440F9F|.E8C4C0FFFFCALLCrackMe3.0043D068我們在反匯編窗口中向上滾動一下再看看:00440F2C|.8B45FCMOVEAX,DWORDPTRSS:[EBP-4]00440F2F|.BA14104400MOVEDX,CrackMe3.0044101400440F34|.E8F32BFCFFCALLCrackMe3.00403B2C;ASCII"RegisteredUser";關(guān)鍵,要用F7跟進(jìn)去;這里跳走就完蛋00440F39|.7551JNZSHORTCrackMe3.00440F8C00440F3B|.8D55FCLEAEDX,DWORDPTRSS:[EBP-4]00440F3E|.8B83C8020000MOVEAX,DWORDPTRDS:[EBX+2C8]00440F44|.E8D7FEFDFFCALLCrackMe3.00420E2000440F49|.8B45FCMOVEAX,DWORDPTRSS:[EBP-4]00440F4C|.BA2C104400MOVEDX,CrackMe3.0044102C954";ASCII"GFX-754-IER-00440F51|.E8D62BFCFFCALLCrackMe3.00403B2C;關(guān)鍵,要用F7跟進(jìn)去;這里跳走就完蛋00440F56|.751AJNZSHORTCrackMe3.00440F7200440F58|.6A00PUSH000440F5A|.B93C104400MOVECX,CrackMe3.0044103C;ASCII"CrackMecrackedsuccessfully"00440F5F|.BA5C104400MOVEDX,CrackMe3.0044105C;ASCII"Congrats!YoucrackedthisCrackMe!"00440F64|.A1442C4400MOVEAX,DWORDPTRDS:[442C44]00440F69|.8B00MOVEAX,DWORDPTRDS:[EAX]00440F6B|.E8F8C0FFFFCALLCrackMe3.0043D06800440F70|.EB3200440F72|>6A00JMPSHORTCrackMe3.00440FA4PUSH000440F74|.B980104400MOVECX,CrackMe3.0044108000440F79|.BA8C104400MOVEDX,CrackMe3.0044108C;ASCII"WrongSerial,tryagain!";ASCII"Beggaroff!"00440F7E|.A1442C4400MOVEAX,DWORDPTRDS:[442C44]00440F83|.8B00MOVEAX,DWORDPTRDS:[EAX]00440F85|.E8DEC0FFFFCALLCrackMe3.0043D06800440F8A|.EB1800440F8C|>6A00JMPSHORTCrackMe3.00440FA4PUSH000440F8E|.B980104400MOVECX,CrackMe3.0044108000440F93|.BA8C104400MOVEDX,CrackMe3.0044108C;ASCII"WrongSerial,tryagain!";ASCII"Beggaroff!"00440F98|.A1442C4400MOVEAX,DWORDPTRDS:[442C44]00440F9D|.8B00MOVEAX,DWORDPTRDS:[EAX]00440F9F|.E8C4C0FFFFCALLCrackMe3.0043D068大家注意看一下上面的注釋,我在上面標(biāo)了兩個關(guān)鍵點。有人可能要問,你怎么知道那兩個地方是關(guān)鍵點?其實很簡單,我是根據(jù)查看是哪條指令跳到“wrongserial,tryagain”這條字串對應(yīng)的指令來決定的。如果你在調(diào)試選項->CPU標(biāo)簽中把“顯示跳轉(zhuǎn)路徑”及其下面的兩個“如跳轉(zhuǎn)未實現(xiàn)則顯示灰色路徑”、“顯示跳轉(zhuǎn)到選定命令的路徑”都選上的話,就會看到是從什么地方跳到出錯字串處的:我們在上圖中地址00440F2C處按F2鍵設(shè)個斷點,現(xiàn)在我們按F9鍵,程序已運行起來了。我在上面那個編輯框中隨便輸入一下,如CCDebuger,下面那個編輯框我還保留為原來的“754-GFX-IER-954”,我們點一下那個“Registernow!”按鈕,呵,OllyDBG跳了出來,暫停在我們下的斷點處。我們看一下信息窗口,你應(yīng)該發(fā)現(xiàn)了你剛才輸入的內(nèi)容了吧?我這里顯示是這樣:堆棧SS:[0012F9AC]=00D44DB4,(ASCII"CCDebuger")EAX=00000009上面的內(nèi)存地址00D44DB4中就是我們剛才輸入的內(nèi)容,我這里是CCDebuger。你可以在堆棧SS:[0012F9AC]=00D44DB4,(ASCII"CCDebuger")這條內(nèi)容上左擊選擇一下,再點右鍵,在彈出菜單中選擇“數(shù)據(jù)窗口中跟隨數(shù)值”,你就會在下面的數(shù)據(jù)窗口中看到你剛才輸入的內(nèi)容。而EAX=00000009指的是你輸入內(nèi)容的長度。如我輸入的CCDebuger是9個字符。如下圖所示:現(xiàn)在我們來按F8鍵一步步分析一下:00440F2C|.8B45FCMOVEAX,DWORDPTRSS:[EBP-4];把我們輸入的內(nèi)容送到EAX,我這里是“CCDebuger”00440F2F|.BA14104400MOVEDX,CrackMe3.0044101400440F34|.E8F32BFCFFCALLCrackMe3.00403B2C;ASCII"RegisteredUser";關(guān)鍵,要用F7跟進(jìn)去;這里跳走就完蛋00440F39|.7551JNZSHORTCrackMe3.00440F8C當(dāng)我們按F8鍵走到00440F34|.E8F32BFCFFCALLCrackMe3.00403B2C這一句時,我們按一下F7鍵,進(jìn)入這個CALL,進(jìn)去后光標(biāo)停在這一句:我們所看到的那些PUSHEBX、PUSHESI等都是調(diào)用子程序保存堆棧時用的指令,不用管它,按F8鍵一步步過來,我們只關(guān)心關(guān)鍵部分:00403B2C/$5300403B2D|.5600403B2E|.57PUSHEBXPUSHESIPUSHEDI00403B2F|.89C600403B31|.89D7EDIMOVESI,EAXMOVEDI,EDX;把EAX內(nèi)我們輸入的用戶名送到ESI;把EDX內(nèi)的數(shù)據(jù)“RegisteredUser”送到00403B33|.39D0CMPEAX,EDX;用“RegisteredUser”和我們輸入的用戶名作比較00403B35|.0F848F000000JECrackMe3.00403BCA;相同則跳00403B3B|.85F6TESTESI,ESI;看看ESI中是否有數(shù)據(jù),主要是看看我們有沒有輸入用戶名00403B3D|.746800403B3F|.85FF00403B41|.746BJESHORTCrackMe3.00403BA7TESTEDI,EDIJESHORTCrackMe3.00403BAE;用戶名為空則跳00403B43|.8B46FC00403B46|.8B57FC度送EDX00403B49|.29D0長度相減MOVEAX,DWORDPTRDS:[ESI-4]MOVEDX,DWORDPTRDS:[EDI-4];用戶名長度送EAX;“RegisteredUser”字串的長SUBEAX,EDX;把用戶名長度和“RegisteredUser”字串00403B4B|.7702JASHORTCrackMe3.00403B4F;用戶名長度大于“RegisteredUser”長度則跳00403B4D|.01C2ADDEDX,EAX;把減后值與“RegisteredUser”長度相加,即用戶名長度00403B4F|>5200403B50|.C1EA02度除以4PUSHEDXSHREDX,2;用戶名長度值右移2位,這里相當(dāng)于長00403B53|.7426JESHORTCrackMe3.00403B7B;上面的指令及這條指令就是判斷用戶名長度最少不能低于400403B55|>8B0EECXMOVECX,DWORDPTRDS:[ESI];把我們輸入的用戶名送到外掛編寫必備工具2——OllyDBG(OD)入門系列3OllyDBG入門系列(三)-函數(shù)參考現(xiàn)在進(jìn)入第三篇,這一篇我們重點講解怎樣使用OllyDBG中的函數(shù)參考(即名稱參考)功能。仍然選擇鏡像打包中的一個名稱為CrackHead的crackme。老規(guī)矩,先運行一下這個程序看看:呵,竟然沒找到輸入注冊碼的地方!別急,我們點一下程序上的那個菜單“Shit”(真是Shit啊,呵呵),在下拉菜單中選“TryIt”,會來到如下界面:我們點一下那個“CheckIt”按鈕試一下,哦,竟然沒反應(yīng)!我再輸個“78787878”試試,還是沒反應(yīng)。再試試輸入字母或其它字符,輸不進(jìn)去。由此判斷注冊碼應(yīng)該都是數(shù)字,只有輸入正確的注冊碼才有動靜。用PEiD檢測一下,結(jié)果為MASM32/TASM32,怪不得程序比較小。信息收集的差不多了,現(xiàn)在關(guān)掉這個程序,我們用OllyDBG載入,按F9鍵直接讓它運行起來,依次點擊上面圖中所說的菜單,使被調(diào)試程序顯示如上面的第二個圖。先不要點那個“CheckIt”按鈕,保留上圖的狀態(tài)。現(xiàn)在我們沒有什么字串好參考了,我們就在API函數(shù)上下斷點,來讓被調(diào)試程序中斷在我們希望的地方。我們在OllyDBG的反匯編窗口中右擊鼠標(biāo),在彈出菜單中選擇查找->當(dāng)前模塊中的名稱(標(biāo)簽),或者我們通過按CTR+N組合鍵也可以達(dá)到同樣的效果(注意在進(jìn)行此操作時要在OllyDBG中保證是在當(dāng)前被調(diào)試程序的領(lǐng)空,我在第一篇中已經(jīng)介紹了領(lǐng)空的概念,如我這里調(diào)試這個程序時OllyDBG的標(biāo)題欄顯示的就是“[CPU-主線程,模塊-CrackHea]”,這表明我們當(dāng)前在被調(diào)試程序的領(lǐng)空)。通過上面的操作后會彈出一個對話框,如圖:對于這樣的編輯框中輸注冊碼的程序我們要設(shè)斷點首選的API函數(shù)就是GetDlgItemText及GetWindowText。每個函數(shù)都有兩個版本,一個是ASCII版,在函數(shù)后添加一個A表示,如GetDlgItemTextA,另一個是UNICODE版,在函數(shù)后添加一個W表示。如GetDlgItemTextW。對于編譯為UNCODE版的程序可能在Win98下不能運行,因為Win98并非是完全支持UNICODE的系統(tǒng)。而NT系統(tǒng)則從底層支持UNICODE,它可以在操作系統(tǒng)內(nèi)對字串進(jìn)行轉(zhuǎn)換,同時支持ASCII和UNICODE版本函數(shù)的調(diào)用。一般我們打開的程序看到的調(diào)用都是ASCII類型的函數(shù),以“A”結(jié)尾。又跑題了,呵呵?,F(xiàn)在回到我們調(diào)試的程序上來,我們現(xiàn)在就是要找一下我們調(diào)試的程序有沒有調(diào)用GetDlgItemTextA或GetWindowTextA函數(shù)。還好,找到一個GetWindowTextA。在這個函數(shù)上右擊,在彈出菜單上選擇“在每個參考上設(shè)置斷點”,我們會在OllyDBG窗口最下面的那個狀態(tài)欄里看到“已設(shè)置2個斷點”。另一種方法就是那個GetWindowTextA函數(shù)上右擊,在彈出菜單上選擇“查找輸入函數(shù)參考”(或者按回車鍵),將會出現(xiàn)下面的對話框:看上圖,我們可以把兩條都設(shè)上斷點。這個程序只需在第一條指令設(shè)斷點就可以了。好,我們現(xiàn)在按前面提到的第一條方法,就是“在每個參考上設(shè)置斷點”,這樣上圖中的兩條指令都會設(shè)上斷點。斷點設(shè)好后我們轉(zhuǎn)到我們調(diào)試的程序上來,現(xiàn)在我們在被我們調(diào)試的程序上點擊那個“CheckIt”按鈕,被OllyDBG斷下:00401323|.E84C010000;GetWindowTextACALL<JMP.&USER32.GetWindowTextA>00401328|.E8A50000000040132D|.3BC60040132F|.7542CALLCrackHea.004013D2CMPEAX,ESIJNZSHORTCrackHea.00401373JMPSHORTCrackHea.0040135FASCII"Nowwriteakeyg"ASCII"enandtutandy";關(guān)鍵,要按F7鍵跟進(jìn)去;不等則完蛋;比較00401331|.EB2C00401333|.4E6F77207>00401343|.656E20616>00401353|.6F7527726>0040135F|>6A00ASCII"ou'redone.",0PUSH0;Style=MB_OK|MB_APPLMODAL00401361|.680F304000PUSHCrackHea.0040300F;Title="Crudd'sCrackHead"00401366|.6833134000PUSHCrackHea.00401333;Text="Nowwriteakeygenandtutandyou'redone."0040136B|.FF75080040136E|.E819010000PUSHDWORDPTRSS:[EBP+8]CALL<JMP.&USER32.MessageBoxA>;hOwner;MessageBoxA從上面的代碼,我們很容易看出00401328地址處的CALLCrackHea.004013D2是關(guān)鍵,必須仔細(xì)跟蹤。而注冊成功則會顯示一個對話框,標(biāo)題是“Crudd'sCrackHead”,對話框顯示的內(nèi)容是“Nowwriteakeygenandtutandyou'redone.”現(xiàn)在我按一下F8,準(zhǔn)備步進(jìn)到00401328地址處的那條CALLCrackHea.004013D2指令后再按F7鍵跟進(jìn)去。等等,怎么回事?怎么按一下F8鍵跑到這來了:00401474$-FF252C204000;USER32.GetWindowTextA0040147A$-FF2530204000;USER32.LoadCursorA00401480$-FF251C204000;USER32.LoadIconA00401486$-FF2520204000;USER32.LoadMenuA0040148C$-FF2524204000;USER32.MessageBoxAJMPDWORDPTRDS:[<&USER32.GetWindowText>JMPDWORDPTRDS:[<&USER32.LoadCursorA>]JMPDWORDPTRDS:[<&USER32.LoadIconA>]JMPDWORDPTRDS:[<&USER32.LoadMenuA>]JMPDWORDPTRDS:[<&USER32.MessageBoxA>]原來是跳到另一個斷點了。這個斷點我們不需要,按一下F2鍵刪掉它吧。刪掉00401474地址處的斷點后,我再按F8鍵,呵,完了,跑到User32.dll的領(lǐng)空了??匆幌翺llyDBG的標(biāo)題欄:“[CPU-主線程,模塊-USER32],跑到系統(tǒng)領(lǐng)空了,OllyDBG反匯編窗口中顯示代碼是這樣:77D3213C6A0C77D3213E68A021D37777D32143E87864FEFFPUSH0CPUSHUSER32.77D321A0CALLUSER32.77D185C0怎么辦?別急,我們按一下ALT+F9組合鍵,呵,回來了:00401328|.E8A50000000040132D|.3BC60040132F|.7542CALLCrackHea.004013D2CMPEAX,ESIJNZSHORTCrackHea.00401373;關(guān)鍵,要按F7鍵跟進(jìn)去;不等則完蛋;比較光標(biāo)停在00401328地址處的那條指令上。現(xiàn)在我們按F7鍵跟進(jìn):004013D2/$56004013D3|.33C0PUSHESIXOREAX,EAX;ESI入棧;EAX清零004013D5|.8D35C4334000LEAESI,DWORDPTRDS:[4033C4];把注冊碼框中的數(shù)值送到ESI004013DB|.33C9XORECX,ECX;ECX清零004013DD|.33D2004013DF|.8A06到AL004013E1|.46004013E2|.3C2DXOREDX,EDXMOVAL,BYTEPTRDS:[ESI];EDX清零;把注冊碼中的每個字符送INCESICMPAL,2D;指針加1,指向下一個字符;把取得的字符與16進(jìn)制值為2D的字符(即“-”)比較,這里主要用于判斷輸入的是不是負(fù)數(shù)004013E4|.7508JNZSHORTCrackHea.004013EE;不等則跳004013E6|.BAFFFFFFFF到EDX,即16進(jìn)制FFFFFFFFMOVEDX,-1;如果輸入的是負(fù)數(shù),則把-1送004013EB|.8A06MOVAL,BYTEPTRDS:[ESI]INCESIJMPSHORTCrackHea.004013FB;取“-”號后的第一個字符;指針加1,指向再下一個字符004013ED|.46004013EE|>EB0B004013F0|>2C30SUBAL,30;每位字符減16進(jìn)制的30,因為這里都是數(shù)字,如1的ASCII碼是“31H”,減30H后為1,即我們平時看到的數(shù)值004013F2|.8D0C89LEAECX,DWORDPTRDS:[ECX+ECX*4]存在ECX中的結(jié)果乘5再送到ECX;把前面運算后保;每位字符運算后004013F5|.8D0C48LEAECX,DWORDPTRDS:[EAX+ECX*2]的值與2倍上一位字符運算后值相加后送ECX004013F8|.8A06MOVAL,BYTEPTRDS:[ESI]INCESI;指針加1,指向再下一個字符ORAL,ALJNZSHORTCrackHea.004013F0;取下一個字符004013FA|.46004013FB|>0AC0004013FD|.^75F1;上面一條和這一條指令主要是用來判斷是否已把用戶輸入的注冊碼計算完004013FF|.8D040ALEAEAX,DWORDPTRDS:[EDX+ECX];把EDX中的值與經(jīng)過上面運算后的ECX中值相加送到EAX00401402|.33C2入的是負(fù)數(shù),則此處功能就是把EAX中的值取反00401404|.5EPOPESIXOREAX,EDX;把EAX與EDX異或。如果我們輸;ESI出棧??吹竭@條和下一條指令,我;把ESI中的值與797A7553H們要考慮一下這個ESI的值是哪里運算得出的呢?00401405|.81F653757A79XORESI,797A7553異或0040140B\.C3RETN這里留下了一個問題:那個ESI寄存器中的值是從哪運算出來的?先不管這里,我們接著按F8鍵往下走,來到0040140B地址處的那條RETN指令(這里可以通過在調(diào)試選項的“命令”標(biāo)簽中勾選“使用RET代替RETN”來更改返回指令的顯示方式),再按一下F8,我們就走出00401328地址處的那個CALL了?,F(xiàn)在我們回到了這里:0040132D|.3BC60040132F|.7542CMPEAX,ESIJNZSHORTCrackHea.00401373;比較;不等則完蛋光標(biāo)停在了0040132D地址處的那條指令上。根據(jù)前面的分析,我們知道EAX中存放的是我們輸入的注冊碼經(jīng)過計算后的值。我們來看一下信息窗口:ESI=E6B5F2F9EAX=FF439EBE左鍵選擇信息窗口中的ESI=E6B5F2F9,再按右鍵,在彈出菜單上選“修改寄存器”,我們會看到這樣一個窗口:可能你的顯示跟我不一樣,因為這個crackme中已經(jīng)說了每個機器的序列號不一樣。關(guān)掉上面的窗口,再對信息窗口中的EAX=FF439EBE做同樣操作:由上圖我們知道了原來前面分析的對我們輸入的注冊碼進(jìn)行處理后的結(jié)果就是把字符格式轉(zhuǎn)為數(shù)字格式。我們原來輸入的是字串“12345666”,現(xiàn)在轉(zhuǎn)換為了數(shù)字12345666。這下就很清楚了,隨便在上面那個修改ESI圖中顯示的有符號或無符號編輯框中復(fù)制一個,粘貼到我們調(diào)試的程序中的編輯框中試一下:呵呵,成功了。且慢高興,這個crackme是要求寫出注冊機的。我們先不要求寫注冊機,但注冊的算法我們要搞清楚。還記得我在前面說到的那個ESI寄存器值的問題嗎?現(xiàn)在看看我外掛編寫必備工具2——OllyDBG(OD)入門系列4OllyDBG入門系列(四)-內(nèi)存斷點還記得上一篇《OllyDBG入門系列(三)-函數(shù)參考》中的內(nèi)容嗎?在那篇文章中我們分析后發(fā)現(xiàn)一個ESI寄存器值不知是從什么地方產(chǎn)生的,要弄清這個問題必須要找到生成這個ESI值的計算部分。今天我們的任務(wù)就是使用OllyDBG的內(nèi)存斷點功能找到這個地方,搞清楚這個值是如何算出來的。這次分析的目標(biāo)程序還是上一篇的那個crackme,附件我就不再上傳了,用上篇中的附件就可以了。下面我們開始:還記得我們上篇中所說的關(guān)鍵代碼的地方嗎?溫習(xí)一下:00401323|.E84C010000;GetWindowTextACALL<JMP.&USER32.GetWindowTextA>00401328|.E8A50000000040132D|.3BC60040132F|.7542CALLCrackHea.004013D2CMPEAX,ESIJNZSHORTCrackHea.00401373;關(guān)鍵,要按F7鍵跟進(jìn)去;不等則完蛋;比較我們重新用OllyDBG載入目標(biāo)程序,F(xiàn)9運行來到上面代碼所在的地方(你上次設(shè)的斷點應(yīng)該沒刪吧?),我們向上看看能不能找到那個ESI寄存器中最近是在哪里賦的值。哈哈,原來就在附近?。何覀儸F(xiàn)在知道ESI寄存器的值是從內(nèi)存地址40339C中送過來的,那內(nèi)存地址40339C中的數(shù)據(jù)是什么時候產(chǎn)生的呢?大家注意,我這里信息窗口中顯示的是DS:[0040339C]=9FCF87AA,你那可能是DS:[0040339C]=XXXXXXXX,這里的XXXXXXXX表示的是其它的值,就是說與我這里顯示的9FCF87AA不一樣。我們按上圖的操作在數(shù)據(jù)窗口中看一下:從上圖我們可以看出內(nèi)存地址40339C處的值已經(jīng)有了,說明早就算過了?,F(xiàn)在怎么辦呢?我們考慮一下,看情況程序是把這個值算出來以后寫在這個內(nèi)存地址,那我們要是能讓OllyDBG在程序開始往這個內(nèi)存地址寫東西的時候中斷下來,不就有可能知道目標(biāo)程序是怎么算出這個值的嗎?說干就干,我們在OllyDBG的菜單上點調(diào)試->重新開始,或者按CTR+F2組合鍵(還可以點擊工具欄上的那個有兩個實心左箭頭的圖標(biāo))來重新載入程序。這時會跳出一個“進(jìn)程仍處于激活狀態(tài)”的對話框(我們可以在在調(diào)試選項的安全標(biāo)簽下把“終止活動進(jìn)程時警告”這條前面的勾去掉,這樣下次就不會出現(xiàn)這個對話框了),問我們是否要終止進(jìn)程。這里我們選“是”,程序被重新載入,我們停在下面這一句上:00401000>/$6A00PUSH0;pModule=NULL現(xiàn)在我們就要來設(shè)內(nèi)存斷點了。在OllyDBG中一般我們用到的內(nèi)存斷點有內(nèi)存訪問和內(nèi)存寫入斷點。內(nèi)存訪問斷點就是指程序訪問內(nèi)存中我們指定的內(nèi)存地址時中斷,內(nèi)存寫入斷點就是指程序往我們指定的內(nèi)存地址中寫東西時中斷。更多關(guān)于斷點的知識大家可以參考論壇精華7->基礎(chǔ)知識->斷點技巧->斷點原理這篇Lenus兄弟寫的《如何對抗硬件斷點之一---調(diào)試寄存器》文章,也可以看這個帖:/showthread.php?threadid=10829。根據(jù)當(dāng)前我們調(diào)試的具體程序的情況,我們選用內(nèi)存寫入斷點。還記得前面我叫大家記住的那個40339C內(nèi)存地址嗎?現(xiàn)在我們要用上了。我們先在OllyDBG的數(shù)據(jù)窗口中左鍵點擊一下,再右擊,會彈出一個如下圖所示的菜單。我們選擇其中的轉(zhuǎn)到->表達(dá)式(也可以左鍵點擊數(shù)據(jù)窗口后按CTR+G組合鍵)。如下圖:現(xiàn)在將會出現(xiàn)這樣一個對話框:我們在上面那個編輯框中輸入我們想查看內(nèi)容的內(nèi)存地址40339C,然后點確定按鈕,數(shù)據(jù)窗口中顯示如下:我們可以看到,40339C地址開始處的這段內(nèi)存里面還沒有內(nèi)容。我們現(xiàn)在在40339C地址處后面的HEX數(shù)據(jù)或ASCII欄中按住左鍵往后拖放,選擇一段。內(nèi)存斷點的特性就是不管你選幾個字節(jié),OllyDBG都會分配4096字節(jié)的內(nèi)存區(qū)。這里我就選從40339C地址處開始的四個字節(jié),主要是為了讓大家提前了解一下硬件斷點的設(shè)法,因為硬件斷點最多只能選4個字節(jié)。選中部分會顯示為灰色。選好以后松開鼠標(biāo)左鍵,在我們選中的灰色部分上右擊:經(jīng)過上面的操作,我們的內(nèi)存斷點就設(shè)好了(這里還有個要注意的地方:內(nèi)存斷點只在當(dāng)前調(diào)試的進(jìn)程中有效,就是說你如果重新載入程序的話內(nèi)存斷點就自動刪除了。且內(nèi)存斷點每一時刻只能有一個。就是說你不能像按F2鍵那樣同時設(shè)置多個斷點)?,F(xiàn)在按F9鍵讓程序運行,呵,OllyDBG中斷了!7C932F398808MOVBYTEPTRDS:[EAX],CL;這就是我們第一次斷下來的地方7C932F3B407C932F3C4F7C932F3D4E7C932F3E^75CB7C932F408B4D10INCEAXDECEDIDECESIJNZSHORTntdll.7C932F0BMOVECX,DWORDPTRSS:[EBP+10]上面就是我們中斷后反匯編窗口中的代碼。如果你是其它系統(tǒng),如Win98的話,可能會有所不同。沒關(guān)系,這里不是關(guān)鍵。我們看一下領(lǐng)空,原來是在ntdll.dll內(nèi)。系統(tǒng)領(lǐng)空,我們現(xiàn)在要考慮返回到程序領(lǐng)空。返回前我們看一下數(shù)據(jù)窗口:現(xiàn)在我們轉(zhuǎn)到反匯編窗口,右擊鼠標(biāo),在彈出菜單上選擇斷點->刪除內(nèi)存斷點,這樣內(nèi)存斷點就被刪除了。現(xiàn)在我們來按一下ALT+F9組合鍵,我們來到下面的代碼:00401431|.8D359C334000LEAESI,DWORDPTRDS:[40339C];ALT+F9返回后來到的位置00401437|.0FB60DEC334000MOVZXECX,BYTEPTRDS:[4033EC]0040143E|.33FFXOREDI,EDI我們把反匯編窗口往上翻翻,呵,原來就在我們上一篇分析的代碼下面???現(xiàn)在我們在0040140C地址處那條指令上按F2設(shè)置一個斷點,現(xiàn)在我們按CTR+F2組合鍵重新載入程序,載入后按F9鍵運行,我們將會中斷在我們剛才在0040140C地址下的那個斷點處:0040140C/$600040140D|.6A000040140F|.E8B4000000PUSHADPUSH0CALL<JMP.&KERNEL32.GetDriveTypeA>;/RootPathName=NULL;\GetDriveTypeA00401414|.A2EC334000MOVBYTEPTRDS:[4033EC],AL;磁盤類型參數(shù)送內(nèi)存地址4033EC00401419|.6A000040141B|.6A000040141D|.6A000040141F|.6A0000401421|.6A0000401423|.6A0B00401425|.689C334000PUSH0PUSH0PUSH0PUSH0PUSH0PUSH0B;/pFileSystemNameSize=NULL;|pFileSystemNameBuffer=NULL;|pFileSystemFlags=NULL;|pMaxFilenameLength=NULL;|pVolumeSerialNumber=NULL;|MaxVolumeNameSize=B(11.)PUSHCrackHea.0040339C;|VolumeNameBuffer=CrackHea.0040339C0040142A|.6A00PUSH0;|RootPathName=NULL0040142C|.E8A3000000;\GetVolumeInformationACALL<JMP.&KERNEL32.GetVolumeInformationA>00401431|.8D359C334000在分區(qū)的卷標(biāo)名稱送到ESI00401437|.0FB60DEC334000MOVZXECX,BYTEPTRDS:[4033EC]LEAESI,DWORDPTRDS:[40339C];把crackme程序所;磁盤類型參數(shù)送ECX0040143E|.33FF00401440|>8BC100401442|.8B1E到EBXXOREDI,EDIMOVEAX,ECXMOVEBX,DWORDPTRDS:[ESI];把EDI清零;磁盤類型參數(shù)送EAX;把卷標(biāo)名作為數(shù)值送00401444|.F7E3名值相乘00401446|.03F8果保存在EDI中00401448|.49MULEBXADDEDI,EAXDECECX;循環(huán)遞減取磁盤類型參數(shù)值與卷標(biāo);每次計算結(jié)果再加上上次計算結(jié);把磁盤類型參數(shù)作為循環(huán)次數(shù),依次;判斷是否計算完遞減00401449|.83F9000040144C|.^75F20040144E|.893D9C334000CMPECX,0JNZSHORTCrackHea.00401440MOVDWORDPTRDS:[40339C],EDI;沒完繼續(xù);把計算后值送到內(nèi)存地址40339C,這就是我們后來在ESI中看到的值00401454|.6100401455\.C3POPADRETN通過上面的分析,我們知道基本算法是這樣的:先用GetDriveTypeA函數(shù)獲取磁盤類型參數(shù),再用GetVolumeInformationA函數(shù)獲取這個crackme程序所在分區(qū)的卷標(biāo)。如我把這個Crackme程序放在F:\OD教程\crackhead\目錄下,而我F盤設(shè)置的卷標(biāo)是GAME,則這里獲取的就是GAME,ASCII碼為“47414D45”。但我們發(fā)現(xiàn)一個問題:假如原來我們在數(shù)據(jù)窗口中看到的地址40339C處的16進(jìn)制代碼是“47414D45”,即“GAME”,但經(jīng)過地址00401442處的那條MOVEBX,DWORDPTRDS:[ESI]指令后,我們卻發(fā)現(xiàn)EBX中的值是“454D4147”,正好把我們上面那個“47414D45”反過來了。為什么會這樣呢?如果大家對x86系列CPU的存儲方式了解的話,這里就容易理解了。我們知道“GAME”有四個字節(jié),即ASCII碼為“47414D45”。我們看一下數(shù)據(jù)窗口中的情況:0040339C47414D45000000000000000000000000GAME............大家可以看出來內(nèi)存地址40339CH到40339FH分別按順序存放的是47414D45。如下圖:系統(tǒng)存儲的原則為“高高低低”,即低字節(jié)存放在地址較低的字節(jié)單元中,高字節(jié)存放在地址較高的字節(jié)單元中。比如一個字由兩個字節(jié)組成,像這樣:1234,這里的高字節(jié)就是12,低字節(jié)就是34。上面的那條指令MOVEBX,DWORDPTRDS:[ESI]等同于MOVEBX,DWORDPTRDS:[40339C]。注意這里是DWORD,即“雙字”,由4個連續(xù)的字節(jié)構(gòu)成。而取地址為40339C的雙字單元中的內(nèi)容時,我們應(yīng)該得到的是“454D4147”,即由高字節(jié)到低字節(jié)順序的值。因此經(jīng)過MOVEBX,DWORDPTRDS:[ESI]這條指令,就是把從地址40339C開始處的值送到EBX,所以我們得到了“454D4147”。好了,這里弄清楚了,我們再接著談這個程序的算法。前面我們已經(jīng)說了取磁盤類型參數(shù)做循環(huán)次數(shù),再取卷標(biāo)值A(chǔ)SCII碼的逆序作為數(shù)值,有了這兩個值就開始計算了?,F(xiàn)在我們把磁盤類型值作為n,卷標(biāo)值A(chǔ)SCII碼的逆序數(shù)值作為a,最后得出的結(jié)果作為b,有這樣的計算過程:第一次:b=a*n第二次:b=a*(n-1)+b第三次:b=a*(n-2)+b…第n次:b=a*1+b可得出公式為b=a*[n+(n-1)+(n-2)+…+1]=a*[n*(n+1)/2]還記得上一篇我們的分析嗎?看這一句:00401405|.81F653757A79XORESI,797A7553;把ESI中的值與797A7553H異或這里算出來的b最后還要和797A7553H異或一下才是真正的注冊碼。只要你對編程有所了解,這個注冊機就很好寫了。如果用匯編來寫這個注冊機的話就更簡單了,很多內(nèi)容可以直接照抄。到此已經(jīng)差不多了,最后還有幾個東西也說一下吧:1、上面用到了兩個API函數(shù),一個是GetDriveTypeA,還有一個是GetVolumeInformationA,關(guān)于這兩個函數(shù)的具體用法我就不多說了,大家可以查一下MSDN。這里只要大家注意函數(shù)參數(shù)傳遞的次序,即調(diào)用約定。先看一下這里:00401419|.6A000040141B|.6A000040141D|.6A000040141F|.6A0000401421|.6A0000401423|.6A0B00401425|.689C334000PUSH0PUSH0PUSH0PUSH0PUSH0PUSH0B;/pFileSystemNameSize=NULL;|pFileSystemNameBuffer=NULL;|pFileSystemFlags=NULL;|pMaxFilenameLength=NULL;|pVolumeSerialNumber=NULL;|MaxVolumeNameSize=B(11.)PUSHCrackHea.0040339C;|VolumeNameBuffer=CrackHea.0040339C0040142A|.6A00PUSH0;|RootPathName=NULL0040142C|.E8A3000000;\GetVolumeInformationACALL<JMP.&KERNEL32.GetVolumeInformationA>把上面代碼后的OllyDBG自動添加的注釋與MSDN中的函數(shù)原型比較一下:BOOLGetVolumeInformation(LPCTSTRlpRootPathName,//addressofrootdirectoryofthefilesystem//addressofnameofthevolume//lengthoflpVolumeNameBuffer//addressofvolumeserialnumberLPTSTRlpVolumeNameBuffer,DWORDnVolumeNameSize,LPDWORDlpVolumeSerialNumber,LPDWORDlpMaximumComponentLength,//addressofsystem'smaximumfilenamelengthLPDWORDlpFileSystemFlags,LPTSTRlpFileSystemNameBuffer,DWORDnFileSystemNameSize);//addressoffilesystemflags//addressofnameoffilesystem//lengthoflpFileSystemNameBuffer大家應(yīng)該看出來點什么了吧?函數(shù)調(diào)用是先把最后一個參數(shù)壓棧,參數(shù)壓棧順序是從后往前。這就是一般比較常見的stdcall調(diào)用約定。2、我在前面的00401414地址處的那條MOVBYTEPTRDS:[4033EC],AL指令后加的注釋是“磁盤類型參數(shù)送內(nèi)存地址4033EC”。為什么這樣寫?大家把前一句和這一句合起來看一下:外掛編寫必備工具2——OllyDBG(OD)入門系列5OllyDBG入門系列(五)-消息斷點及RUN跟蹤找了幾十個不同語言編寫的cr
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度化工廠員工勞動合同模板全面修訂版
- 2025年度數(shù)據(jù)中心能源優(yōu)化合同能源服務(wù)協(xié)議書
- 2025年度國際健康養(yǎng)生旅游項目合同
- 2025版廠區(qū)環(huán)境監(jiān)測與風(fēng)險評估合同4篇
- 2025年度大型公共場所消防設(shè)施維護(hù)保養(yǎng)合同
- 2025年度文化產(chǎn)業(yè)項目投資合同履約擔(dān)保函
- 2025年度新能源發(fā)電項目EPC總承包合同
- 2025年度品牌推廣顧問聘請合同(品牌戰(zhàn)略)
- 2025年度化學(xué)品進(jìn)出口貿(mào)易糾紛解決合同樣本
- 二人共同投資合作合同書樣本版B版
- 小學(xué)六年級數(shù)學(xué)上冊《簡便計算》練習(xí)題(310題-附答案)
- 地理標(biāo)志培訓(xùn)課件
- 培訓(xùn)如何上好一堂課
- 高教版2023年中職教科書《語文》(基礎(chǔ)模塊)下冊教案全冊
- 2024醫(yī)療銷售年度計劃
- 稅務(wù)局個人所得稅綜合所得匯算清繳
- 人教版語文1-6年級古詩詞
- 上學(xué)期高二期末語文試卷(含答案)
- 人教版英語七年級上冊閱讀理解專項訓(xùn)練16篇(含答案)
- 死亡病例討論模板
- 宜城安達(dá)特種水泥有限公司雙寨子礦區(qū)鋁土礦礦產(chǎn)資源開發(fā)利用與生態(tài)復(fù)綠方案
評論
0/150
提交評論