一、前言
通過前文對(duì)逆向原理的說明,想必對(duì)逆向這個(gè)方向已經(jīng)有了初步的了解。那么工欲善其事,必先利其器,本篇主要介紹一下我所接觸到得相關(guān)逆向工具。也作為我上階段學(xué)習(xí)的一個(gè)記錄。
話說,逆向真的是很有意思啊hhhhhh~
二、靜態(tài)調(diào)試與動(dòng)態(tài)調(diào)試
對(duì)于軟件的逆向分析,可以分為靜態(tài)調(diào)試和動(dòng)態(tài)調(diào)試。與之相對(duì)應(yīng)的是各有擅長(zhǎng)的靜態(tài)調(diào)試工具(IDA、C32ASM、Win32Dasm等),和動(dòng)態(tài)調(diào)試工具(Ollydbg、X64dbg等),當(dāng)然大部分工具都是兼具這兩種能力的,根據(jù)自己的習(xí)慣選用合適的即可。
所謂靜態(tài)調(diào)試,就是在本地對(duì)其程序結(jié)構(gòu)進(jìn)行分析,此時(shí)程序并未在運(yùn)行狀態(tài),某種程度上類似于源代碼審計(jì)。
所謂動(dòng)態(tài)調(diào)試,就是在程序運(yùn)行過程中,以斷點(diǎn)的方式使程序運(yùn)行到想要的位置,以此來分析程序的運(yùn)行邏輯,尋找可能的突破點(diǎn),某種程度上相當(dāng)于滲透測(cè)試。
三、從Ollydbg開始
為什么從Ollydbg開始,因?yàn)镮DA_Pro實(shí)在是讓小白留下了無奈的淚水。。。
Ollydbg運(yùn)行在windows平臺(tái)上,是Ring 3級(jí)調(diào)試器,可以對(duì)程序進(jìn)行動(dòng)態(tài)調(diào)試和附加調(diào)試,支持對(duì)線程的調(diào)試同時(shí)還支持插件擴(kuò)展功能,它可以分析函數(shù)過程、循環(huán)語句、選擇語句、表[tables]、常量、代碼中的字符串、欺騙性指令、API調(diào)用、函數(shù)中參數(shù)的數(shù)目,import表等等;支持調(diào)試標(biāo)準(zhǔn)動(dòng)態(tài)鏈接庫(kù)(Dlls),目前已知OllyDbg 可以識(shí)別2300多個(gè)C和Windows API中的常用函數(shù)及其使用的參數(shù),是Ring3級(jí)功能最強(qiáng)大的一款動(dòng)態(tài)調(diào)試工具。
其中?Ring 3級(jí)指的是Intel將CPU的特權(quán)級(jí)別分為四個(gè)級(jí)別:RING0,RING1,RING2,RING3。在windows下,只可使用其中兩個(gè)級(jí)別RING0和RING3,其中為RING0為僅供操作系統(tǒng)使用的特權(quán)指令。
在各大論壇均可下載獲取到OD的漢化版安裝包,打開之后可看到如下界面:





數(shù)據(jù)窗口可查看指定內(nèi)存數(shù)據(jù)
堆棧窗口則包含程序運(yùn)行的堆棧信息,可以幫助進(jìn)行動(dòng)態(tài)調(diào)試
我們可以直接將要逆向的程序拖入OD的窗口中實(shí)現(xiàn)加載,在前文曾經(jīng)提到,所謂逆向,就是把程序還原到源代碼級(jí)別。也就是匯編語言級(jí)別,作為初學(xué)者,可以把匯編語言理解為機(jī)器語言的封裝。那么我們的程序也在運(yùn)行時(shí),也是通過編譯器&解釋器來講高級(jí)語言代碼還原為機(jī)器碼,實(shí)現(xiàn)成功運(yùn)行。
基于此,那么我們逆向的思路就是,通過修改OD分析得到的匯編指令,在程序運(yùn)行的關(guān)鍵位置(如判斷語句,跳轉(zhuǎn)語句,生成key子程序等)對(duì)其進(jìn)行修改,以實(shí)現(xiàn)程序以我們想要的方式運(yùn)行,最終成功破解。
四、嘗試一下
成功源于自信,自信造就成功。在漫漫長(zhǎng)的學(xué)習(xí)路上,實(shí)現(xiàn)一個(gè)小小的成就,可以很好的激勵(lì)自己,獲得繼續(xù)學(xué)習(xí)下去的動(dòng)力。這樣你可以清楚的知道,通過一段時(shí)間的學(xué)習(xí),具體掌握了寫什么,可以實(shí)現(xiàn)到什么地步。
故而,我們嘗試對(duì)第一個(gè)程序進(jìn)行破解,在論壇上可以找到很多demo程序,用以初學(xué)者體驗(yàn)?zāi)嫦?。解壓之后得到?/p>

首先,我們嘗試對(duì)CM1(無殼)程序嘗試進(jìn)行破解。通過運(yùn)行該程序,可以了解到該程序通過校驗(yàn)賬號(hào)和密碼,如驗(yàn)證成功則成功登錄。


