我的破解心得(11) (9千字)

看雪資料發表於2001-03-13

破解程式:
    Matcom 4.0 for BC

破解工具:
    SoftICE 3.0 For Windows 95
    W32DASM 8.5

破解者:
    chcw

    Matcom的評估版有時間限制,下面我們將破解掉Matcom的這個功能限制。

1. 在時間限制過了之後,執行Matcom,程式提示"error, MIDEVA, License expired",記下這個錯誤資訊。
2. 用W32Dasm反彙編Mideva.exe,在Refs/String Data References中查詢在上一步中記下的錯誤資訊:
  "License expired"。
3. 用滑鼠雙擊該字串,並關掉SDR視窗。此時,亮條停留在00429367處:

    * Possible StringData Ref from Data Obj -> "License expired"
                                      |
    :00429367 B8116C5000              mov eax, 00506C11        <-亮條所在處

4. 從亮條所在處向上找,可以發現在地址:00429315處有一條跳轉語句,這是一個跳轉表:
    :00429315 FF24851C934200          jmp dword ptr [4*eax+0042931C] <-0042931C是一個跳轉地址表
                                        eax==5時,跳轉到:00429367處執行

  繼續向上找,可以發現這是一個子程式:
    * Referenced by a CALL at Addresses:
    |:00416913  , :00429E72 
    |
    :0042930A 55                      push ebp
  在入口處可以找到呼叫該子程式的語句為:00416913,:00429E72。看來,在Matcom的程式
  中,可能有多處對時間的期限進行檢查。
5. 選擇Goto/Goto Location,鍵入地址00416913,按"OK"後,亮條將停留在地址00416913處:
    :00416913 E8F2290100              call 0042930A
  從該語句處向上找,可以發現在執行該語句前有一個條件跳轉:
    :004168F1 E83F320100              call 00429B35
                        ...
    :004168FF 83BD74ECFFFF00          cmp dword ptr [ebp+FFFFEC74], 00000000
    :00416906 7E1C                    jle 00416924
  而函式00429B35很可能與判斷時間是否過期有關。
6. 選擇Goto/Goto Location,鍵入地址00429E72,按"OK"後,亮條將停留在地址00429E72處:
    :00429E67 FFB150020000            push dword ptr [ecx+00000250]    <- 輸入錯誤碼
    :00429E6D 6890CA5100              push 0051CA90
    :00429E72 E893F4FFFF              call 0042930A        
  從該語句處向上找,可以發現在執行該語句前呼叫了函式00429605
    :00429D4E E8B2F8FFFF              call 00429605
7. 按下工具欄上的Call按鈕,分別對函式00429B35和函式00429605執行文字跳轉,觀測它們
  的可能流程,發現這兩個函式都呼叫了同一個子函式004961D0,由此我們猜想,子函式
  004961D0可能是一個檢測時間的子函式。
8. 選擇Goto/Goto Location,鍵入地址004961D0,按"OK"後,亮條將停留在地址004961D0處:
    * Referenced by a CALL at Addresses:
    |:00429655  , :00429B4B 
    |
    :004961D0 55                      push ebp
  該函式中有一個函式呼叫KERNEL32.GetLocalTime()讀取系統的時間,這證明了我們先前的
  猜想。我們可以直接在函式004961D0中進行修改,以實現解除時間限制的目的。但這裡我採
  用了另一種破解方法。
9. 用SoftICE載入Mideva.exe程式,在函式004961D0處設定斷點:
    BPX 004961D0
10. 鍵入'X'命令,程式開始執行,顯示完展示畫面後,觸發SoftICE:
    0137:00496208    CALL 00495EA0
    鍵入BC *, 清除原先的斷點。按F10, 執行完該程式呼叫。
11. 繼續按F10鍵,直到0137:00429670處:
    0137:00429670    CALL 00429567        <-    呼叫函式00429567
    0137:00429675    ADD ESP, 00000008
    0137:00429678    TEST EAX, EAX
    0137:0042967A    JE 00429A8F
    程式呼叫該函式後,根據其返回值的不同,進行條件跳轉。因此有必要對它進行分析。
12. 按F8, 進入該函式:

    0137:0042957F    CALL 0042949E        ;    獲取Windows目錄
                ...                            
    0137:00429591    CALL 004831E4        ;    將Windows目錄複製到另一緩衝區內。
                ...    
    0137:00429599    PUSH 004FF6E8        ;    字串 "MT_LIC.TXT"
    0137:0042959E    PUSH [EBP+0C]
    0137:004295A1    CALL 00483108        ;    生成MT_LIC.TXT檔案的全路徑    
    0137:004295A6    ADD ESP, 00000008    
    0137:004295A9    PUSH [EBP+0C]
    0137:004295AC    CALL 0042A5B4        ;    開啟MT_LIC.TXT檔案

    該函式有四處函式呼叫,連續按F10,執行完這些呼叫,同時觀察呼叫前的引數和呼叫後
    的返回值。我們可以大致瞭解到該函式的作用是開啟一個在Windows目錄下名為MT_LIC.TXT
    的檔案。
      鍵入BC *, 清除所有斷點。按Ctrl-D,執行完原應用程式,退出SoftICE。
