Java 程式的破解方法 (8千字)

看雪資料發表於2002-08-15

Java 程式的破解方法

軟體名稱:極速××××1.94(國產軟體)
未註冊版限制:1、無法使用軟體的嚮導功能;
            2、不能自定義超時時間。
破解工具:J++Extract 1.1、Jad 1.5.7g。
破解人:飛鷹[BCG]
E-mail:flithawk@163.com
網址:http://flithawk.longcity.net
破解步驟:

    我一開始並不知道該軟體是用 Java 語言編寫,因為它是一個.exe可執行程式,當我用 Trw 2000 跟蹤時才發現的,再加上該軟體容量很小(只有58KB),所以我才斷定它是用 Java 編寫的解釋執行程式。對待這種解釋執行的程式,最有力的工具就是相應的反編譯器。

    J++Extract 工具可以把用 Java 編寫的 EXE 檔案解包成相應的 class 檔案(*.class)、資原始檔(*.gif, *.bmp, *.resources 和其它)和相應的應用程式圖示。把該軟體解包後生成了三個 class 檔案:About.class、Net007Net.class、reg.class和一個批處理檔案:peedip.bat,還有其它的一些檔案這裡就不提了,與研究軟體的註冊演算法無關。執行 peedip.bat 批處理檔案後出現了軟體的主介面,所以這個批處理檔案應該是整個軟體解包後的主載入程式。從上面解包出來的 class 檔案的檔名中我初步判斷 reg.class 檔案應該就是軟體的“註冊”窗體,其中必含有軟體的註冊演算法;About.class 檔案應該是軟體的“關於”窗體;那麼 Net007Net.class 檔案就是軟體的“主”窗體了。

    Jad 工具可以把 CLASS 檔案反編譯成幾乎和原始碼一模一樣的程式碼。所以,我用 Jad 分別反編譯了上面解包出來的三個 .class 檔案。經過分析後,肯定了我一開始的猜測是正確的,reg.class 檔案中果然存放著軟體的註冊演算法,反編譯後該檔案中的程式碼如下所示:其中,“//”處是我自己加入的註釋。

import com.ms.wfc.app.Application;
import com.ms.wfc.core.*;
import com.ms.wfc.ui.*;
import java.io.*;

public class reg extends Form
{

    public reg()
    {
        components = new Container();
        userName = new Edit();
        regB = new Button();
        userNo = new Edit();
        label1 = new Label();
        label2 = new Label();
        label3 = new Label();
        label4 = new Label();
        label5 = new Label();
        button1 = new Button();
        initForm();
    }

    private void initForm() //該過程應該是初始化窗體
    {
        IResourceManager resources = new ResourceManager(this, "reg");
        setText("\u6CE8\u518C");
        setAutoScaleBaseSize(new Point(6, 12));
        setBorderStyle(1);
        setClientSize(new Point(309, 183));
        setIcon((Icon)resources.getObject("this_icon"));
        setMaximizeBox(false);
        setMinimizeBox(false);
        setStartPosition(1);
        userName.setLocation(new Point(152, 104));
        userName.setSize(new Point(144, 19));
        userName.setTabIndex(0);
        userName.setText("");
        regB.setLocation(new Point(8, 152));
        regB.setSize(new Point(72, 24));
        regB.setTabIndex(1);
        regB.setText("\u73B0\u5728\u6CE8\u518C");
        regB.addOnClick(new EventHandler(this, "regB_click"));
        userNo.setLocation(new Point(152, 128));
        userNo.setSize(new Point(144, 19));
        userNo.setTabIndex(2);
        userNo.setText("");
        label1.setForeColor(Color.HIGHLIGHT);
        label1.setLocation(new Point(8, 104));
        label1.setSize(new Point(144, 16));
        label1.setTabIndex(3);
        label1.setTabStop(false);
        label1.setText("\u8BF7\u8F93\u5165\u60A8\u7533\u8BF7\u7684\u7528\u6237\u540D :");
        label2.setForeColor(Color.HIGHLIGHT);
        label2.setLocation(new Point(8, 128));
        label2.setSize(new Point(144, 16));
        label2.setTabIndex(4);
        label2.setTabStop(false);
        label2.setText("\u8BF7\u8F93\u5165\u60A8\u6536\u5230\u7684\u6CE8\u518C\u7801 :");
        label3.setForeColor(Color.HIGHLIGHT);
        label3.setLocation(new Point(8, 8));
        label3.setSize(new Point(288, 32));
        label3.setTabIndex(5);
        label3.setTabStop(false);
        label3.setText("\u6CE8\u518C\u7248\u7684\u529F\u80FD\u66F4\u52A0\u5168\u9762\uFF0C\u66F4\u52A0\u65B9\u4FBF\uFF0C\u5982\u679C\u4F60\u89C9\u5F97\u503C\u5F97\u7684\u8BDD\u5C31\u6CE8\u518C\u5427\u3002\u5C31\u5F53\u7ED9\u6211\u4E70\u5305\u70DF\u5F97\u4E86^_^"); //在該窗體中顯示的中文字元
        label4.setForeColor(Color.HIGHLIGHT);
        label4.setLocation(new Point(8, 40));
        label4.setSize(new Point(288, 16));
        label4.setTabIndex(6);
        label4.setTabStop(false);
        label4.setText("\u6CE8\u518C\u65B9\u6CD5 :");
        label5.setForeColor(Color.HIGHLIGHT);
        label5.setLocation(new Point(8, 56));
        label5.setSize(new Point(288, 40));
        label5.setTabIndex(7);
        label5.setTabStop(false);
        label5.setText("\u6CE8\u518C\u65B9\u6CD5\u8BF7\u8BE6\u89C1\u6211\u7684\u4E3B\u9875\u4E0A\u7684\u8BF4\u660E\u3002\u7528\u771F\u5B9E\u59D3\u540D\u4F1A\u6709\u60CA\u559C\u7B49\u4F60\u3002");
        button1.setLocation(new Point(224, 152));
        button1.setSize(new Point(72, 24));
        button1.setTabIndex(8);
        button1.setText("\u4EE5\u540E\u518D\u8BF4");
        button1.addOnClick(new EventHandler(this, "button1_click"));
        setNewControls(new Control[] {
            button1, label5, label4, label3, label2, label1, userNo, regB, userName
        });
    }

