一步一步破解
JIRA3.6
上周在springside上看到jira这个团队软件,下载下来试用了一番,觉得挺好用得,正好前一段看到了jad这个反编译软件,就想试手一下自己破解这个jira。下面详细叙述了破解的过程,因为不太熟悉这个破解,只是以前大概知道,几乎没有用过所以想试手一下。整个过程花费了昨天晚上一晚上,从6点多到11点,总算破解好了。
先说一下我用得工具吧
eclipse3.2,这个就不用说了吧,主要是试一下3.2的新特性,用3.1也可以的
winrar 解压*.jar文件
然后就是我关键的工具了,
Jad 1.5.8e for Windows 9x/NT/2000 on Intel platform
其实我最开始使用的不是这个版本,而是1.5.7然后再破解的过程中,反编译java文件总是有问题,说
JavaClassFileParseException: Class file version mismatch
Parsing atlassian-extras-0.7.19/com\atlassian\license\applications\perforceplugi
n/PeforcePluginLicenseTypeStore.class...The class file version is 47.0 (only 45.
3 and 46.0 are supported)
然后就去google了一下,发现原来是jad的版本问题,所以到http://www.kpdus.com/jad.html#download 下载了最新的JAD,就是1.5.8e这个版本。
下面说一下我破解的过程吧,首先,我们可以使用评估版本的license搭建并且跑起来jira,那么可以看到在每一个具体页面底部,都可以看到一个license信息。既然这个页面可以看到license信息,那么,这个文件肯定最终是去读取了license文件信息的,那么具体逻辑是在哪里呢,我就看了一下web.xml,可以知道,jira是使用sitemath来做页面布局的,具体查看
sitemath.xml以及相应的
decorator.xml,可以知道每个页面底部几乎都是使用
footer.jsp来显示的
打开footer.jsp,可以看到最初几句
1 <%@ page import="com.atlassian.jira.config.properties.APKeys,
2 com.atlassian.jira.util.BuildUtils,
3 com.atlassian.jira.ManagerFactory,
4 com.atlassian.license.*,
5 com.atlassian.license.applications.jira.JiraLicenseTypeStore,
6 com.atlassian.jira.web.action.util.JiraLicenseUtils"%>
7
看到其中com.atlassian.license.
*,那么我们可以猜测,具体的license就应该与这个相关了
在
footer.jsp
中可以发现下面这句
License curLicense
=
null
;
if
(JiraLicenseUtils.isLicenseSetup())
curLicense
=
LicenseManager.getInstance().getLicense(JiraLicenseUtils.JIRA_LICENSE_KEY);
使用如下命令行,反编译atlassian-extras-0.7.19.jar包(注:这个包JIRA 3.6破解
http://www.blogjava.net/martinx/archive/2006/05/07/44914.html
这篇文章也提到了,但是没有给出如何确定这个包的,其实可以通过eclipse的工程,把整个工程加载,包括类库,然后就可以看到类层次结构了,然后就可以知道具体在那个包了)
jad -o -r -sjava -dsrc atlassian-extras-0.7.19/**/*.class
这样可以把整个atlassian-extras-0.7.19.jar包下的文件都反编译,然后我把反编译的结果java文件导入到了eclipse,新建了一个工程,这样方便后续的处理和查找以及编译等等。
接着,从反编译出来的
JiraLicenseUtils.java
可以发现如下定义
public
static
final
String JIRA_LICENSE_KEY
=
"
JIRA
"
;
分析这一句
curLicense
=
LicenseManager.getInstance().getLicense(JiraLicenseUtils.JIRA_LICENSE_KEY);
主要是
LicenseManager
的
getLicense
方法
License license
=
LicenseDecoder.getLicense(pair, applicationName);
licenseList.put(applicationName, license);
可以看出,是通过
LicenseDecoder
类得到
License
方法的,后面一句是作缓存。
在继续跟踪
LicenseDecoder
可以发现是通过
License loadLicense(LicensePair pair, PublicKey publicKey, String applicationName)
方法来初始化
License
的
继续看下去,可以发现只有这一句具体实例化了一个
Lisence
return
new
DefaultLicense(dateCreated, datePurchased, organisation, licenseType, users, partnerName, licenseId);
到现在,就已经定位到具体的License类了,但是具体是不是这个类呢,这时候就是使用eclipse强大的功能的时候了
使用classic search,如下,可以发现声明中有License的,大约有7、8个类,具体看一下,可以发现仅有刚才的DefaultLIcense是继承了License接口的,那么可以基本确定就是这个类了。
但是,又不是很放心,所以又在License接口上如下查看了一下
这个两个综合,可以印证一个思想,就是所有的License只有一个实现,就是DefaultLicense,那么,问题就好办了,只要修改DefaultLicense类文件就可以了
看看反编译的文件,知道License接口如下,在具体看一下License接口:
1public interface License
2 2{
3 3
4 4 public abstract Date getDateCreated();
5 5
6 6 public abstract Date getDatePurchased();
7 7
8 8 public abstract String getOrganisation();
9 9
1010 public abstract LicenseType getLicenseType();
1111
1212 public abstract boolean isExpired();
1313
1414 public abstract Date getExpiryDate();
1515
1616 public abstract String toString();
1717
1818 public abstract boolean isLicenseLevel(Collection collection);
1919
2020 public abstract int getUsers();
2121
2222 public abstract String getPartnerName();
2323
2424 public abstract String getLicenseId();
2525}
26
可以猜想,修改这个接口的实现,使其返回我们需要的值,那么就可以绕过License验证了。另外,我们注意到
public
abstract
LicenseType getLicenseType();
这个方法,返回值是LicenseType,大概就是我们不同的License类型的一个区别吧,突然想到,其实把这些LicenseType都改成JIRA_ENTERPRISE_FULL_LICENSE几乎类似的,那么也可以绕过这个,不过这个没有具体试过,有兴趣的可以一试。
public
class
JiraLicenseTypeStore
extends
LicenseTypeStore
2
{
3
4
public
JiraLicenseTypeStore()
5
{
6
applicationLicenseTypes.add(JIRA_STANDARD_ACADEMIC);
7
applicationLicenseTypes.add(JIRA_STANDARD_EVALUATION);
8
applicationLicenseTypes.add(JIRA_STANDARD_NON_PROFIT);
9
applicationLicenseTypes.add(JIRA_STANDARD_FULL_LICENSE);
10
applicationLicenseTypes.add(JIRA_PROFESSIONAL_ACADEMIC);
11
applicationLicenseTypes.add(JIRA_PROFESSIONAL_EVALUATION);
12
applicationLicenseTypes.add(JIRA_PROFESSIONAL_NON_PROFIT);
13
applicationLicenseTypes.add(JIRA_PROFESSIONAL_FULL_LICENSE);
14
applicationLicenseTypes.add(JIRA_ENTERPRISE_ACADEMIC);
15
applicationLicenseTypes.add(JIRA_ENTERPRISE_EVALUATION);
16
applicationLicenseTypes.add(JIRA_ENTERPRISE_NON_PROFIT);
17
applicationLicenseTypes.add(JIRA_ENTERPRISE_FULL_LICENSE);
18
}
19
20
public
Collection getAllLicenses()
21
{
22
return
applicationLicenseTypes;
23
}
24
25
public
String getPublicKeyFileName()
26
{
27
return
publicKeyFileName;
28
}
29
30
public
String getPrivateKeyFileName()
31
{
32
return
privateKeyFileName;
33
}
34
35
public
static
LicenseType JIRA_STANDARD_ACADEMIC
=
new
DefaultLicenseType(
197
,
"
JIRA Standard: Academic
"
,
false
,
false
);
36
public
static
LicenseType JIRA_STANDARD_EVALUATION
=
new
DefaultLicenseType(
109
,
"
JIRA Standard: Evaluation
"
,
true
,
false
);
37
public
static
LicenseType JIRA_STANDARD_NON_PROFIT
=
new
DefaultLicenseType(
157
,
"
JIRA Standard: Non-Profit / Open Source
"
,
false
,
false
);
38
public
static
LicenseType JIRA_STANDARD_FULL_LICENSE
=
new
DefaultLicenseType(
179
,
"
JIRA Standard: Commercial Server
"
,
false
,
false
);
39
public
static
LicenseType JIRA_PROFESSIONAL_ACADEMIC
=
new
DefaultLicenseType(
91
,
"
JIRA Professional: Academic
"
,
false
,
false
);
40
public
static
LicenseType JIRA_PROFESSIONAL_EVALUATION
=
new
DefaultLicenseType(
47
,
"
JIRA Professional: Evaluation
"
,
true
,
false
);
41
public
static
LicenseType JIRA_PROFESSIONAL_NON_PROFIT
=
new
DefaultLicenseType(
76
,
"
JIRA Professional: Non-Profit / Open Source
"
,
false
,
false
);
42
public
static
LicenseType JIRA_PROFESSIONAL_FULL_LICENSE
=
new
DefaultLicenseType(
87
,
"
JIRA Professional: Commercial Server
"
,
false
,
false
);
43
public
static
LicenseType JIRA_ENTERPRISE_ACADEMIC
=
new
DefaultLicenseType(
269
,
"
JIRA Enterprise: Academic
"
,
false
,
false
);
44
public
static
LicenseType JIRA_ENTERPRISE_EVALUATION
=
new
DefaultLicenseType(
201
,
"
JIRA Enterprise: Evaluation
"
,
true
,
false
);
45
public
static
LicenseType JIRA_ENTERPRISE_NON_PROFIT
=
new
DefaultLicenseType(
213
,
"
JIRA Enterprise: Non-Profit / Open Source
"
,
false
,
false
);
46
public
static
LicenseType JIRA_ENTERPRISE_FULL_LICENSE
=
new
DefaultLicenseType(
267
,
"
JIRA Enterprise: Commercial Server
"
,
false
,
false
);
47
public
static
String publicKeyFileName
=
"
com/atlassian/jira/issue/Bug.class
"
;
48
public
static
String privateKeyFileName
=
"
jira/jira.byte
"
;
49
50
}
那么,分析了上述的类,那么,就来修改一下DefaultLicense了,首先把初始化修改一下,如下:
1
public
DefaultLicense(Date dateCreated, Date datePurchased, String organisation, LicenseType licenseType,
int
users, String partnerName, String licenseId)
2
2
{
3
3
Calendar calendar
=
Calendar.getInstance();
4
4
calendar.set(
1982
,
4
,
21
);
5
5
this
.dateCreated
=
calendar.getTime();
6
6
this
.datePurchased
=
calendar.getTime();
7
7
this
.organisation
=
"
escout@sjtu
"
;
8
8
this
.licenseType
=
JiraLicenseTypeStore.JIRA_ENTERPRISE_ACADEMIC;
9
9
this
.users
=
10000
;
10
10
this
.partnerName
=
partnerName;
11
11
this
.licenseId
=
licenseId;
12
12
}
接着,把修改的DefaultLicense文件,覆盖到atlassian-extras-0.7.19.jar解压开的同名文件处覆盖,同时使用下面的命令重新打包
D:\develope\jadnt157\atlassian-extras-0.7.19>jar cvf atlassianextras-0.7.19.jar
./
然后把修改后的jar放到web-inf/lib目录下覆盖同名文件。重启tomcat,这时候,我本来想应该就可以了,谁知打开浏览器,白屏!没有任何页面显示,ft。
想了想,打开tomcat的log文件,发现如下几行。
2006-05-12 21:26:08,421 ERROR [web.action.util.JiraLicenseUtils] The current license is too old (Mon Jun 14 21:26:05 CST 1982) to run this version (3.6 - Tue Apr 11 00:00:00 CST 2006) of JIRA.
埃,本来想用一个比较有纪念意义的日期呢,看来不能随心所欲啊。
后来又改了一下,最终如下:
1
public
class
DefaultLicense
2
implements
License
3
{
4
5
public
DefaultLicense(Date dateCreated, Date datePurchased, String organisation, LicenseType licenseType,
int
users, String partnerName)
6
{
7
Calendar calendar
=
Calendar.getInstance();
8
calendar.add(Calendar.DAY_OF_MONTH,
-
5
);
9
this
.dateCreated
=
calendar.getTime();
10
this
.datePurchased
=
calendar.getTime();
11
this
.organisation
=
"
escout@sjtu
"
;
12
this
.licenseType
=
JiraLicenseTypeStore.JIRA_ENTERPRISE_ACADEMIC;
13
this
.users
=
10000
;
14
this
.partnerName
=
partnerName;
15
this
.licenseId
=
""
;
16
}
17
18
public
DefaultLicense(Date dateCreated, Date datePurchased, String organisation, LicenseType licenseType,
int
users, String partnerName, String licenseId)
19
{
20
Calendar calendar
=
Calendar.getInstance();
21
calendar.add(Calendar.DAY_OF_MONTH,
-
1
);
22
this
.dateCreated
=
calendar.getTime();
23
this
.datePurchased
=
calendar.getTime();
24
this
.organisation
=
"
escout@sjtu
"
;
25
this
.licenseType
=
JiraLicenseTypeStore.JIRA_ENTERPRISE_ACADEMIC;
26
this
.users
=
10000
;
27
this
.partnerName
=
partnerName;
28
this
.licenseId
=
licenseId;
29
}
30
31
public
Date getDateCreated()
32
{
33
return
dateCreated;
34
}
35
36
public
Date getDatePurchased()
37
{
38
return
datePurchased;
39
}
40
41
public
String getOrganisation()
42
{
43
return
organisation;
44
}
45
46
public
LicenseType getLicenseType()
47
{
48
return
licenseType;
49
}
50
51
public
String toString()
52
{
53
return
licenseType.getNiceName()
+
"
licensed to
"
+
organisation;
54
}
55
56
public
boolean
isExpired()
57
{
58
return
false
;
59
}
60
61
public
Date getExpiryDate()
62
{
63
return
null
;
64
}
65
66
public
String getPartnerName()
67
{
68
return
partnerName;
69
}
70
71
public
boolean
isLicenseLevel(Collection levels)
72
{
73
for
(Iterator iterator
=
levels.iterator(); iterator.hasNext();)
74
{
75
String level
=
(String)iterator.next();
76
if
(getLicenseType().getDescription().toLowerCase().indexOf(level.toLowerCase())
!=
-
1
)
77
return
true
;
78
}
79
80
return
false
;
81
}
82
83
public
int
getUsers()
84
{
85
return
-
1
;
86
}
87
88
public
String getLicenseId()
89
{
90
return
licenseId;
91
}
92
93
public
static
long
EVALUATION_PERIOD
=
0x9fa52400L
;
94
protected
Date dateCreated;
95
protected
Date datePurchased;
96
protected
String organisation;
97
protected
LicenseType licenseType;
98
private
int
users;
99
private
String partnerName;
100
private
String licenseId;
101
102
}
再次打包放到jira/web-inf/lib/目录下,重启,这下好了,jira license detail显示:
escout@sjtu
|
08/五月/06 |
JIRA Enterprise: Commercial Server |
R5AM<<8X9R |
Your commercial JIRA support and updates are available until 09/五月/07. |
哈哈,初次破解成功!!
附记:初次破解,没有多少经验,所以更多记录了一下实际的步骤。后来我测试了一下,当把系统时间更改了之后,Support Period在重启tomcat之后才会更新,所以大概这个状态在运行时是保存在Application对象中的吧