利用动态加载技术实现APK安全加固

原理分析见《利用动态加载技术加固APK原理解析》

源代码地址:https://github.com/mars-ma/ApkSecure/

bin目录下是直接可用的工具,注意readme.txt的说明,需要配置好java运行环境。

config.xml注意这里需要安装WinRAR对APK压缩,需要给出安装好的WinRAR的路径。签名和密码的配置也在这里。

dex/apksecure下是壳dex的源码

java_tool/ApkSecure下是java工具类的源码

加固技术实现(基础)

Java加壳工具的实现

实现Java加壳程序需要壳Classes.dex,以及相关so库。Java加固工具的工作流程如下:

反编译原APK,将AndroidManifest.xml中的Application Name改为壳中的Application Name。

标签下增加,存入原Application Name,以便在解壳后恢复原始Application。

将反编译的APK再次编译得到新的Apk。

将新的Apk解压,将原Classes.dex(可能是多个)拷贝到assets下,并用加密算法加密为新的文件,再用zip压缩。

用壳classes.dex替换新APK中的classes.dex。

将解压的新的Apk用压缩工具压缩成zip,更改后缀名为.apk,用jarsigner签名。

壳DEX的实现

壳dex负责逆向解密出dex,上述加固思路已经详细说明,通过构造DexClassLoader,并用反射技术替换调默认的ClassLoader。执行流程如下:

将assets下加密的.dex文件拷贝至自己的数据目录,先用java.util.zip解压文件并用解密算法解密出原.dex文件。

以解密出的原.dex为路径,构造DexClassLoader,并用反射技术替换调默认的PathClassLoader。

将ActivityThread中ApplicantsInfo的Class Name替换为存在下中的应用名,并用新的ClassLoader加载原Application替换调现有Application,最后执行原Application对象的onCreate函数。

最初版本遇到的问题:

壳dex中不能包含和原dex相同的全限定类名

java.util.zip压缩的apk无法被系统识别资源,后续使用了zip4j可以正常工作。

JNI反射内部类的签名格式是"a/b/C$D"

压缩后apk明显大于原始apk,因为增加了解密用的so文件。

Android4.4及以下使用HashMap类,以上使用ArrayMap类,反射时要适配不同的API版本。


2017.5.19 

支持multidex,但是未做ART虚拟机下DexClassLoader加载.dex时跳过编译.oat的优化,对于使用ART虚拟机,且体积较大的dex存在加载缓慢的问题。

待优化:

绕过ART虚拟机编译OAT文件

防止so的动态调试

防止dump dex

你可能感兴趣的:(利用动态加载技术实现APK安全加固)