個人博客
Android應用加固的簡單實現方案(二)
前言
上一篇文章介紹了基於dex加固方案的兩種具體實現。相對於手動加固,基於gradle實現的加固方案效率有了進一步提升。但是,還是需要在殼Module中增加util相關工具類的引用,為進一步減少代碼侵入性,在前面方案的基礎上,進一步完善插件的功能。
實現原理
為了避免在殼Module中引入脫殼相關的工具類,可以在aar生成后,利用ASM生成需要的class文件,然后修改aar中的classes.jar文件,將我們生成的class文件加入到classes.jar中。而殼Module的啟動Application也需要在編譯后修改attachBaseContext方法,加入脫殼代碼的引用。這塊都可以通過修改class中的方法來實現。而脫殼后,實質上還是運行apk中的代碼,因此,apk中也需要對應修改以上兩處。
基於以上思路,實現可以加固的一個簡單插件。
源碼地址:https://github.com/milovetingting/Shell
使用步驟
- 新建項目,再新建一個Android Library類型的Module作為殼Module,名稱隨意,以"shell"為例,在殼Module中新建繼承自Application的類,以"ShellApplication"為例,在ShellApplication中重寫attachBaseContext方法,這個方法需要調用super.attachBaseContext(base)方法:
public class ShellApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
}
}
-
主Module需要依賴剛才新建的殼Module,並指定主Module的啟動Application為剛才新建的ShellApplication。
-
項目根目錄下的build.gradle中引入插件:
buildscript {
dependencies {
//...
classpath 'com.wangyz.plugins:ShellPlugin:1.0.0'
//...
}
}
- app模塊下的build.gradle引入插件及配置插件
apply plugin: 'com.wangyz.plugins.ShellPlugin'
//主要注意shellModuleName和shellApplication的配置
shellConfig {
//殼Module的名稱
shellModuleName = 'shell'
//殼Module中Application的全類名
shellApplication = 'com.wangyz.shell.ShellApplication'
keyStore = 'E:\\Code\\Android\\android.keystore'
keyStorePassword = 'android'
keyPassword = 'android'
alias = 'android'
}
-
sync工程
-
在打包apk前,先執行Build-Clean Project,然后雙擊gradle面板的app/Tasks/build/assembleRelease,就會在項目根目錄/殼Module名稱-release/outputs/下生成signed.apk,這個apk就是加固過的apk.
注意事項
-
這里只是演示加固的思路,對於加密部分,只是用了簡單的^操作,具體可以自己換成AES,RSA或者其它加密方式。
-
插件會用到dx,gralde的命令,因此需要配置這兩個的路徑
-
插件會用到ASM,在編譯出class后修改class。在生成apk后,沒有修改過代碼或者沒有執行sync的操作后,transform的回調不會走,因此也不會執行修改class的邏輯,因此在每次生成加固apk前,需要執行clean項目的操作。
-
引入插件后的配置文件一定不能錯,重點關注shellModuleName和shellApplication,否則會導致生成的apk無法正常使用。