APP下载

基于软件分析的Android应用重打包检测与防御研究

2023-08-10刘天一周延森崔见泉

计算机应用与软件 2023年7期
关键词:解密攻击者应用程序

刘天一 周延森 崔见泉

(国际关系学院信息科技学院 北京 100091)

0 引 言

Android作为智能手机主流操作系统,其恶意软件数量在移动恶意软件中所占比重超过50%且快速上升。攻击者将重新打包的应用程序作为其恶意行为的传播媒介,降低了其本应自行开发的成本与难度,同时也利用了原合法软件的受欢迎度和可信度。文献[1-2]表明Android应用市场中5%~15%的应用是被重新打包过的。

国内外针对Android应用重打包的研究目前多集中在相似度比对上。Kim等[3]提出的RomaDroid工具使用最长公共子序列(LCS)算法来测量两个应用程序之间的相似性;Hu等[4]提出了一种基于UI结构相似性的克隆程序检测方法;Wu等[5]提出的MSimDroid 方法基于多维相似性,包括整个应用程序相似度、资源相似度、代码相似度、联合策略进行相似度计算;汪润等[6]提出了一种基于深度学习的Android重打包应用检测方法,并利用 Siamese LSTM 网络学习程序的语义特征表示,实现重打包应用的检测;沈月东[7]提出的Android重打包行为分析技术,通过进行非第三方库代码部分的API调用的统计和聚类,以应用对的形式检测出重打包和被重打包的应用;熊鹰[8]提出的基于用户角度的重打包检查方法,通过用户端特征提取以及服务端相似应用匹配实现重打包检测。

基于相似度的重打包检测方式面临的最大问题是需要有足够的数据集来对比分析,如未能与原合法应用程序匹配则难以判定,且基于相似度的软件水印、软件胎记多数只能作为知识产权侵权行为被发现后的追责依据,并不能从根本上解决剽窃、重打包攻击等问题。同时,随着软件分析技术的发展,仅依靠相似度的重打包检测为攻击者绕过或欺骗检测所设定的门槛与难度也在随之降低。

1 相关研究工作

1.1 Android重打包原理

1) Android逆向。Android应用程序通常由Java语言开发编写,编译成.class文件,转换为一个可以在Android平台的Dalvik虚拟机上运行的.dex文件,最后将字节码.dex文件、描述权限信息等内容的AndroidManifest.xml文件、资源文件打包在一个.apk文件中。作为解释型语言,Java高度抽象的特性也意味着其易被反编译,随之衍生出的逆向工具也在很大程度上降低了Android应用重打包行为的工作量。

其逆向流程如图1所示,其中,Apktool是被最广泛使用的开源APK逆向工程软件,可以将Dalvik字节码反编译成.smali代码,然后再生成App的重打包版本;Jadx或商用软件JEB可以对.smali代码进行直接处理与调试,并能展示出与源代码几乎相同的Java代码;dex2jar可以借助baksmali等反汇编方式生成.jar文件进而解压得到Java代码。

图1 dex文件逆向

2) Android重打包。Android应用程序的开发周期普遍较长,原软件开发者付出了大量成本。然而,重打包App的成本普遍较低,难度也较小,图2展示了Android应用程序重打包的基本流程。

图2 Android应用程序重打包流程

应用程序开发者发布App,用户通过Google Play或第三方应用市场下载软件到移动设备,由于“下载”行为不存在身份鉴别,攻击者同样能够以合法用户身份从应用市场下载.apk文件到本地。通过自动化反编译或人工分析,从.apk文件中能够获取到可读性较强的.smali代码、Manifest文件与资源文件等,并经由逆向工具进一步获得接近于原程序的Java代码。基于以上文件,攻击者通过修改.dex代码、lib库或向其他资源文件添加恶意代码片段或针对广告进行增添或替换,将修改后的文件再通过Apktool等工具重新打包成.apk文件,使用官方的Android开源项目私钥将重打包软件签名合法化,上传到应用市场,诱导用户下载使用。

重打包后的应用会保留一些特性,如与原App有一定程度上的代码相似性、与原App有着不同的开发者签名。应用市场多以此为依据,结合恶意行为分析和短时间段内的模拟运行,判别一个App是否安全和能否被发布。目前重打包的防御措施多集中于提升攻击者的攻击难度以及重打包行为发生后的判定上。

1.2 自解密代码

自解密代码SDC(Self Decryption Code)是在程序特定分支中依赖于分支内常量通过加密或Hash等方式对代码块进行处理,保障语义等价的前提下重写原分支,替换后仅可以通过动态运行实现自动解密恢复,文献[9]论证了其可靠性的基础理论依据。