    private void regB_click(Object source, Event e)
    {
        name();
    }

    public static void main(String args[])
    {
        Application.run(new reg());
    }

    private void button1_click(Object source, Event e)
    {
        dispose();
    }

    public void dispose()
    {
        super.dispose();
        components.dispose();
    }

    public void name()
    {
        // 從這裡開始是軟體的註冊演算法
        char a[] = new char[100]; //定義一個100維的字元陣列a
        a = userName.getText().toUpperCase().toCharArray(); //將你輸入的使用者名稱轉換為大寫賦給陣列a
        char b[] = new char[20]; //定義一個20維的字元陣列b
        for(int i = 0; i < a.length; i++) //第一次迴圈計算,並將計算出的每個結果依次賦給陣列b
b[i] = (char)((a[i] + (i + a.length) * a.length) % 26 + 65);

for(int i = a.length; i < 20; i++) //第二次迴圈計算,並將計算出的每個結果依次賦給陣列b
b[i] = (char)((a[0] * i * i) % 26 + 65);
// 到這裡就可以算出20個字元,分別存放在b[0]至b[19]中

String s = new String("SpeedIP-" + String.copyValueOf(b)); //"SpeedIP"+字元陣列b=字串s
// 到此註冊演算法完畢,註冊碼的格式為:SpeedIP-********************
if(userNo.getText().equals(s)) //判斷你輸入的註冊碼是否與軟體產生的一樣,不一樣則註冊失敗
try
{
FileOutputStream fout = new FileOutputStream("named.dll");
//註冊成功後,在軟體當前目錄下建立一個 named.dll 檔案
DataOutputStream o = new DataOutputStream(fout);
o.writeBoolean(true); //寫入已註冊標誌 01
o.writeUTF(userName.getText()); //將你輸入的使用者名稱寫入到 named.dll 檔案中
o.close();
//關閉檔案
fout.close();
}
catch(Exception _ex) { }
else
MessageBox.show("\u8BF7\u4F7F\u7528\u6B63\u7248\u6CE8\u518C\u7801\uFF0C\u4E0D\u8981\u90A3\u4E48\u5C0F\u6C14\u561B\uFF0C\u8C22\u8C22\uFF01", "\u4E0D\u597D\u54E6"); //“註冊失敗”的提示資訊
dispose(); //釋放窗體
}

Container components;
Edit userName;
Button regB;
Edit userNo;
Label label1;
Label label2;
Label label3;
Label label4;
Label label5;
Button button1;
}

經過 Jad 工具反編譯後的 CLASS 檔案果然可讀性很高,經過分析註冊演算法後,我們知道該軟體的註冊碼格式為:字串“SpeedIP-”再加上20位字串,即SpeedIP-********************,其中 * 代表一個字元。上面註冊演算法的分析,我是以 C 語言的方式來理解的,所以,我就用 C 語言來編寫一個與之相對應的註冊器吧!

#include "stdio.h"
main()
{
int i,x;
char a[100],b[20];
while(1)
{
printf("\n******** China Beginner's Cracking Group ********\n");
printf("This KeyGen is write by flithawk[BCG]!\n");
printf("E-mail:flithawk@163.com\n");
printf("Please Input your name(1-100):");
scanf("%s",a);
if(strlen(a)>0 && strlen(a)<101) break;
  }
  x=strlen(a);
  for(i=0;i<x;i++)
    b[i]=(toupper(a[i])+(i+x)*x)%26+65;
  for(i=x;i<20;i++)
    b[i]=(toupper(a[0])*i*i)%26+65;
  b[i]='\0';
  printf("Your register number is:SpeedIP-%s\n",b);
  printf("****** Welcome to BCG-http://www.china.net ******");
}

該註冊器在 Windows Me 下用 TC2.0 編譯透過。

透過該註冊器計算出來一個有用的註冊資訊:

使用者名稱:flithawk[BCG]
註冊碼:SpeedIP-FYIGHNWXAOCTCASUGCIY

當我用 flithawk[BCG] 為名註冊成功後,開啟 named.dll 後,發現它的格式為:

00000000 | 0100 0D66 6C69 7468 6177 6B5B 4243 475D | . flithawk[BCG]

其中:01 就是已註冊標誌,0D 表示使用者名稱的長度。

知道了 named.dll 檔案的格式後,我們完全可以自己構造一個,免去用註冊器算註冊碼的麻煩,下面是我自己構造的一個 named.dll 檔案,內容為:

00000000 | 0100 0342 4347 | . BCG

經過測試發現完全可以註冊成功。但好像該軟體不支援用中文名進行註冊。

至此,整個軟體的破解宣告結束,謝謝大家看完!

                                          Crack by 飛鷹[BCG]  flithawk@163.com  2002.8.16
                                          歡迎光臨漢化新世紀: http://www.hanzify.org

相關文章