1.4 Crack小實驗
在開始講述漏洞利用原理之前,本節先用一個非常簡單的破解小實驗來幫助大家復習一下前面所講述的概念和工具,消除對二進制文件本能的恐懼。
下面是一段用于密碼驗證的C代碼:
#include <stdio.h> #define PASSWORD "1234567" int verify_password (char *password) { int authenticated; authenticated=strcmp(password,PASSWORD); return authenticated; } main() { int valid_flag=0; char password[1024]; while(1) { printf("please input password: "); scanf("%s",password); valid_flag = verify_password(password); if(valid_flag) { printf("incorrect password!\n\n"); } else { printf("Congratulation! You have passed the verification!\n"); break; } } }
如圖1.4.1所示,我們必須輸入正確的密碼“1234567”才能得到密碼驗證的確認,跳出循環。看到程序源碼后不難發現,程序是提示密碼錯誤請求再次輸入,還是提示密碼正確跳出循環,完全取決于main函數中的if判斷。

圖1.4.1 程序運行情況
如果我們能在.exe文件中找到if判斷對應的二進制機器代碼,將其稍作修改,那么即使輸入錯誤的密碼,也將通過驗證!本節實驗就帶領大家來完成這樣一件事情,這實際上是一種最簡單的軟件破解,也被稱為“爆破”。
題外話:軟件破解技術是自成體系的另一門安全技術,其關鍵在于在調試時巧妙地設置斷點,尋找關鍵代碼段。本例的破解方法有很多,比如直接在PE中搜索密碼、crack子函數等,在此只舉其中一個來介紹。這個實驗的目的在于練習使用工具,復習前面的概念,而并非真正研究破解技術。
實驗環境如表1-4-1所示。
表1-4-1 實驗環境
說明:如果完全采用實驗指導所推薦的實驗環境,將精確地重現指導中所有的細節,包括動態調試時的內存地址和靜態調試的文件偏移地址;否則,一些地址可能需要重新調試來確定。
首先打開IDA,并把由VC 6.0得到的.exe文件直接拖進IDA,稍等片刻,IDA就會把二進制文件翻譯成質量上乘的反匯編代碼。
如圖1.4.2所示,默認情況下,IDA會自動識別出main函數,并用類似流程圖的形式標注出函數內部的跳轉指令。如果按F12鍵,IDA會自動繪制出更加專業和詳細的函數流程圖,如圖1.4.3所示。

圖1.4.2 IDA的流程圖界面1

圖1.4.3 IDA的流程圖界面2
在IDA的圖形顯示界面中,用鼠標選中程序分支點,也就是我們要找的對應于C代碼中的if分支點,按空格鍵切換到匯編指令界面,如圖1.4.4所示。

圖1.4.4 用IDA定位破解點
光標仍然顯示高亮的這條匯編指令就是剛才在流程圖中看到的引起程序分支的指令??梢钥吹竭@條指令位于PE文件的.text節,并且IDA已經自動將該指令的地址換算成了運行時的內存地址VA:0040106E。
現在關閉IDA,換用OllyDbg進行動態調試來看看程序到底是怎樣分支的。用OllyDbg把PE文件打開,如圖1.4.5所示。

圖1.4.5 加載PE文件
OllyDbg在默認情況下將程序中斷在PE裝載器開始處,而不是main函數的開始。如果您有興趣,可以按F8鍵單步跟蹤,看看在main函數被運行之前,裝載器都做了哪些準備工作。一般情況下,main函數位于GetCommandLineA函數調用后不遠處,并且有明顯的特征:在調用之前有3次連續的壓棧操作,因為系統要給main傳入默認的argc、argv等參數。找到main函數調用后,按F7鍵單步跟入就可以看到真正的代碼了,如圖1.4.6所示。

圖1.4.6 定位main函數
我們也可以按快捷鍵Ctrl+G直接跳到由IDA得到的VA:0x0040106E處查看那條引起程序分支的關鍵指令,如圖1.4.7所示。

圖1.4.7 定位if分支
選中這條指令,按F2鍵下斷點,成功后,指令的地址會被標記成不同顏色。
按F9鍵讓程序運行起來,這時候控制權會回到程序,OllyDbg暫時掛起。到程序提示輸入密碼的Console界面隨便輸入一個錯誤的密碼,回車確認后,OllyDbg會重新中斷程序,收回控制權,如圖1.4.8所示。

圖1.4.8 破解前的狀態
密碼驗證函數的返回值將存在EAX寄存器中,if()語句通過以下兩條指令實現。
TEST EAX,EAX JE XXXXX
也就是說,EAX中的值為0時,跳轉將被執行,程序進入密碼確認流程;否則跳轉不執行,程序進入密碼重輸的流程。由于現在輸入的是錯誤密碼,所以可以在預執行區看到提示:“Jump is not taken”。
如果我們把JE這條指令的機器代碼修改成JNE(非0則跳轉),那么整個程序的邏輯就會反過來:輸入錯誤的密碼會被確認,輸入正確的密碼反而要求重新輸入!當然,把
TEST EAX, EAX
指令修改成
XOR EAX, EAX
也能達到改變程序流程的目的,這時不論正確與否,密碼都將被接受。
雙擊JE這條指令,將其修改成JNE,單擊“Assemble”按鈕將其寫入內存,如圖1.4.9所示。

圖1.4.9 破解后的狀態
OllyDbg將匯編指令翻譯成機器代碼后寫入內存。原來內存中的機器代碼74(JE)現在變成了75(JNE)。此外,在預執行區中的提示也發生了變化,提示跳轉將要發生,也就是說,在修改了一個字節的內存數據后,錯誤的密碼也將跳入正確的執行流程!后面您可以單步執行,看看程序是不是如我們所料執行了正確密碼才應該執行的指令。
上面只是在內存中修改程序,我們還需要在二進制文件中也修改相應的字節。這就要用到第2章講到的內存地址VA與文件地址之間的對應關系了。
用LordPE打開.exe文件,查看PE文件的節信息,如圖1.4.10所示。

圖1.4.10 計算文件偏移地址
我們已經知道跳轉指令在內存中的地址是VA=0x0040106E,按照第2章VA與文件地址的換算公式:
文件偏移地址=虛擬內存地址(VA)-裝載基址(Image Base)-節偏移
= 0x0040106E-0x00400000-(0x00001000-0x00001000)
= 0x106E
也就是說,這條指令在PE文件中位于距離文件開始處106E字節的地方。用UltraEdit按照二進制方式打開crack_me.exe文件,如圖1.4.11所示。

圖1.4.11 修改PE文件
按快捷鍵Ctrl+G,輸入0x106E直接跳到JE指令的機器代碼處,如圖1.4.12所示。

圖1.4.12 修改PE文件
將這一個字節的74(JE)修改成75(JNE),保存后重新運行可執行文件,如圖1.4.13所示。原本正確的密碼“1234567”現在反而提示錯誤了。

圖1.4.13 成功破解密碼驗證
- Kali Linux Social Engineering
- 腦洞大開:滲透測試另類實戰攻略
- 可信計算3.0工程初步
- 信息系統安全檢測與風險評估
- 黑客攻防技巧
- Wireshark 2 Quick Start Guide
- 反黑命令與攻防從新手到高手(微課超值版)
- Preventing Digital Extortion
- 信息安全工程與實踐
- 信息系統安全等級化保護原理與實踐
- 隱私保護機器學習
- 5G網絡安全規劃與實踐
- CPK通向賽博安全之路:理論與實踐CPK Solution to Cyber Security:Theory and Practice
- Blockchain Development with Hyperledger
- 互聯網域名國際化與安全技術導論