在借鉴文献[10-11]的基础上,本文所设计的SDC结构如图3所示。首先对条件分支中表达式的常量(记为w)使用不可逆的处理(如单向Hash)得到一个新常量es,以此实现对原常量w的隐藏。之后将常量w与实时计算生成的校验码c一同作为密钥对分支中全部代码和划分后的部分水印信息进行加密操作,并用加密得到的乱码形式代码替换源代码。

图3 SDC结构

当运行到该分支时,程序会实时计算校验码并执行解密操作从而完成自动解密,还原源代码和这部分的水印信息。其中变量v是程序运行到这一分支时变量中所存储的值,理论上应与w相等,因而用同样随机串对变量v的值进行同样处理,会得到一个与es相等的值,以上做到了对含有常量w的原表达式的等价转换。

由于原常量w已经通过es的替换实现了不可逆的隐藏,且由原常量w生成es的过程存在着一个无法预测的随机值,再加上Hash算法的单向性,从而提高了从es到w的还原难度,作为密钥组成部分的w就成为了只有原开发者知道的信息。因此,预测常量w的方法一种是根据程序上下文语义结合数据流分析等方式合理推断,但由于通过SDC算法转换程序最后的呈现大部分是无实际意义的乱码,难以完成单纯的静态分析;另一种是在动态运行过程中从变量v进行突破。

1.3 软件水印

软件水印是将特定数据w作为水印嵌入程序P中,得到一个其水印难以被轻易检测和移除的新程序Pw。水印的目的不是阻止应用程序被非法使用,而是证明其所使用的软件和算法的所有权,从而辅助知识产权权益保护、打击盗版。水印分为静态和动态、明显可见和隐藏不可见,文献[7]利用SDC构造的水印即属于无须加以隐藏的动态软件水印。

2 基于软件分析的Android重打包检测研究

本文针对Android应用重打包检测在软件分析领域所面临的挑战,分析其检测方式在目前可预计的规避策略,从而设计开发出更为可靠的重打包防御方案。

2.1 实验设计

由于多数Android重打包检测研究并未公开代码和数据集,本文首先使用合法应用程序集借助混淆、自解密代码等技术构造特定数据样本,并简要实现了基于代码相似度的检测算法,复现了WuFan、AndroidSOO等开源重打包检测工具的检测过程。

实验具体流程如图4所示。针对不同类型的重打包防御方式,论文相应地设计了不同的绕过检测或妨碍防御的策略,以此来对重打包检测算法进行有针对性的测试及分析。

图4 实验设计

2.2 自解密代码的实现及数据集构造

本实验数据集分为合法App、简单处理的重打包App、利用混淆等处理意图绕过检测的重打包App三部分。其中,本文默认从Google官方应用市场下载得到的应用均为合法应用(实际上可能会存在约1.2%的重打包应用),对其进行简单的逆向、修改和重打包后即构成了第二部分数据集,而构造第三部分数据样本时的处理如下:

1) 混淆相关处理。本文首先对重打包程序进行基础混淆操作,包括:① 名字改编,即将域名、方法名、类名、包名等有实际意义的标志符替换成无意义的相对较短的字符串。② 在不影响程序语义的前提下修改修饰符。③ 加入无效代码对方法的实现结构进行调整。④ 方法参数转换。⑤ 常量计算替换。

2) 自解密代码构造。本文通过自解密代码技术为意图绕过重打包检测的数据集构造提供进一步的辅助。SDC[10-11]作为一种有效的重打包防御方式,但本文认为其主要思想同样也可以成为攻击者对抗重打包检测的技术之一。

本文在Java代码层面,借助第二节中SDC的自加密-自解密框架和信息不对称理论,实现了一个简易版本的自解密代码转换器,其中,利用的单向函数为MD5,对称加解密算法为DES,随机串的添加在本文所编写的md5enc方法中实现。

以程序1为例,其在Java代码层面经过混淆、自解密代码转换等处理后得到的等价代码如程序2所示,可以看出二者直观结构呈现不同,但二者功能上并不存在差异,编译运行后得到同样的运行结果。

程序1原始代码

