源码分析 | 咋嘞?你的IDEA过期了吧!加个Jar包就破解了,为什么?

20200106231952583.png

微信公众号:bugstack虫洞栈 | 博客:https://bugstack.cn
沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。目前已完成的专题有;Netty4.x实战专题案例、用Java实现JVM、基于JavaAgent的全链路监控、手写RPC框架、架构设计专题案例、源码分析等。
你用剑🗡、我用刀🔪,好的代码都很烧😏,望你不吝出招💨!

一、前言介绍

2020年了,对于一个程序猿来说;

2020 = 1024 + 996 | 404 + 404 + 404 + 404 + 404
2021 = 1024 + 997
2022 = 1024 + 9106
2023 = 1024 + 9107
...
20xx = 从今年开始可怕

当你过了元旦,爽了周末,清早上班,拿起杯子,加点新(薪)水,打开电脑,收起烦恼,翘起小脚,上扬嘴角。一切就绪都准备好,好!撸代码!啊!!!IDEA duang duang duang,过期了!

微信公众号:bugstack虫洞栈 & IDEA 过期

脑瓜一热赶紧搜索破解码;

  • 第一个,失败
  • 第二个,失败
  • 第三个,失败
  • ...
  • 第N个,终于,破解了三个月,先用着,先用着,以后再说!

可能大部分伙伴都在搜各种一堆一大串的破解码往里面粘,一个个试到最后终于过了。但也有一部分老司机是不搜破解码的,他们使用jar包破解,有效期100年。

那么!本文并不想引导用户都去使用破解版,像IDEA这么优秀,其实给你提供了很多选择;

  1. 如果你是学生可以免费使用
  2. 分为社区版和旗舰版,你可以使用社区版 Free, open-source
  3. 一般大公司都是有正版授权的,可以使用
  4. 如果你有开源项目也可以申请 IDEA 授权

所以,个人开发使用社区版本即可,不要使用破解。

好!回归正题,本文主要讲解是为什么放个Jar包就能破解,最后在使用一个jar进行破解演示。在以下章节中你可以学习到如下知识;

  • Java Agent 非硬编码式代理类,这也就是常说的探针技术
  • ASM 字节码编程简单使用
  • 工程打包额外加载其他 jar 方法
  • 最后是一个破解演示,仅适合个人学习使用

二、案例工程

我们通过一个案例工程来模拟破解过程是怎么做到的,其实每个版本的IDEA都在增强防护机制,破解也越来越难。

itstack-demo-code-idea
└── src
    ├── main
    │   ├── java
    │   │   └── org.itstack.demo
    │   │       └── JetbrainsCrack.java
    │   └── resources    
    │       └── META-INF    
    │           └── MANIFEST.MF
    └── test
         └── java
             ├── com.jetbrains.ls.newLicenses
             │   └── DecodeCertificates.java             
             └── org.itstack.demo.test
                 └── ApiTest.java

三、环境配置

  1. JDK 1.8
  2. IDEA 2019.3.1
  3. asm-all 3.3.1

四、代码讲述

在案例中我们模拟 IDEA 有一个 DecodeCertificates 类,用于做授权码校验。之后通过我们的 java agent 编程模拟授权被破解。

1. Java Agent 介绍

在 JDK1.5 以后,JVM 提供了 agent 技术构建一个独立于应用程序的代理程序(即为Agent),用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的AOP功能。

2. ASM 介绍

ASM 是一个 JAVA 字节码分析、创建和修改的开源应用框架。在 ASM 中提供了诸多的API用于对类的内容进行字节码操作的方法。与传统的 BCEL 和 SERL 不同,在 ASM 中提供了更为优雅和灵活的操作字节码的方式。目前 ASM 已被广泛的开源应用架构所使用,例如:Spring、Hibernate 等。

3. 开始我们的模拟破解之路

JetbrainsCrack.java & Agent 操作类
/**
 * 博客:http://bugstack.cn
 * 公众号:bugstack虫洞栈 | 更多原处优质干货
 * Agent 类,所有程序启动只要配置了 -javaagent: 都会走到 premain 方法
 */
public class JetbrainsCrack {

