Kevin Shan

浅析一款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  阅读(3064)  评论(1编辑  收藏  举报