iOS App 安全加固方案调研

7,736 阅读12分钟
原文链接: mp.weixin.qq.com

背景

iOS 系统向来以安全著称,苹果为保证 iOS 系统安全,采用了 App 签名、沙盒机制、地址随机化诸多安全防护措施。iOS 系统虽然安全,但并非坚不可破。iOS 系统的安全,更是让许多开发者忽略了自身 App 的安全。

在越狱设备中可以访问 App 中的沙盒数据、Keychain 存储的数据;使用 class-dump 工具可以导出 Objective-C 中的头文件;借助 IDA、Hopper 等反汇编、反编译工具可以静态分析代码逻辑; 运用 Cycript、debugserver+lldb 可以动态调试程序;另外攻击者还可以编写 tweak 注入到 App 中,篡改应用逻辑,二次打包实现 App 多开。

目前市场上 BAT、TMD、网易等大厂 App 做了一定的安全加固,然而大多数 App 都没有基本的安全防护。App 如果不进行安全加固,在越狱环境下犹如裸奔,严重者被黑产利用,给公司造成经济损失。

本文调研了当下几家有影响力的安全公司 iOS 安全加固解决方案及技术特点,以及阿里、腾讯、头条等旗下知名 App 所使用的一些安全加固技术,并总结了常用的安全加固方法,为 58 App 安全加固提供参考。

安全公司 App 加固解决方案

在介绍具体的安全加固技术之前,我们先来了解当前主流安全公司的 iOS 安全加固解决方案及技术特点。要想获取的信息,请参考相应的官方资料。本文对于各家产品的优劣不做对比,以下排名不分先后。

注:本节有关各家产品的介绍及截图均来自对应的官方网站,如有涉及侵权,请联系作者删除。

  • 爱加密

根据 iOS 的技术原理和破解原理,爱加密全球首家推出 iOS 应用加固技术,通过对本地传输数据等进行安全防护,从而保护应用免遭破解攻击。

  • 数字遁甲

全球首创的 iOS 应用二进制加固技术,应用防护等级更高,保护应用和数据的安全。

  • 通付盾

iOS 应用加固采用 IPA 加壳保护技术,使用先进的动态注入技术对 IPA 进行加壳保护,从而防止应用被篡改、逆向分析等,保护应用的数据安全、业务安全等。

  • 几维安全

iOS 源码混淆保护产品是一款纯离线的源码加密工具, 主要用于保护 iOS 项目中的核心代码,避免因逆向工程或破解, 造成核心技术被泄漏、代码执行流程被分析等安全问题。该加密工具和普通编译器相似,基于项目源代码可将 Objective-C、Swift、C、C++ 代码编译成二进制代码, 不同之处在于,加密工具在编译时,能够对代码采取混淆、轻量虚拟化、字符串加密等安全措施。从而避免攻击者通过 IDA Pro 等逆向工具反编译二进制代码, 分析业务代码执行流程,进一步篡改或窃取核心技术。

几维安全还有另外一款 iOS 源码虚拟化保护产品,主要面向移动游戏、智能设备、物联网等行业,具体介绍请移步官网。

  • 网易易盾

源码编译即加密,降低应用破解风险

  • 360加固保

iOS 加固是旨在为广大的 iOS 软件开发者以及厂商源代码提供加密保护,通过代码加密、指令混淆等技术手段在编译阶段对源代码进行常量加密、逻辑混淆、结构混排等保护,增加反编译、篡改和注入的难度,提高核心代码及数据的安全性。

  • 阿里聚安全

阿里聚安全产品因业务策略调整,于2018年8月下架,支持安卓,未找到 iOS 相关资料。

  • 顶象技术

顶象 iOS 加固保护是顶象基于虚机源码保护技术,针对 iOS 平台推出的下一代加固产品。可以对 iOS App 中的可执行文件进行深度混淆、加固,并使用顶象独创的虚拟机技术对代码进行加密保护。

常用的安全加固技术

在了解完业界安全公司的 iOS 安全解决方案后,可以看出数据保护,混淆保护,反调试保护,异常检测是几种最常用的 App 加固手段,接下来我们详细介绍这几种技术。有几家公司提到的代码虚拟化技术,笔者未曾了解,在此不做讨论。

数据保护

数据保护主要包括网络数据、IPA 内置资源数据、沙盒数据、Keychain 数据。

网络数据

