前言
为了方便新手理解加壳,本篇文章打算从反编译入手,通过场景问答的形式来讲解加壳。
场景一
如果一个Android新手,想要查看一个APK的代码,他会怎么做?
搜索引擎走起:通过Google/Baidu,发现一堆"反编译APK"的文章。
这些文章基本思路:
1:解压缩APK包,获取Dex文件,通过dex2jar,转换成jar文件
2:上面获取到的jar文件,通过 JD-GUI进行查看
3:通过ApkTool反编译APK,获取到资源文件,再重新打包,签名
那么走一遍,尝试一下(新建APP,走一遍工具,得到如下图)
场景二
不想APK源码被查看,能怎么办?
整理下反编译代码链路:APK->DEX->JAR>JD-GUI查看
思路一:在APK->DEX这一步的时候,能不能让DEX文件获取不到?
尝试:把DEX文件干掉,重新签名->安装->安装失败(否定)
尝试:把DEX文件放到assets下,重新签名->安装->安装失败(否定)
结论:APK按照一定的格式才能被安装
发散思路:能不能把DEX文件藏起来,用其他的DEX文件代替?
尝试:新建工程B,把A的DEX文件放到assets下,再把B的DEX放到A中,重新签名->安装->安装成功
打开崩溃?A中类找不到?
解决:可以通过B的DEX,反射加载A中的DEX文件,这边先给出代码截图。
具体思路会在文章:<APK中类的查找与加载>中讲解)
那么走一遍,尝试一下
1:B工程新建Application,在onCreate里面通过反射加载assets里面的classes.dex文件(见上2张截图)
2:A工程先生成一个Release包,再提取classes.dex放到A工程assets里面
3:A工程在AndroidManifest.xml里面,添加B的Application
4:A工程打包,用B工程的classes.dex替换掉A的classes.dex,A重新打包,安装,正常加载
(见截图)
思路与结果:
APP启动时,先加载B的Application,在通过B的Application加载A的Dex文件,达到加壳的目的
这样可以让用户不能直接反编译源码,这就是最简单的加壳(具体代码:见Gitlab)
总结与拓展
上面虽然说明了最简单的加壳,但如果想实用的话,还有非常多的问题。
例如:
1:对壳DEX进行反编译,查看代码,还能找到真正的DEX,怎么处理?
2:怎么去加壳支付宝APK?
3:这只是最基本的代码加壳了,那资源能加壳吗?
4:上面只是在APK->DEX这一步做文章,那么能不能让DEX转换成JAR的时候失败?能不能让JAR文件不能被JD-GUI查看?
欢迎查看加壳系列文章
1:自动加壳工具
2:加壳后APP启动优化
3:加壳二代之壳加解密
4:dex2jar原理与破坏
5:加壳之SO库加壳
6:加壳三代之指令抽离
7:加壳四代之指令转换
相关文章
1:APK中类的查找与加载
2:最简单的插件
3:最简单的热更新
4:Tinker原理讲解一
5:Tinker原理讲解二
6:Tinker原理讲解三