開場白就不說了,直接切入正題吧。
本破解的前提是安裝了IDEA 5.0并獲得了30天的評估序列號,即IDEA可以啟動(dòng)但有30天的時(shí)間限制。
首先根據(jù)bin目錄下idea.bat的內(nèi)容確定入口類:



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即是啟動(dòng)jar包。
用Win RAR打開idea.jar,依次進(jìn)入com、intellij目錄,可發(fā)現(xiàn)intellij下包甚多,應(yīng)該就是IDEA的核心。接下來就是憑運(yùn)氣和“天賦”了,序列號的校驗(yàn)?zāi)K就在這些包中,找出來只是時(shí)間問題。
最終我把焦點(diǎn)定在com.intellij.licensecommon.license.LicenseDataImpl(LicenseData是個(gè)抽象類)。使用DJ Java Decompiler對LicenseDataImpl.class進(jìn)行反編譯,得到的源代碼如下:
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行,原先是調(diào)用了兩個(gè)方法進(jìn)行驗(yàn)證。根據(jù)方法名推測isEvaluationExpired()應(yīng)該是校驗(yàn)評估序列號是否到期,isValid()則是驗(yàn)證授權(quán)的合法性,這樣只要直接使用boolean常量繞開檢查就行了(第61行和68行)。這樣修改后重新編譯生成新的LicenseDataImpl.class,放回jar包覆蓋原先的class文件就行了。
最后是驗(yàn)證。我在我的機(jī)器上將時(shí)間調(diào)到2006年8月,啟動(dòng)IDEA,雖然界面仍顯示“Expiration date: September, 1, 2005”,但是IDE依然正常工作,破解成功
補(bǔ)充一句,在驗(yàn)證時(shí)需要了解操作系統(tǒng)中的其它軟件是否對系統(tǒng)時(shí)間更改有保護(hù)性措施。像在我的機(jī)器上將時(shí)間調(diào)后1年后,卡巴斯基就過期了,將時(shí)間調(diào)回來后卡巴斯基被鎖死,保持過期狀態(tài),最后只能重裝。所以大家在調(diào)系統(tǒng)時(shí)間的時(shí)候可要考慮周到啊。
posted on 2005-08-05 19:11
^ Mustang ^ 閱讀(6161)
評論(13) 編輯 收藏 所屬分類:
破解