【0-1】从0.1开始学Android逆向-APK基本结构概要分析
概要
最近在进行Android的逆向,在这里整理知识点和分享Android逆向知识。如果文章中有任何勘误,诚挚的邀请师傅们批评改正!
0.什么是逆向?
逆向工程(Reverse Engineering)是一种分析和解剖已有产品、系统或软件的过程,以了解其内部工作原理、设计、功能或源代码。逆向工程可以应用于多个领域,包括软件开发、硬件设计、网络安全和犯罪侦查等。Android逆向就是对apk进行逆向咯,其中会包括多方面的知识涉及到密码学、算法分析、网络协议等知识。但是并不是说没有这些“前置”知识就无法学习Android逆向。我觉得学习是一个在湖面上搭桥的过程,要么一步一步搭出来一个稳定的桥——向前拓展、加固后方,或者是用大量的木头填满这里 哈哈哈。说白了就是不必担心,车到山前必有路。
1.什么是apk文件?
在这里只对apk进行最基础的介绍,了解apk文件基础知识。
apk本质上是一个具有特殊文件夹结构的zip压缩包,其中包括——静态资源文件(assets
)、库文件(lib
)、签名文件(META-INF
)、编译资源文件(res
)、配置清单文件(AndroidManifest.xml
)、核心代码文件(classes.dex
)和资源映射文件(resources.arsc
)等信息,如下图某个apk应用的结构。
核心逻辑【classes.dex】
当我们进行逆向时,分析内容一般是 apk 的核心逻辑,所以我们常常读取的内容为 classes.dex 文件。这里我们随便拿一个 jar 来进行分析[https://www.nssctf.cn/problem/2878] 首先将 .apk 文件解压,如下图。
然后我们使用 dex2jar 工具将 classes.dex 反编译为 .jar 文件,并将其解压如下图。
.jar 文件和 .apk 文件都是类似的,是一个压缩文件,可以用解压软件解压或预览,其中的文件夹逻辑如下。
在这个 .jar 文件夹中,所有存在的文件均为 .class 文件,保存了 apk的 代码逻辑。MainActivity
文件在ilililil
文件夹中,推测其为 apk 的主逻辑。那么到现在我们大概了解了 Android 逆向分析的重点——对 dex 文件进行分析,找出其中的主要函数逻辑。注意,在这里,我们只是通过逆向方式展示说明文件的结构信息,并不是在介绍逆向分析的方法。
当然了,如果你在这里感到麻烦和害怕,那就多余了!众所周知,程序员都是懒比,其实已经有了很多可以自动实现上述步骤的程序。jadx-gui、AndroidKiller、jeb等等,各有各的优点和特色。
静态资源文件【assest】
静态资源文件主要指存放在 assets 文件夹中的文件。 assets 文件夹是一种未经编译的资源目录,它会被打包进 APK 文件中,在安装应用程序之后可以被访问。 assets 文件夹中的文件不会被解压缩,这意味着它们的访问速度会比较快,但是会占用更多的安装包空间。通常情况下,开发者会将应用程序中的静态文件、配置文件、原始数据或者其他不常改变的文件放在 assets 文件夹中。这样可以使得应用程序的下载包大小变小,并且可以更快速地访问这些文件。
编译资源文件【res】
编译资源文件主要指存放在 res 文件夹中的文件。 res 文件夹存放的也是资源文件,与 assets 文件夹不同的是,这里是编译后的资源文件。直接打开可能显示乱码。在 res 文件夹中你会找到许多子文件夹,每个子文件夹都用来存放特定类型的资源文件,res文件夹示例见图6。主要的文件夹包括 drawable 文件夹、 layout 文件夹和 values 文件夹。
drawable
文件夹用来存放图片资源文件,包括位图文件(.png, .jpg, .gif 等)和矢量图文件(.svg)。
layout
文件夹用来存放布局文件,布局文件用来描述应用程序的界面结构。
values
文件夹用来存放值资源文件,值资源文件用来存放应用程序中使用的常量值和颜色信息。
在 Android 系统中,所有的资源文件都必须在 res 文件夹中存放,并且需要使用特定的文件名和文件夹名。这样的好处是, Android 系统会自动为每个资源文件分配一个唯一的资源 ID ,使得安卓系统可以方便地引用这些资源。
库文件【lib】
在安卓系统中库文件分文两种,一种是共享库文件(Shared Libraries
),另一种是本地库文件(Native Libraries
)。共享库文件是可供多个应用程序使用的库,它们被存放在系统目录中。在 Android 系统中,共享库文件以 .so 为后缀,常见的共享库文件包括 libc.so
和 libm.so
是不是有Linux那个味道hhhh。
lib用来存储应用独立使用的静态库。下图中,lib文件夹下有三个文件夹,包括armeabi、armeabi-v7a和x86文件夹,分别用来存储适配arm5架构、arm7架构、Intel32架构的CPU处理器版本的安卓系统。在这个例子中,目录下均有libJNIEncrypt.so
文件,这个文件是可以被IDA打开并分析的,其中可能含有多个自定义的函数。程序开发者可以利用静态库实现加解密等操作。
配置清单文件【AndroidManifest.xml】
AndroidManifest.xml文件是配置清单文件,也是编译过的文件,用来描述应用程序的清单信息。包括包名、应用名、权限、安卓四大组件、版本等重要信息都在这里面声名。
当打包应用程序时,AndroidManifest.xml
文件会自动生成,并且会被打包进 APK 文件中。当你安装应用程序时,Android 系统会读取这个文件,以确定应用程序的基本信息和权限要求,文件反编译后如下图。
开发者可以在 AndroidManifest.xml
文件中声明应用程序使用的权限,例如访问网络、访问文件、访问相机等。在应用程序安装时,用户会看到这些权限的描述信息,然后决定是否允许应用程序使用这些权限。
AndroidManifest.xml
文件还用来声明应用程序的主要组件,例如活动(Activity
)、服务(Service
)、广播接收器(BroadcastReceiver
)等。这些组件是安卓应用程序的四大组件的组成部分,它们负责实现应用程序的功能。
资源映射文件【resources.arsc】
它用来存放应用程序的资源表。资源表是一种二进制文件,它包含了应用程序的资源 ID 和资源类型的映射关系。
它存储了资源的 ID。在打包过程中,但凡使用到资源的地方都是使用这个 ID 来代替的。ARSC 文件就是一个资源索引表,它可以帮助系统根据资源 ID 快速找到资源。
签名文件【META-INF】
在这里我们可以了解签名过程:
第一步,遍历应用中的文件并计算文件对应的摘要,将所有的文件摘要进行 Base64 编码后写入签名文件即MANIFEST.MF
文件,文件示例内容下图所示,我们也可以看到刚刚分析的classes.dex
文件:
第二步——对MANIFEST.MF
整个文件做一次摘要和Base64编码,存放到CERT.SF
文件的头属性中。再对MANIFEST.MF
文件中各个属性块做摘要和Base64编码,存到到一个属性块中。
第三步——对CERT.SF
文件做签名,内容存档到CERT.RSA
中。
大概保护长成这样:SF可以保证MANIFEST.MF
不受篡改,MANIFEST.MF
检测文件不受篡改,当然了,你可以把它的东东全部删掉然后重新签名 😛,不过检测签名是否被修改就是别的事情了,在这里不过多赘述。JAR 已签名的 APK 的验证(v1 方案)
JAR 已签名的 APK 是一种标准的已签名 JAR,其中包含的条目必须与 META-INF/MANIFEST.MF 中列出的条目完全相同,并且所有条目都必须已由同一组签名者签名。其完整性按照以下方式进行验证:
官方描述如下:
APK 签名方案 v2
参考链接
Android 系统架构详解——文江博客
安卓反编译(一):反编译概述——战神波波
APK的基本结构——白泽图鉴
Android 逆向笔记 —— ARSC 文件格式解析——路遥
Android 签名——dboy_sl