开场白就不说了,直接切入正题吧。
本破解的前提是安装了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进行反编译,得到的源代码如下:
1
package com.intellij.licensecommon.license;
2
3
import com.intellij.licensecommon.util.*;
4
import java.util.*;
5
6
public 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
}
156
a
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 ^ 阅读(6157)
评论(13) 编辑 收藏 所属分类:
破解