Intellij Mybatis 插件破解教程

96
作者 wooyoo
2016.12.08 09:12 字数 1148

背景

Intellij上的mybatis插件是一个十分优秀的插件,但是需要付费。在网上搜索一番之后,发现果然有破解版,遂来研究一番破解原理。

环境

  • 操作系统:mac os 10.11.6
  • Intellij版本:2016.2
  • mybatis插件版本:2.87
  • 破解工具:
    • JBE:java字节码修改工具
    • JD-GUI:java反编译工具

工具介绍

JD-GUI

该工具的使用方式很简单。具体界面如下:


JBE

jbe是基于jclasslib的字节码修改工具,十分强大。假设我们要修改某个方法对应的字节码,具体步骤如下图所示:


  1. 首先点击图中数字1所指的icon,选择你要修改的class文件。
  2. 然后点击Methods,可以看到该class文件中的类所含有的方法列表。
  3. 点击我们需要修改的方法,然后点击code。
  4. 在右边区域我们可以看到Code Editor。点击进入之后,我们就可以修改字节码了。
  5. 修改完成之后点击图中数字6所指的save method保存字节码,此时对应的class文件会同步更新。

破解步骤

思路

软件破解的一般思路,都是hack进校验license的函数,修改里面的校验逻辑。有个小技巧可以帮助我们更快地定位校验激活码的函数:我们可以全局地搜一下"license"、"activate"、"key"以及"valid"等词语,搜索出来的代码一般都是跟处理激活码有关的。

详细步骤

  1. 首先安装没有破解的mybatis插件,然后退出Intellij。在mac os下,插件位于~/Library/Application\ Support/IntelliJIdea2016.2/mybatis_plus/lib。主要的代码位于mybatis_plus.jar中。
  2. 我们通过JD-GUI打开mybatis_plus.jar,观察代码结构。通过观察以及研究网上他人提供的破解版之后,我们发现一共需要修改以下4个类:
    • com.seventh7.mybatis.service.JavaService
    • com.seventh7.mybatis.util.JavaUtils
    • com.seventh7.mybatis.ref.RefProject
    • com.seventh7.mybatis.ref.license.ActivationDriver

JavaService修改

修改stop方法,原来的方法:


我们需要将这段代码逻辑删去,我们通过jbe修改字节码,原来的字节码如下:

aload_0
iconst_1
putfield com/seventh7/mybatis/service/JavaService/stopped Z
invokestatic com/seventh7/mybatis/setting/MybatisSetting/getInstance()Lcom/seventh7/mybatis/setting/MybatisSetting;
getstatic com/seventh7/mybatis/ref/license/LicenseData/EMPTY Lcom/seventh7/mybatis/ref/license/LicenseData;
invokevirtual com/seventh7/mybatis/setting/MybatisSetting/setLicenseData(Lcom/seventh7/mybatis/ref/license/LicenseData;)V
goto 9
astore_1
return

我们将不需要的字节码全部删去,只留下return语句:

return

保存之后我们再看反编译之后的stop方法如下:


我们可以看到,原来的逻辑都被删除了。

JavaUtils修改

修改refValid方法,原来的方法如下:


最直观的做法是在方法的最后将valid和validated重置为true,原来的字节码较长,只截取了return valid的字节码:

......
getstatic com/seventh7/mybatis/util/JavaUtils/valid Z
ireturn

所以我们需要在getstatic之前添加重置为true的字节码:

......
iconst_1
putstatic com/seventh7/mybatis/util/JavaUtils/validated Z
iconst_1
putstatic com/seventh7/mybatis/util/JavaUtils/valid Z
getstatic com/seventh7/mybatis/util/JavaUtils/valid Z
ireturn

iconst_1表示将常量1推入操作数栈,然后通过putstatic修改validated和valid的值。保存之后我们再看反编译之后的refValid方法如下:


RefProject修改

修改notifyLicenseInvalid方法,原来方法如下:


修改这个方法的思路和修改JavaService一样,将代码逻辑删除即可,最后的方法如下:


ActivationDriver修改

修改activate方法,原来方法如下:


这段代码的修改可能会比较复杂,我直接参考了网上别人的思路。我们需要删去原来代码中通过http请求校验license的逻辑,并且返回一个自己mock的ActivationResult对象。我们观察原来的字节码:

