MagicWin 98 Release 1.20 破解手記 (20千字)

看雪資料發表於2002-06-01

MagicWin 98 Release 1.20 破解手記

**************************************************
目的:製作序號產生器
Cracked by  WksWlj999@sohu.com
軟體說明:著名的內碼轉換工具
破解工具:w32dasm8.93;SoftICE 4.05 For Win9X
日期:2002年5月25日

注意:高手莫看!這是小弟看了“看雪”兄的大作《加密與解密――軟體保護技術及完全解決方案》一書後,恰好機子上裝的MagicWin 98沒有註冊,就拿它來開刀吧,本人剛剛涉足加密與解密,水平有限,文中有不足之處還望各位大蝦不吝指教!此文僅供初學者參考。
***************************************************

執行MagicWin 98,在註冊視窗輸入    Your Name:WksWlj999
                Serial Number:MGW45146-10(程式預設自動填入)
                Registration Code:369369369369(隨便輸,為何要這麼長呢,下面會講的)

然後在SoftICE裡下斷點"bpx getdlgitemtext"(為何在16位API函式下斷點呢,因為我用w32dasm8.93檢視過MagicWin 98的函式輸入表啊!),然後點"Register",SoftICE攔截並中斷跳出,按F11返回MagicWin 98的領空。

* Possible Reference to Dialog: DialogID_0001, CONTROL_ID:006E, ""
                                  |
:0047.0408 6A6E                  push 006E
:0047.040A 16                    push ss
:0047.040B 8D46E4                lea ax, [bp-1C]
:0047.040E 50                    push ax
:0047.040F 6A1C                  push 001C
:0047.0411 9AFFFF0000            call USER.GETDLGITEMTEXT
:0047.0416 56                    push si        //按F11返回後停在此處

下命令"bc *"清除下的斷點,然後按F10單步跟蹤......

:0047.0434 50                    push ax
:0047.0435 680001                push 0100
:0047.0438 9AFFFF0000            call USER.GETWINDOWTEXT
:0047.043D 837E0800              cmp word ptr [bp+08], 0000
:0047.0441 7503                  jne 0446
:0047.0443 E9BC00                jmp 0502        //來到這個絕對跳轉,繼續F10跟蹤

--------------------------------------------------------------
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0047.0443(U)
|
* Possible Reference to Menu: MenuID_0001
                                  |
* Possible Reference to Dialog: DialogID_0001
                                  |
* Possible Reference to String Resource ID=00001: "ASCII"
                                  |
:0047.0502 6A01                  push 0001
:0047.0504 16                    push ss
:0047.0505 8D86C8FE              lea ax, [bp+FEC8]
:0047.0509 50                    push ax        //輸入的Your Name:"WksWlj999"進棧,以下簡稱"Name"
:0047.050A 16                    push ss
:0047.050B 8D46C8                lea ax, [bp-38]
:0047.050E 50                    push ax        //輸入的假Registration Code:"369369369369"進棧,以下簡稱"Code"
:0047.050F 16                    push ss
:0047.0510 8D46E4                lea ax, [bp-1C]
:0047.0513 50                    push ax        //程式預設的Serial Number:"MGW45146-10"進棧,以下簡稱"Serial"
:0047.0514 9AFFFF0000            call 0037.03ABh    //這個緊跟的Call很可疑,按F8跟進
:0047.0519 83C40E                add sp, 000E

* Possible Reference to Menu: MenuID_0001
                                  |
* Possible Reference to Dialog: DialogID_0001
                                  |
:0047.051C 3D0100                cmp ax, 0001        //比較AX與0001(根據call 0037.03ABh的結果,註冊正確返回AX=0否則AX=1)
:0047.051F 7558                  jne 0579        //AX=1則跳到註冊錯誤對話方塊
:0047.0521 9AFFFF0000            call 0044.0073h    //以下前往註冊正確對話方塊
:0047.0526 52                    push dx
:0047.0527 50                    push ax
:0047.0528 9AFFFF0000            call 0044.002Dh
:0047.052D 52                    push dx
:0047.052E 50                    push ax
:0047.052F 1E                    push ds
......
----------------------------------------------------
接call 0037.03ABh,F8進入後,F8單步跟蹤

