posted on 2009-10-15 20:09
云自无心水自闲 阅读(11198)
评论(16) 所属分类:
java 、
心得体会
javarebel是一个工具,主要是用于热加载,比如说在tomcat之类的应用服务器中,更新了class或者某些资源文件,使用了jrebel之后,就不需要重新启动应用服务器。这对于开发的人来说,是特别方便的。当然java也提供了hotspot的jvm,但是如果你修改的类中有方法名称变动的话,hotspot就无能为力了,必须要重要启动应用服务器。
这里有一点先声明一下,本文只是破解仅限于学习和研究使用,勿用于其他用途。
第一步当然是下载jrebel
下载地址:http://www.zeroturnaround.com/jrebel/download/
下载下来的是一个zip压缩包,打开之后会发现一个jrebel.jar,这就是其最重要的运行包了。其他都是一些文档和插件。
第二步,是进行反编译。
我推荐一个工具:http://java.decompiler.free.fr/,分成eclipse插件和单独的运行程序两种,我下载的是单独的运行程序,只有一个绿色的exe文件,点击后直接运行。
看了一下,最显眼的自然是userlicense类了。
1package com.zeroturnaround.licensing;
2
3import java.io.serializable;
4import java.util.map;
5
6public class userlicense
7 implements serializable
8{
9 static final long serialversionuid = 1l;
10 private byte[] signature;
11 private byte[] license;
12 private map datamap;
13
14 public byte[] getsignature()
15 {
16 return this.signature;
17 }
18
19 public void setsignature(byte[] paramarrayofbyte) {
20 this.signature = paramarrayofbyte;
21 }
22
23 public byte[] getlicense() {
24 return this.license;
25 }
26
27 public void setlicense(byte[] paramarrayofbyte) {
28 this.license = paramarrayofbyte;
29 }
30}
31
然后就找到了调用getlicense方法的js类(名字很奇怪,因为是混淆过的原因,js类反编译后的源码附在最后面了)
这个类中很明确地显示了license的获取方法。
首先是:jreble.lic文件,用winrar打开jrebel.jar就看到这个文件了。
从源码来看,userlicense是用objectinputstream通过readobject得到了。
然后,属性license里面其实是一个map,用objectinputstream从bytearrayinputsteam中通过readobject得到。于是写了下面这样的测试代码
1package temp.jrebel;
2
3import java.io.bufferedinputstream;
4import java.io.bufferedoutputstream;
5import java.io.bytearrayinputstream;
6import java.io.bytearrayoutputstream;
7import java.io.file;
8import java.io.fileinputstream;
9import java.io.fileoutputstream;
10import java.io.ioexception;
11import java.io.objectinputstream;
12import java.io.objectoutputstream;
13import java.util.calendar;
14import java.util.gregoriancalendar;
15import java.util.iterator;
16import java.util.map;
17import junit.framework.assert;
18import org.junit.test;
19import com.zeroturnaround.licensing.userlicense;
20
21public class parselicense {
22 @test
23 public void parselicensefile() {
24 object localobject1 = null;
25 try {
26 system.out.println("start to get lic file.");
27 file localfile2 = new file("d:\\temp\\jrebel.lic");
28 assert.assertnotnull(localfile2);
29
30 system.out.println("start to get objectinputstream.");
31 localobject1 = new objectinputstream(new bufferedinputstream(
32 new fileinputstream(localfile2)));
33 assert.assertnotnull(localobject1);
34
35 system.out.println("start to get userlicense.");
36 userlicense localuserlicense1 = (userlicense)((objectinputstream)localobject1).readobject();
37 assert.assertnotnull(localuserlicense1);
38
39 system.out.println("start to get objectinputstream2.");
40 objectinputstream localobjectinputstream = new objectinputstream(new bytearrayinputstream(localuserlicense1.getlicense()));
41 assert.assertnotnull(localobjectinputstream);
42
43 system.out.println("start to get localmap.");
44 map localmap = (map)localobjectinputstream.readobject();
45 assert.assertnotnull(localmap);
46
47 system.out.println("start tot output value.");
48 for ( iterator iter = localmap.keyset().iterator(); iter.hasnext(); ) {
49 string key = (string)iter.next();
50 system.out.println("key: " key ", value: " localmap.get(key));
51 }
52
53 } catch (exception e) {
54 e.printstacktrace();
55 assert.fail("faile to parse license. ");
56 } finally {
57 if (localobject1 != null) {
58 try {
59 ((objectinputstream) localobject1).close();
60 } catch (ioexception localioexception12) {
61 }
62 }
63 }
64
65 }
66}
67
68
concole中果然如我所愿地,把map里的值都打印出来了。到了这一步,剩下的就简单了,把map里面的validateuntil属性的日期换一下,重新生成一个license文件就行了。
把上面的代码修改一下,很容易地就生成了新的license文件。
原来license里面的试用期只有一个月,比如,我是2009-10-15下载的,那么这个jrebel.lic文件里的validateuntil日期就是11月14日,现在我把他改成了明年元旦。
1package temp.jrebel;
2
3import java.io.bufferedinputstream;
4import java.io.bufferedoutputstream;
5import java.io.bytearrayinputstream;
6import java.io.bytearrayoutputstream;
7import java.io.file;
8import java.io.fileinputstream;
9import java.io.fileoutputstream;
10import java.io.ioexception;
11import java.io.objectinputstream;
12import java.io.objectoutputstream;
13import java.util.calendar;
14import java.util.gregoriancalendar;
15import java.util.iterator;
16import java.util.map;
17import junit.framework.assert;
18import org.junit.test;
19import com.zeroturnaround.licensing.userlicense;
20
21public class parselicense {
22 @test
23 public void parselicensefile() {
24 object localobject1 = null;
25 try {
26 system.out.println("start to get lic file.");
27 file localfile2 = new file("d:\\temp\\jrebel.lic");
28 assert.assertnotnull(localfile2);
29
30 system.out.println("start to get objectinputstream.");
31 localobject1 = new objectinputstream(new bufferedinputstream(
32 new fileinputstream(localfile2)));
33 assert.assertnotnull(localobject1);
34
35 system.out.println("start to get userlicense.");
36 userlicense localuserlicense1 = (userlicense)((objectinputstream)localobject1).readobject();
37 assert.assertnotnull(localuserlicense1);
38
39 system.out.println("start to get objectinputstream2.");
40 objectinputstream localobjectinputstream = new objectinputstream(new bytearrayinputstream(localuserlicense1.getlicense()));
41 assert.assertnotnull(localobjectinputstream);
42
43 system.out.println("start to get localmap.");
44 map localmap = (map)localobjectinputstream.readobject();
45 assert.assertnotnull(localmap);
46
47 system.out.println("start tot output value.");
48 for ( iterator iter = localmap.keyset().iterator(); iter.hasnext(); ) {
49 string key = (string)iter.next();
50 system.out.println("key: " key ", value: " localmap.get(key));
51 }
52
53
54 system.out.println("start to change date.");
55 calendar cal = new gregoriancalendar(2010, 01, 01);
56 localmap.put("validuntil", cal.gettime());
57
58 system.out.println("start to set a new date to license.");
59 bytearrayoutputstream out1 = new bytearrayoutputstream();
60 objectoutputstream out2 = new objectoutputstream(out1);
61 out2.writeobject(localmap);
62 out1.tobytearray();
63 localuserlicense1.setlicense(out1.tobytearray());
64 out1.close();
65 out2.close();
66
67
68 system.out.println("start to get objectinputstream2.");
69 localobjectinputstream = new objectinputstream(new bytearrayinputstream(localuserlicense1.getlicense()));
70 assert.assertnotnull(localobjectinputstream);
71
72 system.out.println("start to get localmap.");
73 localmap = (map)localobjectinputstream.readobject();
74 assert.assertnotnull(localmap);
75
76 for ( iterator iter = localmap.keyset().iterator(); iter.hasnext(); ) {
77 string key = (string)iter.next();
78 system.out.println("key: " key ", value: " localmap.get(key));
79 }
80
81
82 string newlicensefile = "d:\\temp\\new.lic";
83 objectoutputstream out3 = new objectoutputstream(new bufferedoutputstream(new fileoutputstream(newlicensefile)));
84 out3.writeobject(localuserlicense1);
85 out3.close();
86
87 } catch (exception e) {
88 e.printstacktrace();
89 assert.fail("faile to parse license. ");
90 } finally {
91 if (localobject1 != null) {
92 try {
93 ((objectinputstream) localobject1).close();
94 } catch (ioexception localioexception12) {
95 }
96 }
97 }
98
99 }
100}
101
102
103
这是我用反编译工具反编译出来的部分源码:
/* */ package com.zeroturnaround.javarebel;
/* */ public class js
/* */ implements dn
/* 405 */ if (localuserlicense != null) {
/* */ try {
/* 407 */ if (eo.a(localuserlicense)) {
/* 408 */ jdfield_a_of_type_int = 1;
/* */ }
/* 410 */ objectinputstream localobjectinputstream = new objectinputstream(new bytearrayinputstream(localuserlicense.getlicense()));
/* 411 */ localmap = (map)localobjectinputstream.readobject();
/* 412 */ localobjectinputstream.close();
/* */
/* 414 */ if ((!("javarebel".equals(localmap.get("product")))) && (!("jrebel".equals(localmap.get("product"))))) {
/* 415 */ jdfield_a_of_type_int = 0;
/* */ }
/* 417 */ ih.log("license information: " localmap);
/* */
/* 420 */ boolean bool1 = boolean.valueof((string)localmap.get("commercial")).booleanvalue();
/* 421 */ if ((jdfield_a_of_type_int == 1) && (bool1)) {
/* 422 */ jdfield_a_of_type_int = 3;
/* */ }
/* */
/* 425 */ localobject = (string)localmap.get("limited");
/* */
/* 427 */ if ((localobject != null) && (jdfield_a_of_type_int == 1)) {
/* 428 */ if (((string)localobject).equals("true")) {
/* 429 */ jdfield_a_of_type_int = 2;
/* 430 */ jn.a("license: evaluation");
/* */ }
/* 432 */ else if (((string)localobject).equals("scala")) {
/* 433 */ jdfield_a_of_type_int = 2;
/* 434 */ jdfield_b_of_type_int |= 1;
/* 435 */ jn.a("license: scala");
/* */ }
/* 437 */ else if (((string)localobject).equals("liverebel")) {
/* 438 */ jdfield_a_of_type_int = 2;
/* 439 */ jdfield_b_of_type_int |= 2;
/* 440 */ jn.a("license: liverebel");
/* */ }
/* */ }
/* 443 */ if (jdfield_a_of_type_int == 1) {
/* 444 */ localdate2 = (date)localmap.get("validuntil");
/* 445 */ localdate3 = (date)localmap.get("validfrom");
/* */ }
/* 447 */ else if (jdfield_a_of_type_int == 2) {
/* 448 */ localdate2 = (date)localmap.get("limiteduntil");
/* 449 */ localdate3 = (date)localmap.get("limitedfrom");
/* */ }
/* */
/* 452 */ if (c.contains(localmap.get("uid")))
/* 453 */ jdfield_a_of_type_int = 0;
/* */ }
/* */ catch (exception localexception1)
/* */ {
/* 457 */ ih.log("exception checking the jrebel license");
/* 458 */ localexception1.printstacktrace();
/* 459 */ ih.error(localexception1);
/* */ }
/* */ }
/* */
/* 463 */ ih.echo();
/* 464 */ ih.echo("#############################################################");
/* 465 */ ih.echo();
/* 466 */ ih.echo(" jrebel " str1 " (" ((jdfield_a_of_type_javalangclass == null) ? (js.jdfield_a_of_type_javalangclass = a("com.zeroturnaround.javarebel.java4.install")) : jdfield_a_of_type_javalangclass).getpackage().getimplementationtitle() ")");
/* 467 */ ih.echo(" (c) 凯发天生赢家一触即发官网 copyright zeroturnaround, ltd, 2007-2009. all rights reserved.");
/* 468 */ ih.echo();
/* */
/* 470 */ if (ga.c()) {
/* */ try {
/* 472 */ numberformat localnumberformat = numberformat.getnumberinstance();
/* 473 */ localnumberformat.setminimumfractiondigits(0);
/* 474 */ localnumberformat.setmaximumfractiondigits(1);
/* */
/* 476 */ string str3 = localnumberformat.format(cu.a() * 96.0d / 3600.0d);
/* 477 */ localobject = localnumberformat.format(cu.a() * 195.0d / 3600.0d);
/* */
/* 479 */ string str4 = localnumberformat.format(cu.b() * 96.0d / 3600.0d);
/* 480 */ string str5 = localnumberformat.format(cu.b() * 195.0d / 3600.0d);
/* */
/* 482 */ string str6 = "" (cu.c() 1);
/* 483 */ string str7 = "" (cu.c() 1);
/* */
/* 485 */ ih.echo(" a rough estimate: over the last " str6 " days jrebel ");
/* 486 */ ih.echo(" prevented the need for at least " cu.a() " redeploys/restarts.");
/* 487 */ ih.echo(" using industry standard build and redeploy times, ");
/* 488 */ ih.echo(" jrebel saved you between " str3 " and " ((string)localobject) " hours.");
/* */
/* 490 */ if (cu.c() > 60) {
/* 491 */ ih.echo(" over the last " str7 " days jrebel saved you");
/* 492 */ ih.echo(" between " str4 " and " str5 " hours.");
/* */ }
/* */
/* 495 */ ih.echo();
/* */ }
/* */ catch (exception localexception2) {
/* 498 */ ih.error(localexception2);
/* */ }
/* */ }
/* */
/* 502 */ if (jdfield_a_of_type_int == 3) {
/* 503 */ jdfield_a_of_type_boolean = true;
/* */
/* 505 */ str2 = (string)localmap.get("seats");
/* */
/* 507 */ bool2 = ("1".equals(str2)) && (((localmap.get("organization") == null) || ("".equals(localmap.get("organization"))) || (((string)localmap.get("organization")).equalsignorecase("personal"))));
/* */
/* 511 */ localobject = new stringbuffer(" this product is licensed to ");
/* 512 */ if ((bool2) && (localmap.get("name") != null) && (!("".equals(localmap.get("name"))))) {
/* 513 */ ((stringbuffer)localobject).append(localmap.get("name"));
/* */
/* 515 */ if ((localmap.get("organization") != null) && (!("".equals(localmap.get("organization"))))) {
/* 516 */ ((stringbuffer)localobject).append(" (");
/* 517 */ ((stringbuffer)localobject).append(localmap.get("organization"));
/* 518 */ ((stringbuffer)localobject).append(") ");
/* */ }
/* 520 */ jn.a("license: personal");
/* */ }
/* */ else {
/* 523 */ ((stringbuffer)localobject).append(localmap.get("organization"));
/* 524 */ jn.a("license: corporate");
/* */ }
/* */
/* 527 */ ih.echo(((stringbuffer)localobject).tostring());
/* */
/* 529 */ if ("unlimited".equals(str2)) {
/* 530 */ ih.echo(" for unlimited number of developer seats on site.");
/* */ }
/* 532 */ else if ((str2 != null) && (!(bool2))) {
/* 533 */ ih.echo(" for up to " str2 " developer seats on site. ");
/* */ }
/* 535 */ else if (bool2) {
/* 536 */ ih.echo(" for personal use only. ");
/* */ }
/* */
/* 539 */ if ((localmap.get("comment") != null) && (!("".equals(localmap.get("comment"))))) {
/* 540 */ ih.echo(" " localmap.get("comment"));
/* */ }
/* */
/* 543 */ if (localdate2 != null) {
/* 544 */ a(localdate1, localdate2);
/* */ }
/* */
/* 547 */ ih.echo();
/* 548 */ ih.echo("#############################################################");
/* 549 */ ih.echo();
/* */ }
/* 551 */ else if (jdfield_a_of_type_int == 2) {
/* 552 */ if (((jdfield_b_of_type_int & 0x2) == 0) && ((((localdate2 != null) && (localdate1.after(localdate2))) || ((localdate3 != null) && (localdate1.before(localdate3))))))
/* */ {
/* 555 */ ih.echo(" your jrebel limited license has expired!");
/* */ }
/* */ else {
/* 558 */ jdfield_a_of_type_boolean = true;
/* */ }
/* */
/* 561 */ if ((jdfield_b_of_type_int & 0x2) == 0) {
/* 562 */ str2 = (string)localmap.get("seats");
/* */
/* 564 */ bool2 = "1".equals(str2);
/* */
/* 566 */ localobject = new stringbuffer(" this product is licensed to ");
/* 567 */ if ((bool2) && (localmap.get("name") != null) && (!("".equals(localmap.get("name"))))) {
/* 568 */ ((stringbuffer)localobject).append(localmap.get("name"));
/* */
/* 570 */ if ((localmap.get("organization") != null) && (!("".equals(localmap.get("organization"))))) {
/* 571 */ ((stringbuffer)localobject).append(" (");
/* 572 */ ((stringbuffer)localobject).append(localmap.get("organization"));
/* 573 */ ((stringbuffer)localobject).append(") ");
/* */ }
/* */ }
/* */ else {
/* 577 */ ((stringbuffer)localobject).append(localmap.get("organization"));
/* */ }
/* */
/* 580 */ ih.echo(((stringbuffer)localobject).tostring());
/* */
/* 582 */ if (localdate2 != null) {
/* 583 */ ih.echo(" until " simpledateformat.getdateinstance(1, locale.english).format(localdate2));
/* */ }
/* */
/* 586 */ if ("unlimited".equals(str2)) {
/* 587 */ ih.echo(" for unlimited number of developer seats on site.");
/* */ }
/* 589 */ else if ((str2 != null) && (!("1".equals(str2)))) {
/* 590 */ ih.echo(" for up to " str2 " developer seats on site. ");
/* */ }
/* */
/* 593 */ if ((localmap.get("comment") != null) && (!("".equals(localmap.get("comment"))))) {
/* 594 */ ih.echo(" with the following restrictions: ");
/* 595 */ ih.echo(" " ((string)localmap.get("comment")));
/* */ }
/* */
/* 598 */ if (localdate2 != null) {
/* 599 */ a(localdate1, localdate2);
/* */ }
/* */ }
/* */
/* 603 */ if (localmap.get("organization") != null) {
/* 604 */ str2 = (string)localmap.get("organization");
/* 605 */ if (str2.indexof("[open-source]") != -1) {
/* 606 */ jn.a("giveaway: oss");
/* */ }
/* */
/* */ }
/* */
/* 613 */ ih.echo();
/* 614 */ ih.echo("#############################################################");
/* 615 */ ih.echo();
/* */ }
/* 617 */ else if (jdfield_a_of_type_int == 1) {
/* 618 */ if ((localdate2 == null) || (localdate1.after(localdate2))) {
/* 619 */ ih.echo(" your jrebel evaluation license has expired!");
/* */ }
/* 621 */ else if ((localdate3 == null) || (localdate1.before(localdate3))) {
/* 622 */ ih.echo(" your jrebel evaluation could not have started yet!");
/* */ }
/* */ else {
/* 625 */ jdfield_a_of_type_boolean = true;
/* */
/* 627 */ long l1 = localdate2.gettime() - localdate1.gettime();
/* 628 */ long l2 = l1 / 86400000l;
/* */
/* 630 */ ih.echo(" you are running jrebel evaluation license.");
/* 631 */ ih.echo(" you have " (l2 1l) " days until the license expires. ");
/* 632 */ ih.echo();
/* 633 */ ih.echo(" you will see this notification until you obtain a ");
/* 634 */ ih.echo(" full license for your installation. ");
/* */ }
/* 636 */ ih.echo(" ");
/* 637 */ ih.echo(" visit www.jrebel.com for instructions on obtaining ");
/* 638 */ ih.echo(" a full license. if you wish to continue your evaluation ");
/* 639 */ ih.echo(" please e-mail to support@zeroturnaround.com. ");
/* 640 */ ih.echo(" ");
/* 641 */ ih.echo(" if you think you should not see this message contact ");
/* 642 */ ih.echo(" support@zeroturnaround.com or check that you have your ");
/* 643 */ ih.echo(" license file in the same directory as the jar file. ");
/* 644 */ ih.echo(" ");
/* 645 */ ih.echo("#############################################################");
/* 646 */ ih.echo();
/* */
/* 649 */ eo.a(localuserlicense);
/* */ }
/* */ else {
/* 652 */ ih.echo(" you do not have a valid jrebel license! ");
/* 653 */ ih.echo(" ");
/* 654 */ ih.echo(" visit www.jrebel.com for instructions on obtaining ");
/* 655 */ ih.echo(" a full or evaluation license. ");
/* 656 */ ih.echo(" ");
/* 657 */ ih.echo(" if you think you should not see this message contact ");
/* 658 */ ih.echo(" support@zeroturnaround.com or check that you have your ");
/* 659 */ ih.echo(" license file in the same directory as the jar file. ");
/* 660 */ ih.echo(" ");
/* 661 */ ih.echo("#############################################################");
/* 662 */ ih.echo();
/* */ }
/* */
/* 665 */ if (!(jdfield_a_of_type_boolean)) {
/* 666 */ system.exit(1);
/* */ }