VB家庭課堂 v2.0的演算法和序號產生器

看雪資料發表於2015-11-15

軟體名稱: 家庭課堂 v2.0  
軟體語言: 簡體中文
介面預覽:  
軟體型別: 共享軟體 / 網路工具 / 搜尋工具
執行環境: Win9x/WinME/Win2000/WinXP
授權方式: 共享軟體 ShareWare
軟體大小: 1.39 MB
軟體等級:  
整理時間: 2003-3-6
開 發 商:  
下載地址: http://www.ttdown.com/SoftView_11635.htm


軟體簡介
本軟體模擬課堂環境,上下課語音提醒,還可以為您合理分配學習計劃。另附加:語音報時、鈴聲設定,課間音樂播放等功能。增加了在家學習的自覺性、趣味性,提高了學習效率。

【作者宣告】:本人只是對Crack感興趣,沒有其它目的。
【破解工具】:Ollydbg1.09 中文版


―――――――――――――――――――――――――――――
【過    程】:
  這是個vb軟體p-code編碼。用原來的方法在msvbvm60.dll中選擇斷點下,都沒有
成功,我用Ollydbg的搜尋字串參考功能,也沒有發現有用的字元,不怕,還有別的
辦法。用OD載入後停在程式的入口處。用F9直接執行後,出來註冊視窗。軟體的序列
號:52111616828655  填註冊試驗碼:7894561230123456 。這時不要按註冊鍵,在
程式的入口處,用向上的方向鍵滾動程式碼向上看看,就是程式的呼叫API的地方,由於
我們現在還不知道那個有用,在他們的地址處全部下斷點。再會到程式中,然後按註冊鍵,
真的被OD中斷了.看來OD的功能真不錯.

6A3822BF  FILD    WORD PTR SS:[ESP]  

<--在這裡把序列號的各位的hex值的10進位制值取出

6A3822C2  POP     EAX
6A3822C3  XOR     EAX, EAX
6A3822C5  MOV     AL, BYTE PTR DS:[ESI]
6A3822C7  INC     ESI
6A3822C8  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
6A382E31  MOVSX   EAX, WORD PTR DS:[ESI]
6A382E34  FLD     QWORD PTR DS:[EAX+EBP]
6A382E37  XOR     EAX, EAX
6A382E39  MOV     AL, BYTE PTR DS:[ESI+2]
6A382E3C  ADD     ESI, 3
6A382E3F  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
6A3841D9  FADDP   ST(1), ST            <--在這裡相加(十進位制)
6A3841DB  XOR     EAX, EAX
6A3841DD  MOV     AL, BYTE PTR DS:[ESI]
6A3841DF  INC     ESI
6A3841E0  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
77A10E7E  FILD    DWORD PTR DS:[EDI+8] <--這裡取出引數15(F)
77A10E81  JMP     SHORT 77A10E86                
|
77A10E83  FLD     DWORD PTR DS:[EDI+8] <--引數15
77A10E86  FADD    QWORD PTR DS:[ESI+8]

<--ST=15+DS:[ESI+8]=15+729(序列號相加的值)=744

77A10E89  JMP     SHORT 77A10EB3                  
|
779BB282  MOV     EDX, DWORD PTR SS:[EBP+10]
779BB285  FBSTP   TBYTE PTR DS:[EDX]  

<--把上面的值按十進值傳送到DS:[EDX]記憶體中

779BB287  FLDCW   WORD PTR SS:[EBP-2]
779BB28A  LEAVE
|
779BEFCA  MOV     AL, BYTE PTR SS:[ESP+ESI+10]
779BEFCE  ADD     ECX, 2
779BEFD1  MOV     DL, AL
779BEFD3  AND     AL, 0F
779BEFD5  SHR     DL, 4
779BEFD8  MOVZX   DX, DL
779BEFDC  ADD     EDX, 30
779BEFDF  MOVZX   AX, AL
779BEFE3  MOV     WORD PTR DS:[ECX-2], DX
779BEFE7  ADD     EAX, 30
779BEFEA  MOV     WORD PTR DS:[ECX], AX
779BEFED  ADD     ECX, 2
779BEFF0  DEC     ESI
779BEFF1  JNS     SHORT 779BEFCA                 ; <--這段把計算的值變成數字

;<--第一組計算完成"744"
|
779BF1C4  LEA     ECX, DWORD PTR DS:[EDX+EAX+30]  ;<--ECX=F(引數)
779BF1C8  MOV     EAX, EDI
779BF1CA  MOV     WORD PTR SS:[ESP+ESI*2+1A], CX
779BF1CF  MOV     ECX, 0A
779BF1D4  CDQ
779BF1D5  IDIV    ECX
779BF1D7  ADD     EDX, 30
779BF1DA  MOV     WORD PTR SS:[ESP+ESI*2+1C], DX  

<--取它的十進位制值的第一位,變成數字DX=31

779BF1DF  AND     EBP, 80000000
779BF1E5  MOV     WORD PTR SS:[ESP+1C], 2D
779BF1EC  CMP     EBP, 80000000
779BF1F2  MOV     EAX, 1
779BF1F7  JNZ     SHORT 779BF1FC                 ; OLEAUT32.779BF1FC
|
77A10E7E  FILD    DWORD PTR DS:[EDI+8] <--這裡取出引數49(31H)(上面的值)
77A10E81  JMP     SHORT 77A10E86                   ; OLEAUT32.77A10E86
|
779BB282  MOV     EDX, DWORD PTR SS:[EBP+10]
779BB285  FBSTP   TBYTE PTR DS:[EDX]  

<--把上面的值按十進值傳送到DS:[EDX]記憶體=49

;<--第二組計算完成"49"
|
77A109AB  MOV     ECX, EBX                         \
77A109AD  MOV     EDI, EAX                         |
77A109AF  MOV     EDX, ECX                         |
77A109B1  SHR     ECX, 2                           |
77A109B4  REP     MOVS DWORD PTR ES:[EDI], DWORD>  |
77A109B6  MOV     ECX, EDX                         |
77A109B8  AND     ECX, 3                           |
77A109BB  REP     MOVS BYTE PTR ES:[EDI], BYTE P>  |
77A109BD  MOV     ECX, DWORD PTR SS:[EBP+8]        >-->這段用於連線上面的值
77A109C0  MOV     ESI, DWORD PTR SS:[EBP+C]        |
77A109C3  LEA     EDI, DWORD PTR DS:[EAX+EBX]      |
77A109C6  MOV     EAX, ECX                         |
77A109C8  SHR     ECX, 2                           |
77A109CB  REP     MOVS DWORD PTR ES:[EDI], DWORD>  |
77A109CD  MOV     ECX, EAX                         |
77A109CF  AND     ECX, 3                           |
77A109D2  XOR     EAX, EAX                         |
77A109D4  REP     MOVS BYTE PTR ES:[EDI], BYTE P>  /
77A109D6  POP     EDI

;第三組是最難跟蹤,來看看我是怎樣跟蹤出來的。
首先看第一個引數計算:
|
77A11ECD  MOV     EAX, DWORD PTR DS:[ESI+8]
77A11ED0  MOV     DWORD PTR SS:[EBP+C], EAX
77A11ED3  MOV     EAX, DWORD PTR DS:[EDI+8]
77A11ED6  MOV     DWORD PTR SS:[EBP+8], EAX
77A11ED9  MOV     EAX, DWORD PTR SS:[EBP+C]   <--EAX=2E7(743=744-1)
77A11EDC  IMUL    DWORD PTR SS:[EBP+8]        

<--EAX=2E7*SS:[EBP+8]=2E7*31(引數)

77A11EDF  MOV     ECX, DWORD PTR SS:[EBP+10]  // EAX=8E37
77A11EE2  JO      SHORT 77A11EEF                
77A11EE4  MOV     DWORD PTR DS:[ECX], 3
77A11EEA  MOV     DWORD PTR DS:[ECX+8], EAX
77A11EED  JMP     SHORT 77A11F00
|
779A23FF  MOV     ESI, DWORD PTR SS:[ESP+10]  <--ESI=9110
779A2403  MOV     EBX, ECX
779A2405  MOV     EAX, ESI
779A2407  XOR     EDX, EDX
779A2409  MOV     EDI, 0A
779A240E  ADD     ECX, 2
779A2411  DIV     EDI
779A2413  MOV     EAX, CCCCCCCD
779A2418  MOV     EDI, EDX
779A241A  MUL     ESI
779A241C  SHR     EDX, 3
779A241F  ADD     EDI, 30
779A2422  MOV     ESI, EDX
779A2424  MOV     WORD PTR DS:[ECX-2], DI  

