返回介绍

16.3 分析 apktool 的源码

发布于 2024-10-10 22:32:20 字数 4817 浏览 0 评论 0 收藏 0

上面说了为什么要分析 apktool 的源码,下面就真正开始分析。当然第一步是得到 apktool 的源码,地址为 https://code.google.com/p/android-apktool/ 。看到有 Google 的域名是不是很郁闷?的确,国内程序员一般打开时始终处于 loading 状态,直至报错,所以只能去万能的 GitHub 上搜索了,找到了地址 https://github.com/iBotPeaches/Apktool 。可以看到有很多人关注,而且代码是有人维护和更新的,所以下载到本地。

但是下载后发现是一个 Gradle 项目,所以就给 Eclipse 装一个 Gradle 插件,然后导入项目即可。但是又遇到一个问题,还是国内网络的问题,Gradle 下载失败,因为这里引用了一些第三方的 jar,如下所示:

那么,只能无奈地手动去一个一个找这些 jar 包,这个过程还是比较辛苦的,有些 jar 很难找,不过最后还是都找到了,不再有报错,项目结构如图 16-1 所示。

图 16-1 apktool 项目结构

Apktools 这个项目是入口,也是主要功能项目类,Baksmali 和 Smali、SmaliUtil 是操作 smali 的工具类,BrutCommon 和 BrutDir、BrutUtil 是一些辅助的工具类,代码简单,不做太多的解释。除了 Apktools 之外,其他项目都是功能库,它们之间的引用关系如下:

·Baksmali 依赖于 SmaliUtil。

·BrutDir 依赖于 BrutCommon、BrutUtil。

·BrutUtil 依赖于 BrutCommon。

·Smali 依赖于 SmaliUtil。

·Apktools 依赖于 Baksmali、BrutCommon、BrutDir、BrutUtil、Smali。

直接来看看主要功能 Apktools 项目。首先 Java 项目的入口方法肯定是 main 方法,搜一下找到这个 Main 类:

在方法中得到参数,然后进行参数的分析和组装。继续往下看执行代码:

这里看到了经常用的一些命令参数,它们的含义都了解了,ApkDecoder 类是反编译的核心类:

最终也是调用它的 decode 方法,如下所示:

可以看到使用了 Androlib 这个核心类来做了一些操作,首先判断是否需要解析 arsc 格式的资源文件,下面仔细解析 resource.arsc 和 AndroidManifest.xml 这两个文件:

这里解析了 dex 文件,得到 smali 源码,而且区分了多个 dex 的情况。可以发现,apktool 在整个反编译的过程中有三个核心点:解析 resource.arsc 文件、AndroidManifest.xml 文件、dex 文件。

关于这三个文件,在本书的前几章已经讲解过具体格式和解析方法,所以这里就不详细介绍了。

继续分析 Androidlib 这个核心解析类,就几个方法,下面来一一讲解。

1.解析原生文件

这个方法主要解析原生的文件,就是 Android 在编译 apk 的过程中不参与编译的文件目录,一般是 assets 和 libs:

2.解析配置文件

这个方法主要是解析 AndroidManifest.xml 文件格式的:

Android 在安装一个 apk 的时候,肯定也需要解析 AndroidManifest.xml 文件,而且 Android 中解析 XML 文件采用的是 Pull 解析法,所以这里直接把 Android 中的一些方法拷贝过来了,如图 16-2 所示。

然后再找一个 xmlPull 的解析 jar 包即可,如图 16-3 所示。

图 16-2 apktool 解析 AndroidManifest 功能类

图 16-3 apktool 项目引入的 jar 包

3.解析资源文件

这个方法是用来解析 resource.arsc 文件的,这个文件主要包含了所有资源文件的一种格式。Android 中资源文件都有相应的类型,以及唯一的一个整型 id 值,那么这个文件就包含这些内容,如下所示:

这个方法用到的解析类和 AndroidManifest.xml 的解析类是一样的,因为它们都属于 arsc 格式,而且资源文件也是 XML 格式。这里值得注意的是,会产生一个反编译中最关键的文件 public.xml,这个文件位于反编译之后的 res\values\public.xml 目录下:

可以看到,每个 id 字段都有对应的类型、名称和 id 值,而这里的 id 值是一个整型值,8 个字节,由 PackageId+TypeId+EntryId:三部分组成,如下所示:

·PackageId:包的 id 值,Android 中如果是第三方应用的话,这个值默认是 0x7F,系统应用的话是 0x01,具体可以看后面的 aapt 源码得知,占用两个字节。

·TypeId:资源的类型 id 值,一般 Android 中有以下几个类型:attr、drawable、layout、dimen、string、style 等,这些类型的值是从 1 开始逐渐递增的,顺序不能改变,attr=0x01,drawable=0x02……占用两个字节。

·EntryId:具体的类型下资源实体的 id 值,从 0 开始,依次递增,占用四个字节。

4.解析 dex 文件

这个方法主要是将 dex 文件解析成 smali 源码:

这里使用了 SmaliDecoder 的 decode 方法,如下所示:

这里需要借助一个工具包 dexlib,它用来处理 dex 文件,处理完 dex 文件之后,再交给 baksmali 工具类生成 smali 文件即可。

源码分析完了,下面开始测试一下。这里为了运行简单,在入口的 main 方法中手动构造一个参数:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文