淺析一款java軟體的破解
朋友覺得java平台下一款IDE軟體比較好用,就想讓我幫忙破解一下。我也正好練練手。下面記記流水帳。
本文只是作為學習的目的,不會提供破解補丁。也請勿作為商業用途。
一,準備工作。
要破解一款軟體,有些工具是必不可少的。
1,練習破解檔案:xdevelop-2.0-win32.exe。X-develop是一個同時支援.NET平台和Java平台的多語言整合編程環境(IDE)。
2,XJad2.2:java反編譯工具。 http://www.blogjava.net/96sd2
3,jclasslib: 查看java位元組碼。 http://www.ej-technologies.com/download/jclasslib/files.html
4,WinHex:十六進位編輯器。
5, JVM Specification. http://java.sun.com/docs/books/vmspec/html/Mnemonics.doc.html
二,開始破解。
首先,安裝Xdevelop。反編譯app.jar。
在com\omnicore\xdevelop包中,發現了很多與License相關的檔案,最重要的是ApplicationLicenseManager.java。
然後試圖讀懂ApplicationLicenseManager類,以便清楚整個註冊機制。在讀原始碼的過程中,發現私人變數都已經被混淆器改成了毫無意義的名字,幸好該類不是很長。
邊讀代碼邊將確定的私人變數名稱替換成有意義的名字,很快整個類就看完了。
整個類看完之後發現起機制還是很完善的。
其註冊過程大概如下。
1,輸入註冊碼,或者從使用者的Home目錄下的xdevelop-2.0.ser檔案中讀取註冊碼。
2,用SHA雜湊演算法求出註冊碼20位元組長度的雜湊值。
3,在安裝目錄的根目錄下面有個tools.lib的檔案,這是一個zip壓縮過的檔案,解壓縮開後可以看到a,b,c,d四個檔案。解壓縮出a,b,c,d四個檔案,並用DSA演算法檢驗這些檔案是否被篡改,篡改了當然拋異常了。公開金鑰長度為368位。
4,按b,c,d的順序在b,c,d中搜尋註冊碼的雜湊值,如果發現,就算註冊成功。當然,在不同檔案中存在的註冊碼會認成不同的版本。如EDUCATIONAL版和FULL版。
理解了這個註冊流程,基本放棄寫註冊機的念頭。因為我們必須知道DSA的私密金鑰。在不知道DSA私密金鑰的情況下,要破解出它的私密金鑰基本上是不現實的。所以我只好選擇了寫個破解補丁。採用爆破的方式修改代碼邏輯使程式永遠認為是註冊版。以下是反編譯出的checkSerialNumber方法。
public boolean checkSerialNumber(String s)
{
if (s == null)
return false;
s = s.trim().toUpperCase(Locale.US);
if ($$1000028 == null)
$$1000047();
$$1000031.reset();
byte abyte0[];
try
{
abyte0 = $$1000031.digest(s.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException unsupportedencodingexception)
{
throw new InternalError();
}
if ($$1000046(abyte0, $$1000028))
{
$$1000032 = false;
$$1000026 = abyte0;
return true;
}
if ($$1000046(abyte0, $$1000030)) //
{
$$1000032 = true;
$$1000026 = abyte0;
return true;
}
if ($$1000046(abyte0, $$1000029))
{
$$1000032 = true;
$$1000026 = abyte0;
return true;
} else
{
return false;
}
}
大概翻譯一下如下
public bool checkSerialNumber(string s)
{
if (s == null)
return false;
s = s.trim().toUpperCase(Locale.US);
if (__unZipDField == null)
__1000047();
SHAInstance.reset();
byte abyte0[];
try
{
abyte0 = SHAInstance.digest(s.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException unsupportedencodingexception)
{
throw new InternalError();
}
if (FindHashSerialNumber(abyte0, _unZipDField))
{
_isEducationalLicense = false;
_hashSerialNumber = abyte0;
return true;
}
if (FindHashSerialNumber(abyte0, _unZipBField)) // FindHashSerialNumber會返回一個bool值,指示是否找到,我們可以用noop語句替換這句代碼,使得if語句塊始終都能執行。這樣,不管結果如何,都算註冊成功。
{
_isEducationalLicense = true;
_hashSerialNumber = abyte0;
return true;
}
if (FindHashSerialNumber(abyte0, _unZipCField))
{
_isEducationalLicense = true;
_hashSerialNumber = abyte0;
return true;
} else
{
return false;
}
}
FindHashSerialNumber會返回一個bool值,指示是否找到,我們可以用noop語句替換這句代碼,使得if語句塊始終都能執行。這樣,不管結果如何,都算註冊成功。好,破解思路有了,那我們怎樣修改java的位元組碼來替換它的if語句了?
首先,解壓縮app.jar檔案。java中jar檔案是個zip壓縮檔。解壓縮後用jclasslib開啟解壓出來的ApplicationLicenseManager.class檔案。找到checkSerialNumber方法。彙編代碼如下:
...
74 ifeq 92 (+18) //這裡就是我們需要用noop語句替換的if語句
77 aload_0
78 iconst_0
79 putfield #504 <com/omnicore/xdevelop/ApplicationLicenseManager.$$1000032>
82 aload_0
83 aload_2
84 putfield #102 <com/omnicore/xdevelop/ApplicationLicenseManager.$$1000026>
87 iconst_1
88 ireturn
...
74行的代碼 ifeq 92 (+18)就是我們要有noop替換的語句。
現在到http://java.sun.com/docs/books/vmspec/html/Mnemonics.doc.html上查看這些彙編對應的opcode碼如下:
0 (0x00) nop
153 (0x99) ifeq
42 (0x2a) aload_0
3 (0x03) iconst_0
181 (0xb5) putfield
所以
74 ifeq 92 (+18) // == 0x990012
77 aload_0 // == 0x2a
78 iconst_0 // == 0x03
79 putfield #504 <com/omnicore/xdevelop/ApplicationLicenseManager.$$1000032> // == 0xb501f8
用WinHex開啟ApplicationLicenseManager.class檔案,搜尋十六進位9900122a03b501f8,將990012替換成000000即完成破解。因為nop對應的opcode為00.
接下來就是儲存ApplicationLicenseManager.class檔案,將剛才解壓開的檔案包仍然用winrar壓縮成ZIP壓縮檔格式,命名為app.jar.替換lib目錄中的app.jar即可正常使用。如果不想輸入註冊碼,直接在自己的HOME目錄下建立一個名為xdevelop-2.0.ser的檔案,隨便輸入幾個字元作為註冊碼即可。
--kevin
txhak@163.com