我注意到一个现象,不少团队在做 iOS 应用安全时直接上混淆工具,但不清楚混淆到底做了什么——是改了类名方法名就算完,还是能把控制流程也一并打乱。原生代码混淆其实分好几个层次,不同层次的混淆强度和成本差别很大。这里把几种主流方案的技术原理和操作方式拆开讲讲。
符号混淆
这是最基础的混淆层,把类名、方法名、属性名替换成无意义的乱码。OC 是动态语言,运行时通过 selector 调用方法,符号名暴露在 Mach-O 的 __objc_methname 段里,class-dump 可以直接导出所有接口声明。符号混淆就是把这一层的名字全改成无意义的乱码,让 class-dump 导出来的结果无法阅读。Swift 做了名字修饰(name mangling),符号天然比 OC 难读,但核心的类和方法仍然可以通过二进制分析定位。IpaGuard 在这层支持对 OC 和 Swift 的代码符号做全面替换,设置中还能调节混淆强度。
控制流混淆
在符号层之上,控制流混淆通过打乱代码的执行顺序来增加反编译难度。Obfuscator-LLVM 是这层比较成熟的方案,它在 LLVM 编译过程中插入不透明谓词、虚假控制流和代码扁平化,让 Hopper 和 IDA 等反编译工具还原出的伪代码逻辑混乱难以理解。问题是它只覆盖编译期能处理的代码,对于已经编译成二进制的 IPA 来说控制流已经固定,改不动了。另外每次 Xcode 更新后要等适配才能用。
字符串加密
硬编码在二进制里的 API 地址、密钥、日志字符串是攻击者重点搜寻的目标。字符串加密把明文字符串在编译时替换成运行时解密,这样二进制里不会直接出现敏感内容。Obfuscator-LLVM 有字符串加密 pass,IpaGuard 在 IPA 层也支持对二进制中的相关配置信息做处理。两层配合的话代码层做了符号混淆和字符串加密,资源层做了文件改名和 MD5 修改,覆盖面就宽了。
资源文件保护
代码之外的资源文件也需要保护。图片、plist、json、js 等资源文件的名称改成无意义字符串,MD5 重新生成。IpaGuard 在这块可以直接处理编译后的 .ipa,不需要源码。改名、改 MD5、加不可见水印、压缩 HTML/JS 在一并完成。可执行文件里的调试信息也会被自动清理掉,减少攻击者可利用的信息量。
两种路径怎么选
源码级混淆(Obfuscator-LLVM)强度高、能改控制流,但配置复杂、且只覆盖编译层。IPA 级混淆(IpaGuard)不需要源码、操作简单、能覆盖资源和调试信息,但改不了控制流。两个不是二选一的关系,先做源码层混淆再做 IPA 级资源保护,代码层和资源层都处理到位了,叠加效果比只做一层好得多。根据自己的实际开发环境和项目需求来组合使用就行。