|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2004-02-03, 08:39 PM | #1 |
榮譽會員
|
一篇破文----是一個象棋方面的軟體
朋友托我給他看一看一個名叫「象棋橋」的軟體。下載,安裝,執行,註冊是用戶名和註冊碼的形式,經過幾個小時的努力,搞定。有些經驗不敢獨享,遂寫篇文章和大家交流。
破解對像:象棋橋2.1版 下載位址:http://www.shareware.net.cn/download.asp?id={FD40E2F5-C31E-4A96-B31C-9D6EA03F08D8} 破解環境:win2000 使用工具:stud_pe.1.7.1,odbg109b,dede25,w32Dasm(20020828) 破解程序: 選用stud_pe看看是用什麼加的殼,結果讓高手(先聲明我是菜鳥)大失所望,沒加殼,是用delphi寫的,知道用什麼工具了吧,Yes!DEDE啦。(別高興太早,繼續看後面!) 先執行程序,點註冊,彈出註冊視窗,在裡面隨便輸入用戶名,註冊碼,彈出對話視窗說「註冊碼錯誤!」(當然是錯啦!),但就是這個MessageBox框卻成為我們搜尋真正註冊碼的突破點! 根據一般的經驗我們可以這樣做: 1.用靜態反彙編的工具(如w32dasm,IDA等),將軟體反彙編; 2.在反彙編的程序中搜尋相應字串串(如本例中的「註冊碼錯誤!」); 3.找到引用字串串的地方,然後記下位址,用偵錯工具(如odbg,trw等)載入原程序; 4.在剛才的記下的位址處下斷點,使程序執行,輸入測試的註冊碼,程序就會斷在斷點處; 5.這時我們就可以在這個地方附近分析加程式碼,一般的情況下程序都是根據根據你輸入的用戶,運算出一個正確的註冊碼,拿來和你輸入的註冊碼比較,如果錯誤就顯示出錯對話視窗; 6.我們就可以利用原程序來產生真正的註冊碼,而不必弄清楚其加密算法,就可以得到註冊碼。 最浪費時間的是在第5步的,我們只是斷在了此處,只是意味著程序判斷出你輸入的註冊碼與原註冊碼不符,所以跳轉到這裡來顯示錯誤對話視窗的。因此,我們要沿著這個位址向上探所,不時地下斷點,反覆地進行偵錯,這樣才能找到真正的算法程式碼。 如果運氣好的話,你在堆棧裡找一找有沒有可疑的字串串,尤其和你輸入的註冊碼存放位置比較接近的地方,這個字串串很可能就是真正的註冊碼! 但大多數情況下還是要分析的,當然在搜尋真正算法程式碼的程序也是有技巧可循的,就是仔細地看一看暫存器所指的記憶體的字串串,堆棧中所存的字串串的位址等。如果用的是odbg的話,它會及時明顯地指示出來的,你只要稍加注意就行了。如果在某處發現了你輸入的用戶名時就要倍加注意了,這時很可能程序已經開始了運算,一步步向下偵錯,可能就會發現運算出來的真正註冊碼了!尤其發現兩個字串串和游標(其中一個是你輸入的測試註冊碼)放在兩個暫存器中,然後進入一個CALL的時候,有極大的可能另外那個字串串就是真正的註冊碼! 按照上面的思路我開始了對破解對象的偵錯。因為我已經測出是Delphi寫的軟體,所以不用wdasm了,直接用DeDe來反彙編就更方便。拿來DeDe,轉儲成功!在表單中找疑似對像(可不是非-典哦......),發現了一個RegFrm,看到它還包含了很多控件,有tbutton1和tbutton2兩個控件,無疑一個是OK,一個是CANCEL。再看看RegFrm的程序段中,有沒有TbuttonClick字樣,居然沒有?我暈,這怎麼辦?看起來用DEDE是找不到註冊碼的算法程式碼所在位置了,我換WDASM。 於拿來另外這件法寶WDASM,反彙編,用stringref來搜尋「註冊碼錯誤!」,居然也沒找到?這怎麼回事,看起來只有另想辦法了! 憑經驗,我們上面提到了,錯誤顯示是一個MessageBox對話視窗。於是我們可以這樣做,找到程序中所有引用MessageBoxA這個API的地方下斷點,然後再利用上面的思路來找算法程式碼。 用odbg109b載入程序,完成後,在CPU DISASSEBLE視窗中右擊,執行「Search For Name(label) in current module」,之後在顯示的視窗中,我們找MessageBoxA這個label,找到兩個,我們在第2個上面右擊,執行「Set breakpoint on every reference",於是我們已經在每個MessageBoxA上都下了斷點。然後[F9]執行程序,發生中斷就按「Shift+F9」,讓原程序執行。我們再點註冊按鈕,輸入用戶名和測試註冊碼,點確定,這下可好了,我們中斷在一個MessageBoxA處: 005018C6 |. 50 PUSH EAX ; |hOwner ;下面就是中斷位址 005018C7 |. E8 985CF0FF CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA 利用上面介紹的思路,我們沿著這個位址向上找,發現這個位址所在的程式碼區是一個子程序: 0050187C /$ 55 PUSH EBP <----在這裡右擊看一看 0050187D |. 8BEC MOV EBP,ESP 0050187F |. 83C4 F8 ADD ESP,-8 00501882 |. 53 PUSH EBX 00501883 |. 894D F8 MOV DWORD PTR SS:[EBP-8],ECX 00501886 |. 8955 FC MOV DWORD PTR SS:[EBP-4],EDX 00501889 |. 8BD8 MOV EBX,EAX 0050188B |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 0050188E |. E8 F127F0FF CALL CCBridge.00404084 00501893 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 00501896 |. E8 E927F0FF CALL CCBridge.00404084 0050189B |. 33C0 XOR EAX,EAX 0050189D |. 55 PUSH EBP 0050189E |. 68 E9185000 PUSH CCBridge.005018E9 005018A3 |. 64:FF30 PUSH DWORD PTR FS:[EAX] 005018A6 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP 005018A9 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 005018AC |. 50 PUSH EAX 005018AD |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 005018B0 |. E8 DF27F0FF CALL CCBridge.00404094 005018B5 |. 50 PUSH EAX 005018B6 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 005018B9 |. E8 D627F0FF CALL CCBridge.00404094 005018BE |. 50 PUSH EAX 005018BF |. 8BC3 MOV EAX,EBX 005018C1 |. E8 DA88F3FF CALL CCBridge.0043A1A0 005018C6 |. 50 PUSH EAX ; |hOwner 005018C7 |. E8 985CF0FF CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA 005018CC |. 8BD8 MOV EBX,EAX 005018CE |. 33C0 XOR EAX,EAX 005018D0 |. 5A POP EDX 005018D1 |. 59 POP ECX 005018D2 |. 59 POP ECX 005018D3 |. 64:8910 MOV DWORD PTR FS:[EAX],EDX 005018D6 |. 68 F0185000 PUSH CCBridge.005018F0 005018DB |> 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8] 005018DE |. BA 02000000 MOV EDX,2 005018E3 |. E8 8C23F0FF CALL CCBridge.00403C74 005018E8 \. C3 RETN 我們可以預計是系統判斷完註冊碼之後就會使用這個程序的。於是我們只要找到是哪段程式碼使用了這個程序就可以了,於是我們到這個程序的首位址處:0050187C /$ 55 PUSH EBP,在這裡右擊,執行goto,看一看下面,有很多的CaLL From XXXXXXXX,這麼多的程式碼使用這個程序,我們怎麼知道哪一個是註冊碼算法啊?我暈...... 別著急,[F2]我們先在這裡(0050187C)下個斷點。 ****:用Alt+F2關閉程序,再用Ctrl+F2重新裝載程序。[F9]執行程序,發生中斷就按「Shift+F9」,讓原程序執行。我們再點註冊按鈕,輸入用戶名和測試註冊碼,點確定。 我們中斷在0050187C處,這時我們看CPU視窗的右下角的堆棧視窗中顯示: 0162FBF8 0051E61A RETURN to CCBridge.0051E61A from CCBridge.0050187C 於是我們可以判斷在位址0051E615(call XXXXXX是6個字元,0051E615=0051E61A-6)處有個CALL CCBridge.0050187C。於是我們轉到0051E615處,果然不出我們的所料。 0051E5FA . 8B0D A4655300 MOV ECX,DWORD PTR DS:[5365A4] ; CCBridge.00546B7C 0051E600 . 8B89 4C020000 MOV ECX,DWORD PTR DS:[ECX+24C] 0051E606 . 8B15 A4655300 MOV EDX,DWORD PTR DS:[5365A4] ; CCBridge.00546B7C 0051E60C . 8B92 48020000 MOV EDX,DWORD PTR DS:[EDX+248] 0051E612 . 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 0051E615 . E8 6232FEFF CALL CCBridge.0050187C <----------------預料結果 0051E61A > 33C0 XOR EAX,EAX 我們沿著這個位址向上找,我們發現了: 0051E3EB . BA 70E65100 MOV EDX,CCBridge.0051E670 ; ASCII "CCB21R-" 這個位址引用了字串串"CCB21R-",我這就是註冊碼開始的幾個字串。於是[F2]在這裡下斷點,重複上文「****」處的操作,這時我們在註冊碼的編輯框處要輸入如「CCB21R-12345"形式的註冊碼,於是我們中斷在: 0051E3EB . BA 70E65100 MOV EDX,CCBridge.0051E670 ; ASCII "CCB21R-" 0051E3F0 . E8 EB5BEEFF CALL CCBridge.00403FE0 0051E3F5 . 75 1E JNZ SHORT CCBridge.0051E415 0051E3F7 . 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C] 0051E3FA . 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 0051E3FD . 8B80 70090000 MOV EAX,DWORD PTR DS:[EAX+970] 0051E403 . E8 5462F6FF CALL CCBridge.0048465C 0051E408 . 8B55 E4 MOV EDX,DWORD PTR SS:[EBP-1C] 0051E40B . 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10] 0051E40E . E8 CD5BEEFF CALL CCBridge.00403FE0 <----這裡便是真正註冊碼與我們輸入的註冊碼比較處 我們用[F8]繼續一走,一直到0051E40E處,這時我們看到: EAX指向了一個字串串「12345」 <--這不是我們輸入的註冊碼的後幾位嗎? DEX指向了一個字串串「15168」 <--這就是根據我們輸入的用戶運算後的真正註冊碼了!! (CCB21R-15168,和我輸入的用名試驗一下果然正確,要問我的註冊名是什麼,她是我老婆的中文名,是什麼?可不能告訴你喲......) 明白了吧,想做記憶體註冊機的,就可以斷在這裡啦! 如果想做個算法註冊機,就要分析上面這段程式碼哦! 注意:我為了簡化寫作,略去了在不知註冊碼形式下試驗的程序,註冊碼的形式是:「CCB21R-」+5個數字。 總結:1.odbg109b是一個十分強大的工具,其中有很多功能需要我們去開發; 2.寫這篇冗長的文章主要是給大一個分析的思路,就是要掌握設定斷點的技巧; 3.更不要忽略堆棧中的內容。 聲明:本篇只是做為技術交流,別無他意!有意轉載,請保持原文的完整性!謝謝觀賞! by powerful |
送花文章: 3,
|