基于APK文件格式的反编译对抗机制
基于APK文件格式的反编译对抗机制商业APP为了防止反编译、被篡改,往往会采用第三方的APP加固方案,通过对源代码的混淆、加固、加壳等技术手段,隐藏源APP的逻辑结构,大大提高了反编译的难度,达到保障APP的安全与稳定运行的目的。而网赌、电诈、色情等涉网犯罪APP,基于成本考虑,其幕后的开发者往往不会采用第三方加固方案,但有可能会采用一些无成本的对抗机制,基于APK文件格式的反编译对抗就是其中的一种。该对抗机制主要利用了反编译工具的一些缺陷,导致APK反编译失败(图1)。
图 1 APK反编译失败笔者研究发现,目前涉网犯罪APP主要利用了两种对抗机制,其一是修改APK文件,其二是修改AndroidManifest文件(AndroidManifest.xml)。两种对抗机制的原理本质上是一样的,都是修改对应二进制文件的一些特征数据,以达到“欺骗”反编译工具的目的,但是Android系统的包安装服务不会检测这些特征数据,因而又不影响APK的正常安装和运行。
一、基于ZIP文件格式的反编译对抗1、ZIP文件格式编译后生成的APK文件本质上就是一个ZIP压缩包,可以直接通过解压缩工具打开和解压。一个典型的ZIP文件的二进制数据由三部分组成:数据区、目录区、目录结束标记区。笔者新建一个txt文本文件(demo.txt),写入内容“this isdemo file”,保存后,压缩成一个ZIP文件(demo.zip),然后用十六进制编辑器010 Editor打开。如下图所示,该ZIP文件的二进制内容已被010 Editor识别并按颜色划分为三个不同的区域(黑色区域和灰色区域同属数据区,只是为了突出文件内容):
图2 ZIP文件二进制内容组成数据区数据区记录了所有被压缩文件的内容信息,每个被压缩的文件由文件头、文件内容和文件描述三部分组成。其中,文件头和文件内容必然存在,文件描述则不一定存在。表 1 文件头
[="]偏移字节描述
04文件头标识,值固定(0x04034b50)
42解压文件所需 pkware最低 版本
62通用位标记(最低位奇数代表加密,偶数代表未加密)
82压缩方法
102文件最后修改时间(MS-DOS时间)
122文件最后修改日期(MS-DOS日期)
144CRC-32校验码
184压缩后的大小
224未压缩的大小
262文件名长度
282扩展区长度(一般为 00 00)
30n文件名
30+nm扩展区(不一定存在)
文件头后则是文件内容,而文件描述只有当文件头的通用标记字段的第3位设为1时才会出现,一般在磁盘上存储的ZIP文件都没有文件描述。目录区目录区记录了压缩包里所有的子目录的描述信息。表 2 目录区数据结构
偏移字节描述
04目录文件头标识(固定值0x02014b50)
42压缩所用的pkware版本
62解压所需pkware最低版本
82通用位标记(最低位奇数代表加密,偶数代表未加密)
102压缩方法
122文件最后修改时间(MS-DOS时间)
142文件最后修改日期(MS-DOS日期)
162CRC-32校验码
204压缩后的大小
244未压缩的大小
282文件名长度
302扩展区长度
322文件注释长度
342文件开始位置的磁盘编号
362内部文件属性
384外部文件属性
424文件头的相对位移
46n目录文件名
46+nm扩展区
46+n+mk文件注释内容
目录结束标记区目录结束标记区用于标记压缩包目录数据的结束。表 3 目录结束标记区
偏移字节描述
04目录结束标记(固定值0x06054b50)
42当前磁盘编号
62目录区开始位置的磁盘编号
82当前磁盘上记录的目录数
102目录总数
124目录区大小
164目录区开始位置偏移
202注释长度
22n注释内容
2、典型对抗样例为了不影响APK的正常安装和运行,幕后开发者不可能修改APK文件(ZIP包)的任意内容,而只能修改某些不会被Android包安装服务检测的特征数据,包括通用标记字段的加密标记位、磁盘编号、目录总数等,修改的位置集中在APK文件的头部和尾部。通用标记字段修改通用标记字段后,解压APK会提示输入密码,而实际上APK肯定不可能存在密码,否则无法正常安装。破解方法就是将字段改成“00 00”即可(要注意,通用标记字段同时存在于数据区和目录区)。
图 3 通用标记字段被修改磁盘编号修改磁盘编号后,解压文件会提示“头部错误”,这个错误利用的是ZIP文件的“过时缺陷”。ZIP格式诞生于MS-DOS时代,当时由于数据主要存储于软件和光盘,受容量限制,ZIP文件可能需要分盘存储,因此ZIP文件中要记录磁盘编号,因此当前磁盘编号和目录区开始位置磁盘编号可能不一致。而现在ZIP文件都存储在磁盘中,容量足够,无须分盘存储,因此当前磁盘编号和目录区开始位置磁盘编号一致(一般为0)。破解方法就是将当前磁盘编号和目录区开始位置磁盘编号字段都修改成“00 00”。
图 4 磁盘编号被修改目录数目录数类似于磁盘编号,ZIP文件也记录了当前磁盘记录的目录数以及目录总数,修改该字段后也会导致解压APK文件失败。破解方法就是将当前磁盘记录的目录数以及目录总数保持一致,如下图所示把“7777”修改成“3F 0A”即可:
图5 目录数被修改二、基于AndroidManifest文件格式的反编译对抗1、AndroidManifest文件格式AndroidManifest文件(AndroidManifest.xml)是APK中的关键文件,记录了APP的包名、版本、权限信息、四大组件信息等信息。Android的包安装服务通过解析该文件才能正常的安装APK。AndroidManifest文件有文本和二进制两种形式。APP开发阶段,开发者通过文本形式的AndroidManifest文件明文配置APP的各项信息;APP打包后,各项信息则被编译工具编译成二进制数据存储于AndroidManifest二进制文件中。因此,未经反编译直接解压APK后,打开AndroidManifest文件,只能看到乱码。
AndroidManifest文件结构较复杂,一般可以借助看雪大神MindMac出品的AndroidManifest二进制文件结构图(图6)以及AndroidManifest模板(十六进制编辑器自带的010 Editor模板,图7)进行学习和研究:
图6 AndroidManifest二进制文件结构图
图7 010 Editor自带的 AndroidManifest模板2、典型对抗样例基于AndroidManifest文件格式的反编译对抗的原理和基于ZIP文件格式的反编译对抗原理是一样的,对AndroidManifest某些特征数据的修改可以“欺骗”反编译工具从而导致反编译失败,但Android的包安装服务对该类“欺骗”免疫而不会影响APP的正常安装。
幻数(MagicNumber)AndroidManifest文件的幻数(Magic Number),即文件头为0x00080003。将其修改后,反编译工具就无法识别AndroidManifest文件,导致反编译失败。破解方法就是修复幻数,如下图,即需将“0000 08 00”修改成“03 00 08 00”:
图 8 幻数被修改字符串个数字符串个数是另一种典型的对抗,不同于一眼就能看穿的对幻数的修改,对字符串个数的修改需要对整个字符串组块进行分析(主要分析字符串偏移区)。如下图所示,该APK实际包含的字符串个数为350个,但开发者明显修改了(分析红框区域的字符串编号和绿框区域的字符串编号异同以及蓝框区域的字符串编码)AndroidManifest文件中记录的字符串个数,从而会导致反编译失败,而破解的方法就是修复字符串个数:
图 9 字符串个数被修改综上所述,基于当前已获得的APK样本,笔者研究分析了基于APK文件格式的两种反编译对抗的原理以及其典型对抗样例,并总结了相应的破解方法。后续,笔者将持续跟踪此类反编译对抗机制,在已有成果上完善补充。
格式有点乱,建议用markdown写比较好一些,文章末尾好像还有2个图没有插入正文中。 BDUN 发表于 2022-3-28 14:09
大神 这是什么情况呢
我是小白,你这个有可能是目录区的标记损坏了。目录区的英文叫 Central Directory,标记是0x504b0102。用010 Edtior打开,运行下ZIP模板看看 https://attach.52pojie.cn/forum/202202/09/164120q9t25ttnu5bu5avs.png
大神 这是什么情况呢 点赞点赞{:1_921:} 大神真厉害 BDUN 发表于 2022-3-28 14:09
大神 这是什么情况呢
下载正版,去正规渠道下载 膜拜大佬 谢大佬分享,学习了 谢大佬分享,学习{:1_893:}