* Referenced by a CALL at Address:
|:0037.017F
|
:0037.03AB 55                    push bp
:0037.03AC 8BEC                  mov bp, sp
:0037.03AE 81EC8600              sub sp, 0086
:0037.03B2 56                    push si
:0037.03B3 57                    push di
:0037.03B4 C746FE0000            mov word ptr [bp-02], 0000
:0037.03B9 66FF7606              push word ptr [bp+06]        //Serial進棧,d *(bp+06)可看到"MGW45146-10"
:0037.03BD 9AFFFF0000            call KERNEL.LSTRLEN        //計算長度置入AX=Bh
:0037.03C2 50                    push ax            //長度AX=Bh進棧儲存
:0037.03C3 66FF760A              push word ptr [bp+0A]        //假Code進棧,d *(bp+0A)可看到"369369369369"
:0037.03C7 9AFFFF0000            call KERNEL.LSTRLEN        //計算長度置入AX=Ch
:0037.03CC 5A                    pop dx            //Serial長度BH出棧,DX=Bh
:0037.03CD 3BD0                  cmp dx, ax            //比較Serial和假Code的長度
:0037.03CF 7E25                  jle 03F6            //Serial長度小於等於假Code長度Bh(即11位)就跳,否則註冊
:0037.03D1 66FF760A              push word ptr [bp+0A]          錯誤,這就是為何假Code的長度要大於等於Serial長度的原因!
:0037.03D5 1E                    push ds

......

跳到這裡
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0037.03CF(C), :0037.03E0(C), :0037.03F1(C)
|
:0037.03F6 C45E0A                les bx, [bp+0A]
:0037.03F9 26803F00              cmp byte ptr es:[bx], 00    //假Code是否為空?
:0037.03FD 7503                  jne 0402            //不空就跳到0402
:0037.03FF E9C801                jmp 05CA



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.03FD(C)
|
:0037.0402 16                    push ss
:0037.0403 8D867AFF              lea ax, [bp+FF7A]
:0037.0407 50                    push ax
:0037.0408 66FF7606              push word ptr [bp+06]
:0037.040C 9AFFFF0000            call KERNEL.LSTRCPY        //複製Serial到記憶體地址[bp+FF7A]
:0037.0411 16                    push ss
:0037.0412 8D867AFF              lea ax, [bp+FF7A]
:0037.0416 50                    push ax            //"d ax"可看到複製來的Serial:"MGW45146-10"
:0037.0417 9AFFFF0000            call KERNEL.LSTRLEN        //計算長度置入AX
:0037.041C 8BF8                  mov di, ax

* Possible Reference to Menu: MenuID_0003
                                  |

* Possible Reference to Dialog: DialogID_0003
                                  |

* Possible Reference to String Resource ID=00003: "ChineseGuoBiao"
                                  |
:0037.041E BA0300                mov dx, 0003            //dx=3
:0037.0421 8D867DFF              lea ax, [bp+FF7D]        //將[bp+FF7D]地址傳入AX,即Serial第4位的地址
:0037.0425 8BF0                  mov si, ax
:0037.0427 EB4C                  jmp 0475            //跳到0475,將Serial執行換位操作



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.0479(C)
|
:0037.0429 8BC2                  mov ax, dx //0429-0479處程式碼功能是保持Serial Number的前3位不變,然後依次將其
:0037.042B 050400                add ax, 0004 第4位與第8位互換位置,第5位與第9位互換,第6位與第10位互換,第7位
:0037.042E 3BC7                  cmp ax, di 與第11位互換,第8位與第9位互換,第9位與第10位互換,第10位與第11位互換
:0037.0430 7D1E                  jge0450 比如:Serial是"XXX12345678",則換位結束後得到"XXX56782341"
:0037.0432 368A0C                mov cl , ss:[si]        
:0037.0435 8D867EFF    leaax, [bp+FF7E] //經驗證,換位規則是:當Serial長度小於等於3時,不換位,直接在Serial後加上
:0037.0439 8BDA                  mov bx,dx Name的長度與其各位ASC碼值的和(十進位制),即為正確的Code;當Serial長度
:0037.043B 03D8                  add bx, ax 大於3時,從第4位開始,先將位數加4,值在Serial長度範圍內,則將此位與其
:0037.043D 368A07         mov al , ss:[bx] 位數加4所在位互換位置,然後順序執行下一位的判斷;若其值超出Serial長度
:0037.0440 368804                mov ss:[si], al 範圍,則判斷此位的下一位數是否在Serial長度範圍內,若在則將此位與
:0037.0443 8D867EFF              lea ax, [bp+FF7E] 其下一位互換,然後順序執行下一位的判斷,若超出則換位結束。
:0037.0447 8BDA                  mov bx, dx
:0037.0449 03D8                  add bx, ax
:0037.044B 36880F                mov ss:[bx], cl
:0037.044E EB23                  jmp 0473




* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.0430(C)
|
:0037.0450 8BC2                  mov ax, dx
:0037.0452 40                    inc ax
:0037.0453 3BC7                  cmp ax, di
:0037.0455 7D1C                  jge 0473
:0037.0457 368A0C                mov cl , ss:[si]
:0037.045A 8D867BFF              lea ax, [bp+FF7B]
:0037.045E 8BDA                  mov bx, dx
:0037.0460 03D8                  add bx, ax
:0037.0462 368A07                mov al , ss:[bx]
:0037.0465 368804                mov ss:[si], al
:0037.0468 8D867BFF              lea ax, [bp+FF7B]
:0037.046C 8BDA                  mov bx, dx
:0037.046E 03D8                  add bx, ax
:0037.0470 36880F                mov ss:[bx], cl

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0037.044E(U), :0037.0455(C)
|
:0037.0473 46                    inc si
:0037.0474 42                    inc dx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.0427(U)
|
:0037.0475 36803C00              cmp byte ptr ss:[si], 00    //ss:[si]處位元組是否為空,即比較是否Serial Number換位結束
:0037.0479 75AE                  jne 0429            //不空則跳至0429繼續換位

* Possible Reference to Menu: MenuID_0003
                                  |

* Possible Reference to Dialog: DialogID_0003
                                  |

* Possible Reference to String Resource ID=00003: "ChineseGuoBiao"
                                  |
:0037.047B BA0300                mov dx, 0003
:0037.047E 3BD7                  cmp dx, di
:0037.0480 7D19                  jge 049B

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.0499(C)
|
:0037.0482 8D867AFF              lea ax, [bp+FF7A]        //此句過後緊跟著下"d AX"命令可看到換位後的Serial Number="MGW6-105144"
:0037.0486 8BDA                  mov bx, dx            //dx=0003
:0037.0488 03D8                  add bx, ax            //位置調整到Serial Number的第dx位
:0037.048A 8BF3                  mov si, bx
:0037.048C 368A07                mov al , ss:[bx]        //取Serial Number的第4位
:0037.048F 02C2                  add al , dl            //al=al+dl
:0037.0491 0410                  add al, 10            //al=al+10h
:0037.0493 368804                mov ss:[si], al
:0037.0496 42                    inc dx            //dx=dx+1
:0037.0497 3BD7                  cmp dx, di
:0037.0499 7CE7                  jl 0482            //0482-0499處程式碼功能是取換位後的Serial Number的第4位到第11位,將它們的
                                  ASC碼值分別加上13h,14h,15h,16h,17h,18h,19h,1Ah得到"MGWIAFFLIMN"
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.0480(C)
|
:0037.049B 66FF760E              push word ptr [bp+0E]        //Your Name:="WksWlj999"進棧,d *(bp+0e)在資料窗可看到
:0037.049F 9AFFFF0000            call KERNEL.LSTRLEN        //計算長度,AX=9h
:0037.04A4 8BC8                  mov cx, ax            //CX=AX=9h        
:0037.04A6 660FBFC1              movsx eax, ecx
:0037.04AA 668946FA              mov [bp-06], eax        
:0037.04AE 33D2                  xor dx, dx            //dx=0
:0037.04B0 8B760E                mov si, [bp+0E]
:0037.04B3 3BD1                  cmp dx, cx            //dx大於等於Your Name的長度嗎?
:0037.04B5 7D15                  jge 04CC            //大於等於則跳到04CC,否則繼續

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.04CA(C)
|
:0037.04B7 8E4610                mov es, [bp+10]        //04B7-04CA處程式碼功能將Your Name的長度9h與其每位的ASC碼值(16進位制)加到一起
:0037.04BA 268A04                mov al , es:[si]          並將和存入地址[bp-06]中
:0037.04BD 98                    cbw
:0037.04BE 660FBFC0              movsx eax, eax
:0037.04C2 660146FA              add [bp-06], eax
:0037.04C6 46                    inc si
:0037.04C7 42                    inc dx
:0037.04C8 3BD1                  cmp dx, cx
:0037.04CA 7CEB                  jl 04B7

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0037.04B5(C)
|
:0037.04CC 66FF76FA              push word ptr [bp-06]        //將和進棧,d *(bp-06)可看到資料窗中"16 03 00 00"即和是0316h(16進位制)
:0037.04D0 1E                    push ds