13. 檔名"MT_LIC.TXT"很容易使人聯想起License, 這很可能是Matcom For BC的註冊資訊檔案。
    到Windows目錄下,發現並沒有mt_lic.txt這個檔案,但卻有一個mt_eval.txt檔案,其內容是:
    16/3/1999-17/4/1999-116897682,正是我們填入的Evaluation註冊碼。由此,我們可
    猜想,Matcom For BC程式共有下面兩種註冊方式:
    1.評估註冊(Evaluation), 評估註冊資訊記錄在mt_eval.txt檔案中,該種註冊方式有一
          定的時間期限。
    2.完全註冊,完全註冊資訊記錄在mt_lic.txt檔案中,該種註冊方式為全功能註冊,沒有
      任何使用上的限制。
    Matcom For BC程式的註冊流程為:    
                                是            是
Windows目錄下有mt_lic.txt嗎?----->mt_lic.txt合法嗎?---->完全註冊成功
    |                |        
        |                 否 |
    |                    |     
  否    |                註冊失敗(顯示Corrupt License File)    
    |
    |              是              是    
Windows目錄下有mt_eval.txt嗎?----->mt_eval.txt合法嗎?----->評估使用
    |                |    
    |            否  |    
  否    |                |    
    |        若時間格式錯誤,則顯示Wrong Date Format。
    |        若超過了評估時間期限,則顯示License expired。
提示使用者輸入評估密碼    

      看來,我們只需構造出正確的mt_lic.txt檔案,即可實現完全註冊。
14. 用Notepad在Windows目錄下建立mt_lic.txt檔案,並輸入檔案的內容為"CHCW9530109"(檔案
    內容隨意,不過最好長一些)。
15. 再次用SoftICE載入Mideva.exe程式,在0137:00429670處設定斷點:
    BPX 0137:00429670
    鍵入'X'命令,程式執行,觸發SoftICE:
    0137:00429670    CALL 00429567
    鍵入BC *, 清除原先的斷點。按F10, 執行完該呼叫。在上面我們已經說過,函式00429567的
    作用是開啟檔案mt_lic.txt。在開啟檔案之後,程式勢必要讀取檔案中的資料。連續按F10鍵,
    到00429691處有一個函式呼叫:
    0137:00429691    CALL 0040BA24
    按F10, 執行完該呼叫。鍵入:s ds:0 l ffffffff 'CHCW9530109' ,發現檔案mt_lic.txt中
    的資料"CHCW9530109"已經被讀入記憶體中地址013F:00D17CB4中。
16. 對地址013F:00D17CB4設定斷點:
    BPM 013F:00D17CB4
17. 鍵入"X",程式繼續執行,觸發SoftICE:
    0137:00430E49    MOVSX EDX, BYTE PTR [EAX]    <-- 觸發斷點處    
    0137:00430E4C    CMP EDX, 0000000A        
                ...
    0137:00430E6C    MOV BYTE PTR [ECX], DL        <-- 存放至記憶體地址DS:ECX處
                ...
    0137:00430E9E    JL 00430E60            <-- 迴圈處理所有字元
    0137:00430EA0    MOV EAX, DWORD PTR [EBP+0C]
    這部分程式的作用將讀入記憶體中的字串逐個進行處理(去掉\n\r等字元)後,存放到記憶體
    013F:0100AE04處。   
18. 鍵入BC *, 清除原先的斷點,並將游標移到0137:00430EA0處,鍵入"HERE"。跳出上述處理程式,
    然後就對目標記憶體區域再設定斷點:
    BPM 013F:0100AE04
18. 鍵入"X",程式繼續執行,觸發SoftICE:
    0137:0048321C    MOV EDX, DWORD PTR [EAX]    <-- 觸發斷點處    
    0137:0048321E    ADD EAX, 00000004        
    這部分程式的作用只是獲取字串"CHCW9530109"的長度。
