中文站

一文读懂Android资源文件保护

一、前言

随着Android应用被破解和被盗版的案例越来越多,程序安全逐渐引起用户的重视。

在激烈的攻防过程中,安全保护手段不仅限于代码,还有资源文件。这是由于资源文件会暴露出大量敏感信息和破解线索,一旦被篡改或被删除,程序将无法正常运行。

加固是保护程序安全的重要途径之一,更是程序合规上架的必然要求。本文针对第三方apk的资源保护(加密)方案进行简单的梳理,以帮助用户更好地选择和使用加固产品。

二、资源文件介绍

先来看看资源文件的解释。安卓资源文件一般指res和assets目录下的文件,而res和assets资源文件在apk编译和运行过程中存在一定差异。


1、res资源

res目录只能有一层子目录,且子目录必须是预定义的,如res/layout、res/values等。

res会在R.java生成索引ID,没用到的资源不会被打包进apk中,但res/raw文件夹除外。

res用getResource()访问。

2、assets资源

assets资源目录可以自定义。

assets资源会原封不动地打包到apk中。

assets用AssetsManager访问。

三、资源文件保护方案

打包后的apk如需资源加密,只能通过在运行过程中hook相关的函数接口进行解密,来达到保护效果。市场上的资源文件保护方案可分为定制方案和通用方案两大类。两种方案各有优劣。


1、# 定制方案 #

定制方案的使用场景多样,一般根据文件类型分类,包括脚本类和资源类。其中,js,lua,python等脚本,根据不同的脚本引擎做加密,同时利用hook或重写解释器的方式重新解析脚本进行解密,而u3d资源,png,jpg图片等资源,可能会涉及资源读取方式或基于图片格式制定的加密方式,加密后需在特定时机进行解密。

# 优点 #

a、针对性强,只针对特殊类型的文件,如js,lua脚本,u3d资源

b、兼容性好

c、性能好

# 缺点#

a、保护范围小

b、每种类型的资源需针对分析加载原理,开发维护成本高

2、# 通用方案 #

# 优点 #

a、保护范围广

b、维护成本小

# 缺点#

a、兼容性无法完全保证

b、开发难度大

c、性能低

因定制保护的方案每个类型都能单独成为一个专题进行介绍,无法简单地通过一篇文件说明,下面主要介绍通用的资源保护方案的实现以及难点分析。

四、通用方案

(一)实现原理

apk本质上是个zip格式文件,读取资源文件即读取zip里的文件。因此,其原理离不开读文件和解压两个过程。如果能在读文件或者解压两个过程进行hook,并对文件内容进行解密,就能达到资源保护的效果。简单来讲,一个是针对libz.so进行hook,一个是针对libc.so进行hook。

1、Libz hook

(1)# 优点 #

a、使用标准api,特征稳定,易于hook

b、处理只限于libz.so即可达到目的,简单且高效

c、使用got hook,功能稳定性好

(2)# 缺点#

a、用户代码必须满足压缩数据,使用libz中的uncompress函数进行解压并读取数据

b、第三方sdk或游戏引擎因将libz静态编译到so中,可能不满足使用条件

2、Libc hook

(1)# 优点 #

a、hook范围广,适配更多情景

(2)# 缺点#

a、全范围hook会导致性能降低

b、采用inline hook,可能引发兼容性问题

从通用性来说hook libc的方案可以兼容更多用户使用场景,但只要用户使用标准接口,不进行自定义或不以第三方不明确的sdk做资源读取,hook libz也能适配大部分的资源读取。

(二)通用方案难点分析

1、# 四个条件 #

对于加固功能的开发者而言,开发资源加固功能的前提是,资源读取的流程可被hook,否则文件无法在合适的时机进行解密。由此可见,用户在选择做资源保护时,要确定是否满足以下四个条件。以下条件皆围绕一个核心,即程序读取apk的资源过程需要保证能被hook。如果条件满足,使用通用的手段保护资源文件在理论上是可行的。

# 未使用任何第三方sdk读取资源,可能存在不确定隐私

# 自研so未自实现解压方法

# 自研的so中实现了解压方法,且通过libc直接读取apk

#自研的so中实现了解压方法,未做so加固,内存中so结构完整

2、# 三个问题 #

在用户apk实现满足以上规则的同时,资源加密还需解决如下问题:

(1)# 文件如何加密和解密

答:文件的加密和解密方法影响到加固后apk的结构,需要定义一套加密规则保证加密后zip格式的完整性,以及解密后文件的完整性。

(2)# 解压文件是否存在校验

答:因apk的zip头部保存了解压后的文件crc以及长度,需要考虑部分情况下,文件解密后,crc和长度是否需要校验的情况。

(3)# Android碎片化严重的情况下如何兼容各种机型

答:需要考虑不同版本下,Android系统下libc和libz的实现变化,保证兼容性。

3、# 四种不兼容 #

值得注意的是,对于在内存里做解密操作的功能而言,一些无法兼容的情况仍然存在,下面指出几个常见的不兼容问题。

(1)# 自研so实现zip解压方法,且使用汇编读取文件

答:这种情况,无明显hook特征,无法正常解密文件。

(2)# 用户so实现zip解压,且使用so加固破坏了so的内存结构

答:在对so进行hook的前提下,破坏so结构可能无法进行hook并解密。

(3)# 用户加固资源后,热更新机制为服务端读取apk包并和内存读取的apk进行hash对比

答:资源加密最重要的一个效果就是无法静态分析,也就是第三方工具读取apk会读到密文。但内存中读取apk是明文,必然导致文件无法正常校验。

(4)# res资源因其种类较为复杂,且包含包名、图标文件

答:这些文件是需要被系统读取,而非由apk运行时解密,做加密前需要过滤出哪些文件不能加密。

五、结语

综上所述,安卓程序在推进资源保护之前,仍面临一些准备工作,如检查是否满足条件与是否存在相关问题。

在做资源的保护时,结合自身产品情况,尽可能做到以下两点:一是针对性,资源和产品相关,不可盲目加密所有资源,应基于产品特性选择合适的加固方案。二是可控性,让资源的读写方式标准化,采用第三方框架读写资源可能会导致兼容性问题。

程序App风险事件频发,在落实加固保护的过程中,将资源文件的保护放在优先位置的重要性不言而喻。