开场白就不说了,直接切入正题吧。
本破解的前提是安装了IDEA 5.0并获得了30天的评估序列号,即IDEA可以启动但有30天的时间限制。
首先根据bin目录下idea.bat的内容确定入口类:
SET CLASS_PATH=%IDEA_HOME%\lib\idea.jar
SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\openapi.jar
SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\jdom.jar
SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\log4j.jar
SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\extensions.jar
SET CLASS_PATH=%CLASS_PATH%;%IDEA_JDK%\lib\tools.jar
第一行中的idea.jar即是启动jar包。
用Win RAR打开idea.jar,依次进入com、intellij目录,可发现intellij下包甚多,应该就是IDEA的核心。接下来就是凭运气和“天赋”了,序列号的校验模块就在这些包中,找出来只是时间问题。
最终我把焦点定在com.intellij.licensecommon.license.LicenseDataImpl(LicenseData是个抽象类)。使用DJ Java Decompiler对LicenseDataImpl.class进行反编译,得到的源代码如下:
1package com.intellij.licensecommon.license;
2
3import com.intellij.licensecommon.util.*;
4import java.util.*;
5
6public class LicenseDataImpl
7 extends AbstractLicenseData{
8 static Date makeDate(int i,int j,int k){
9 Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("Europe/Prague"));
10 calendar.clear();
11 calendar.set(i,j,k);
12 return calendar.getTime();
13 }
14
15 public LicenseDataImpl(String s,String s1){
16 super(s,s1);
17 g = null;
18 }
19
20 public LicenseDataImpl(String s,String s1,long l){
21 super(s,s1,l);
22 g = null;
23 }
24
25 public String toString(){
26 return getUserName() + ":" + getKey();
27 }
28
29 public boolean willNeedUpgrade(){
30 a();
31 if(g.majorVersion >= 5)
32 return false;
33 if(g.generationDate == null)
34 return true;
35 else
36 return a(g.generationDate,FREE_UPGRADE_DATE);
37 }
38
39 private boolean a(Date date,Date date1){
40 long l = date.getTime();
41 long l1 = date1.getTime();
42 return l < l1 - 0xa4cb80L;
43 }
44
45 public boolean needsUpgrade(Date date){
46 if(date == null)
47 return false;
48 if(date.before(DEAD_LINE_DATE))
49 return false;
50 else
51 return willNeedUpgrade();
52 }
53
54 public boolean isEvaluationExpired(Date date){
55 if(date == null)
56 return false;
57 if(!willExpire())
58 return false;
59 else
60 //return date.after(g.expirationDate);
61 return false;
62 }
63
64 public boolean isValid(){
65 a();
66 //return b();
67
68 return true;
69 }
70
71 private void a(){
72 if(b())
73 return;
74 try{
75 g = LicenseDecoder.decodeLicenseKey(getUserName(),getKey());
76 }
77 catch(InvalidLicenseKeyException invalidlicensekeyexception){}
78 }
79
80 private boolean b(){
81 return g != null;
82 }
83
84 public boolean willExpire(){
85 return getExpirationDate() != null;
86 }
87
88 public Date getExpirationDate(){
89 a();
90 return g.expirationDate;
91 }
92
93 public boolean isNonCommercial(){
94 a();
95 return g.licenseType == 1;
96 }
97
98 public boolean isCommercial(){
99 a();
100 return g.licenseType == 0;
101 }
102
103 public boolean isSite(){
104 a();
105 return g.licenseType == 2;
106 }
107
108 public boolean isOpenSource(){
109 a();
110 return g.licenseType == 3;
111 }
112
113 public boolean isYearAcademic(){
114 a();
115 return g.licenseType == 5;
116 }
117
118 public boolean shouldDetectDuplicates(){
119 return!isSite() && !willExpire();
120 }
121
122 public Date getUpgradeDeadline(){
123 return DEAD_LINE_DATE;
124 }
125
126 public boolean isPersonal(){
127 a();
128 return g.licenseType == 4;
129 }
130
131 public Date getGenerationDate(){
132 a();
133 return g.generationDate;
134 }
135
136 public int getMajorVersion(){
137 a();
138 return g.majorVersion;
139 }
140
141 public int getMinorVersion(){
142 a();
143 return g.minorVersion;
144 }
145
146 public static LicenseDataImpl create(String s,String s1){
147 return new LicenseDataImpl(s,s1);
148 }
149
150 public static LicenseDataImpl createFromUser(String s,String s1){
151 LicenseDataImpl licensedataimpl = new LicenseDataImpl(s,s1);
152 licensedataimpl.setFromUser(true);
153 licensedataimpl.setAccepted(false);
154 return licensedataimpl;
155 }
156a
157 public static LicenseDataImpl create(String s,String s1,long l){
158 return new LicenseDataImpl(s,s1,l);
159 }
160
161 public static final int CURRENT_MAJOR_VERSION = 5;
162 public static final int CURRENT_MINOR_VERSION = 0;
163 public static final Date DEAD_LINE_DATE = makeDate(2005,8,1);
164 public static final Date FREE_UPGRADE_DATE = makeDate(2005,4,1);
165 private static final long f = 0xa4cb80L;
166 public static final String IDEA_VERSION = "IntelliJ IDEA 5";
167 private LicenseInfo g;
168}
169
顺便说一句,对于Alloy来说,IDEA基本没有做混淆(可能是公共方法太多的原因),因此反编译后源代码的可读性很好,而且反编译后的源代码基本可以正确编译。
见第60行和66行,原先是调用了两个方法进行验证。根据方法名推测isEvaluationExpired()应该是校验评估序列号是否到期,isValid()则是验证授权的合法性,这样只要直接使用boolean常量绕开检查就行了(第61行和68行)。这样修改后重新编译生成新的LicenseDataImpl.class,放回jar包覆盖原先的class文件就行了。
最后是验证。我在我的机器上将时间调到2006年8月,启动IDEA,虽然界面仍显示“Expiration date: September, 1, 2005”,但是IDE依然正常工作,破解成功
补充一句,在验证时需要了解操作系统中的其它软件是否对系统时间更改有保护性措施。像在我的机器上将时间调后1年后,卡巴斯基就过期了,将时间调回来后卡巴斯基被锁死,保持过期状态,最后只能重装。所以大家在调系统时间的时候可要考虑周到啊。
posted on 2005-08-05 19:11
^ Mustang ^ 阅读(6152)
评论(13) 编辑 收藏 所属分类:
破解