19. 再鍵入"X",程式繼續執行,又會觸發SoftICE:
    0137:00429278    PUSH EBP            <-- 函式入口點
              ...
    0137:004292DB    MOV EDX, DWORD PTR [EBP+10]
    0137:004292DE    MOV DWORD PTR [EDX], EAX
    0137:004292E0    JMP 004292E7
              ...    
    0137:00429300    MOV EDX, DWORD PTR [EBP+10]
    0137:00429303    AND DWORD PTR [EDX], FFFFFFFF    <-- 返回值存放在DS:EDX處
    0137:00429306    POP ECX
    0137:00429307    POP ECX
    0137:00429308    POP EBP
    0137:00429309    RET
    函式00429278的引數是字串"CHCW9530109"和串的長度,在對字串進行某種計算後,返回一
    個數值。由於這裡計算的方法比較古怪,又看不出它的用意,比較可疑。鍵入BC *, 清除原先斷
    點後,我們再對存放返回值的記憶體區域設定斷點:
    BPM 013F:0100AE04
20. 再鍵入"X",程式繼續執行,又會觸發SoftICE:
    0137:00429995    MOV EDX, DWORD PTR [EBP-40]    <-- 觸發斷點處, 該語句將19步中的返回值放入EDX中。
    0137:00429998    SUB EDX, DWORD PTR [EBP-44]    
    0137:0042999B    MOV DWORD PTR [EBP-74], EDX
    0137:0042999E    MOV [EBP-2C], 0014
    0137:004299A4    FILD DWORD PTR [EBP-74]
    0137:004299A7    FADD DWORD PTR [00429B2D]    ;一系列浮點操作
                ...
    0137:004299FE    FSTSW AX
    0137:00429A00    SAHF
    0137:00429A01    JE 00429A32
                ...
    0137:00429A28    MOV DWORD PTR [EBX+00000250], 00000002    ;置錯誤碼為2
    0137:00429A32    MOV ECX, DWORD PTR [EBP+08]
    在上面的程式段中,我們發現在0137:00429A01處有一句條件跳轉je 00429A32,而在跳轉的目的地址
    處有一條置錯誤碼的語句(在第4步中,我們已經知道,在跳轉表中錯誤碼為2是"Corrupted license file")。
    看來,在je之前的浮點指令段十分關鍵。
    鍵入"WF"命令,開啟浮點棧視窗。除錯浮點指令段,可以知道其大致的操作是:
    比較 (X+1) ^ 2 和 (X-1) ^ 2 是否相等(其中X是第19步中的返回值)。
21. 經過簡單的運算,即可解出方程(X+1) ^ 2 = (X-1) ^ 2的根是X=0。因此,註冊成功的條件之一是字
    符串"CHCW9530109"在第19步運算後得到的最後返回值是0。採用我的破解心得(4)中的方法可將第19步
    中的子函式00429278擷取出來。
    分析該子程式(設為f(x))後,我發現它似乎使用了一個所謂的"不可逆加密"的方法, 即已知
    f(x)=0, 卻無法解得x的值。唯一的方法是窮舉,其複雜度是35^n,是不可解問題。我使用產生式算
    法,運算了若干個小時後,以失敗告終。
22. 在遺憾之餘,我發現Matcom For BC計算評估密碼時也會呼叫函式00429278,引數為
    字串"16/3/1999-17/4/1999-116897682"和長度19, 而引數串的前19個字元恰好為使用期限:
    "16/3/1999-17/4/1999",呼叫函式後得到的返回值的十進位制則恰為116897682。       
        由上可知,MatCom For BC中評估密碼的加密方法是:密碼的前一部分為使用期限,以使用期限字元
    串為引數,透過函式00429278計算出密碼後一部分的數值,組合後即為合法的評估密碼。這樣,雖然我
    們無法實現MatCom For BC的完全註冊,但是我們可以根據評估加密方法,隨意的改動使用期限。
23. 這樣,我就結束了對Matcom For BC的破解。對該程式的註冊加密方法,我還是比較滿意的,因為它針對
    兩種不同的註冊效果,採用同一種加密方法提供了兩種不同難度的加密。而在我的破解心得(5)中所述及
    的HyperCam,卻對Single User/Unlimited Site License/Unlimited Word-Wide License採用了幾
    乎完全相同的加密方法,使人破解起來感到索然無味。

附:函式00429278,為簡化起見,我已將其改寫為C程式碼。若有網友能用較低的複雜度由返回值反解得該函式
    的輸入引數,請寫信告知與我,謝謝。

--------------------- Function f00429278() -----------------------

unsigned long f00429278(unsigned char *regcode,int len)
{
    unsigned char c;
    unsigned long extc, result;
    result=0xBEEFBEEF;
    while (len--)    {
        c=*regcode;
        if (isalpha(c) || isdigit(c))     {
            extc=toupper(c);
            extc+=256;
            if ((long)extc<=1) continue;
            do {
                if ((result ^ extc) & 1)
                    result = (result >>1) ^ 0x4C11DB7;
                else
                    result >>=1;
            } while ((extc >>= 1) > 1);
        }
        regcode++;
    }
    return result;
}
---------------------End of Function f00429278()-----------------------


  

相關文章