<--DS:[ECX-2]="37136"(第三組註冊碼)

779A2428  TEST    ESI, ESI                  
779A242A  JA      SHORT 779A2405    
;
<--這段實際上就是把  779A23FF  MOV  ESI, DWORD PTR SS:[ESP+10] 處的ESI值變換成10進位制值      
// 第三組值已經計算出來,大家發現了嗎?  ESI=9110《--這個9110值是怎麼來的,因為上面的計算只計算出來了一個EAX=8E37 這個值,怎麼變成了9110呢?我首先以為這個值是常數,但是我把機器碼改變再跟蹤時發現-第三組值會變化。這說明9110這個不是常數,我跟蹤時沒有發現它的變化再跟蹤了一次,還是沒有發現(可能是我太粗心)。
// 不過沒有關係,OD給我們提供了很好的跟蹤能力。來看看我是怎樣發現計算的地方的--首先關閉所有原來的斷點,然後在 779A23FF 處下斷點,重新註冊一回,被中斷在這個地方。然後用F9執行程式,觀察暫存器資料視窗中ESI賦值的情況,如果ESI被賦9110這個值時,滑鼠選擇暫存器資料視窗的堆疊的SS:[0012E3D8]=00009110,右擊出現功能選單時選擇〔在轉存中跟蹤地址〕這時在轉存視窗中出現了地址 0012E3D8: 10 91 00 00 .這時重新註冊一次,被中斷在上面設的斷點處,這時用滑鼠選擇 10 91 資料塊,右擊出現功能選單時選擇〔斷點〕-_[記憶體寫入],用F9執行程式,這時當記憶體地址 0012E3B8 處寫入資料時就會被OD中斷,不斷的檢查這個地址被寫入的資料是不是 10 91 當寫入是10 91時就會發現在
|
779A2492  PUSH    EAX       <--這裡EAX=9110 被寫入記憶體 0012E3D8 處
779A2493  CALL    779A23E0                    
779A2498  MOV     EAX, ESI
779A249A  POP     ESI

好,向上面走了一步了,再來,我們向上找看EAX是在那裡被賦值的:
|
779A2480  MOV     EAX, DWORD PTR SS:[ESP+4] <--原來是這裡EAX被賦值=9110
779A2484  XOR     ECX, ECX
779A2486  TEST    EAX, EAX
779A2488  PUSH    ESI
779A2489  MOV     ESI, DWORD PTR SS:[ESP+C]
779A248D  SETL    CL
779A2490  PUSH    ECX
779A2491  PUSH    ESI
779A2492  PUSH    EAX     <--這裡被寫入記憶體,向上找。
779A2493  CALL    779A23E0                
779A2498  MOV     EAX, ESI
779A249A  POP     ESI
779A249B  RETN    8

好,找到被賦值的地方就好辦了。關閉所有原來的斷點(包括記憶體斷點),重新下斷點在779A2480處,重新註冊,被中斷在這裡,然後就按上面的辦法繼續跟蹤直到發現計算的地方。
|
77A10E03    8B45 10         MOV     EAX, DWORD PTR SS:[EBP+10]
77A10E06    6A 03           PUSH    3
77A10E08    5B              POP     EBX
77A10E09    8948 08         MOV     DWORD PTR DS:[EAX+8], ECX <--這裡ECX=9110
77A10E0C  ^ E9 D3FEFFFF     JMP     77A10CE4                  