* Possible StringData Ref from Data Seg 069 ->"%"
                                  |
:0037.04D1 681F1E                push 1E1F
:0037.04D4 8D867AFF              lea ax, [bp+FF7A]        //將"MGWIAFFLIMN"的首地址入ax
:0037.04D8 8BD7                  mov dx, di            //將"MGWIAFFLIMN"的長度Bh入dx
:0037.04DA 03D0                  add dx, ax            //dx=dx+ax,此時dx指向的是緊跟"MGWIAFFLIMN"後的位置
:0037.04DC 16                    push ss            //USER._WSPRINTF函式的引數1進棧
:0037.04DD 52                    push dx            //USER._WSPRINTF函式的引數2進棧
:0037.04DE 9AFFFF0000            call USER._WSPRINTF        //將和0316h由16進位制轉換為十進位制的790d並輸出到dx指向的位置
:0037.04E3 83C40C                add sp, 000C
:0037.04E6 16                    push ss
:0037.04E7 8D867AFF              lea ax, [bp+FF7A]        
:0037.04EB 50                    push ax            //"d ax"可看到真的Registration Code="MGWIAFFLIMN790"
:0037.04EC 66FF760A              push word ptr [bp+0A]        //"d *(bp+0a)"可看到輸入的假Registration Code="369369369369"
:0037.04F0 9AFFFF0000            call USER.LSTRCMP        //關鍵的比較!!!註冊碼正確置ax=0,錯誤置ax=1
:0037.04F5 0BC0                  or ax, ax
:0037.04F7 7425                  je 051E            //關鍵的跳轉!!!ax=0則跳轉到註冊正確程式段,可在此處使用"r fl z"命令
:0037.04F9 66FF760A              push word ptr [bp+0A]          使ZF標誌位=1,則跳到051E,註冊就成功了.然後程式會自動將正確的Serial Number
:0037.04FD 1E                    push ds              和計算出的真Registration Code以及你輸入的Name一起寫到MagicWin.ini中儲存起來
                                  下次啟動程式就可從MagicWin.ini中讀取出正確的註冊資訊了.@_@
* Possible StringData Ref from Data Seg 069 ->"B"
                                  |
:0037.04FE 68231E                push 1E23
:0037.0501 9AFFFF0000            call USER.LSTRCMPI
:0037.0506 0BC0                  or ax, ax
:0037.0508 7414                  je 051E
:0037.050A 66FF760A              push word ptr [bp+0A]
:0037.050E 1E                    push ds

* Possible StringData Ref from Data Seg 069 ->"M"
                                  |
:0037.050F 68E11D                push 1DE1
:0037.0512 9AFFFF0000            call USER.LSTRCMPI
:0037.0517 0BC0                  or ax, ax
:0037.0519 7403                  je 051E
:0037.051B E9AC00                jmp 05CA

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0037.04F7(C), :0037.0508(C), :0037.0519(C)
|
:0037.051E 66FF760A              push word ptr [bp+0A]
:0037.0522 1E                    push ds
-------------------------------------------------------------------------
總結一下:
    Your Name:WksWlj999
    Serial Number:MGW45146-10
    Registration Code:MGWIAFFLIMN790
