iOS开发中有一个方向叫,你想工程开发,曾经也试着话时间去研究过相关的技术,熟悉使用那些相关的工具,但是毕竟没有专门实战过项目,也就只能简单的入门一下。而随着iOS开发年限的增长,和所了解到的东西,发现有不少公司或者朋友都在关注安全这一块,虽然Apple已经把安全做得很到位了,但是还是有这一块的问题存在,所以我根据个人的能力并结合网上的相关资料,简单的整理了一下,不管是作为了解,还是项目实战,或者为了面试,我都希望能有所帮助……
已经app store上线的程序,苹果采取DRM进行保护,这样直接使用反汇编工具IDA是提示文件加密的,但现在DRM不堪一击。
先来说说iOS开发中有那些安全风险
iOS应用安全
1、内购破解:
插件法(仅越狱)、iTools工具替换文件法(常见为存档破解)、八门神器修改
2、网络安全风险:
截获网络请求,破解通信协议并模拟客户端登录,伪造用户行为,对用户数据造成危害
3、应用程序函数PATCH破解:
> 利用FLEX 补丁软件通过派遣返回值来对应用进行patch破解
4、源代码安全风险:
通过使用ida等反汇编工具对ipa进行逆向汇编代码,导致核心代码逻辑泄漏与被修改,影响应用安全
面对这些iOS应用存在的风险,iOS应用如何防止被反编译,
防止反编译
防砸壳
我们要分析一个 app,最开始一般是砸壳
$ DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /path/to/XXX.app/XXX
然后将解密之后的二进制文件扔给类似 hopper 这样的反编译器处理。
注意:直接将没有砸壳的二进制文件扔个 hopper 反编译出来的内容是无法阅读的(被苹果加密了)
对于这一步的防范,有两种方式。
限制二进制文件头内的段
通过在 Xcode 里面工程配置 build setting 选项中将-Wl,-sectcreate,RESTRICT,restrict,/dev/null
添加到 “Other Linker Flags”
- setuid 和 setgid (Apple 不接受调用这两个函数的 app,因为它可以通过查看符号表来判断您的二进制运行文件是否包含这两个函数)
检测tweak(越狱设备)
我们会使用 TheOS 创建 tweak 类型的工程。然后针对我们要分析的类,使用提供的 logify.pl 命令生成的 mk 文件来打印该类所有方法的入参和出参。这对分析 app 的运行方式有很大的帮助。当然,我们也可以自己创建某个类的 mk,来 hook 某个函数,让它以我们想要的方式运行,
对于这一步的防范
可以在工程的 main 函数里面加入一层判断,首先读取 /Library/MobileSubstrate/DynamicLibraries 下所有的 plist 文件的内容,查看是否某个 plist 含有你的 app 的 bundle id,是的话,可以判定有人想利用 tweak 攻击你的 app,这时候你可以采取比如说将 app 给 crash 掉,或者限制某些功能等方式来应对
就是 MobileSubstrate 在 app 加载到内存的时候会先去检查 /Library/MobileSubstrate/DynamicLibraries 下面是否有需要加载的 tweak,有的话就加载,怎么判断有没有?就是根据 plist 里面的 bundle ID 判断的。
防 http 抓包
就是将 NSURLSessionConfiguration 的 connectionProxyDictionary 设置成空的字典,因为这个属性就是用来控制会话的可用代理的。
但是由于 OC 方法很容易被 hook,避免抓包是不可能的,所以,个人认为最好的方式是对请求参数进行加密(最好是非对称加密,比如 RSA)
加密硬编码的明文字符串
你的 app 被人抓包了,某些数据请求接口也被人发现了,那么很简单,逆向人员可以直接拷贝特征比较明显的字符串到 hopper 中搜索,通过查看该字符串被引用的地方,可以很快的找到相应的逻辑代码。
对于这一步的防范
需要做的就是对硬编码的明文进行加密或混淆。 有个开源代码可以用,UAObfuscatedString,但是这个开源混淆代码写出来的字符串是相当长的(也就是麻烦),同时不支持加密,还有一个不错的MixPlainText(可以在编译期间加密所有代码中的明文字符串,在 app 运行的时候解密字符串)
使用 Swift 开发
class-dump 工具目前就不支持含有 Swift 的二进制文件。 TheOS 也是最近才开始支持 Swift,但是还没有加到主分支上(可以参见 Features)。所以目前来看,至少 Swift 可能比纯 OC 的工程要安全一点点
使用静态内连 C 函数
由于 OC 语言的动态性,导致 OC 的代码是最容易被破解分析的。在安全性上,更推荐使用 C 语言写成的函数。但是 C 语言的函数也是可以被 hook 的,主要有3种方式:
- 使用 Facebook 开源的 fishhook
- 使用 MobileSubstrate 提供的 hook C 语言函数的方法
- void MSHookFunction(void function, void replacement, void** p_original);
使用 mach_override,关于 mach_override 和 fishhook 的区别请看 mach_override 和 fishhook 区别
由于上面这三种方式可以 hook C 函数。要想不被 hook 解决方法是使用静态内联函数,这样的话需要被 hook 的函数没有统一的入口,逆向人员想要破解只能去理解该函数的逻辑。
使用 block
严格来说使用 block 并不能很大程度提高安全性,因为逆向人员只要找到使用该 block 的方法,一般来说在其附近就会有 block 内代码的逻辑。
其实使用 block 的安全性是比直接使用 oc 方法是要高的。尤其是含有嵌套的 block 或者是作为参数传递的 block,处理起来就更加复杂了。所以,如果能将内敛 C 函数,嵌套 block , block 类型参数组合起来的话,安全性应该是会有一定提升。
代码混淆(或者加密)
方法体,方法名高级混淆
对应用程序的方法名和方法体进行混淆,保证源码被逆向后无法解析代码
程序结构混排加密
对应用程序逻辑结构进行打乱混排,保证源码可读性降到最低
本地数据加密
对NSUserDefaults,sqlite存储文件数据加密,保护帐号和关键信息
URL编码加密i
对程序中出现的URL进行编码加密,防止URL被静态分析
网络传输数据加密
对客户端传输数据提供加密方案,有效防止通过网络接口的拦截获取数据
代码混淆的方式有几种
- 添加无用又不影响逻辑的代码片段,迷糊逆向人员
- 对关键的类、方法,命名成与真实意图无关的名称
对于第二种,目前有一些自动化工具,个人认为最好的一个加密混淆工具是 ios-class-guard,不过目前这个项目已经停止维护了。但是这种方式的混淆我觉得才是最终极的方案。
念大婶在博客中介绍了两种方法,用于保护代码逻辑,对抗逆向分析
- 代码混淆 通过宏定义,混淆objective-c消息(函数),用于对抗class-dump。
- 敏感逻辑用C实现 通过static关键字和函数指针的方式,将关键逻辑隐藏,可以对抗class-dump和Cycript攻击。
其实只有成功的应用才会被反编译资源。。。如果应用知名度不够高或者没什么用户量的话,无需浪费时间避免反编译,而是花时间、精力和金钱来迭代版本和推广App!
######相关链接推荐