    public static void premain(String args, Instrumentation inst) {
        System.out.println("**************************************");
        System.out.println("*       公众号:bugstack虫洞栈       *");
        System.out.println("*     博客:https://bugstack.cn      *");
        System.out.println("*   你用剑,我用刀,好的代码都很烧! *");
        System.out.println("**************************************");
        inst.addTransformer(new MethodEntryTransformer());
    }

    static class MethodEntryTransformer implements ClassFileTransformer {

        private Logger logger = LoggerFactory.getLogger(MethodEntryTransformer.class);

        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

            try {
                if (className.equals("com/jetbrains/ls/newLicenses/DecodeCertificates")) {
                    ClassReader cr = new ClassReader(classfileBuffer);
                    ClassNode cn = new ClassNode();
                    cr.accept(cn, 0);
                    List<MethodNode> methodNodes = cn.methods;
                    for (MethodNode methodNode : methodNodes) {
                        if ("decodeLicense".equals(methodNode.name)) {
                            InsnList insns = methodNode.instructions;
                            //清除指令
                            insns.clear();
                            insns.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 将本地指定的引用存入栈中
                            insns.add(new InsnNode(Opcodes.ARETURN));          // 从方法中返回引用类型的数据
                            // 访问结束
                            methodNode.visitEnd();
                            ClassWriter cw = new ClassWriter(0);
                            cn.accept(cw);
                            byte[] bytes = cw.toByteArray();
                            // 输出字节码到Class
                            this.outputClazz(bytes);
                            // 返回最新字节码
                            return cw.toByteArray();
                        }
                    }
                }
            } catch (Exception e) {
                return classfileBuffer;
            }

            return classfileBuffer;
        }