註冊資訊儲存在安裝目錄下的MagicWin.ini檔案中格式如下:

[Software Lock]
Serial No=MGW45146-10
Password=MGWIAFFLIMN790
Second Lock=47974l    //這個值不曉得做什麼用,好象註冊成功後把它刪除,程式也能正常使用

[Usage]
Count=5            //這個是未註冊前已使用的次數

[UserInfo]
User=WksWlj999

根據上面的除錯結果寫出MagicWin 98 Release 1.20的序號產生器如下:(用VB6編的,小弟C語言地不行,彙編看看程式碼還可以,自己寫也不行,雖然討厭VB6必須帶一個老大的MSVBVM60.dll,也沒辦法:-(,早說了我們水平不行嘛!(自己找臺階下了^_^))

----------------SATART CODE-----------------------------------
Dim myname As String        '定義變數
Dim serial As String
Dim mycode As String
Dim i As Integer
Dim ADD As Integer

Private Sub Command1_Click()
    serial = Text1.Text    '獲取輸入的Serial Number
    myname = Text2.Text    '獲取輸入的Your Name

    '根據Serial長度判斷是否執行換位操作
    If Len(serial) <= 3 Then
        mycode = serial
        Else
        'Serial長度>4,執行換位
        mycode = Serial_Change(serial)
        mycode = Serial_PLUS(mycode)
    End If

    '計算Your Name每位的ASC碼值之總和並加上其本身長度,存入ADD變數中
    For i = 1 To Len(myname)
        ADD = ADD + Asc(Mid$(myname, i, 1))
    Next i
    ADD = ADD + Len(myname)

    '組合出完整的Registration Code
    mycode = mycode + CStr(ADD)

    '輸出結果到文字框中
    Text3.Text = mycode
End Sub

'對Serial Number進行換位操作,不明白的話可參見":0037.0429"處的註釋
Function Serial_Change(ByVal OPR_Serial As String) As String
    Dim tempinteger As Integer
    ReDim a(4 To Len(serial)) As Integer    '重定義陣列
    '對陣列a(4 to Len(serial))賦值為與其下標號相同的正整數,即a(4)=4,a(5)=5......
    For i = 4 To Len(serial)
        a(i) = i
    Next i
    '從第4位開始執行換位,換位結束時,陣列的下標代表了其在變換過的Serial中的位置
    '而其值則代表了此位置的數值是原來Serial的哪一位換位過來的,比如換位結束後若
    'a(4)=8則表明換位後的Serial的第4位應該是原始Serial的第8位
    i = 4
    Do While i + 4 <= Len(serial)
        tempinteger = a(i)
        a(i) = a(i + 4)
        a(i + 4) = tempinteger
        i = i + 1
    Loop
    Do While i + 1 <= Len(serial)
        tempinteger = a(i)
        a(i) = a(i + 1)
        a(i + 1) = tempinteger
        i = i + 1
    Loop
    '將a(i)對應的原始Serial中的值取出來,按下標順序排列出換位後的Serial
    OPR_Serial = Left$(OPR_Serial, 3)
    For i = 4 To Len(serial)
        OPR_Serial = OPR_Serial + Mid$(serial, a(i), 1)
    Next i
    Serial_Change = OPR_Serial
End Function

'將換位後的Serial Number的第4位到末位的ASC碼值依次分別加上19d(13h),20d(14h)......
Function Serial_PLUS(ByVal CHG_Serial As String) As String
    Dim tempstring As String
    tempstring = CHG_Serial
    CHG_Serial = Left$(CHG_Serial, 3)
    i = 1
    Do While i + 3 <= Len(tempstring)
        CHG_Serial = CHG_Serial + Chr$(Asc(Mid$(tempstring, i + 3, 1)) + 18 + i)
        i = i + 1
    Loop
    Serial_PLUS = CHG_Serial
End Function
----------------END CODE-------------------------------------
最後補充一下,你可以任意輸入Serial Number,可以包含所有的可顯示字元,但要注意的一點是其ASC碼值經變換加值後再轉換為字元
時,有時無法正常顯示出來,因為其值已經超出255或本身就是無法顯示的。

相關文章