作 者: CCDebuger
時 間: 2006-02-14,13:34:43
鏈 接: http://bbs.pediy.com/showthread.php?t=21308
作者:CCDebuger
上一篇是使用入門,現在我們開始正式進入破解。今天的目標程序是看雪兄《加密與解密》第一版附帶光盤中的 crackmes.cjb.net 鏡像打包中的 CFF Crackme #3,採用用戶名/序列號保護方式。原版加了個 UPX 的殼。剛開始學破解先不涉及殼的問題,我們主要是熟悉用 OllyDBG 來破解的一般方法。我這裏把殼脫掉來分析,附件是脫殼後的文件,直接就可以拿來用。先說一下一般軟件破解的流程:拿到一個軟件先別接着馬上用 OllyDBG 調試,先運行一下,有幫助文檔的最好先看一下幫助,熟悉一下軟件的使用方法,再看看註冊的方式。如果是序列號方式可以先輸個假的來試一下,看看有什麼反應,也給我們破解留下一些有用的線索。如果沒有輸入註冊碼的地方,要考慮一下是不是讀取註冊表或 Key 文件(一般稱 keyfile,就是程序讀取一個文件中的內容來判斷是否註冊),這些可以用其它工具來輔助分析。如果這些都不是,原程序只是一個功能不全的試用版,那要註冊爲正式版本就要自己來寫代碼完善了。有點跑題了,呵呵。獲得程序的一些基本信息後,還要用查殼的工具來查一下程序是否加了殼,若沒殼的話看看程序是什麼編譯器編的,如 VC、Delphi、VB 等。這樣的查殼工具有 PEiD 和 FI。有殼的話我們要儘量脫了殼後再來用 OllyDBG 調試,特殊情況下也可帶殼調試。下面進入正題:
我們先來運行一下這個 crackme(用 PEiD 檢測顯示是 Delphi 編的),界面如圖:
這個 crackme 已經把用戶名和註冊碼都輸好了,省得我們動手^_^。我們在那個“Register now !”按鈕上點擊一下,將會跳出一個對話框:
好了,今天我們就從這個錯誤對話框中顯示的“Wrong Serial, try again!”來入手。啓動 OllyDBG,選擇菜單 文件->打開 載入 CrackMe3.exe 文件,我們會停在這裏:
我們在反彙編窗口中右擊,出來一個菜單,我們在 查找->所有參考文本字串 上左鍵點擊:
當然如果用上面那個 超級字串參考+ 插件會更方便。但我們的目標是熟悉 OllyDBG 的一些操作,我就儘量使用 OllyDBG 自帶的功能,少用插件。好了,現在出來另一個對話框,我們在這個對話框裏右擊,選擇“查找文本”菜單項,輸入“Wrong Serial, try again!”的開頭單詞“Wrong”(注意這裏查找內容要區分大小寫)來查找,找到一處:
在我們找到的字串上右擊,再在出來的菜單上點擊“反彙編窗口中跟隨”,我們來到這裏:
見上圖,爲了看看是否還有其他的參考,可以通過選擇右鍵菜單查找參考->立即數,會出來一個對話框:
分別雙擊上面標出的兩個地址,我們會來到對應的位置:
00440F79 |. BA 8C104400 MOV EDX,CrackMe3.0044108C ; ASCII "Wrong Serial,try again!"
00440F7E |. A1 442C4400 MOV EAX,DWORD PTR DS:[442C44]
00440F83 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
00440F85 |. E8 DEC0FFFF CALL CrackMe3.0043D068
00440F8A |. EB 18 JMP SHORT CrackMe3.00440FA4
00440F8C |> 6A 00 PUSH 0
00440F8E |. B9 80104400 MOV ECX,CrackMe3.00441080 ; ASCII "Beggar off!"
00440F93 |. BA 8C104400 MOV EDX,CrackMe3.0044108C ; ASCII "Wrong Serial,try again!"
00440F98 |. A1 442C4400 MOV EAX,DWORD PTR DS:[442C44]
00440F9D |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
00440F9F |. E8 C4C0FFFF CALL CrackMe3.0043D068
我們在反彙編窗口中向上滾動一下再看看:
00440F2C |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00440F2F |. BA 14104400 MOV EDX,CrackMe3.00441014 ; ASCII "Registered User"
00440F34 |. E8 F32BFCFF CALL CrackMe3.00403B2C ; 關鍵,要用F7跟進去
00440F39 |. 75 51 JNZ SHORT CrackMe3.00440F8C ; 這裏跳走就完蛋
00440F3B |. 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
00440F3E |. 8B83 C8020000 MOV EAX,DWORD PTR DS:[EBX+2C8]
00440F44 |. E8 D7FEFDFF CALL CrackMe3.00420E20
00440F49 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00440F4C |. BA 2C104400 MOV EDX,CrackMe3.0044102C ; ASCII "GFX-754-IER-954"
00440F51 |. E8 D62BFCFF CALL CrackMe3.00403B2C ; 關鍵,要用F7跟進去
00440F56 |. 75 1A JNZ SHORT CrackMe3.00440F72 ; 這裏跳走就完蛋
00440F58 |. 6A 00 PUSH 0
00440F5A |. B9 3C104400 MOV ECX,CrackMe3.0044103C ; ASCII "CrackMe cracked successfully"
00440F5F |. BA 5C104400 MOV EDX,CrackMe3.0044105C ; ASCII "Congrats! You cracked this CrackMe!"
00440F64 |. A1 442C4400 MOV EAX,DWORD PTR DS:[442C44]
00440F69 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
00440F6B |. E8 F8C0FFFF CALL CrackMe3.0043D068
00440F70 |. EB 32 JMP SHORT CrackMe3.00440FA4
00440F72 |> 6A 00 PUSH 0
00440F74 |. B9 80104400 MOV ECX,CrackMe3.00441080 ; ASCII "Beggar off!"
00440F79 |. BA 8C104400 MOV EDX,CrackMe3.0044108C ; ASCII "Wrong Serial,try again!"
00440F7E |. A1 442C4400 MOV EAX,DWORD PTR DS:[442C44]
00440F83 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
00440F85 |. E8 DEC0FFFF CALL CrackMe3.0043D068
00440F8A |. EB 18 JMP SHORT CrackMe3.00440FA4
00440F8C |> 6A 00 PUSH 0
00440F8E |. B9 80104400 MOV ECX,CrackMe3.00441080 ; ASCII "Beggar off!"
00440F93 |. BA 8C104400 MOV EDX,CrackMe3.0044108C ; ASCII "Wrong Serial,try again!"
00440F98 |. A1 442C4400 MOV EAX,DWORD PTR DS:[442C44]
00440F9D |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
00440F9F |. E8 C4C0FFFF CALL CrackMe3.0043D068
大家注意看一下上面的註釋,我在上面標了兩個關鍵點。有人可能要問,你怎麼知道那兩個地方是關鍵點?其實很簡單,我是根據查看是哪條指令跳到“wrong serial,try again”這條字串對應的指令來決定的。如果你在 調試選項->CPU 標籤中把“顯示跳轉路徑”及其下面的兩個“如跳轉未實現則顯示灰色路徑”、“顯示跳轉到選定命令的路徑”都選上的話,就會看到是從什麼地方跳到出錯字串處的:
我們在上圖中地址 00440F2C 處按 F2 鍵設個斷點,現在我們按 F9 鍵,程序已運行起來了。我在上面那個編輯框中隨便輸入一下,如 CCDebuger,下面那個編輯框我還保留爲原來的“754-GFX-IER-954”,我們點一下那個“Register now !”按鈕,呵,OllyDBG 跳了出來,暫停在我們下的斷點處。我們看一下信息窗口,你應該發現了你剛纔輸入的內容了吧?我這裏顯示是這樣:
堆棧 SS:[0012F9AC]=00D44DB4, (ASCII "CCDebuger")
EAX=00000009
上面的內存地址 00D44DB4 中就是我們剛纔輸入的內容,我這裏是 CCDebuger。你可以在 堆棧 SS:[0012F9AC]=00D44DB4, (ASCII "CCDebuger") 這條內容上左擊選擇一下,再點右鍵,在彈出菜單中選擇“數據窗口中跟隨數值”,你就會在下面的數據窗口中看到你剛纔輸入的內容。而 EAX=00000009 指的是你輸入內容的長度。如我輸入的 CCDebuger 是9個字符。如下圖所示:
現在我們來按 F8 鍵一步步分析一下:
00440F2C |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 把我們輸入的內容送到EAX,我這裏是“CCDebuger”
00440F2F |. BA 14104400 MOV EDX,CrackMe3.00441014 ; ASCII "Registered User"
00440F34 |. E8 F32BFCFF CALL CrackMe3.00403B2C ; 關鍵,要用F7跟進去
00440F39 |. 75 51 JNZ SHORT CrackMe3.00440F8C ; 這裏跳走就完蛋
當我們按 F8 鍵走到 00440F34 |. E8 F32BFCFF CALL CrackMe3.00403B2C 這一句時,我們按一下 F7 鍵,進入這個 CALL,進去後光標停在這一句:
我們所看到的那些 PUSH EBX、 PUSH ESI 等都是調用子程序保存堆棧時用的指令,不用管它,按 F8 鍵一步步過來,我們只關心關鍵部分:
00403B2C /$ 53 PUSH EBX
00403B2D |. 56 PUSH ESI
00403B2E |. 57 PUSH EDI
00403B2F |. 89C6 MOV ESI,EAX ; 把EAX內我們輸入的用戶名送到 ESI
00403B31 |. 89D7 MOV EDI,EDX ; 把EDX內的數據“Registered User”送到EDI
00403B33 |. 39D0 CMP EAX,EDX ; 用“Registered User”和我們輸入的用戶名作比較
00403B35 |. 0F84 8F000000 JE CrackMe3.00403BCA ; 相同則跳
00403B3B |. 85F6 TEST ESI,ESI ; 看看ESI中是否有數據,主要是看看我們有沒有輸入用戶名
00403B3D |. 74 68 JE SHORT CrackMe3.00403BA7 ; 用戶名爲空則跳
00403B3F |. 85FF TEST EDI,EDI
00403B41 |. 74 6B JE SHORT CrackMe3.00403BAE
00403B43 |. 8B46 FC MOV EAX,DWORD PTR DS:[ESI-4] ; 用戶名長度送EAX
00403B46 |. 8B57 FC MOV EDX,DWORD PTR DS:[EDI-4] ; “Registered User”字串的長度送EDX
00403B49 |. 29D0 SUB EAX,EDX ; 把用戶名長度和“Registered User”字串長度相減
00403B4B |. 77 02 JA SHORT CrackMe3.00403B4F ; 用戶名長度大於“Registered User”長度則跳
00403B4D |. 01C2 ADD EDX,EAX ; 把減後值與“Registered User”長度相加,即用戶名長度
00403B4F |> 52 PUSH EDX
00403B50 |. C1EA 02 SHR EDX,2 ; 用戶名長度值右移2位,這裏相當於長度除以4
00403B53 |. 74 26 JE SHORT CrackMe3.00403B7B ; 上面的指令及這條指令就是判斷用戶名長度最少不能低於4
00403B55 |> 8B0E MOV ECX,DWORD PTR DS:[ESI] ; 把我們輸入的用戶名送到ECX
00403B57 |. 8B1F MOV EBX,DWORD PTR DS:[EDI] ; 把“Registered User”送到EBX
00403B59 |. 39D9 CMP ECX,EBX ; 比較
00403B5B |. 75 58 JNZ SHORT CrackMe3.00403BB5 ; 不等則完蛋
根據上面的分析,我們知道用戶名必須是“Registered User”。我們按 F9 鍵讓程序運行,出現錯誤對話框,點確定,重新在第一個編輯框中輸入“Registered User”,再次點擊那個“Register now !”按鈕,被 OllyDBG 攔下。因爲地址 00440F34 處的那個 CALL 我們已經分析清楚了,這次就不用再按 F7 鍵跟進去了,直接按 F8 鍵通過。我們一路按 F8 鍵,來到第二個關鍵代碼處:
00440F49 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 取輸入的註冊碼
00440F4C |. BA 2C104400 MOV EDX,CrackMe3.0044102C ; ASCII "GFX-754-IER-954"
00440F51 |. E8 D62BFCFF CALL CrackMe3.00403B2C ; 關鍵,要用F7跟進去
00440F56 |. 75 1A JNZ SHORT CrackMe3.00440F72 ; 這裏跳走就完蛋
大家注意看一下,地址 00440F51 處的 CALL CrackMe3.00403B2C 和上面我們分析的地址 00440F34 處的 CALL CrackMe3.00403B2C 是不是彙編指令都一樣啊?這說明檢測用戶名和註冊碼是用的同一個子程序。而這個子程序 CALL 我們在上面已經分析過了。我們執行到現在可以很容易得出結論,這個 CALL 也就是把我們輸入的註冊碼與 00440F4C 地址處指令後的“GFX-754-IER-954”作比較,相等則 OK。好了,我們已經得到足夠的信息了。現在我們在菜單 查看->斷點 上點擊一下,打開斷點窗口(也可以通過組合鍵 ALT+B 或點擊工具欄上那個“B”圖標打開斷點窗口):
爲什麼要做這一步,而不是把這個斷點刪除呢?這裏主要是爲了保險一點,萬一分析錯誤,我們還要接着分析,要是把斷點刪除了就要做一些重複工作了。還是先禁用一下,如果經過實際驗證證明我們的分析是正確的,再刪不遲。現在我們把斷點禁用,在 OllyDBG 中按 F9 鍵讓程序運行。輸入我們經分析得出的內容:
用戶名:Registered User
註冊碼:GFX-754-IER-954
點擊“Register now !”按鈕,呵呵,終於成功了:
--------------------------------------------------------------------------------
【版權聲明】 本文純屬技術交流, 轉載請註明作者並保持文章的完整, 謝謝!