        private void outputClazz(byte[] bytes) {
            // 输出类字节码
            FileOutputStream out = null;
            try {
                out = new FileOutputStream("ASMDecodeCertificates.class");
                logger.info("ASM类输出路径:{}", (new File("")).getAbsolutePath());
                out.write(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != out) try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}
  • 在这个类中可以看到有一个 premain 方法,这个是在被 java agent 处理后的程序入口,所有信息类和方法都会到这个入口
  • 之后我们使用 inst.addTransformer(new MethodEntryTransformer()); 添加我们自己的处理逻辑,这个逻辑也是用字节码编程技术代理类的过程。这个过程也就是我们平时开发中那些不需硬编码就可以监控方法执行时长的逻辑一样
  • MethodEntryTransformer 实现了 ClassFileTransformer 的 transform 方法,也就是真正操作字节码的过程。

    • 在这个类方法中首先需要找到我们的授权码校验类 com/jetbrains/ls/newLicenses/DecodeCertificates ,每一个版本的IDEA不一样,同时授权逻辑校验也不一样
    • 紧接着在找到授权校验类里面的校验方法,if ("decodeLicense".equals(methodNode.name))
    • 接下来就需要对字节码进行处理了,这里面的处理过程比较粗暴,直接将原来方法里的指令内容清空。然后使用 new VarInsnNode(Opcodes.ALOAD, 1) 将本地指定的引用存入栈中
    • 之后将我们的入参内容直接返回,new InsnNode(Opcodes.ARETURN),从方法中返回引用类型的数据。在以往旧版本的 IDEA 破解中比较简单,直接把最终需要的破解内容返回即可,里面描述了 IDEA 各个软件的使用期限
    • 最终将我们处理后的字节码返回给方法,return cw.toByteArray();这个时候虽然你大爷还是你大爷,但你大娘已经不是你大娘了
  • 为了测试的验证我们将变更后的字节码代码(大娘)输出到工程目录下,也就是一个 class 文件,下文测试时候验证

4. DecodeCertificates.java & 模拟 ideaIU-15.0.1 软件授权码校验类

public class DecodeCertificates {

    public String decodeLicense(String usingKey) {
        // 模拟校验授权码
        return "usingKey is error:"+ usingKey;
    }

}
  • 这个类比较简单只是模拟有这么个方法用于校验授权码

5. ApiTest.java & 测试类

/**
 * 博客:http://bugstack.cn
 * 公众号:bugstack虫洞栈 | 更多原处优质干货
 * 测试类配置 VM 参数
 * Idea VM options:-javaagent:E:\itstack\GIT\itstack.org\itstack-demo-code\itstack-demo-code-idea\target\itstack-demo-code-idea-1.0-SNAPSHOT.jar
 */
public class ApiTest {

    private static Logger logger = LoggerFactory.getLogger(ApiTest.class);

    public static void main(String[] args) throws Exception {
        DecodeCertificates decodeCertificates = new DecodeCertificates();
        // 模拟usingKey:认购有效期至2089年7月8日
        String license = decodeCertificates.decodeLicense("Subscription is active until July 8, 2089");
        logger.info("测试结果:{}", license);
    }

}

6. MANIFEST.MF 配置引导启动时加载

Manifest-Version: 1.0
Premain-Class: org.itstack.demo.JetbrainsCrack
Can-Redefine-Classes: true

7. POM 配置打包时加入ASM包

<!-- 将javassist包打包到Agent中 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <artifactSet>
            <includes>
                <include>asm:asm-all:jar:</include>
            </includes>
        </artifactSet>
    </configuration>
</plugin>

五、工程测试

  1. 先单纯的直接运行ApiTest.java ,测试结果如下(模拟返回授权不可用);

    21:23:46.101 [main] INFO  org.itstack.demo.test.ApiTest - 测试结果:usingKey is error:Subscription is active until July 8, 2089
  2. 第二步测试前先打包下工程,这个时候你会看到如下结果;

    [INFO] --- maven-install-plugin:2.4:install (default-install) @ itstack-demo-code-idea ---
    [INFO] Installing E:\itstack\GIT\itstack.org\itstack-demo-code\itstack-demo-code-idea\target\itstack-demo-code-idea-1.0-SNAPSHOT.jar to D:\Program Files (x86)\apache-maven-3.6.2\repository\org\itstack\demo\itstack-demo-code-idea\1.0-SNAPSHOT\itstack-demo-code-idea-1.0-SNAPSHOT.jar
    [INFO] Installing E:\itstack\GIT\itstack.org\itstack-demo-code\itstack-demo-code-idea\dependency-reduced-pom.xml to D:\Program Files (x86)\apache-maven-3.6.2\repository\org\itstack\demo\itstack-demo-code-idea\1.0-SNAPSHOT\itstack-demo-code-idea-1.0-SNAPSHOT.pom
    [INFO] Installing E:\itstack\GIT\itstack.org\itstack-demo-code\itstack-demo-code-idea\target\itstack-demo-code-idea-1.0-SNAPSHOT-sources.jar to D:\Program Files (x86)\apache-maven-3.6.2\repository\org\itstack\demo\itstack-demo-code-idea\1.0-SNAPSHOT\itstack-demo-code-idea-1.0-SNAPSHOT-sources.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  3.080 s
    [INFO] Finished at: 2020-01-05T23:25:08+08:00
    [INFO] ------------------------------------------------------------------------
  • 这里的 itstack-demo-code-idea-1.0-SNAPSHOT.jar 就是我们的 Agent 包,按实际情况复制自己的路径
  1. 配置 VM options:-javaagent:E:itstackGITitstack.orgitstack-demo-codeitstack-demo-code-ideatargetitstack-demo-code-idea-1.0-SNAPSHOT.jar

    微信公众号:bugstack虫洞栈 & IDEA VM options

  2. 运行 ApiTest 测试,正确结果如下;

    23:29:42.803 [main] INFO  org.itstack.demo.test.ApiTest - 测试结果:usingKey is error:Subscription is active until July 8, 2089
    
    Process finished with exit code 0
    • 这个过程就是你使用 jar 包破解 IDEA 的过程,了解这个技术点可以用在很多不需要硬编码就能做到的服务中,比如监控,调试等
  3. 别忘了我们还在 Agent 中输出了新的字节码,看看这个时候的类是什么样(你大爷还是你大爷,但你大娘可不是你大娘了)
被代理前
public class DecodeCertificates {

    public String decodeLicense(String usingKey) {
        // 模拟校验授权码
        return "usingKey is error:"+ usingKey;
    }

}
被代理后
package com.jetbrains.ls.newLicenses;

public class DecodeCertificates {
    public DecodeCertificates() {
    }

    public String decodeLicense(String usingKey) {
        return usingKey;
    }
}

六、综上总结

  • 建议个人使用社区版即可,不要尝试破解尊重IDEA,本文只为学习 javaagent 技术
  • ASM 这个东西特别强大,其实字节码编程还有 javassist,在一起 RPC 框架中有非常多的使用
  • 关于 java agent 我已经专题方式写过案例文章,可以参考;https://bugstack.cn/itstack-d...

七、关注公众号

微信公众号:bugstack虫洞栈

Image placeholder
coolszh
未设置
  76人点赞

没有讨论,发表一下自己的看法吧

推荐文章
嗨!你的 2019 晒好封存了吗?快来看程序老兵的 2019 吧!

时间过得真是太快快快了,2019还剩下最后几个小时了。回望即将过去的这一年,老兵哥做了不少事情,有计划内的,也有计划外的,当然还有不少事情没做。赶在最后时刻晒一晒我的2019年,希望从成绩荣誉中获得一

Carbon —— PHP 中日期 / 时间处理,你只需要这个扩展包就够了

在PHP中使用日期和时间并不是容易或清晰的任务。我们必须处理strtotime,格式化问题,大量计算等等。 这个漂亮的包叫做Carbon可以帮助在PHP开发中处理日期/时间变得更加简单、更语义化,从

丰巢刷脸取件被小学生破解,号称3D、深度学习加持的人脸识别究竟靠谱吗?

大数据文摘出品作者:曹培信经费不够,2D来凑?前些天,丰巢智能快递柜被“小学生”用打印照片破解,让人大跌眼镜。据《人民日报》报道,嘉兴上外秀洲外国语学校402班科学小队向都市快报《好奇实验室》报料:他

如何合并多个js和css文件?

如何合并多个js和css文件?(1)G.js文件~function(){ window.G={}; G.Method={ add:function(){ alert(111); }, sub:func

SQL 查询语句总是先执行 SELECT?你们都错了

很多SQL查询都是以SELECT开始的。不过,最近我跟别人解释什么是窗口函数,我在网上搜索”是否可以对窗口函数返回的结果进行过滤“这个问题,得出的结论是”窗口函数必须在WHERE和GROUPBY之后,

如果我问你:排序算法的「稳定性」有何意义?你怎么回答?

虽然我们在工作不一定经常去写排序算法,但是排序算法却是充斥着我们的程序生活,比如你不经意间调用了SDK中的某个sort算法,其背后无非是什么快排、归并等算法。而且在我们面试的过程中也会经常被问及,如果

Requests源码分析

Requests源码分析最近python学习到了瓶颈了,这次准备从KennethReitz大神的requests入手分析源码,看大神的代码是一种学习的好方法,让我从中学到很多以前不知道的知识reque

英特尔第二代至强与傲腾,为企业IT带来了什么?

在企业IT基础设施领域,英特尔第二代至强可扩展处理器与傲腾数据中心级持久内存名声在外,是英特尔以数据为中心的产品组合中的代表之作。于今年4月份发布的第二代英特尔至强可扩展处理器,以强大的平台能力,实现

新突破!人工智能会根据你的声音来预测你的长相

麻省理工学院的研究人员发明了一种新的人工智能,它实现了一项惊人的成就:仅通过分析一个人声音的短片段,它就能重建他们在现实生活中的样子。人工智能的预测结果并不完美,但总的来说还是相当不错的,这项研究也是

leveldb源代码分析系列1:MemTable的实现

MemTable及其实现这是一个第零层的主题,预计扩展如下第一层主题:1.1comparator介绍1.2skiplist实现介绍1.3数据压缩相关介绍1.4Put流程1.5Get流程leveldb中

leveldb源代码分析系列1.1:memtable中comparator的实现

leveldb中memtable封装了一个skiplist用来存储真正的数据,跳跃列表的实现一定需要定义存储项的序关系,而在leveldb中这个序关系通过comparator相关类来实现。leveld

leveldb源代码分析系列1.2:skiplist实现

skiplist的实现介绍leveldb中的SkipList是一个模板类,其模板参数的类型分别是存储的Key类型和Comparator类型。虽然名字是Key类型,但其实存储了整个entry,只不过Co

我哪里配置错误,为什么每次都无法正常跳转到支付宝的支付界面?

我每次学这套课程,都卡在这里,过不去。心里好难受~ 以下是我的配置整个过程:以下命令都执行过了。phpartisantinker phpartisanconfig:clear >>>config('p

三个方面告诉你,为什么说传统安全托管服务已过时

随着组织发展其安全程序,其安全环境的复杂性也在增长。复杂性和变化要求采用一种全新的方式来应对现代安全运营中心(SOC)。根据Gartner的数据现实,到2022年,50%的SOC将转变为具有集体事件响

日均5亿查询量的京东订单中心,为什么舍MySQL用ES?

京东到家订单中心系统业务中,无论是外部商家的订单生产,或是内部上下游系统的依赖,订单查询的调用量都非常大,造成了订单数据读多写少的情况。我们把订单数据存储在MySQL中,但显然只通过DB来支撑大量的查

从容器到云原生,为什么灵雀云敢说自己“没有明显短板”?

Kubernetes虽然是最热门容器技术,但是放眼中国市场,除了阿里云、腾讯云、华为云这几家大厂,能把Kubernetes整明白并且可以成功落地的企业,凤毛麟角。容器改变了软件开发和部署的面貌,也导致

分层存储超详细解读,为什么大数据时代它已不可或缺

如今,分层存储已成为了一种常见的存储方法,它将数据存储在具有不同特性(如性能、成本和容量)的不同存储介质上。不同的存储媒介被分配到不同的层次结构中,其中最高性能的存储媒介被认为是第0层或第1层,然后是

深入探究 RocketMQ 事务机制的实现流程,为什么它能做到发送消息零丢失?

1、解决消息丢失的第一个问题:订单系统推送消息领丢失既然我们已经明确了消息在基于MQ传输的过程中可能丢失的几个地方,那么我们接着就得一步一步考虑如何去解决各个环节丢失消息的问题,首先要解决的第一个问题

5G已经来了,Wi-Fi 6还会远么?

即将于2019下半年发布的WI-Fi6,将使无线网络比以往更快、更可靠、更节能,但这究竟意味着什么呢?Wi-Fi6是Wi-Fi联盟为802.11ax命名的新名字,旨在使Wi-Fi世代更易于普通计算机用

数据结构与算法分析——开篇以及复杂度分析

开篇 你也许已经发现了,工作了几年,原以为已经是一只老鸟。但看到刚参加工作的同事,你发现,原来自己一直在原地踏步。跟新人相比,你的唯一优势就是对业务更熟悉而已,别的就没有什么优势了。 怎样才能够让自己

数据结构与算法分析——开篇以及复杂度分析

开篇你也许已经发现了,工作了几年,原以为已经是一只老鸟。但看到刚参加工作的同事,你发现,原来自己一直在原地踏步。跟新人相比,你的唯一优势就是对业务更熟悉而已,别的就没有什么优势了。怎样才能够让自己更上

Python数据分析实战 | 爬遍拉勾网,带你看看数据分析师还吃香吗?

微信公众号:「Python读财」如有问题或建议,请公众号留言伴随着移动互联网的飞速发展,越来越多用户被互联网连接在一起,用户所积累下来的数据越来越多,市场对数据方面人才的需求也越来越大,由此也带火了如

Python分析42年高考数据,告诉你高考为什么这么难?

大数据文摘授权转载自数据森麟作者:徐麟对于已经工作的“上班族”来说,6月7号到9号三天无疑是兴奋到飞起的,终于迎来了令人愉悦的端午假期。然而有那么一群人,将在端午节日之际迎来人生特别重要的一次经历或者

Passport 验证 Token 方法和持续刷新过期时间问题

项目介绍最近在做一个后台项目,目标是登录后无操作30分钟后自动过期,一直操作的情况下,过期时间一直刷新(目前不考虑每次操作修改对数据库的压力)token有效期检测 操作后自动刷新过期时间 管理员手动登

程序员垃圾代码分类指南

上一篇文章《程序员垃圾分类图鉴》和大家聊了聊程序员的垃圾分类,有的程序员直呼太真实,有的程序员觉得太讽刺,不应该给程序员进行这样的分类。其实每个行业都会存在各种各样糟糕的情况,娱乐性的分类会将问题放大