向上查詢:
|
77A10DDB    8B76 08         MOV     ESI, DWORD PTR DS:[ESI+8] <--ESI=DS:[0012E7A4]=2D9
77A10DDE    8B7F 08         MOV     EDI, DWORD PTR DS:[EDI+8]
77A10DE1    8975 08         MOV     DWORD PTR SS:[EBP+8], ESI  <--ESI=2D9
77A10DE4    897D 0C         MOV     DWORD PTR SS:[EBP+C], EDI  <--EDI=8E37
77A10DE7    8D0C37          LEA     ECX, DWORD PTR DS:[EDI+ESI] <--這裡ECX=9110(8E37+2D9)
77A10DEA    33FE            XOR     EDI, ESI                  
77A10DEC    B8 00000080     MOV     EAX, 80000000
77A10DF1    85F8            TEST    EAX, EDI
77A10DF3    75 0E           JNZ     SHORT 77A10E03                    
77A10DF5    33F1            XOR     ESI, ECX
77A10DF7    85F0            TEST    EAX, ESI
77A10DF9    74 08           JE      SHORT 77A10E03      <--這裡跳到 77A10E03              
77A10DFB    DB45 08         FILD    DWORD PTR SS:[EBP+8]

; 到這裡,我們發現了9110這個關鍵值是2D9+8E37得來的,8E37是第一引數時計算的。那麼這個2D9是怎麼來的,繼續。關閉所有斷點,然後在77A10DDB處下斷點,重新註冊。找到是記憶體0012E7A4值賦值給ECX的,這次把斷點下在它的前面,第一次關鍵值8E37計算的地方:77A11EDC 然後重新註冊。中斷後發現這個值是在跳轉的過程中不經意的計算的,可能是我沒有注意:(  。
|
6A38449E  POP     EAX                   <--EAX=31(引數)
6A38449F  XOR     DWORD PTR SS:[ESP], EAX <--SS:[ESP]=2E8(744,第一組值) XOR 31=2D9
6A3844A2  XOR     EAX, EAX
6A3844A4  MOV     AL, BYTE PTR DS:[ESI]
6A3844A6  INC     ESI
6A3844A7  JMP     DWORD PTR DS:[EAX*4+6A37DA58]

;到這裡,第三組註冊碼計算完成。連線方法同上面一樣,不貼了。
;第四組註冊碼的計算比較簡單。
|
77A11F72  FLD     DWORD PTR DS:[ESI+8]
77A11F75  FMUL    QWORD PTR DS:[EDI+8]  

<--ST=744*3=2232(引數)&& 計算1

77A11F78  JMP     SHORT 77A11F9C                  
|
77A11F96  FLD     QWORD PTR DS:[EDI+8]
77A11F99  FMUL    QWORD PTR DS:[ESI+8]  

<--ST=2232*15(F,引數)=33480 && 計算2

77A11F9C  FST     QWORD PTR SS:[EBP-8]
|
6A3842DD  FMULP   ST(1), ST             <--ST=744*8(引數)=5952  && 計算3
6A3842DF  XOR     EAX, EAX
6A3842E1  MOV     AL, BYTE PTR DS:[ESI]
6A3842E3  INC     ESI
6A3842E4  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
6A3842DD  FMULP   ST(1), ST  

(再來一次)<--ST=5952*8(引數)=47616 && 計算4

6A3842DF  XOR     EAX, EAX                
6A3842E1  MOV     AL, BYTE PTR DS:[ESI]
6A3842E3  INC     ESI
6A3842E4  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
6A3842DD  FMULP   ST(1), ST  

(再來一次)<--ST=47616*55(引數)=2618880 && 計算5

6A3842DF  XOR     EAX, EAX                
6A3842E1  MOV     AL, BYTE PTR DS:[ESI]
6A3842E3  INC     ESI
6A3842E4  JMP     DWORD PTR DS:[EAX*4+6A37DA58]
|
77A10EAD  FLD     QWORD PTR DS:[ESI+8]  <--ST=33480
77A10EB0  FADD    QWORD PTR DS:[EDI+8]  

<--ST=33480+2618880=2652360 && 計算6

77A10EB3  FST     QWORD PTR SS:[EBP-8]  
77A10EB6  MOV     ECX, DWORD PTR SS:[EBP-4]
|
779BB285  FBSTP   TBYTE PTR DS:[EDX]  <--ST=2652360(第四組註冊碼)
779BB287  FLDCW   WORD PTR SS:[EBP-2]
|
779BEFCA  MOV     AL, BYTE PTR SS:[ESP+ESI+10]
779BEFCE  ADD     ECX, 2
779BEFD1  MOV     DL, AL
779BEFD3  AND     AL, 0F
779BEFD5  SHR     DL, 4
779BEFD8  MOVZX   DX, DL
779BEFDC  ADD     EDX, 30
779BEFDF  MOVZX   AX, AL
779BEFE3  MOV     WORD PTR DS:[ECX-2], DX
779BEFE7  ADD     EAX, 30
779BEFEA  MOV     WORD PTR DS:[ECX], AX
779BEFED  ADD     ECX, 2
779BEFF0  DEC     ESI
779BEFF1  JNS     SHORT 779BEFCA       ; <--這段把計算的值變成數字做註冊碼

;下面的連線是一樣的就不貼了。

;最後是比較的地方
|
77A14331  MOV     EDI, DWORD PTR SS:[EBP+C]    

; EDI<--0013E7F4  UNICODE "789451230123456"--試驗碼

77A14334  MOV     ESI, DWORD PTR SS:[EBP+8]    

; ESI<--0013C0E4  UNICODE "74449371362652360"--正確的註冊碼

77A14337  MOV     ECX, DWORD PTR SS:[EBP+10]
77A1433A  XOR     EAX, EAX
77A1433C  REPE    CMPS WORD PTR ES:[EDI], WORD PTR >; <--這裡進行比較
77A1433F  JE      SHORT 77A14346                  
77A14341  SBB     EAX, EAX
77A14343  SBB     EAX, -1                     <--賦失敗標誌
77A14346  TEST    EAX, EAX
77A14348  JG      SHORT 77A1437D                  
77A1434A  JGE     SHORT 77A14350                  
77A1434C  XOR     EAX, EAX                    <--賦成功的標誌
77A1434E  JMP     SHORT 77A143AB                  

====================================================

到這裡演算法跟蹤已經完成,總結一下。
說明:這是一個典型的vb P-CODE編碼的程式,可以看出它的計算和比較已全部在MSVBVM60.DLL和OLEAUT32.DLL中,程式本身只是提供跳轉和資料的地方,所以跟蹤起來很雜。沒有了流程線。但是,只要有耐心還是可以跟蹤出來演算法的。

    註冊碼的計算方法:
         1.把序列號的各位hex的10進位制值相加,然後+15(引數)。
           得到的值就是註冊碼的前三位。
         2.第4、5位是固定值49
         3.把第一組的值-1後×49+第一組的值 XOR 49 得到的值就是第三組註冊碼
         4.把第一組值×3565得到的值就是第四組註冊碼
         5.把上面的各組連線起來就是正確的註冊碼

這樣看來註冊碼的計算並不複雜。
這是它的序號產生器原始碼:
----vb6.0下透過----

Dim i As Integer
Dim e As Integer

Dim edx As Long
Dim ebx As Long
Dim eax As Long
Dim sn1 As String
Dim sn2 As String
Dim sn3 As String

Dim startin As String '以上定義變數及變數型別
startin = Text2.Text   '變數startin接收輸入的資料
nlen = Len(startin)    '取輸入資料的長度
If nlen < 13 Then       '如果小於13位就不正確
MsgBox ("你還沒有輸入機器碼,或者長度不正確,請核對後重新輸入")
GoTo tc                '結束
Else:
End If

i = 0
e = 1
begin:
eax = AscB(Mid(startin, e, 1))
i = i + 1
e = e + 1
ebx = ebx + eax
If i < nlen Then
GoTo begin        '這段迴圈把機器碼的各位hex的10進位制值相加
Else
End If
ebx = ebx + 15    '加引數15
sn1 = CStr(ebx)   '轉變為字元
'--第一組計算完成--

'--開始計算第三組--

sn2 = CStr((ebx - 1) * 49 + (ebx Xor 49))

'--開始計算第四組--

sn3 = CStr(ebx * 3565)

Text1.Text = sn1 + "49" + sn2 + sn3  '輸出為註冊碼
tc: End Sub

                                                by  fxyang[OCN][BCG]

                                                    2003.5.2

相關文章