本篇文章主要是为了让更多人了解在这周的开源周报中提到的关于 apk 的加壳究竟是什么
加壳是什么
加壳,加壳的全称应该是可执行程序资源压缩,压缩后的程序可以直接运行。一般来说加壳的目的是为了阻止外部程序或软件对加壳程序本身的反汇编分析或者动态分析,以达到保护壳内原始程序以及软件不被外部程序破坏,保证原始程序正常运行。这种技术也常用来保护软件版权,防止软件被破解。但对于病毒,加壳可以绕过一些杀毒软件的扫描,从而实现它作为病毒的一些入侵或破坏的一些特性。
加壳的方式
其实是利用特殊的算法,对可执行文件里的资源进行压缩,这个压缩之后的文件可以独立运行,解压过程完全隐蔽,都在内存中完成。它们附加在原程序上通过加载器载入内存后,先于原始程序执行,得到控制权,执行过程中对原始程序进行解密、还原,完成后再把控制权交还给原始程序,执行原来的代码部分。这可以隐藏程序真正的入口点从而防止被破解。加上外壳后,原始程序代码在磁盘文件中一般是以加密后的形式存在的,只在执行时在内存中还原,这样就可以比较有效地防止破解者对程序文件的非法修改,同时也可以防止程序被静态反编译。
Apk 加壳原理
在 Android 中没有经过加密的 Apk 给人的感觉就是在裸奔,通过apktool , dex2jar , AndroidKill 等各式各样的反编译工具就可以轻松的获取其 smail 代码,程序被反编译以后,对于懂 smail 语法的逆向工程师来说就一览无余了。尽可能给自己的 Apk 多采取一些防护措施已经成为了一种必然。
Apk 加壳的步骤:
源 Apk:需要加壳的 Apk
加密的 Apk:源 Apk 经过加密算法加密后的 Apk
加壳程序 Apk:是有解密源 Apk 和动态加载启动源 Apk 的外壳
关于 Dex:
他是 Android 系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。当 java 程序编译成 class 后,还需要使用 dx 工具将所有的class 文件整合到一个 Dex 文件,目的是其中各个类能够共享数据,在一定程度上降低了冗余,同时也是文件结构更加紧凑。
文件结构:
Magic
Magic 数是为了方便虚拟机识别目标文件是否是合格的 Dex 文件,在 Dex文件中 magic 的值固定
checksum
文件校验码 ,使用 alder32 算法校验文件除去 maigc ,checksum 外余下的所有文件区域 ,用于检查文件错误
signature
使用 SHA-1 算法 hash 除去 magic ,checksum 和 signature 外余下的所有文件区域 ,用于唯一识别本文件 。
file_size
当前Dex 文件的大小 。
改动 Dex 文件实际上是改动它的头部,即记录整个 Dex 文件相关属性的部分。改动其文件效验码 checksum 才能让这个合并后的 Dex 文件是正确的,改动 file_size 来重新设定 Dex 文件的大小,最后在文件的末尾标注上加密后 Apk 的大小,这样在脱壳时就能得到正确的 Apk 了。
将 Dex 与加密算法加密后的 Apk 合并生成新的Dex 后需要修改新 Dex 文件的这三个值,为了方便从新 Dex 中获得加密的 Apk,我们需要知道加密的 Apk 的大小,为了方便以后获得,我们将其大小放置在新 Dex 的后面。新生成的 Dex 文件结构:
生成新 Dex 后,将加壳程序 Apk 的 Dex 文件替换,重新签名后加壳的Apk 即完成了。