背景 其实这篇文章一年半前就应该写了,那个时候就曾经研究过 Atlassian 的授权机制。主要是那个时候发现了 Stash 这个宝贝。上网遍寻了一下,也没有发现关于 Stash 的破解。但是,关于 Jira 的破解文章就有好多,仔细看了一下,无外乎也就是替换 Version2LicenseDecoder.class
这个文件,然后使用自己编码的,或者明文的 License 授权文件,来达到激活产品的目的。既然 Jira 已经有很多人写过了,那么我们就拿 Stash 来玩玩吧。
声明: 撰写本文的目的,仅在于研究学习 Atlassian 授权的原理和机制,请勿将本文涉及到的任何内容用于商业用途。请大家尽可能地支持正版软件,因为这样我们才能有更多好用的软件。Stash 官方 10 用户的授权 仅仅为 $10 美金,也就是 60 多块钱的事儿,对于小团队来说绝对是白菜价了。
License 分析 其实 License 分析的部分早就有人已经做过了,请参考《Atlassian JIRA 授权许可证机制分析 》。
不多说,先上一段 Python 代码。注意 M2Crypto
需要自行安装,该代码在 Python 2.7 下运行通过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import M2Cryptoimport base64import hashlibimport structimport zlibENCODED_LICENSE_LENGTH_BASE = 31 LICENSE_PREFIX = '' .join(map (chr , [13 , 14 , 12 , 10 , 15 ])) SEPARATOR = 'X' ATLASSIAN_PUBLIC_KEY = './atlassian_pub.pem' license_key = ''' AAABDg0ODAoPeNptUNtKxDAQfc9XBHyOpKlttZCH2gas9LK0VRF8idlRI91akrS4f293q4iyMAPDn Msc5uwBtjgDhVmI6VXsRbEf4rTtMKMeQxlYZfTo9MfAb/MmeYqxmGU/ycMGpQaOQyYd8AOfLMUi9 K6NPC+0gsGC2OqjWlSdaDZN3gr068CdmeAPvduPUMkd8LQuS9GkeVKsuFROz7AK+pV7D8YeTBgqp R4cDHJQID5HbfY/iXxCPcJCVJtXOWi7Hk17PY7a4Q6sW82rafcMpn65s4slJx5qwcxg8oxf06AgN 7TzSZFEAWkuxCNqRcWXJgXzaHQZROg7+0Iv8uwUcjrUZjLqTVr4/74vnyt/nTAsAhR8v6Zm5YfvZ WVBnwouY7xhT+jwUgIUbRhGVaC8P9JCvDPT1MXIwnCgGqA=X02dp2 ''' license_content = license_key.replace("\r" , "" ).replace("\n" , "" ).replace("\t" , "" ).replace(" " , "" ) x_position = license_content.rfind(SEPARATOR) if license_content[x_position + 1 :x_position + 3 ] != "02" : print "Invalid license version, only license version 2 is supported!" exit() license_length = int (license_content[x_position + 3 :], ENCODED_LICENSE_LENGTH_BASE) encoded_bytes = license_content[:license_length] decoded_bytes = base64.b64decode(encoded_bytes) text_length, = struct.unpack(">I" , decoded_bytes[:4 ]) license_bytes = decoded_bytes[4 :4 + text_length] if license_bytes[:5 ] != LICENSE_PREFIX: print "Invalid license version 2 file" exit() license_text = zlib.decompress(license_bytes[5 :]) license_hash = decoded_bytes[4 + text_length:] print license_textpublic_key = M2Crypto.DSA.load_pub_key(ATLASSIAN_PUBLIC_KEY) official = public_key.verify_asn1(hashlib.sha1(license_bytes).digest(), license_hash) if official: print "This license is official signed." else : print "This license is not official signed."
其中 license_key
就是我们从 Atlassian 官方得到的试用 License。出于隐私保护的角度出发,我这里使用了大眼夹的 License。./atlassian_pub.pem
是从 Atlassian 官方的授权文件中提取出来的 Public Key,其内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 -----BEGIN PUBLIC KEY----- MIIBuDCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/ JmYLdrmVClpJ+f 6 AR7ECLCT7up1/63 xhv4O1fnxqimFQ8E+4 P208UewwI1VBNaFpEy9nXzrith1yrv8 iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwky jMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ ohNWLx+2 J6ASQ7zKTxvqhRkImog9/h WuWfBpKLZl6Ae1UlZAFMO/7 PSSoDgYUAAoGBAIvfweZvmGo5otwawI3no7Udanxa l3hX2haw962KL/nHQrnC4FG2PvUFf34OecSK1KtHDPQoSQ+DHrfdf6vKUJphw0Kn 3 gXm4LS8VK/LrY7on/ wh2iUobS2XlhuIqEc5mLAUu9Hd+1 qxsQkQ50d0lzKrnDqPsM0WA9htkdJJw2nS -----END PUBLIC KEY-----
如果你需要验证是否官方签名的话,可以自行创建这个文件,如果不需要的话,把 print license_text
之后的代码段全部删掉便可。运行上面的代码,我们得到如下的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Description =JIRA\: EvaluationCreationDate =2012-12-27jira.LicenseEdition =ENTERPRISE Evaluation =true jira.LicenseTypeName =COMMERCIAL jira.active =true licenseVersion =2MaintenanceExpiryDate =2013-01-26Organisation =Clippit Testjira.NumberOfUsers =-1 ServerID =B05L-H0T3-LA75-R4EYSEN =SEN-L2107857LicenseID =LIDSEN-L2107857LicenseExpiryDate =2013-01-26PurchaseDate =2012-12-27This license is official signed.
可以看到,这是一个经过官方签名和认证的有效 License,授权信息都已经比较清晰明了了,就不多做解释了。那么 Stash 的授权信息长什么样呢?Stash 的试用 License 大概长成这个样子(部分内容出于隐私保护已经马赛克化):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Description =Stash Unlimited Users [Legacy]\: Evaluation LicenseCreationDate =2015-02-26Evaluation =true stash.active =true licenseVersion =2MaintenanceExpiryDate =2015-03-28Organisation =Tommy Laustash.LicenseTypeName =COMMERCIAL ServerID =ABCD-1234-EFGH-5678SEN =SEN-L1234567LicenseID =LIDSEN-L1234567LicenseExpiryDate =2015-03-28stash.NumberOfUsers =-1 PurchaseDate =2015-02-26This license is official signed.
可以看到大大的一个 Evaluation=true
,其实只要把这里改成 false
,再修改一下对应的信息,比如 Description
, MaintenanceExpiryDate
, LicenseExpiryDate
, Organisation
, ServerID
为自己的信息,重新编码一下,就可以生成一个新的证书了。
伪造数字签名 与前文提到的替换公钥的方式不同,我选择了修改源代码然后重新编译的方式。这样的好处是就算是修改了原始文件,官方的授权证书依然可以正常使用。而不会出现输入正版授权反而提示授权无效的情况。
要修改的主要是名为 Version2LicenseDecoder.class
的 com.atlassian.extras.decoder.v2.Version2LicenseDecoder
类。对于我现在使用的 Stash v3.7.0 来说,主要是以下两个文件:
atlassian-extras-decoder-v2-3.2.jar
atlassian-universal-plugin-manager-plugin-2.18.2.jar
第一个是用于 Stash 授权的,第二个是用于 Plugin 授权的。同时第二个文件是打包在 stash-bundled-plugins.zip
文件中的,需要提取、修改后重新替换包内的同名文件。而对于 Version2LicenseDecoder.java
的修改,主要是把 127 行开始的数字签名代码屏蔽掉,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
然后重新编译成 Version2LicenseDecoder.class
,并替换上述提到的两个文件,atlassian-extras-decoder-v2-3.2.jar
和 atlassian-universal-plugin-manager-plugin-2.18.2.jar
。这样,任意数字签名的符合 Atlassian 编码规范的 License 都可以正常的进行授权了。
最后 写本文的目的和初衷,都是为了研究和学习。请勿向本人索取修改好的文件,帮忙生成证书等。如果想要生成证书,请参考下面引用的博文。
参考: