|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2004-01-10, 10:36 PM | #1 |
榮譽會員
|
菜鳥對Splish-crackme的算法分析
菜鳥對Splish-crackme的算法分析
作者:winroot 工具: TRW2000 v1.22 W32dasmVGOLD 環境:M$ win98 這是我第一次寫pj文章,請大家指教.因我是只大菜鳥,所以文中難免有錯誤,請各位高手指正. 這個crackme有3問(Nag&Serial&hard code)其他兩個很簡單,無太大意義,也就不必說了. 主要是name/serial W32dasmVGOLD點擊表單項的參考-->字串串資料參考-->"Sorry, please try again" 出錯後我們看到 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004016C8(C)<------從這裡跳出錯的我們就跳回去 | :004016E2 6A00 push 00000000 * Possible StringData Ref from Data Obj ->"Splish, Splash" | :004016E4 680A304000 push 0040300A * Possible StringData Ref from Data Obj ->"Sorry, please try again." | :004016E9 6867304000 push 00403067 :004016EE 6A00 push 00000000 _________________________________________________________________________ 到了004016C8我們往上看,看到 :004016A6 EB4D jmp 004016F5 無條件跳~~~那麼她下面的部分就與這句上面部分無關(不知對不對??) 我們就來看這句話的下面: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040167C(U) | :004016A8 8D354D324000 lea esi, dword ptr [0040324D] //傳送位址給esi :004016AE 8D3D58324000 lea edi, dword ptr [00403258] //傳送位址給edi :004016B4 33DB xor ebx, ebx//ebx=0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004016CB(U) | :004016B6 3B1D63344000 cmp ebx, dword ptr [00403463] | :004016BC 740F je 004016CD //跳走到正確 | :004016BE 0FBE041F movsx eax, byte ptr [edi+ebx] | :004016C2 0FBE0C1E movsx ecx, byte ptr [esi+ebx] | :004016C6 3BC1 cmp eax, ecx | 這裡肯定是關鍵 :004016C8 7518 jne 004016E2//不等就跳失敗 | ~~~~~~~~~~~~~~ ~~~~~~~~~~~~ | :004016CA 43 inc ebx //加1 | :004016CB EBE9 jmp 004016B6//我就是跳~~~~~ | 在這裡會有幾個疑問: 1.如果eax=ecx,每次ebx=ebx加1然後直到eax和dword ptr [00403463]相等. 那麼,dword ptr [00403463]是什麼? 2.dword ptr [00403258] dword ptr [0040324D] 裡面究竟是什麼? 那麼我們就搜尋這幾個位址~~~ ___________________________________________________________________________ 先不要看程式碼,先看下面的解釋 * Referenced by a CALL at Address: |:00401402 | :004015E4 55 push ebp :004015E5 8BEC mov ebp, esp :004015E7 6A20 push 00000020 :004015E9 6842324000 push 00403242 :004015EE FF750C push [ebp+0C] * Reference To: USER32.GetWindowTextA, Ord:015Bh | :004015F1 E834010000 Call 0040172A//取serial :004015F6 85C0 test eax, eax//此時eax=serial長度如果serial長度是0出錯 :004015F8 0F8495000000 je 00401693//跳出 :004015FE A367344000 mov dword ptr [00403467], eax//把eax的值送入00403467 :00401603 6A0B push 0000000B :00401605 6836324000 push 00403236 :0040160A FF7508 push [ebp+08] * Reference To: USER32.GetWindowTextA, Ord:015Bh | :0040160D E818010000 Call 0040172A//取name :00401612 85C0 test eax, eax//看eax=name的長度是不是0 :00401614 7468 je 0040167E :00401616 A363344000 mov dword ptr [00403463], eax//把eax的值送入00403463 :0040161B 33C9 xor ecx, ecx// :0040161D 33DB xor ebx, ebx// 清0 :0040161F 33D2 xor edx, edx// :00401621 8D3536324000 lea esi, dword ptr [00403236]//讀取name,計算完後存入00403258 :00401627 8D3D58324000 lea edi, dword ptr [00403258] :0040162D B90A000000 mov ecx, 0000000A//ecx=10 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00401650(C) | :00401632 0FBE041E movsx eax, byte ptr [esi+ebx]//先符號擴展,再傳送給eax :00401636 99 cdq//雙字擴展.(把EAX中的字的符號擴展到EDX中去) :00401637 F7F9 idiv ecx//除以10將餘數放入edx :00401639 33D3 xor edx, ebx//兩者異或 :0040163B 83C202 add edx, 00000002//edx=edx+2 :0040163E 80FA0A cmp dl, 0A//如果dl不小於10就跳dl=edx :00401641 7C03 jl 00401646 :00401643 80EA0A sub dl, 0A//dl=dl-10 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00401641(C) | :00401646 88141F mov byte ptr [edi+ebx], dl//傳值 :00401649 43 inc ebx//自加一 :0040164A 3B1D63344000 cmp ebx, dword ptr [00403463]//比較name長度如果不相等就跳 :00401650 75E0 jne 00401632 :00401652 33C9 xor ecx, ecx// :00401654 33DB xor ebx, ebx// 清零 :00401656 33D2 xor edx, edx// :00401658 8D3542324000 lea esi, dword ptr [00403242]//讀取serial,計算完後存入0040324D :0040165E 8D3D4D324000 lea edi, dword ptr [0040324D] :00401664 B90A000000 mov ecx, 0000000A//eax=10 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040167A(C) | :00401669 0FBE041E movsx eax, byte ptr [esi+ebx]//變成雙字元 :0040166D 99 cdq //雙字擴展.(把EAX中的字的符號擴展到EDX中去) :0040166E F7F9 idiv ecx//除以10將餘數放入dl=edx :00401670 88141F mov byte ptr [edi+ebx], dl//將dl值傳入edi+ebx :00401673 43 inc ebx//ebx自加一 :00401674 3B1D67344000 cmp ebx, dword ptr [00403467]//比較如果不等就跳 :0040167A 75ED jne 00401669 :0040167C EB2A jmp 004016A8// 絕對跳轉 我覺得肯定有和我一樣的初學者會問:你是怎麼知道取serial和取name??? 答案是:你看* Reference To: USER32.GetWindowTextA, Ord:015Bh 說明使用GetWindowText這個函數,(如果和我一樣沒有學過編程的人就需要查winapi) GetWindowText 參數 類型及說明 hwnd Long,欲獲取文字的那個視窗的關鍵 lpString String,預定義的一個緩衝區,至少有cch+1個字串大小;隨同視窗文字載入 cch Long,lpString緩衝區的長度 那麼在彙編中它就會表現為: :00401603 6A0B push 0000000B// :00401605 6836324000 push 00403236//3個參數 :0040160A FF7508 push [ebp+08]// :004015F1 E834010000 Call 0040172A//取name 這時eax=name長度 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 知道這些我們來解答上面的問題: 1.dword ptr [00403463]是什麼? :00401616 A363344000 mov dword ptr [00403463], eax//把eax的值送入00403463 是name的長度 2.dword ptr [00403258] dword ptr [0040324D] 裡面究竟是什麼? :00401621 8D3536324000 lea esi, dword ptr [00403236]//讀取00403236,存入00403258 :00401627 8D3D58324000 lea edi, dword ptr [00403258] 那麼00403236是什麼?看:00401605 6836324000 push 00403236 是GetWindowText的一個參數,是什麼呢?我們用trw看一下是輸入的name 所以dword ptr [00403258]是name ascii對應的數值. 同理:dword ptr [0040324D]是serial ascii對應的數值. 好了,既然是算法分析我們就看他把name怎麼變了?? 從00401632到00401650是個循環!!!! 只要仔細分析就不難得出: ____________________________________________________________循環直到ebx=eax_______ | | | |~如果大於10就減10| | |~>esi+ebx--->eax---->edx=edx%ebx--->edx=edx^ebx--->edx=edx+2| |-| | |~小於10就跳 | name| | ~>eax=name長度設為變數i 計算完後存入00403258 再看 ____________________________________________________________循環直到ebx=eax_______ | | | | |~>esi+ebx--->eax---->edx=edx%ebx------------------------------------------------| | serail| | ~>eax=serail長度設為變數 計算完後存入0040324D 最後兩者比較,註冊碼只有和註冊名位數相同的部分才起作用 這就是我的算法分析~~~~!!!!! 如果要寫註冊機,只要把註冊嗎那段求逆就行了 #include "stdio.h" main() {char name[30],serial; int i,j,a,b,m,n; printf(" your name:"); scanf("%s",name); n=strlen(name); printf("your serial is:"); for(i=0;i<n;i++) {a=name[i]; b=a%10; m=b^i; m=m+2; if(m>=10) m=m-10; for(j=0;j<10;j++) {serial=m+j*10; if(serial>48) {if(serial<122) printf("%c",serial); else break;} } } printf("\n"); } |
送花文章: 3,
|