作者

大家好,我叫小嘉;

自己20年毕业于广东工业大学,于2020年6月参加37手游安卓团队;

现在主要负责国内游戏发行安卓相关开发。

布景

最近在接触游戏包生成渠道包相关事务,其间涉及到一个安卓相关知识点《安卓Apk的反编译》,自己以为除了忙于日常事务外,还需求花点时间沉淀技能点(如:写写博客),协助自己成长;

尽管现在自己初入职场许多不懂,但是相信一点点的积累到了后面会很有协助。

最后希望这篇文章也能够对刚进职场和游戏发行行业的安卓同学有学习作用,一起沟通,共同进步。

APK内容

apk 实际上是一个zip 文件,打开后的内容如下图所示:

安卓游戏发行-应届生安卓反编译初探

【META-INF】

寄存的是签名信息,用来保证apk包的完整性和体系的安全。里边包含了三个文件,MANIFEST.MF、CERT.SF、CERT.RSA

1)MANIFEST.MF:列出了apk的所有文件,以及这些文件内容所对应的base64-encoded SHA1 哈希值,具体如下:

Name: classes.dex
SHA1-Digest: l8Lc+gtdLvtxJ1K+kscUmWQGQ1E=

2)CERT.SF:列出了MANIFEST.MF这个文件中每条信息的hash值,具体如下:

Name: classes.dex
SHA1-Digest: ubmMiUS24rU/6K5JloMVG4vHKIU=

上面这条hash值ubmMiUS24rU/6K5JloMVG4vHKIU=对应的是MANIFEST.MF中下面这几行字符串的hash值

Name: classes.dex
SHA1-Digest: l8Lc+gtdLvtxJ1K+kscUmWQGQ1E=

3)CERT.RSA:包含了公钥和私钥签名后的一些信息

【res目录】

这个目录主要是寄存资源的

1)animator:用于界说特点动画的 XML 文件

2)anim:界说突变动画的 XML 文件。(特点动画也能够保存在此目录中,但是为了区别这两种类型,特点动画首选 animator/ 目录。)

3)color:用于界说颜色状况列表的 XML 文件。请参阅颜色状况列表资源 4)drawable:位图文件(.png、.9.png、.jpg、.gif)或编译为以下可制作目标资源子类型的 XML

5)mipmap:适用于不同启动器图标密度的可制作目标文件。

6)layout:用于界说用户界面布局的 XML 文件

7)menu:用于界说使用菜单(如选项菜单、上下文菜单或子菜单)的 XML 文件

8)raw:要以原始方式保存的任意文件

APK反编译后的内容 apktool 反编译apk 后的内容如下:

1)assets: 一些媒体相关资源,aapt 打包时没有进行紧缩,也没有资源ID值。

2)META-INF:apk 包相关签名文件。

3)lib: so 文件相关。

4)res: apk 所会用到的一些资源文件。aapt 东西将 xml 文件进行紧缩,节约空间,所以都是 二进制文件。

5)class_xxx.dex 文件:dalvik 虚拟机的可执行文件(java->class->dex)。

6)AndroidManifest.xml:清单文件,aapt 东西也将其紧缩成了二进制文件。

7)resources.arsc:Resources 是经过 resources.arsc 把Resource的ID转化成资源文件的名称,然后交由AssetManager来加载的。而Resources.arsc这个文件是寄存在APK包中的,他是由AAPT东西在打包进程中生成的,他自身是一个资源的索引表,里边维护者资源ID、Name、Path或许Value的对应关系,AssetManager经过这个索引表,就能够经过资源的ID找到这个资源对应的文件或许数据。将一个 apk 拖进 AS 之后,显现resources.arsc 内容如下:

安卓游戏发行-应届生安卓反编译初探

8)其余文件夹:apk 会用到,但不是公共结构。

APK反编译相关流程

apktool 反编译针对不同的文件夹进行了不同的处理。下面是decode 的大致流程(描绘的是一般大致流程):

安卓游戏发行-应届生安卓反编译初探

下面将按图中标红步骤,依据apktool源码来进行解说:

1)程序主要类进口:

安卓游戏发行-应届生安卓反编译初探

开端反编译前会有一些参数的设置,如:d 代表反编译/ b 代表回编译等

