看透激活码
-javaagent:C:\Users\LYM\code\break_scripts\Jetbrains\ja-netfilter.jar=jetbrains
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5050
Arrays.stream(configs).map(c->c.getProvider().getService("CertStore", "X509")).toList()
Files.write(Path.of("C:/Users/LYM/code/break_scripts/"), new ArrayList<>(((PKIXBuilderParameters) params).unmodTrustAnchors).get(0).getTrustedCert().getEncoded())
java.nio.file.Files.write(java.nio.file.Path.of("C:/Users/LYM/code/break_scripts/2022.3.3-33.crt"),getEncoded())
Arrays.toString(CertificateFactory.getInstance("X509").generateCertificate(new FileInputStream("C:/Users/LYM/code/break_scripts/license-XIZQAN09CR.crt")).getEncoded())
RSACore.parseMsg(signature, ((RSAPublicKeyImpl) key).getModulus())
l2cached.getOrDefault(x + "," + y + "," + z, null);
info.toString().contains("JetProfile CA")
JDK版本问题¶
- SunCertPathBuilder#depthFirstSearchForward:JDK8和JBR17.0.10差不多,但是JBR17.0.6不一样
- JDK8和JBR17.0.10
- ForwardBuilder#verifyCert:trust不再verify,即便verify也不是签名的verify
- PathComplete后,BasicChecker变成必须的了
- 正是在BasicChecker执行userCert.verify(CACert.public)
- JDK8和JBR17.0.10
- RSASignature:JDK8和JBR17.0.6差不多,但是JBR17.0.10不一样
- JBR17.0.10
- 反过来了,
MessageDigest(decrypted, padding(encodeSignature(digest)))
- 反过来了,
- JBR17.0.10
-
ja-netfilter
- 不知道为什么,使用IDEA2022.3.3的JBR或者JDK17.0.2都不能触发ja-netfilter代理,JDK8就可以,但是IDEA2022.3.3是怎么被激活的呢?明明是JBR17.0.6
- 但是不知道为什么,RemoteDebug IDEA2022.3.3(JBR17.0.6)却可以
-
怪哉,无idea.key和plugin_PCWMP.license也可以运行2022.3
激活码¶
idea.key¶
- license中的时间和证书中的时间不对应
- 43B4A73YYJ
- licenseeName=lan yu
- license.paidUpTo=2017-02-25
- user subject=CN=prod3y
- certValidity: 2015.11.02-2018.11.01
- fingerprint-sha1=e14efa20f0e96ba056c8d4417e68fbd588bae410
- FDXL1Y2811
- licenseeName=mao zedong
- license.paidUpTo=2024-03-26
- user subject=CN=prod2y-from-20221010
- certValidity: 2022.10.11-2024.10.12
- fingerprint-sha1=3bbe60ad7e0a57418be433db0286fdde6cf94dda
- K384HW36OB
- licenseeName=kiddy inseams
- license.paidUpTo=2024-05-11
- user subject=CN=prod2y-from-20221010
- certValidity: 2022.10.11-2024.10.12
- fingerprint-sha1=3bbe60ad7e0a57418be433db0286fdde6cf94dda
- XIZQAN09CR
- licenseeName=Benoit Menendez
- license.paidUpTo=2025-08-01
- user subject=CN=prod2y-from-20201019
- certValidity: 2020.10.19-2022.10.21
- fingerprint-sha1=e22bb88395f33a1cfbd70abaeb1c912c7d1a5160
plugin_PCWMP.license¶
- Personal Code With Me Plugin的license
- 和idea.key激活码不一样,可能在idea.key可以的,pcwmp就不行,也可能反过来
激活idea¶
-
2024激活成功时,还顺便激活了pcwmp
-
输入非法激活码时
- 解码Base64:
- LicenseJSON、 idea.key-256B、
- crl文件、crl文件的用户证书prod2y-from-20201019、crl文件的256B、crl文件的CRL
- idea-rootca( JetProfile CA),不知道那里来的
- idea.key-cert
- java.security.cert.CertPathBuilder#build:所有都验证成功
- 即便
- 是43B4A73YYJ(2015-2018)、K384HW36OB
- 是sun.security.x509.X509CertImpl#checkValidity(java.util.Date)(只传入了证书的NoBefore)
- 即便
- 因此不是证书问题
- 解码Base64:
激活失败错误信息注意¶
- Key is invalid、License is valid till Mar 26, 2024
- 在激活页面输入非法激活码错误
- We could not validate your license FDXL1Y2811、This license K384HW36OB has been suspended.
- 如果在激活后,迅速打开一个项目,短时间内不会怎么样
- 然而点击help/register打开license管理页,就又会出现这样的错误
- 或者过了一小段时间,自动弹出license管理页显示这个错误
- 再次输入激活码,则立刻出现这个错误
- 重新打开IDE,延迟一下页立刻报这个错误
- 如果在激活后,迅速打开一个项目,短时间内不会怎么样
- This license K384HW36OB has been suspended.
- 原因是激活码使用人数过多,关闭网络或者设置IDE的代理激活一下后重新联网即可
- 这是合法key,license
使用ja-netfilter前¶
- 对于最新的ide来说,过期的key一般都无法验证为合法
| 43B4A73YYJ | FDXL1Y2811 | K384HW36OB | XIZQAN09CR | |
|---|---|---|---|---|
| Key is invalid(非法key) | 2022.2、2022.3、2024.1 | 2022.2、2022.3、2024.1 | ||
| We could not validate your license FDXL1Y2811. 合法key,非法license | 2022.2、2022.3 | |||
| This license K384HW36OB has been suspended. | 2022.2、2022.3、2024.1 | |||
| License is valid till xxx(如Mar 26, 2024,过期非法key) | 2024.1 | |||
| 成功 |
使用ja-netfilter后¶
| 43B4A73YYJ | FDXL1Y2811 | K384HW36OB | XIZQAN09CR | |
|---|---|---|---|---|
| Key is invalid(非法key) | 2022.2、2022.3、2024.1 | |||
| We could not validate your license FDXL1Y2811. 合法key,非法license | ||||
| This license K384HW36OB has been suspended. | ||||
| License is valid till xxx(如Mar 26, 2024,过期非法key) | 2024.1 | |||
| 成功 | 2022.2、2022.3 | 2022.2、2022.3、2024.1 | 2022.2、2022.3、2024.1 | |
| ### ja-netfilter作用 | ||||
| - 作用 | ||||
| - 非法key:有些√,有些仍然×(可能是key过期时间太早了) | ||||
| - 过期key:× | ||||
| - 合法key,非法license:√ | ||||
| - 功能 | ||||
| - 替换RSA解密参数,替换RSA解密结果 | ||||
| - 阻断URLConnection | ||||
| - 阻断域名 |
合法key,非法license-->合法license¶
ja-netfilter¶
- 拦截URL
- GET
https://account.jetbrains.com/lservice/rpc/validateKey.action?buildDate=20221129&buildNumber=2022.3.3+Build+IU-223.8836.41&clientVersion=13&hostName=&licenseHash=41472961%2F0%3A1563609451&licenseKey=FDXL1Y2811&machineId=c5ec68a6-6e17-439f-b6fd-d965dda1b541&productCode=II&productFamilyId=II&salt=1713017276076&secure=false&userName=&version=2022300- header:Access-Encoding: gzip
{ "buildDate": "20221129", "buildNumber": "2022.3.3 Build IU-223.8836.41", "clientVersion": "13", "hostName": "", "licenseHash": "41472961/0:1563609451", "licenseKey": "FDXL1Y2811", //C:\Users\LYM\AppData\Roaming\JetBrains\PermanentUserId, 就是从这里获取的 "machineId": "c5ec68a6-6e17-439f-b6fd-d965dda1b541", "productCode": "II", "productFamilyId": "II", //对同一个激活码,只改变salt--当前时间戳ms "salt": "1713017276076", "secure": "false", "userName": "", "version": "2022300" }
总结¶
- 只需要一个合法key:需要在本地校验成功
- 步骤:关闭网络,输入key,OK,重新联网
- 不要打开license管理页,会立刻请求validateKey
- 我试过,几个小时都没事
- 亦或者阻断该validateKey请求,可以用网络代理的方法或者物理机器的方法,也可以用ja-netfilter一样的javaagent方法
- 一种取巧的方式,JetBrains的IDE都有设置proxy功能,随便设个不存在的即可
- 关于ja-netfilter:基本所有有的配置都一样,但是我是不太明白为什么还需要其他插件,感觉只需要plugins-url拦截validateKey请求
- 关于激活码:他们好像都是自己出来的,应该是知道256B、hash、metadata,但是我不知道。。。
激活过程总结¶
- 本地验证Key:
- 格式正确:
{LicenseId}-{LicenseJSON}-{256B}-{LicenseCert}- LicenseId和LicenseJSON必须用-连接着
- 内容完整性(摘要)
- 比如FDXL1Y2811是合法key,修改了LicenseJSON中的paidUpTo,结果FDXL1Y2811报错Key is invalid
- LicenseId和LicenseJSON中的不同也不行
- 即便使用ja-netfilter后,仍然报这个错
- 可能与license的属性hash、metadata,以及key中的256B有关
- 可能是内容完整性校验:签名、摘要
- 可能是根据除hash、metadata外的数据进行特殊哈希
- 因为在签名、摘要都没Debug到,可能用的是特殊的方法
- 感觉paidUpTo没用
- 非法Key:
{"code":"GO","fallbackDate":"2025-08-01","paidUpTo":"2025-08-01","extended":false} - 合法Key:
{"code":"GO","paidUpTo":"2024-05-11","extended":false}- 但是
"licenseeType": "PERSONAL"
- 但是
- 非法Key:
- 比如FDXL1Y2811是合法key,修改了LicenseJSON中的paidUpTo,结果FDXL1Y2811报错Key is invalid
- 格式正确:
- key合法后,才请求
https://account.jetbrains.com/lservice/rpc/validateKey.action验证license
JaNetFilter¶
- Result是在解密或者验签时匹配参数直接返回结果
- 指数 = 65537 → 这是 公钥常用的 e 值(不是私钥 d!)
- 所以这很可能是 验签(signature verification),而不是解密!
- Arg是替换加密或者验签的参数
- e=3 是另一个常见的小公钥指数(虽然不安全,但历史上用过)
- 攻击者可能预先用 e=3 签名了一个 license
- 但 IDEA 代码里写死了用 e=65537 验签
- 所以插件把
65537临时替换成3 - 这个不太清楚怎么回事,好像用的基本都是Result
✅ 正确结论¶
| 插件类型 | 作用时机 | 操作 | 在 IDEA 授权中的典型用途 |
|---|---|---|---|
ResultFilter / ResultTransformer |
在 modPow 开始执行时 |
匹配 (base, exponent, modulus) 参数 → 直接返回预设结果 |
验签或解密时,伪造合法 license 明文(最常用) |
ArgsFilter / ArgsTransformer |
在 modPow 开始执行时 |
匹配 (exponent, modulus) → 替换为新的 (exponent', modulus') |
较少用,可用于让程序用攻击者控制的密钥去解密/验签 |
🔍 详细解释(结合 IDEA 场景)¶
1. ResultFilter:直接返回结果(主流破解方式)¶
- 触发点:IDEA 调用
ciphertext.modPow(privateKeyD, modulusN)(解密 license) - 插件行为:
- 检查
(ciphertext, privateKeyD, modulusN)是否匹配规则 - 如果匹配 → 不计算,直接返回
"{"licensedTo":"HACKER"}" - 效果:
- 即使
ciphertext是乱码或用错误密钥加密的, - IDEA 也拿到了“看起来合法”的明文,激活成功。
- ✅ 这就是为什么破解版 IDEA 能离线激活的核心原因。
📌 重点:它劫持的是“解密结果”或“验签结果”,不是网络响应。
2. ArgsFilter:替换参数(较少见,但可行)¶
- 触发点:同样在
modPow调用时 - 插件行为:
- 检查
(privateKeyD, modulusN)是否匹配(比如 JetBrains 的私钥) - 如果匹配 → 把
privateKeyD和modulusN替换成攻击者自己的(d_fake, n_fake) - 然后 IDEA 实际执行:
ciphertext^d_fake mod n_fake - 前提:
- 攻击者必须提前用
(d_fake, n_fake)加密好 license 明文,使得结果正好是合法内容。 - 缺点:
- 需要控制模数
n,而 IDEA 的n是固定的,难以匹配 - 更复杂,容易出错
📌 所以现实中
ResultFilter更简单、更常用。
🧪 类比理解¶
| 场景 | 正常流程 | ResultFilter 干的事 |
ArgsFilter 干的事 |
|---|---|---|---|
| 考试答题 | 你计算 2+3=? |
监考老师看你写“2+3”,直接给你卷面写“5” | 监考老师把题目改成“1+4”,让你算 |
| IDEA 解密 | 用私钥解密密文 | 看到你要解密,直接塞给你明文 | 把你的私钥换成我的私钥,让你用我的钥匙开锁 |
💡 补充:验签 vs 解密¶
- 验签:
signature^e mod n→ 得到 hash,对比原文 hash
→ 这里e是公钥,插件可匹配(signature, e, n) - 解密:
ciphertext^d mod n→ 得到明文
→ 这里d是私钥,插件匹配(ciphertext, d, n)
ResultFilter 对两者都适用,只要三元组匹配,就返回你想要的结果。
如果你看到某个破解方案只用了 ResultTransformer,那基本可以确定:
👉 它是在 IDEA 本地验证 license 时,直接返回了伪造的授权信息,跳过了所有密码学计算。