《逆向专题》对于apk 的认识

这里简单介绍一下我认识的apk。对于apk 的理解其实也是逆向的基础内容,对于apk的理解和熟悉程度能直接影响我们对逆向过程的理解,也能给我们逆向过程提供更开阔是思路。

主要包括三个内容:

一、apk的包结构

二、apk的打包过程

三、apk的安装过程

四、apk加载/(启动运行)过程

先来看看apk的包结构:

其实我们的apk 也好,jar 也好,其实都是可以看做是一个zip压缩包的。不信的可以自己使用zip工具浏览下压缩包结构。

我们这里随便找一款apk,然后解压开。就可以看到类似以下的结构:

其中各个文件夹存放的内容如下:

assets                  资源文件(图片、音频、数据库、网页、配置文件等)

res                       资源文件,需要编译(布局layout),还有一些drawable, menu,之类的文件

libs                      存放一些第三方的jar包,这个跟一般的java代码类似

META-INF           

存放文件摘要,摘要加密和签名证书等,可以看到对apk中所有的资源都进行了一次hash运算,为了防止apk的文件被修改,如果其中的文件别修改就能被检测出来,很多apk都会做这个校验,以保证apk的安全

META-INF/CERT.RSA    公钥以及加密算法的描述

META-INF/CERT.SF      

加密文件,它是使用私钥对摘要明文加密后得到的密文信息,只有只用私钥匹配的公钥才能正确解开密文

META-INF/MANIFEST.MF

 程序清单文件,包含包中所有文件的摘要明文

resources.arsc  资源文件,经过aapt工具加密的(语言包)

AndroidManifest.xml 清单文件(图标、界面、权限、入口)

classes.dex         

源代码,这是dalvik虚拟机运行的,其实其实就是smali代码。我们可以用一些工具将它转为jar,java之类的。也就是我们的源码。很多大的apk,我们解压之后可能会看到好几个dex文件,这是因为我们每一个dex的文件大小都是有限制的。其实在真正运行的时候,是需要将这些dex都整合起来的。而且一般情况下,这些dex是不会重复的。

lib                        各种平台下使用的对应的so文件,继续打开可以看到:

其实不同的apk可能还会有更多别的文件夹。这就意味着这个apk支持更多的CPU平台。对于我们的语言,最底层是机器码,然后是汇编代码,C语言这样的高级语言。但是对于汇编和机器码来说,这些代码是需要具体机器支持的。即是不同的cpu有自己的一套汇编指令,所以我们如果要兼容不同的cpu,就需要程序提供不同机器上运行的汇编代码。这里的每一个文件夹就是对一个cpu平台做兼容。

这里的armeabi 就是存放支持第5代、第6代的ARM处理器二进制接口(arm是arm指令集的意思,eabi其实是 Embedded Application Binary Interface 的缩写,也就是嵌入式应用二进制接口),早期的手机用的比较多。armeabi-v7a 存放的就是第7代及以上的 ARM 处理器支持。2011年15月以后的生产的大部分Android设备都使用它。当然我们可能会遇到更多的其他cpu架构,比如:

arm64-v8a: 第8代、64位ARM处理器,很少设备,三星 Galaxy S6是其中之一。

x86: 平板、模拟器用得比较多。

x86_64: 64位的平板。

其实这里面的代码可能有兼容的。比如armeabi-v7a其实就是对armeabi的扩展,所以也是兼容armeabi的,也就是说你将v7a 下的so文件移动到 armeabi 下,一般也是没有问题的。但是这里有一点需要注意的,涉及到我们的动态调试。就是我们需要注意下自己的调试机子上的cpu 架构,才能正确找得到自己真实运行的so文件。不然很可能遇到自己机子上真正运行的so平台,跟实际上静态分析上的so不同的情况。

另外我们提一下,在android 2.2到android4.4发布的一段很长的时间里,arm平台只支持armeabi 和 armeabiv7-a两种架构。查看android4.0后的源码可以从设备驱动和上层开发规范中知道,其实这时候android已经可以支持64位架构的arm处理器了,但是那时候无论是dalvik虚拟机还是ART虚拟机都只支持32位的代码。

这种情况一直到android 5.0,ART虚拟机代替了dalvik虚拟机,支持64位程序的运行,ndk也正式加入了arm64-v8a指令集的支持,这套指令集对应的就是ARMv8-A处理器架构。

 

接下来是介绍下apk 的打包过程,大致的流程图如下:

 

根据上图大致可以分为几个步骤

1、打包资源文件。

使用aapt来打包res资源文件,包括assert 、res、AndroidManifest.xml等文件。最后生成R.java和resources.arsc 文件

2、处理AIDL文件

这个不一定有,但是如果app中涉及到跨进程通信的话大多会出现,我们需要将AIDL文件转为java文件。

3、编译生成.class 代码。

项目中的java源码,aidl转化的java代码等全部编译成.class

4、将所有的.class 转为dex文件

android中并不直接执行.class。而是使用的dalvik虚拟机,所以需要将clasa转为dex。这里的class除了有我们的源码,也可能来自于第三方提供的jar。我们需要将所有的.class 都打包成dex。这里需要注意下dex的大小是有限制的,所以可能生成多个dex。

5、打包生成apk文件

通过apkbuilder工具,将aapt生成的resources.arsc和res文件、assets文件和classes.dex一起打包生成apk。打包的工具apkbuilder位于 android-sdk/tools目录下。

6、对apk文件进行签名

只有经过签名的apk才允许被安装,我们开发中能用debug版本安装其实也是开发环境帮我们用自带的debug签名了我们的apk。

7、对签名后的APK文件进行对齐处理

通过zipalign工具,将签名后的apk进行对齐处理。工具位于android-sdk/tools目录下。对齐的主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用就是减少运行时内存的使用。

 

经过这样的步骤,一个apk 就大致诞生了。

 

apk生成之后就到apk的安装了,我们来看看一个apk是如何被安装上的。

码字有点累了,今天到这吧。后面再找时间继续下面的内容。

 

 

 

发布了24 篇原创文章 · 获赞 10 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/lin___/article/details/103437536
今日推荐