虽然苹果已在几年前就强制推行了 HTTPS,但使用 Charles 等抓包工具,仍然可以截取通讯信息。因此对于核心业务接口,有必要自己实现接口签名、数据加密。

IPA 资源数据

在 IPA 包内,我们经常会内置一些 plist、json、SQLite db 等资源数据。通过 iTunes、PP 助手,或者越狱设备,都可以下载导出 IPA 包,查看其中的资源数据。 如果业务敏感数据,明文存储到这些配置文件中,都有相当大的风险,很容易导致数据泄露。

沙盒数据

沙盒机制,作为 iOS 系统中一项强大的安全防护措施,更是让许多开发者掉以轻心,各种数据不做加密,就存储到沙盒中。殊不知在越狱设备中,很容易便可访问沙盒数据,具体步骤如下:

1. 通过 ssh 远程连接到越狱设备

MacBook:~ jiaxw$ ssh <user_id>@<device_ip>

2. 查找目标进程 ID

iPhone6s:~ root# ps -e

‍‍3. 使用 cycript 注入目标进程

iPhone6s:~ root# cycript -p <target_process>

4. 查找沙盒目录

cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]#"file:///var/mobile/Containers/Data/Application/B908340E-8EA1-429E-80C9-5426C9B6BB7F/Documents/"

5. cd 到上一步找到的沙盒文档目录,即可查看沙盒中存储的文件。对于一些方便查看的文件,可以使用 scp 工具将文件传输到 Mac 端,甚至可以将整个沙盒目录打包传输到电脑端。

Keychain 数据

Keychain 中存储的数据虽然较少,但往往都是比较重要的数据。数据不做加密,直接存储到 Keychain 中更是有相当大的风险。借助开源的工具 keychain_dumper 即可轻松访问 Keychain 中存储的数据,其使用方法如下:

混淆保护

混淆保护是一项相当实用有效的安全防护手段,包括符号混淆,字符串混淆,指令混淆。

符号混淆

开篇我们提到过使用 class-dump 等工具,可以提取 Objective-C 中的头文件信息,包括类名、属性、方法、协议。在 Hopper 、IDA 等工具中,搜索类名、方法名即可快速定位到对应的实现位置,分析代码逻辑,篡改程序。 将 App 敏感业务中的类、方法进行混淆,替换为晦涩混乱的符号,可以增加攻击者的逆向难度。

既然有 class-dump 还原头文件,就有对应的 class-guard 用来混淆符号,具体可以参考开源项目 ios-class-guard 实现。

然而笔者调研了微信、支付宝、美团、抖音等 App,发现符号混淆并未被广泛使用。在唐巧老师与蒸米大神的一次访谈中,也提到支付宝也只有核心支付代码做了混淆。 在项目中尤其是大型复杂项目,我们基本上都会使用到 Objective -C 的 Runtime 特性,基于字符串,动态创建类,调用方法。符号混淆存在着潜在的风险,要考虑各种复杂情况,稍有不慎就会导致程序异常,并且难于跟踪调试。 另外大量使用混淆,也不被苹果所允许,有审核被拒的风险。

字符串混淆

代码中的字符串会暴露 App 的很多关键信息,攻击者可以根据界面显示的字符串,或抓包分析接口 URL,快速找到相关逻辑处理函数,从而进行分析破解。加密密钥尤其不能直接明文存储在代码中。 对敏感字符串,进行加密保护,逆向后不能轻易看出字符串含义,可以有效防止攻击者通过反编译工具获取关键词,找到破解突破口。

以一段简单的测试代码为例

#define kEncryptKey @"a0VuY3J5cHRLZXk="@interface ViewController () @end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    [self encryptString:@"this is a string" withKey:kEncryptKey];}@end

使用 Hopper 查看反编译后的伪代码,加密密钥就这样赤裸裸地暴露了。看完之后,你还敢在代码中明文存储密钥吗!! !

指令混淆

指令混淆即逻辑混淆,在编译环节将 iOS 代码逻辑进行复杂化,让代码逻辑变得错综复杂,从而保护敏感逻辑代码,提高破解难度。

在代码中插入冗余的指令虽然提高了攻击者逆向难度,但不可避免会影响程序执行效率,或多或少都会增大可执行文件大小。一些公司宣传的加固后性能零损耗,不那么让人信服。

反调试保护

