背景
Intellij上的mybatis插件是一個十分優(yōu)秀的插件涕刚,但是需要付費。在網(wǎng)上搜索一番之后乙帮,發(fā)現(xiàn)果然有破解版杜漠,遂來研究一番破解原理。
環(huán)境
- 操作系統(tǒng):mac os 10.11.6
- Intellij版本:2016.2
- mybatis插件版本:2.87
- 破解工具:
- JBE:java字節(jié)碼修改工具
- JD-GUI:java反編譯工具
工具介紹
JD-GUI
該工具的使用方式很簡單察净。具體界面如下:
JBE
jbe是基于jclasslib的字節(jié)碼修改工具驾茴,十分強大。假設(shè)我們要修改某個方法對應的字節(jié)碼氢卡,具體步驟如下圖所示:
- 首先點擊圖中數(shù)字1所指的icon锈至,選擇你要修改的class文件。
- 然后點擊Methods译秦,可以看到該class文件中的類所含有的方法列表峡捡。
- 點擊我們需要修改的方法,然后點擊code筑悴。
- 在右邊區(qū)域我們可以看到Code Editor们拙。點擊進入之后,我們就可以修改字節(jié)碼了阁吝。
- 修改完成之后點擊圖中數(shù)字6所指的save method保存字節(jié)碼砚婆,此時對應的class文件會同步更新。
破解步驟
思路
軟件破解的一般思路突勇,都是hack進校驗license的函數(shù)装盯,修改里面的校驗邏輯坷虑。有個小技巧可以幫助我們更快地定位校驗激活碼的函數(shù):我們可以全局地搜一下"license"、"activate"验夯、"key"以及"valid"等詞語猖吴,搜索出來的代碼一般都是跟處理激活碼有關(guān)的。
詳細步驟
- 首先安裝沒有破解的mybatis插件挥转,然后退出Intellij海蔽。在mac os下,插件位于
~/Library/Application\ Support/IntelliJIdea2016.2/mybatis_plus/lib
绑谣。主要的代碼位于mybatis_plus.jar中党窜。 - 我們通過JD-GUI打開mybatis_plus.jar,觀察代碼結(jié)構(gòu)借宵。通過觀察以及研究網(wǎng)上他人提供的破解版之后幌衣,我們發(fā)現(xiàn)一共需要修改以下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修改字節(jié)碼豁护,原來的字節(jié)碼如下:
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
我們將不需要的字節(jié)碼全部刪去,只留下return語句:
return
保存之后我們再看反編譯之后的stop方法如下:
我們可以看到欲间,原來的邏輯都被刪除了。
JavaUtils修改
修改refValid方法猎贴,原來的方法如下:
最直觀的做法是在方法的最后將valid和validated重置為true班缎,原來的字節(jié)碼較長她渴,只截取了return valid
的字節(jié)碼:
......
getstatic com/seventh7/mybatis/util/JavaUtils/valid Z
ireturn
所以我們需要在getstatic之前添加重置為true的字節(jié)碼:
......
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推入操作數(shù)棧达址,然后通過putstatic修改validated和valid的值沉唠。保存之后我們再看反編譯之后的refValid方法如下:
RefProject修改
修改notifyLicenseInvalid方法儡遮,原來方法如下:
修改這個方法的思路和修改JavaService一樣,將代碼邏輯刪除即可激率,最后的方法如下:
ActivationDriver修改
修改activate方法咆繁,原來方法如下:
這段代碼的修改可能會比較復雜慨仿,我直接參考了網(wǎng)上別人的思路牢硅。我們需要刪去原來代碼中通過http請求校驗license的邏輯减余,并且返回一個自己mock的ActivationResult對象。我們觀察原來的字節(jié)碼:
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();
涨薪,這中間的代碼我們都需要刪除。然后我們插入下面的字節(jié)碼:
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對象轉(zhuǎn)換成ActivationResult末捣,并且將其set至ref對象中侠姑。總的字節(jié)碼如下:
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莽红,就可以看到插件已被成功破解啦~
參考資料
感謝以下資料對我的幫助: