标签:
在系统开发调试过程中,因为需要不停地修改代码导致需要不停地发布系统,而等待系统发布完成是个很“漫长而痛苦”的过程。有什么办法可以让修改的代码在不需要重新发布系统的情况下马上生效呢?JRebel就是一个可以解决此问题的组件,它是一个支持java应用热部署的JVM插件。有了JRebel,就可以为程序员节省很多宝贵时间。
JRebel就是一个好的东西,但是它不能被免费拥有。10人的团队使用JRebel一年,官网售价为$4150,你没有看错,是$不是¥!
JRebel字节码是经过混淆处理的,google了一下这方面的资料,得到一些启发,尝试破解最新版,破解成功。
破解过程大致都一样,主要的文件是jrebel.jar、jrebel.lic。可以通过官网在线申请14天的使用注册码,来生成jrebel.lic。
请勿留邮箱求最新版,自己动手丰衣足食,这里仅提供思路和方法。
反编译工具:jd-gui
编辑Java字节码的类库:Javassist
IDEA插件 JRebel:JRebel Plugin For IDEA
JRebel试用注册码在线申请:JRebel is FREE for 14 Days
打开申请注册码的地址,随便填写申请信息,申请成功后会生成一个试用的注册码,先保存起来。
IDEA中安装JRebel完成后,打开settings -> IDE settings -> JRebel -> Open activation dialog -> Paste license file from the clipboard,将上面的试用注册码粘贴到这里。确定后会显示注册成功,但是有限制时间。
关闭IDEA,将JRebel生成的license.lic和安装好的jrebel.jar提取出来,先放到C盘根目录。
jrebel.lic所在路径:C:\Users\当前用户名\.jrebel\jrebel.lic
jrebel.jar所在路径:C:\Users\当前用户名\.IntelliJIdea13\config\plugins\jr-ide-idea\lib\jrebel\jrebel.jar
用反编译工具jd-gui打开jrebel.jar,找到类:com.zeroturnaround.licensing.UserLicense,这是用户license所对应的类。此类同时还提供了分别从URL,byte数组以及文件中反序列化(deserialization)UserLicense对象的三个重载方法。
从上面的UserLicense截图可以看到,UserLicense类有5个成员变量,其中第一个是static,最后一个是transient,这两个变量在对象序列化(serialization)时是不会写入文件的,所以用户license主要包括:signature、license和dataMap。
使用类中的方法loadInstance(File paramFile)测试附件中的license文件jrebel.lic,发现反系列化(deserialization)后UserLicense对象中的signature和license有值,而dataMap的值为null。经过分析发现,把license反序列化到dataMap对象中,即可以得到用户License:
UserLicense userLicense = UserLicense.loadInstance(new File("c:/jrebel.lic")); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(userLicense.getLicense())); dataMap = (Map)ois.readObject();
经过上面的处理,既可以清楚的看到保存在dataMap中的license信息:
license信息是存放在dataMap中的,所以可以读取dataMap并修改值,最简单的方法就是直接变成full版本,或者设置成永久试用。
试用版的dataMap的key并不全,部分key暂时不清楚其作用,还有一些隐藏key。
//设置启动时的打印注释 dataMap.put("Comment","*** Use for study only! ***"); //设置为商业full版本 dataMap.put("commercial","true"); //还有其他的一些隐藏字段 //......
把dataMap序列化到文件中就可以生成了一个新的license文件。
可以通过下面的步骤进行序列化UserLicense
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(dataMap); byte[] licenseBuf = bos.toByteArray(); userLicense.setLicense(licenseBuf); //签名:userLicense.setSignature(signature); ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("c:/jrebel-crack.lic"))); oos.writeObject(userLicense);
大家都知道,非对称加密算法主要是两个用途:一是签名(用自己的密钥签名,对方用自己的公钥验签),二是加密(用对方的公钥加密,对方用自己的密钥解密)。要破解签名,我能想到无非有以下的几种方式:
a> 获取对方的密钥(几乎不可能)
b> 了解license文件的结构,然后伪造签名。比如:自己产生一对公钥和私钥,然后用自己的密钥对license进行签名,把签名信息放入到license中,同时用自己的公钥替换原有的公钥
c> 找到验证签名的地方,让验签结果始终为true(伪造的license也可以通过验签),这种方式的难度在于找到验证签名的地方。
本篇博客破解就是采用这种方式,也是目前破解JRebel最简单的方式。
言归正传,简单查看了用户UserLicense的dataMap的结构,接下来就需要查找有哪些类使用了UserLicense类(验证签名肯定需要用到这个类)。最简单的方法是:把jrebel.jar全部反编译处理,Windows大小写敏感,会提示是否更改,点全部重命名即可,然后查找关键字UserLicense
查找的结果只有几个类使用到了UserLicense类,再在这几个类中查找关键字getSignature(),经过筛选,发现最终只剩下1个类(对于不的版本,经过混淆处理后类名不一样)。
对于jrebel 5.2.2是:com.zeroturnaround.javarebel.Av
对于jrebel 5.6.2是:com.zeroturnaround.javarebel.tP
对于jrebel 5.6.3是:com.zeroturnaround.javarebel.tR
接下来就是让验签的那个方法返回true即可。如果细心摸索,会发现所有返回boolean方法都要调用一个最基本的方法,那么我们只需要修改这个方法返回true即可,也就是修改用到了getSignature()得到UserLicense实体类的签名的那个方法。
对于Class文件的修改,这时候就需要用到javassit或者cglib或者ASM。这里使用javassit方法对Class文件进行修改,其他修改Class方法研究中。
下载javassit的jar包,在Netbeans之类的IDE中新建一个Java项目,并导入javassit.jar。新建一个Main.java,以jrebel 5.6.3为例。
import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; public class Main { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); //取得需要反编译的jar文件,设定路径 pool.insertClassPath("c:/jrebel.jar"); //取得需要反编译修改的文件,注意是完整路径 CtClass cc1 = pool.get("com.zeroturnaround.javarebel.tR"); //5.6.2 CtClass cc1 = pool.get("com.zeroturnaround.javarebel.tP"); CtClass[] params = new CtClass[2]; //方法对应的参数 params[0] = pool.get("com.zeroturnaround.bundled.org.bouncycastle.crypto.params.RSAKeyParameters"); params[1] = pool.get("com.zeroturnaround.licensing.UserLicense"); //取得需要修改的方法 CtMethod method = cc1.getDeclaredMethod("a", params); //插入修改项,我们让他直接返回true(注意:根据方法的具体返回值返回,因为这个方法返回值是boolean,所以直接return true;) method.insertBefore("if(1!=0)return true;"); //写入保存 cc1.writeFile(); //jar uvf jrebel.jar com/zeroturnaround/javarebel/tR.class } }
成功运行后,会在你新建的项目目录下生成对应包名的class文件,使用jd-gui打开生成的tR.class后会发现我们的代码已经添加成功。
替换jar 包下面的class 文件,很多人会想到直接用winrar 打开替换,在一般的情况下,是可行的,但是如果说这个jar 的代码经过混淆后,会有大小写不同,文件名是相同的,在windos下文件名是不区分大小写的。如果直接用winrar替换的话,你会发现,替换的并非是你想替换的那个文件。
现在有2中可以行的方案:
a> 在Linux下把jar包解压,替换,打成jar。这样比较麻烦。
b> 可以直接用Java jar 工具来替换。
jar uvf test.jar test.class
这样会直接把test.class 直接添加到jar包的根目录。
jar uvf test.jar com/test/test.class
这样就可以替换相应目录的class文件了。
这里值得注意的是 test.class 必须放在com/test 文件下,要和jar的路径对应起来,不然会找不到这个文件或目录,jar包和com文件夹的上级在同一个目录。
回到我们生成的tR.class的最顶层包文件夹,使用CMD命令jar uvf jrebel.jar com/zeroturnaround/javarebel/tR.class替换掉原jar包中的tR.class
将我们生成的jrebel.jar和jrebel.lic替换掉原来的文件,生成的jrebel.lic也可以拷贝一份到jrebel.jar所在目录。
重新启动IDEA,会发现jrebel已经破解成功!
Intellij IDEA JRebel 5.6.3 手动破解方法
标签:
原文地址:http://www.cnblogs.com/sunshinexb/p/4773276.html