在越狱机上,使用 debugserver、lldb 工具,可以动态调试分析 App 运行逻辑。使用 MonkeyDev 恢复符号表,重签名后,可以直接在 Xcode 中调试,函数调用堆栈都可以看到。 为防止攻击者动态调试分析 App,在程序中增加反调制机制很有必要。据笔者研究,支付宝、美团、抖音等 App 都实现了反调试防护。

iOS 平台下常见的反调试有以下几种方法:

  • ptrace

ptrace 是一个系统调用,主要用来跟踪调试应用程序,其函数原型如下:

int ptrace(int request, pid_t pid, caddr_t addr, int data);

其中第一个参数 request 指定了要执行的操作,当设定为 PT_DENY_ATTACH 值时,应用程序会通知操作系统自己不允许被跟踪调试。尝试跟踪调试应用进程,都会被拒绝,并且应用程序会收到一个段错误(segmentation violation)。

一个简单的 ptrace 反调试代码示例如下:

int main(int argc, char **argv){    ptrace(PT_DENY_ATTACH, 0, 0, 0);    printf("Try to attach to me!");    while (1)    {        sleep(1);        printf("take a break.");        fflush(stdout);    }    return 0;}

以上代码引自iOS Anti-Debugging Protections,见文未参考资料。

  • sysctl

sysctl 是另外一种常见的反调试方法,与 ptrace 通过阻止调试器依附到进程上不同,sysctl 通过获取进程信息中的标记,判断自己是否正在被调试。sysctl 函数原型如下:

int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);

sysctl 反调试代码示例如下:

#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <sys/sysctl.h>#include <stdlib.h>static int is_debugger_present(void){    int name[4];    struct kinfo_proc info;    size_t info_size = sizeof(info);    info.kp_proc.p_flag = 0;    name[0] = CTL_KERN;    name[1] = KERN_PROC;    name[2] = KERN_PROC_PID;    name[3] = getpid();    if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {        perror("sysctl");        exit(-1);    }    return ((info.kp_proc.p_flag & P_TRACED) != 0);}    int main (int argc, const char * argv[]){    printf("Looping forever");    fflush(stdout);    while (1)    {        sleep(1);        if (is_debugger_present())        {            printf("Debugger detected! Terminating...\n");            return -1;        }        printf(".");        fflush(stdout);    }    return 0;}

以上代码引自iOS Anti-Debugging Protections,见文未参考资料。

异常检测

App 加固除了数据加密、代码混淆、反调试等主动防护外,还可以动态检测 App 异常信息,上报给服务器,作为业务风控参考指标。当App 遭受注入、调试、钩子、篡改、重签名等攻击行为时,警告用户,封号,甚至杀死 App。

比如在使用重签名后的微信时,就会收到官方警告信息,甚至禁用某些功能。

常见的 App 异常检测包括:

  • 越狱设备检测

  • 重签名检测

  • 动态库注入检测

  • 调试检测

  • 钩子检测

总结

随着 MonkeyDev 这样的神器出现,iOS 逆向破解门槛越来越低。即使没有越狱设备,只需要一个砸壳后 IPA 文件,拖入模版工程,简单配置几个参数,就能实现头文件导出、符号表恢复、动态调试、重签名打包功能。 开发者必须提高自己的安全防护意识,不能仅依赖 iOS 系统的安全措施,不要等到 App 出现安全漏洞,公司造成经济损失,亡羊补牢,为时晚矣!

当然也没有绝对的安全,俗话说“道高一尺,魔高一丈”,微信、支付宝都有专门的安全研究团队,技术实力之强一般公司难以望其项背,然而相关的越狱插件却层出不穷,防不胜防。 加密、混淆、反调试等等加固手段只是安全防护的一道道锁,用来增加攻击者的破解难度。单纯依靠客户端的加固,要实现 App 的安全防护也远远不够,安全要从整个系统来考虑,前、后端协同努力,才能更大程度上保证系统安全。

参考资料

iOS 安全攻防

对 iOS app 进行安全加固

iOS App的加固保护原理

iOS安全–浅谈关于iOS加固的几种方法

如何做好iOS应用安全?这有一把行之有效的“三板斧”

为了保护公司的App安全,我用遍了市面上的加固产品

微信是怎么做到亿级用户的异常检测的

iOS 比 Android 还不安全? - 记一次和阿里资深安全工程师蒸米的交流

iOS Anti-Debugging Protections #1

iOS Anti-Debugging Protections #2