將該程序?qū)氲絆D:

那么接下來應(yīng)該怎么辦呢,我們注意到,如果我們輸入錯(cuò)誤的賬號(hào)和密碼,會(huì)觸發(fā)登錄失敗的報(bào)錯(cuò)提示。也就是說,這個(gè)字符串對(duì)應(yīng)的內(nèi)存地址,是在源程序校驗(yàn)用戶口令的子程序之后的。這個(gè)實(shí)現(xiàn)校驗(yàn)的子程序,自然就是我們所尋找的關(guān)鍵位置。那么如何找到呢,我們可以通過動(dòng)態(tài)調(diào)試的方式,使程序運(yùn)行到報(bào)錯(cuò)的位置。在字符串未被加密的情況下,也可以通過搜索提示信息,定位到該行代碼。
在反匯編子窗口中點(diǎn)擊右鍵-->中文搜索引擎-->智能搜索,進(jìn)入字符串子窗口:

通過搜索功能找到報(bào)錯(cuò)提示,點(diǎn)擊右鍵跟隨,成功定位到包含該注釋的內(nèi)存地址及對(duì)應(yīng)的匯編代碼:

那么問題又來了,就算找到了對(duì)應(yīng)的匯編代碼,可他們是什么意思呢?在此簡(jiǎn)單介紹一下相關(guān)的幾個(gè)匯編指令:
MOV? 傳輸指令,把字或字節(jié)從一個(gè)地址傳輸?shù)搅硪粋€(gè)地址
CALL 子程序的入口,在OD中可以通過Enter/Esc或者+/-進(jìn)入或退出子程序
JE/JZ? 跳轉(zhuǎn)指令,若值相等則跳轉(zhuǎn)
JMP 跳轉(zhuǎn)指令,在任何情況下均進(jìn)行跳轉(zhuǎn)
JNE/JNZ? 跳轉(zhuǎn)指令,若值不相等則跳轉(zhuǎn)
PUSH 傳輸指令,把字壓入堆棧
CMP 比較指令,根據(jù)比較結(jié)果設(shè)置標(biāo)志寄存器的值
NOP 空指令,可以理解為空過
再回到我們定位到的地址,我們發(fā)現(xiàn),這是一個(gè)PUSH指令。然后上面幾行,有一個(gè)CALL子程序。那么也就是說,下面一連串的壓棧動(dòng)作,都是這個(gè)子程序處理的結(jié)果。再看這個(gè)子程序上有面以一個(gè)MOV指令,通過我們剛才的了解,我們知道了MOV指令的具體含義。再聯(lián)想到下一條CALL子程序,在信息窗口中可以看到這個(gè)地址的跳轉(zhuǎn)地址。那么我們猜測(cè),這個(gè)MOV指令是把驗(yàn)證CALL的結(jié)果傳遞給了下一條指令,輸出最終的結(jié)果。

在信息窗口中使用右鍵,跟隨到跳轉(zhuǎn)之前的地址,發(fā)現(xiàn)這是一個(gè)驗(yàn)證跳轉(zhuǎn),若值相等則跳轉(zhuǎn)。分析一下運(yùn)行流程:用戶輸入口令-->比較指令得出結(jié)果-->跳轉(zhuǎn)指令進(jìn)行驗(yàn)證跳轉(zhuǎn)-->根據(jù)是否跳轉(zhuǎn)判斷是否成功。

那么我們的逆向思路也就變得清晰,既然是經(jīng)過跳轉(zhuǎn)指令驗(yàn)證之后,才會(huì)到下面輸出錯(cuò)誤結(jié)果的子程序,那么我們不讓他跳轉(zhuǎn)不就行了。于是,之前說到過的空指令就尤為重要了,我們可以把這個(gè)跳轉(zhuǎn)指令使用空指令填充,這樣的話代碼會(huì)一直往下運(yùn)行,也就不會(huì)跳轉(zhuǎn)到登錄失敗的錯(cuò)誤提示了。這也就是大佬們說的,把它給“NOP”掉。

于是我們選中這條指令,使用右鍵-->二進(jìn)制-->使用NOP填充,即可插入NOP指令。然后我們點(diǎn)擊F9使程序運(yùn)行,再次輸入任意口令,就會(huì)發(fā)現(xiàn)已經(jīng)破解成功了:

如何,自己成功嘗試的之后,是不是獲得了一些小小的成就感呢,有沒有體會(huì)到逆向成功的開心。那么再仔細(xì)想想,除了使用空指令填充,還有什么其他的方法嘛,自然是有的。
回到剛才的運(yùn)行流程:用戶輸入口令-->比較指令得出結(jié)果-->跳轉(zhuǎn)指令進(jìn)行驗(yàn)證跳轉(zhuǎn)-->根據(jù)是否跳轉(zhuǎn)判斷是否成功
那也就是說,我們是不是可以追尋正確的口令,或是修改比較指令的結(jié)果或是可以。。。
黑客,這個(gè)詞是用來形容那些熱衷于解決問題、克服限制的人的。