while(k

{

if(x[k]= =1) R=(s*y)%n

else R=s;

s=R*R%n; L=R; k++;

}

return L;

程序2经过混淆、自解密代码转换等处理后的代码

int next=0;

for ( ; ; )

{

switch(md5enc(next))

{

case “4548cce2e2d7fbdea1afc51c7c6ad26”:

k=Integer.parseInt(desdec(String.format("%08d",next),"nISR6pPU35Y="));

s=Integer.parseInt(desdec(String.format("%08d",next),"B/4RM7/980M="));

next=Integer.parseInt(desdec(String.format("%08d",next),"B/4RM7/980M=")); break;

case "aab3238922bcc25a6f606eb525ffdc56":

s=R*R%n; L=R; k++;

next=Integer.parseInt(desdec(String.format("%08d",next),"4km57CcZvD8=")); break;

……

case "9bf31c7ff062936a96d3c8bd1f8f2ff3": return L;

另一方面,对于较为复杂的程序,本实验利用开源的混淆工具,从编译器层面而非直观的代码层面进行混淆等处理。

2.3 实验及结果分析

检测算法的主要思想是在开发者签名不同的前提下对于一个从非官方渠道获取的未知来源的App,通过在已知是合法、非重打包的众多数据集中逐一两两进行相似性比对,计算其相似度。相似度越高(即越接近1.0)则说明这个未知来源的App是重打包的可能性更大,相似度最高值所对应的合法App被认定为其重打包的对象。

本文利用前文所构造的数据样本对基于相似度的重打包检测算法进行对抗测试,具体步骤为:

1) 从可靠性较高的应用市场随机选取.apk文件(记作app-ori)下载到本地。

2) 借助Apktool工具对.apk文件进行解包与反编译,如图5所示。

图5 对.apk文件进行反编译与重打包

3) 使用逆向工具得到Java代码。

4) 添加或修改代码片段得到文件re1。

5) 对re1采用前文所述混淆等方法进行转换,用于妨碍重打包检测,得到re2。

6) 使用Apktool分别对re1、re2重打包生成.apk文件app-re1、app-re2。

7) 将生成的两个.apk文件分别放入重打包检测系统中检测,分别记录各系统关于是否为重打包应用所做出的判定。

8) 通过Android Studio平台模拟器验证应用程序本身功能完整性是否被破坏。

9) 对检测算法的表现进行评估与分析。

上述相似度重打包检测步骤如图6所示。

图6 相似度重打包检测流程

实验主机为:CPU Intel Core i5 @2.30 GHz和8 GB的RAM。由于一个完整的Android应用规模较大,包含上万个文件,尽管本文复现算法时已尽可能简化了检测过程,基于相似度的检测算法仍需数小时的判定时间。基于此我们仅在小规模测试集中实验,针对实验的分析主要基于代码层面。

图7展示了重打包文件与原.apk文件的相似度得分(即Similarity),若作者签名不同而相似度很高则可以判定其是重打包应用。

图7 计算两个.apk文件的相似度

本实验默认app-ori为合法应用,将其作为基准分别计算app-re1和app-re2与该应用的相似度,从而对二者是否为重打包程序进行判断。通过对比针对同一app-ori[i]的两个不同重打包版本app-re1[i]与app-re2[i]在检测中表现出来的差异,以及进一步统计检测系统在不同情况下的漏报率,可以推测出本文在构造特定重打包行为时所采取的混淆、自解密代码转换等技术对重打包检测算法所造成的影响。

实验结果如表1所示,本文构造数据样本时混淆等处理降低了重打包应用与原应用的相似度,使其低于重打包攻击行为的判定阈值,从而在一定程度上欺骗了检测系统。本文所复现的检测算法没有针对代码以外的信息进行处理,将两个包括作者签名在内完全相同的.apk文件(其相似度高达1.0)判定为重打包,而Wu Fan可以对.apk文件的签名做出识别,将其正确判定为作者相同,即“非重打包”,如图7所示。但现实中Android应用市场在正式发布应用前都至少会对其签名进行最基本的验证与校对,验证时即可获知作者信息,因此对持有相同作者信息的App重打包判定可暂不作考虑。

表1 检测性能对比

针对于仅完成了重打包的.apk文件,基于相似度的检测算法均能以很高的准确率检测出其重打包行为(本实验在重打包过程中仅采取较为简单的人工修改或添加,且判定阈值设置较低,真实情况不一定会达到如表1所示百分之百正确率和零漏报率)。针对本实验处理后的重打包测试样本,其与原文件的相似度数值呈明显降低。实验结果显示混淆、自解密代码转换等方法使得多数重打包.apk与原.apk文件的相似度降至基于代码相似度算法的判定阈值之下,从而存在很大概率可成功绕过此类型的重打包检测。

3 Android重打包攻击防御的改进

3.1 系统框架

上文分析了软件分析技术为目前被广泛应用的三种重打包检测方法所带来的影响,基于此,本文综合了以SDC等技术为依据的检测或防御算法,在此基础上提出一种改进的重打包防御框架,如图8所示。

图8 重打包攻击防御系统框架

Android应用开发者在编写完程序代码后:

1) 将源代码进行自动化程序分析,其环境与软件测试保持一致即可,在这个过程中:① 对程序结构进行一定的转换与优化,使之便于后续的水印嵌入和SDC生成,同时也起到混淆的作用,从而降低程序的可读性;② 对可利用的分支语句进行标记,如程序规模较小则利用不透明谓词添加可利用的分支。

2) 构造水印信息并进行切分和压缩等处理。

3) 结合自解密与自防御算法,将水印嵌入程序,同时对代码进行加密处理,生成自解密代码。

4) 将代码与资源等文件打包、签名和上传到应用市场待审核。

随后,权威Android应用市场会对App进行初步检测,在模拟环境下进行运行测试。在测试过程中运行到SDC时,正常情况下程序会自动进行解密还原,若无法进行解密则显然会因为乱码从而导致程序运行崩溃,此时权威应用市场即可根据程序运行错误的提示判定该App有缺陷或有被重打包的可能,拒绝发布该应用。而通过了初步检测以及模拟运行测试的App会被发布到Android应用商店供用户下载。

用户从应用商店等多种渠道下载App到智能移动设备上,若该应用为合法应用,程序会逐步自动解密还原,用户可以在没有额外附加感受的前提下正常使用;若该应用是被重打包过的,程序存在很大的概率会在运行到某处时由于自解密失败而崩溃。此时该程序便无法继续运行,在一定程度上阻止了该重打包应用继续危害用户设备的可能,程序的崩溃也为移动设备使用者发出了该应用可能存在问题的警示,用户可以采取卸载程序以及举报该程序等行为。Android应用市场收到用户的反馈后会对该可疑应用进行进一步筛查和更细致的审计。若该App仅为运行错误则提示更新修复,若该App确实存在恶意行为则下架该应用并对发布者进行一系列惩罚。如果该应用为恶意的且已经对移动设备使用者造成了损失,则需要进一步借助水印中所携带的信息来判定该应用是否为重打包以及责任归属问题。

3.2 改进分析

由于自防御代码[2]意图以程序崩溃作为重打包的代价从而阻止重打包攻击,而自解密代码则是借助SDC嵌入软件水印[7],我们希望可以通过优化水印的构造方式来降低嵌入的成本,从而将二者结合,既可以实现让重打包App自动暴露以达到防御效果,又可以在重打包攻击发生后通过水印所携带的作者信息、发布信息等进行版权保护或恶意行为的责任判定。同时在此基础上结合其他重打包检测与防御系统的优势设计出一个更为可靠的防御框架。

经过处理后的SDC既可以在水印与载体代码之间建立内在依赖,将二者加密为一个SDC段,从而更好地将软件水印融合到程序之中,并提升攻击者移除或篡改水印的成本;又可以利用程序完整性校验码等构造密钥以实现重打包应用的自动化防御;在此基础上引入的加密算法,作为一种重要的混淆技术,也在一定程度上提升了程序的复杂性,使得攻击者阅读代码和重构代码更加困难。

随着软件分析领域的发展,程序综合等技术使得条件分支语句也就是初始SDC的各个“入口”是可以以自动化分析的形式找到并基于概率求解的,这使得攻击者以低于重开发的成本重打包一个被SDC保护的Android应用成为了可能。因此,我们的框架在SDC生成前加入一个步骤,先对源程序进行程序分析以及类似于混淆技术的代码转换处理,以此来增加攻击者自动化求解的难度。

本框架的优势之一是让Android应用程序开发者、移动设备使用者、Android应用市场三方全都参与到重打包的防御中来。开发者可以以自身的操作对代码加以保护从而从根本上阻碍他人的剽窃行为,而不是将版权保护寄托于检测能力参差不齐的第三方应用市场、在他人重打包攻击行为发生后才进行耗时耗力的追责;用户也可以通过程序的运行崩溃感知重打包行为,从而阻止恶意应用继续存在于移动设备之上。

4 结 语

软件分析技术的发展既使攻击者绕过检测、对抗防御、降低攻击成本成为了可能,同时也为重打包防御提供了提升的空间。本文分析了目前常见的重打包检测算法,构造了特定数据样本及绕过检测的策略进行测试,并基于此设计一个综合的重打包防御框架。本文的不足之处在于,没有对提出的方案进行完整的实现与测试评估,仅通过第二节中实验所得出的结论来辅助验证改进设计的合理性,且仅在代码层面而非编译器层面实现了SDC。

猜你喜欢

解密攻击者应用程序
基于微分博弈的追逃问题最优策略设计
炫词解密
解密“一包三改”
炫词解密
删除Win10中自带的应用程序
谷歌禁止加密货币应用程序
正面迎接批判
有限次重复博弈下的网络攻击行为研究
解密“大调解”
三星电子将开设应用程序下载商店