2)解析resource.arsc:

调用次序:setTargetSdkVersion-》getResTable-》loadMainPkg-》getResPackagesFromApk-》,最终是调用到 apktool 的 ARSCDecoder 来进行解析,并将 resources.arsc 存储在 mResTable 中。

安卓游戏发行-应届生安卓反编译初探

安卓游戏发行-应届生安卓反编译初探

3)解码 AndroidManifest.xml 文件:

调用次序:decodeManifestWithResources –》decodeManifest –》decode

解码文件的同时此处会保存该 APK 的一些信息,比方:package,versionCode,versionName,minSdkVersion,targetSdkVersion。

安卓游戏发行-应届生安卓反编译初探

安卓游戏发行-应届生安卓反编译初探

4)解码 res 文件夹:

调用次序:decodeResourcesFull –》decode — 》 fileDecoder.decode –》不同文件格局的 decode关于不同的文件格局:1 raw 文件,直接仿制 2 .xml 文件,需求进行解码 3 .9patch ,需求进行解码。4 其余文件格局,直接仿制。

安卓游戏发行-应届生安卓反编译初探
安卓游戏发行-应届生安卓反编译初探

5)生成 values 文件夹:

values 文件夹内容:

安卓游戏发行-应届生安卓反编译初探

其间,这些文件内容是依据 resources.arsc 内容来进行生成。

调用次序:pkg.listValuesFiles — 》mResSpecs.values() –》ARSCDecoder.readEntry() –》mPkg.addResSpec(spec)

关于不同类型的 xml 文件,生成方法也不一样。

调用次序:AndrolibResources.generateValuesFile –》AndrolibResources. serializeToResValuesXml

安卓游戏发行-应届生安卓反编译初探

安卓游戏发行-应届生安卓反编译初探

public.xml 内容:

安卓游戏发行-应届生安卓反编译初探

public.xml 是为了固定 id,由于apktool 在编译资源的时分会对资源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开端,依次递加,他占用四个字节。

6)生成 smali 文件夹:

这儿需求借助一个东西包dexlib,他是用来处理dex文件的,处理完dex文件之后,在交给baksmali这个东西类生成smali文件即可。

安卓游戏发行-应届生安卓反编译初探

安卓游戏发行-应届生安卓反编译初探

7)生成 libs,lib,assets 文件夹:

关于这类文件直接进行仿制,不需求对这些资源进行改动

安卓游戏发行-应届生安卓反编译初探

8)生成 unknown 文件夹

不知道文件指非apk固定文件的内容:”classes.dex”, “AndroidManifest.xml”, “resources.arsc”, “res”, “r”, “R”, “lib”, “libs”, “assets”, “META-INF”, “kotlin”

此处会对不知道格局文件放在 unknown 文件夹下,并记载文件途径。

安卓游戏发行-应届生安卓反编译初探

9)生成Original 文件夹:

将 AndroidManifest.xml 和 META-INF 放在该目录下。

安卓游戏发行-应届生安卓反编译初探

10)记载不紧缩文件

记载不紧缩的文件,读取文件紧缩等级,当文件紧缩等级为不紧缩或许文件契合下列类型时,不进行紧缩。

安卓游戏发行-应届生安卓反编译初探

11)生成 apktool.yml 文件

apktool.yml 文件内容如下:

安卓游戏发行-应届生安卓反编译初探

1.putUsesFramework(meta); 记载使用的framework —- usesFramework装备项

2.putSdkInfo(meta); 记载sdkversion信息。 —- sdkInfo装备项

3.putPackageInfo(meta);记载packageInfo。 —- packageInfo装备项

4.putVersionInfo(meta); 记载包体versioncode,versionname —- versionInfo装备项

5.putSharedLibraryInfo(meta);记载是否是一个库。 —- sharedLibrary装备项

6.putSparseResourcesInfo(meta); 这个暂时没去了解。—- sparseResources装备

7.putUnknownInfo(meta); 记载不知道文件。 —- unknownFiles装备项

8.putFileCompressionInfo(meta);记载文件紧缩信息。 —- doNotCompress装备项

结束语

进程中有问题或许需求沟通的同学,能够扫描二维码加好友,然后进群进行问题和技能的沟通等;