先跑一下
直接使用這個字符串去check,發現提示信息有關鍵字符串
CODE:0042FB80 00000021 C Sorry , The serial is incorect !
找到這個字符串的引用,有兩個
跟下去發現這兩個字符串都在一個函數中,最下面的3個框中左右都是錯誤,中間是對的,所以核心就在最上層和中間的這段代碼
下面看看這段代碼,直接在ollydbg中暫停,查看參數和返回值等信息
CODE:0042F998 push ebp CODE:0042F999 mov ebp, esp CODE:0042F99B xor ecx, ecx CODE:0042F99D push ecx CODE:0042F99E push ecx CODE:0042F99F push ecx CODE:0042F9A0 push ecx CODE:0042F9A1 push ecx CODE:0042F9A2 push ecx CODE:0042F9A3 push ebx CODE:0042F9A4 push esi CODE:0042F9A5 mov ebx, eax CODE:0042F9A7 xor eax, eax CODE:0042F9A9 push ebp CODE:0042F9AA push offset loc_42FB67 CODE:0042F9AF push dword ptr fs:[eax] CODE:0042F9B2 mov fs:[eax], esp CODE:0042F9B5 mov ds:dword_431750, 29h CODE:0042F9BF lea edx, [ebp+var_10] CODE:0042F9C2 mov eax, [ebx+1DCh] CODE:0042F9C8 call sub_41AA58 ;這個函數返回18 CODE:0042F9CD mov eax, [ebp+var_10] ;這裏取得了用戶名字符串 CODE:0042F9D0 call sub_403AB0 ;以用戶名作爲參數,調用sub_403AB0,這是一個判斷用戶名是不是空的函數 CODE:0042F9D5 mov ds:dword_43176C, eax ;將結果存放在固定位置,後面的第一個關鍵判斷使用這個字符串 CODE:0042F9DA lea edx, [ebp+var_10] CODE:0042F9DD mov eax, [ebx+1DCh] CODE:0042F9E3 call sub_41AA58 CODE:0042F9E8 mov eax, [ebp+var_10] CODE:0042F9EB movzx eax, byte ptr [eax] CODE:0042F9EE mov esi, eax CODE:0042F9F0 shl esi, 3 CODE:0042F9F3 sub esi, eax CODE:0042F9F5 lea edx, [ebp+var_14] CODE:0042F9F8 mov eax, [ebx+1DCh] CODE:0042F9FE call sub_41AA58 CODE:0042FA03 mov eax, [ebp+var_14] CODE:0042FA06 movzx eax, byte ptr [eax+1] CODE:0042FA0A shl eax, 4 CODE:0042FA0D add esi, eax CODE:0042FA0F mov ds:dword_431754, esi CODE:0042FA15 lea edx, [ebp+var_10] CODE:0042FA18 mov eax, [ebx+1DCh] CODE:0042FA1E call sub_41AA58 CODE:0042FA23 mov eax, [ebp+var_10] CODE:0042FA26 movzx eax, byte ptr [eax+3] CODE:0042FA2A imul esi, eax, 0Bh CODE:0042FA2D lea edx, [ebp+var_14] CODE:0042FA30 mov eax, [ebx+1DCh] CODE:0042FA36 call sub_41AA58 CODE:0042FA3B mov eax, [ebp+var_14] CODE:0042FA3E movzx eax, byte ptr [eax+2] CODE:0042FA42 imul eax, 0Eh CODE:0042FA45 add esi, eax CODE:0042FA47 mov ds:dword_431758, esi CODE:0042FA4D mov eax, ds:dword_43176C CODE:0042FA52 call sub_406930 ;以用戶名作爲參數調用 CODE:0042FA57 cmp eax, 4 CODE:0042FA5A jge short loc_42FA79 ;第一個關鍵判斷 CODE:0042FA5C push 0 ; uType CODE:0042FA5E mov ecx, offset aTryAgain_0 ; "Try Again!" CODE:0042FA63 mov edx, offset aSorryTheSerial ; "Sorry , The serial is incorect !" CODE:0042FA68 mov eax, ds:off_430A48 CODE:0042FA6D mov eax, [eax] ; int CODE:0042FA6F call sub_42A170 CODE:0042FA74 jmp loc_42FB37 CODE:0042FA79 ; --------------------------------------------------------------------------- CODE:0042FA79 CODE:0042FA79 loc_42FA79: ; CODE XREF: _TNS_BitBtn1Click+C2↑j CODE:0042FA79 lea edx, [ebp+var_10] CODE:0042FA7C mov eax, [ebx+1DCh] CODE:0042FA82 call sub_41AA58 CODE:0042FA87 mov eax, [ebp+var_10] ;取字符串 CODE:0042FA8A movzx eax, byte ptr [eax] ;取出字符串的第一個地址 CODE:0042FA8D imul ds:dword_431750 ;前面將這個位置賦值成了0x29 CODE:0042FA93 mov ds:dword_431750, eax ;將第一個字符乘以0x29 CODE:0042FA98 mov eax, ds:dword_431750 CODE:0042FA9D add ds:dword_431750, eax ;這裏應該相當於乘以2了 CODE:0042FAA3 lea eax, [ebp+var_4] ;將這個字符串的地址放到局部變量中 CODE:0042FAA6 mov edx, offset _str_CW.Text CODE:0042FAAB call sub_403708 ;以字符串CW作爲第二參數 CODE:0042FAB0 lea eax, [ebp+var_8] ;同上,將字符串地址放入局部變量 CODE:0042FAB3 mov edx, offset _str_CRACKED.Text CODE:0042FAB8 call sub_403708 ;以字符串CRACKED作爲第二參數 CODE:0042FABD push [ebp+var_4] ;push了CW CODE:0042FAC0 push offset _str___5.Text ;push了又一個字符串 CODE:0042FAC5 lea edx, [ebp+var_18] ;這裏是局部變量 CODE:0042FAC8 mov eax, ds:dword_431750 ;這裏是用戶名第一個字符串經過運算之後的結果 CODE:0042FACD call sub_406718 ;這裏又對第一個字符串的運行結果再次進行一個運算 CODE:0042FAD2 push [ebp+var_18] ;將第二次運算結果放入var_18中,這裏入棧了 CODE:0042FAD5 push offset _str___5.Text ;應該也是參數 CODE:0042FADA push [ebp+var_8] CODE:0042FADD lea eax, [ebp+var_C] CODE:0042FAE0 mov edx, 5 CODE:0042FAE5 call sub_4039AC ;關鍵函數了,第一個參數是var_C,第二個是5,後面3個參數依次是前面push的內容 CODE:0042FAEA lea edx, [ebp+var_10] CODE:0042FAED mov eax, [ebx+1E0h] CODE:0042FAF3 call sub_41AA58 ;這個函數讀取了序列碼的地址,然後返給var_10中作爲下一個函數的參數 CODE:0042FAF8 mov edx, [ebp+var_10] ;第二個參數是序列碼字符串 CODE:0042FAFB mov eax, [ebp+var_C] ;第一個參數是var_C,也是字符串 CODE:0042FAFE call sub_4039FC ;要求這個函數返回0 CODE:0042FB03 jnz short loc_42FB1F CODE:0042FB05 push 0 ; uType CODE:0042FB07 mov ecx, offset aCongratz_0 ; "Congratz !!" CODE:0042FB0C mov edx, offset aGoodJobDude ; "Good job dude =)" CODE:0042FB11 mov eax, ds:off_430A48 CODE:0042FB16 mov eax, [eax] ; int CODE:0042FB18 call sub_42A170 CODE:0042FB1D jmp short loc_42FB37 CODE:0042FB1F ; --------------------------------------------------------------------------- CODE:0042FB1F CODE:0042FB1F loc_42FB1F: ; CODE XREF: _TNS_BitBtn1Click+16B↑j CODE:0042FB1F push 0 ; uType CODE:0042FB21 mov ecx, offset aTryAgain_0 ; "Try Again!" CODE:0042FB26 mov edx, offset aSorryTheSerial ; "Sorry , The serial is incorect !" CODE:0042FB2B mov eax, ds:off_430A48 CODE:0042FB30 mov eax, [eax] ; int CODE:0042FB32 call sub_42A170
直接以默認的方式去運行,在ollydbg中看各個函數調用的參數和返回情況
在sub_406930處,傳入用戶名字符串,然後返回-2-(-1-length),也就是length-1,這裏的length包括了'\0'字符,也就是說,最後這個函數的返回位用戶名的字符串長度,最後結果爲0x19,所以第一個條件判斷爲字符串長度大於4。這裏已經符合了
然後是loc_42FA79處的函數,這個函數最後的跳轉步驟在sub_4039FC處,要求這個函數返回0,而這個函數參數有兩個,第一個參數是CW-6560-CRACKED,第二參數爲序列碼。所以這裏猜測應該是根據用戶名生成了6560這個字符串,和CW和CRACKED進行拼接,然後在這裏進行最後一步的判斷
從0042FA79開始,對彙編碼進行了簡要分析,這段可以直接在ollydbg中看各個函數的參數,結果以及棧的變化,可以大致猜出sub_4039AC應該是字符串拼接函數,而關鍵點的函數應該是一個字符串相對的判斷函數。然後直接在序列碼中輸入CW-6560-CRACKED,發現果然正確,而6560這個值就是根據用戶名字符串第一個字符乘以0x29再成2得到的,上文中沒有分析的函數就是用來做字符串拼接(6560這個值在跟蹤函數的過程中也會被放入到棧上,所以只需要用ollydbg跟蹤調試每一步的變化就很容易得出結果了)
最後就OK了