aload_0
invokestatic org/apache/commons/lang/StringUtils/isBlank(Ljava/lang/String;)Z
ifeq 7
ldc "License key invalid"
invokestatic com/seventh7/mybatis/ref/license/ActivationResult/fail(Ljava/lang/String;)Lcom/seventh7/mybatis/ref/license/ActivationResult;
areturn
invokestatic com/intellij/openapi/util/Ref/create()Lcom/intellij/openapi/util/Ref;
astore_1
new com/seventh7/mybatis/ref/license/ActivationDriver$1
dup
aload_1
invokespecial com/seventh7/mybatis/ref/license/ActivationDriver$1/<init>(Lcom/intellij/openapi/util/Ref;)V
astore_2
invokestatic com/seventh7/mybatis/util/JavaUtils$SystemData/getInstance()Lcom/seventh7/mybatis/util/JavaUtils$SystemData;
astore_3
invokestatic com/seventh7/mybatis/ref/http/HttpPostBuilder/builder()Lcom/seventh7/mybatis/ref/http/HttpPostBuilder;
ldc "https://www.codesmagic.com/activate"
invokevirtual com/seventh7/mybatis/ref/http/HttpPostBuilder/url(Ljava/lang/String;)Lcom/seventh7/mybatis/ref/http/HttpPostBuilder;
ldc "no"
aload_0
invokevirtual com/seventh7/mybatis/ref/http/HttpPostBuilder/param(Ljava/lang/String;Ljava/lang/String;)Lcom/seventh7/mybatis/ref/http/HttpPostBuilder;
ldc "md5"
aload_3
invokevirtual com/seventh7/mybatis/util/JavaUtils$SystemData/getMacAddress()Ljava/lang/String;
invokevirtual com/seventh7/mybatis/ref/http/HttpPostBuilder/param(Ljava/lang/String;Ljava/lang/String;)Lcom/seventh7/mybatis/ref/http/HttpPostBuilder;
invokevirtual com/seventh7/mybatis/ref/http/HttpPostBuilder/build()Lorg/apache/http/client/methods/HttpPost;
astore 4
ldc2_w 1000
new com/seventh7/mybatis/ref/http/RetryFixedTimes
dup
iconst_3
invokespecial com/seventh7/mybatis/ref/http/RetryFixedTimes/<init>(I)V
invokestatic com/seventh7/mybatis/ref/http/HttpExecutorFactory/newRetryExecutor(JLcom/seventh7/mybatis/ref/http/RetryStrategy;)Lcom/seventh7/mybatis/ref/http/RetryHttpExecutor;
aload 4
aload_2
invokevirtual com/seventh7/mybatis/ref/http/RetryHttpExecutor/execute(Lorg/apache/http/client/methods/HttpUriRequest;Lcom/seventh7/mybatis/ref/http/HttpHandler;)V
aload_1
invokevirtual com/intellij/openapi/util/Ref/get()Ljava/lang/Object;
checkcast com/seventh7/mybatis/ref/license/ActivationResult
areturn

从第9行开始,也就是HttpHandler<LicenseData> httpHandler = new HttpHandler(),到第37行,也就是return (ActivationResult)ref.get();,这中间的代码我们都需要删除。然后我们插入下面的字节码:

new com/seventh7/mybatis/ref/license/LicenseData
dup
ldc "123"
ldc "123"
invokespecial com/seventh7/mybatis/ref/license/LicenseData/<init>(Ljava/lang/String;Ljava/lang/String;)V
astore_2
aload_1
aload_2
invokestatic com/seventh7/mybatis/ref/license/ActivationResult/success(Lcom/seventh7/mybatis/ref/license/LicenseData;)Lcom/seventh7/mybatis/ref/license/ActivationResult;
invokevirtual com/intellij/openapi/util/Ref/set(Ljava/lang/Object;)V

其中第1行到第6行,翻译成java代码为:

LicenseData localLicenseData = new LicenseData("123", "123");

这里我们自己模拟了一个License对象,然后从第7行到第10行,翻译成java代码为:

localRef.set(ActivationResult.success(localLicenseData));

这里我们将License对象转换成ActivationResult,并且将其set至ref对象中。总的字节码如下:

aload_0
invokestatic org/apache/commons/lang/StringUtils/isBlank(Ljava/lang/String;)Z
ifeq 7
ldc "License key invalid"
invokestatic com/seventh7/mybatis/ref/license/ActivationResult/fail(Ljava/lang/String;)Lcom/seventh7/mybatis/ref/license/ActivationResult;
areturn
invokestatic com/intellij/openapi/util/Ref/create()Lcom/intellij/openapi/util/Ref;
astore_1
new com/seventh7/mybatis/ref/license/LicenseData
dup
ldc "123"
ldc "123"
invokespecial com/seventh7/mybatis/ref/license/LicenseData/<init>(Ljava/lang/String;Ljava/lang/String;)V
astore_2
aload_1
aload_2
invokestatic com/seventh7/mybatis/ref/license/ActivationResult/success(Lcom/seventh7/mybatis/ref/license/LicenseData;)Lcom/seventh7/mybatis/ref/license/ActivationResult;
invokevirtual com/intellij/openapi/util/Ref/set(Ljava/lang/Object;)V
aload_1
invokevirtual com/intellij/openapi/util/Ref/get()Ljava/lang/Object;
checkcast com/seventh7/mybatis/ref/license/ActivationResult
areturn

修改之后的activate方法如下所示:


最后

做完了以上操作,重启intellij,就可以看到插件已被成功破解啦~

参考资料

感谢以下资料对我的帮助:

  1. 从Java代码到字节码
  2. mybatis破解教程
  3. 他人提供的破解版jar包
信息安全