本节针对APP程序代码进行健壮性安全评估,包括对APP运行环境的安全性进行检测,以及对防反编译、防篡改、防调试、防注入等防御攻击的能力进行检测,如下图所示:
(1)运行环境检测。检测客户端的程序是否对已经ROOT的Android系统、Android模拟器和逆向框架进行检测。
(2)防反编译测试。检测客户端的程序是否进行代码加密、代码混淆和代码加固,是否易被逆向并泄露程序的设计原理和运行流程。
(3)防篡改测试。检测客户端的程序是否对程序自身进行校验,在客户端程序被黑客篡改后,能否正常运行,是否存在被黑客修改成为手机木马或钓鱼软件的风险。
(4)防调试测试。检测客户端的程序是否可以被外部程序进行动态调试并输出敏感信息,是否存在账户信息和交易信息等敏感信息泄露的风险。
(5)防注入测试。检测客户端的程序是否存在进程保护和内存保护,防止被外部程序动态代码注入,以及任意修改、转储客户端内存代码等行为。
本节将对APP代码安全的运行环境、防反编译、防篡改、防调试、防注入5个维度设计的安全问题进行解析,对应的安全要求如下:
运行环境要求进行ROOT检测、模拟器环境检测和逆向框架检测;
防反编译要求进行反编译工具检测、代码混淆检测、混淆强度检测和关键代码代码检测:
防篡改要求进行文件防篡改检测和内存数据防篡改检测;
防调试要求进行调试工具防护检测、调试行为防护和内存防护检测;
防注入要求进行进程保护检测。
针对APP运行环境的安全检测主要包括对已经ROOT的Android系统、Android模拟器和逆向框架进行检测。
本节所说的运行环境是指APP安装运行时所处的环境,一般用户的手机未进行ROOT是相对比较安全的,但是一些用户为了体验更好的使用效果,会将手机进行ROOT。被ROOT的手机APP就会获得管理员权限,相当于拿到了一把万能钥匙,可以打开其他APP的房门,进入其他APP的房间。假如拥有万能钥匙的这个APP是恶意的,那么他进入其他APP的房间后,就可以进行信息窃取,内容篡改甚至留下后门等攻击行为,将对其他APP及使用者造成安全风险。
Android模拟器是能在计算机上模拟Android操作系统的一种虚拟机,支持APP的安装、运行、卸载等基本功能,能在计算机上模拟真实设备中操作使用Android系统的全过程。市面上出现各种各样的模拟器。如果APP在运行时没有对模拟器进行检测和防护,就容易让“刷单党”、“薅羊毛党”利用模拟器对APP实现“多开”操作,利用大批量模拟器中的“虚拟用户”伪装成正常用户来骗取APP运行者提供的促销福利。有的攻击者甚至将APP安装到模拟器上,通过篡改模拟器中GPS传感器的经纬度信息来模拟真实用户的运动效果,满足某些运行健康类型的APP通过用户上传GPS信息计算达到一定实际距离的奖励要求,达到骗取APP运营者利益的目的。
Xposed框架是一种程序逆向调试框架,用于帮助开发人员或者安全测试人员将自定义的程序模块挂载到Android App上。一方面有助于深入理解App运行时的每一步动作以及所释放出的数据内容,另一方面有 助于在App运行时修改程序执行流程。Xposed框架的技术原理是替换Android系统/system/bin/路径下的app process 二进制程序文件。app process是启动Android初始Zygote进程的程序,当Android系统启动时,系统init进程会运行/system/bin/app_ process,随后启动Zygote进程,最终我们可以通过Xposed框架挂钩由Zygote进程孵化出的任何进程。除了Xposed框架之外,常见的挂钩框架还有Cydia Substrate、Frida 等。挂钩框架大大提升了攻击者对App的动态逆向能力,针对安全加固后的App,攻击者利用挂钩框架可以开发出脱壳工具,破解得到加固前的App反编译代码文件,还可以对目标App的任意函数进行运行时的动态分析,窃取App运行时产生的业务数据,给App带来更多的安全风险。
针对以上App所在运行环境中可能出现的安全风险,我们要求App运行时对ROOT环境、模拟器和挂钩框架这3个方面进行检测。
1. Android ROOT环境
Android系统ROOT后就代表手机开放了管理员权限,ROOT用户是手机里拥有最高操作权限的管理员用户,又叫根用户。手机ROOT后,普通使用者可以卸载系统自带软件,禁用不需要后台运行的程序,更改字体,提升手机电池使用率,改善人机交互体验。对于安全测试人员而言,手机ROOT是必需的,只有在系统ROOT后才可以任意安装apk 测试文件,导入或导出系统路径下的文件,查看应用路径下的数据,进行动态调试,使用挂钩框架等安全测试工具。但从系统安全性的角度分析,手机ROOT在提供- 些便利的同时,也会被木马病毒恶意利用,攻击手机系统或手机里安装的其他App,例如删除系统重要文件、劫持App、窃取App的信息、篡改App运行时数据等,给使用者带来不必要的安全威胁。
2、Android模拟器
在AndroidApp运营的过程中,市场上出现的一些“外挂”“刷单党”“刷流量”“薅羊毛”等现象会使企业蒙受大量的经济损失。如前所述,一些人会使用Android系统模拟器伪装成正常用户来欺骗App运营者进而谋取利益。因此,对Android系统模拟器的检测也要作为App运营者建立安全风控体系的一个重要环节。
3、Android挂钩框架
Android挂钩框架是一套开源的框架服务, 可在不修改apk文件的情况下通过修改系统来影响App运行过程和运行结果。攻击者利用开源的挂钩框架可以开发出自定义的攻击模块,来实现程序挂钩、算法破解、敏感API监控、网络通信过程监控等。目前使用比较泛的挂钩框架有Xposed、Cydia Sustrate和Frida技术角度分析,这3种挂钩框架存如下区别:
Xposd框架主要针对Java层代码函数进行挂钩操作。
Cydia Sustrate框架支持对lava层和Native层代码函数进行挂钩操作。
Frida框架是个动态代码执行工具包,可用于把一段JavaScript代码注入一个进程中,或者把一个动态库程序加载到一个进程中。
例如,攻击者如果想破解App与服务器端之间的通信数据,通常情况下可以利用Wireshark、Fiddler等网络抓包工具抓取通信过程中的数据包,解析还原出原始通信数据。但如果该通信过程是加密的,那么抓取的数据报文就是加密后的密文。在无法获取通信加密密钥的情况下,攻击者就无法解密App与服务器端通信的有效信息,抓取数据包就无法实现攻击目标了。此时,攻击者可能会选择利用挂钩框架跟踪App的运行过程以及App与服务器端通信过程中涉及数据加密的程序指令,定位 APP中用于加密通信数据的程序代码,分析程序代码中的加密函数,最终得到加密密钥,进而解密通信数据,达成攻击目标。
Android APP反编译是指通过反编译工具或者反汇编工具将apk文件中不可读的二进制文件代码进行逆向还原,得到具备可读性的反编译代代码或者反汇编指令,有助于通过阅读分析代码或指令来了解App的实现原理。
这里的反编译指的是将文件的二进制代码转换成APP开发过程中所使用的编译语言,如Java、Obijective-C、smali等;反汇编指的是将文件的二进制代码转换成汇编制定,如ARM指令,X86指令等,简单起见,本节将反编译和反汇编的过程统称为“反编译“。防反编译是反逆向编译处理后获得App的程序代码。因此App的防反编译安全要求主要是从反编译工具、代码混淆、混淆强度、关键代码这4个方面提出的。
1.反编译工具
Android App主要由,Java语言编写开发完成,通过打包工具将资源文件、字节码文件和清单文件打包到一个以“apk”未扩展名的zip格式压缩包文件中,以该文件作为分发APP的载体,安装到手机等移动设备中。每个apk文件中的代码视为一个APP。APP打包过程如下图所示。
由于Java字节码的特殊性,它非常容易被反编译。对于AndroidApp的apk文件而言,除了全量配置文件和资源文件外,APP核心的可执行文件的代码会存储在classes.dex文件或动态库的so文件中。攻击者可通过Apktool、 dex2jar、JEB 等反编译工具将java源代码通过IDA工具将so文件反汇编成易读的汇编指令代码。
综上所述,App防反编译工具的安全要求主要涉及以下两个方面:
在APP代码中添加防反编译工具的功能代码,防止通用的Apktool等反编译工具对apk文件中的classes.dex文件进行反编译;
在App代码中添加防反汇编工具的功能代码,防止通用的IDA等反汇编工具对apk文件中的动态库so文件进行反汇编。
2.代码混淆
代码混淆是指在App开发过程中,将App源代码中的函数、变量、类等代码名称改写成不具可读性且不具代表性的随机名称,例如,由单个或多个字母、特殊字符组成,如a、b、ac、“-”符号等。App的源代码经过代码混淆后打包生成的apk文件会增加攻击者反编译的难度。因为攻击者利用反编译工具对混淆后的apk文件进行反编译后获得的代码文件仍然是经过代码混淆的,难于阅读和分析理解,从而增加了逆向破解App的难度。
3.混淆强度
App源代码经过代码混淆工具混淆后,虽然增加了攻击者反编译App的难度,但是攻击者如果破解了代码混淆工具,或者通过混淆代码的调用关系和代码结构破译了混淆代码,那么仍然能够获得App源代码的反编译结果。
因此,对于安全性要求高的App而言,仅仅使用代码混淆工具对App的源代码进行混淆无法完全保证源代码的安全,还要进行高强度的代码混淆技术保护,如apk关键的包名、类名、资源文件名称等进行代码混淆的基础上再进行数据加密保护,进一步增加反编译的难度。
4.关键代码
关键代码在这里指的是APP的核心功能代码,主要包括业务逻辑和数据保护两个方面。
不同类型的App具有不同的核心内容,例如,导航类APP的核心功能是为用户实时提供地理位置服务,金融类APP的的核心功能是为用户提供支付、转账、贷款等金融服务,网约车APP的核心功能是为用户提供约车服务。虽然APP的核心功能千差万别,但是它们遵循各自行业的业务规范,这些业务规范反映在App的业务逻辑码中,这就属于App 的关键代码。攻击者一旦通过反编译得到这些关键代码,就可以分析APP业务流程中存在的安全漏洞,攻击APP的核心功能。
不管是什么类型的App,在为用户提供信息服务时, 一般会涉及用户账户、 密码、身份、实名、地理位置等用户个人信息数据的采集和使用,因此开发者需要特别重视用户数据保护的问题。为了防止攻击者通过反编译获得App的关键代码,开发者要对键代码进行重点保护,确保业务逻辑部分和数据保护部分的代码经过了混淆和加密处理,防止攻击者能够轻易获取关键代码,破解App的业务逻辑,甚至窃取用户个人信息。
App防篡改是指防止攻击者恶意修改App的程序名称、安装图标、运行界面等资产信息,在APP中添加具有恶意扣费、信息窃取等恶意行为的攻击代码,或者伪装成原有App的钓鱼 App 来诱骗用户安装并实施攻击。App防篡改的安全要求主要包含程序文件防篡改和内存数据防篡改两个方面。
1.程序文件防篡改
在Android系统中,谷歌公司允许开发者使用Keytool、jarsign 等工具对App进行签名打包,生成的apk文件能够在Andorid设备上正常运行,并可以在应用商店上架发布。
App自签名的机制给攻击者提供了机会,利用Apktool等具有Android代码反编译和apk打包功能的工具,攻击者就可以对apk文件进行反编译,对App的程序代码、图片文件、权限配置、界面布局等程序资产进行篡改,还可以往程序代码中植入恶意代码。攻击者使用工具对篡改后的反编译文件进行自签名,就能生成可正常运行的攻击样本。虽然目前应用商店开始重视App软件著作权,要求开发者上架原创App,降低通过篡改后的攻击样本在应用商店上架的概率,但是在技术上, 攻击者仍可以实现对正版App的篡改攻击,并通过非应用商店等其他App推送渠道进行传播。
攻击者篡改APP 的主要方式是对安装包文件进行篡改。在Android系统中,App的安装包文件后缀为apk,,由META-INF、res、AndroidMainfest.xml、classes.dex、resources.arscdeng等文件或文件来组成。这里的APP程序文件防篡改就是指apk文件能够防止攻击者反编译文件、篡改文件内容、通过工具二次打包生成恶意apk文件等篡改行为。
2.内存数据防篡改
玩过电子竞技游戏的一定知道 “游戏修改大师”等手机游戏破解工具或外挂工具,这些工具通过修改手机内存中的数据来达到游戏过关、任务升级的目的。手机内存数据的篡改在游戏类App里是比较常见的,通过内存数据修改器可以定位和修改游戏里的BOSS血量、金钱、主角战力等游戏指标,绕过游戏付费环节实现升级。这些游戏App的外挂修改器技术实现非常简单,就是锁定游戏运行过程中的某些指标数据,在手机内存中查找到相同数值的变量范围,再通过反复运行游戏对变量范围进行跟踪对比,确定内存中某个变量的变化与游戏中某个指标的变化保持一致, 修改这个变量就能够实现游戏数据的修改。
虽然修改游戏App运行过程中的指标数据据尚未造成严重的安全风险, 但是攻击者如果利用相同的方式篡改手机银行、证券交易、手机支付等金融类APP运行过程中在内存中的转账金额、交易账号、支付对象等重要数据,就可以达到盗取用户资金的目的。那么,如果这些金融类APP不对运行在内存中的数据进行保护,就会存在用户资金失窃的重大安全隐患。
因此,App内存数据防篡改要求App在内存释放数据的过程中采取安全防护措施。在App 运行期间一方面要防止App在内存中暴露 业务逻辑代码和关键业务的明文信息, 另一方面是要防止攻击者任意篡改App在内存中释放的业务逻辑代码和关键业务数据。
App防调试的安全要求是指App在启动运行过程中要防止被攻击者使用调试工具进行动态调试攻击。动态调试攻击指的是攻击者利用调试工具对App运行时的目标进程进行动态跟踪和逆向分析,达到破解程序逻辑、获取运行过程的中间数据等目的。动态调试的过程与开发者在App开发过程中为了满足用户需求而进行程序调试的过程很类似。App防调试的安全要求主要包括调试工具防护、调试行为防护和内存防护这3个方面。
1.调试工具防护
与上文所讲述的运行环境安全要求中的Android挂钩框架环境检测要求类似,调试工具防护是要求App在启动运行时检测运行环境中是否存在来自App程序调试工具的调试信号,一旦发现调试信号就会启动拒绝调试、关闭进程、退出程序等防护机制。
常用的IDA、gdb等调试工具是依赖于Liunx内核中的ptrace系统调用来实现程序调试的,那么对于App防调试的要求就可以落实到对ptrace体函数的检测防护上。例如,App可以建立双向ptrace保护措施,阻止其他进程对本进程进行ptrace调试操作,或者通过轮询的方式检测自身进程是否处于调试状态,一旦发现处于调试状态就立即退出。
2.调试行为防护
调试行为防护的安全要求指的是App在运行行期间能够阻止攻击者对App的核心功能进行调试,防止暴露关键代码和业务逻辑。对于不同行业不同类型的App客户端, 攻击者通过动态调试进行攻击的目的也有所差异,有的是为了获取账号、密码等用户信息,有的是为了修改转账金额、交易对象等支付信息。因此,调试行为防护相比调试工具防护而言,是一个动态博弈的过程,是安全防护措施在性能上的进一步优化,开发者不能盲目地进行全局防护,而是要针对APP中最关键的代码和数据进行重点防护。
3.内存防护
内存防护也称内存数据防转储防护,目的是防止攻击者使用gdb调试工具挂载App的程序进程,利用gcore指令转储内存空间中gdb所附加的App进程中的core文件。在Android App加固技术发展初期,攻击者通过该方法还能够从内存中导出App 的可执行代码和数据,但是随着加固技术的升级和发展,该方法已逐渐失去作用。不过,App内存防护仍然值得开发者重视,防止攻击者利用程序注入工具在App运行时从内存中转储文件。
App的防调试和防注入这两个安全要求是分别针对攻击者动态调试APP获取信息和植入代码这“一出一进”两个数据流向的要求。由于Android系统没有禁止用于程序调试的ptrace系统调用,攻击者在获得ROOT权限的情况下,就可以制作攻击样本,使用调试API对目标进程的内存数据和寄存器数值进行修改,以达到执行sellcode、注入恶意代码攻击目的。在安全测评中,防注入是防止第三方程序动态注入so文件到指定进程。APP可以通过建立双向ptrace保护措施,阻止外部对本进程进行代码注入攻击。
在Windows系统中,攻击者可利用Windows钩子功能,将恶意的DLL文件注入系统内存的其他地址中间,对其他App实施攻击。同样地,在Android系统中,攻击者可以利用inject之类的注入工具将第三方的动态库so文件注入目标App的进程空间中,使得目标进程加载第三方的动态库so文件,改变APP原进程的运行过程,并按照攻击者的意图执行程序。需要注意的是,实现程序注入攻击的前提条件是所处的Android系统环境必须先进行ROOT。
进程注入攻击的基本过程一般有以下 4个步骤:
(1)使用inject工具挂载目标App的程序进程;
(2)让目标进程的执行流程跳转到由mmap函数事先分配的内存空间中;
(3)使用inject工具向目标App中动态加载第三方so文件;
(4)将目标App的进程运行流程跳转至第三方so文件代码的内存空间处执行。
因此,App进程保护的安全要求就是App在运行过程中能够阻止攻击者通过动态注人的方式向所属进程空间注人恶意so文件。
E
N
D
关
于
我
们
Tide安全团队正式成立于2019年1月,是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、系统安全、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。
团队作为“省级等保关键技术实验室”先后与哈工大、齐鲁银行、聊城大学、交通学院等多个高校名企建立联合技术实验室,近三年来在网络安全技术方面开展研发项目60余项,获得各类自主知识产权30余项,省市级科技项目立项20余项,研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。对安全感兴趣的小伙伴可以加入或关注我们。