浅析一款java软件的破解
浅析一款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
posted on 2007-02-01 13:23 Kevin Shan 阅读(3150) 评论(1) 编辑 收藏 举报