Jerry's Blog

Less is more, Live and learning

Hello,I'm an iOS developer in China.


iOS代码混淆之编译优化(三)

这是iOS代码混淆系列文章的最后一篇,前两篇可以点击下方链接查看

iOS代码混淆之方法名替换(一)

iOS代码混淆之资源替换(二)

前言

前2篇文章已近讲了对于函数名的混淆,对项目中关键信息、资源文件的修改等相关混淆手段。但是,仅仅做到这几点就能万事大吉吗,黑客仍然可以通过分析代码逻辑或伪装代码来寻找程序漏洞,那么还有其他更坚固可靠的混淆方式呢,接下来就介绍下编译器级别的加固混淆方案。

iOS编译原理

iOS 开发中 Objective-C 和 Swift 都用的是 Clang / LLVM 来编译的。Clang是作为编译前端,LLVM做为编译后端,共同完成了iOS项目代码的编译阶段。

Clang(编译前端)

Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器,目的是提供惊人的快速编译,比 GCC 快3倍,其中的 clang static analyzer 主要是进行语法分析,语义分析和生成中间代码,当然这个过程会对代码进行检查,出错的和需要警告的会标注出来。

LLVM(编译后端)

LLVM是一个模块化和可重用的编译器和工具链技术的集合,LLVM 核心库提供一个优化器,对流行的 CPU 做代码生成支持。LLVM 比较有特色的一点是它能提供一种代码编写良好的中间代码IR,这意味着它可以作为多种语言的后端,这样就能够提供语言无关的优化同时还能够方便的针对多种 CPU架构生成可执行代码。

Hikari

Hikari 是一个基于 Obfuscator-LLVM 的改进,增加了一些额外的自定义构建通道,更简单易用,结合使用文档,可以快速体验编译级别的代码加固效果。

OLLVM 是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对 LLVM 的代码混淆工具,以增加对逆向工程的难度。目前,OLLVM已经支持LLVM8.0版本。

安装

  1. 在这里下载最新release版的pkg文件双击安装
  2. 安装完成后,重启Xcode就可以在Xcode-> Toolchains -> Hikari 中看到已经有了编译器选项。

使用

然后在 Build Settings -> Other C Flags 中加入混淆标记

-mllvm -enable-bcfobf 		启用伪控制流  
-mllvm -enable-cffobf 		启用控制流平坦化
-mllvm -enable-splitobf 	启用基本块分割  
-mllvm -enable-subobf 		启用指令替换  
-mllvm -enable-acdobf 		启用反class-dump  
-mllvm -enable-indibran 	启用基于寄存器的相对跳转,配合其他加固可以彻底破坏IDA/Hopper的伪代码(俗称F5)  
-mllvm -enable-strcry 		启用字符串加密  
-mllvm -enable-funcwra 		启用函数封装
-mllvm -enable-allobf        依次性启用上述所有标记

修改Xcode 相关配置,得到混淆效果。

  1. 选择Xcode -> Toolchains -> Hikari 将混淆工具和项目关联
  2. 将所有与要运行的 target 相关的 target(包括pod进来的库),在BuildSetting中修改Enable Index-While-Building 的值改为 NO
  3. 修该BuildSetting 中的Optimization Level 的值为 None[-O0]
  4. 重新编译项目即可。

可能遇到的问题

  1. 编译过程中报错,内容如下:

    Undefined symbols for architecture arm64:
      "___isOSVersionAtLeast", referenced from:
          -[MyLayoutPos posNumVal] in MyLayoutPos.o
          -[MyLayoutViewSizeClass myLayoutTopPadding] in MyLayoutSizeClass.o
          -[MyLayoutViewSizeClass myLayoutBottomPadding] in MyLayoutSizeClass.o
          -[MyLayoutViewSizeClass myLayoutLeadingPadding] in MyLayoutSizeClass.o
          -[MyLayoutViewSizeClass myLayoutTrailingPadding] in MyLayoutSizeClass.o
          _HikariFunctionWrapper.7182 in MyLayoutSizeClass.o
          _HikariFunctionWrapper.7188 in MyLayoutSizeClass.o
          ...
    ld: symbol(s) not found for architecture arm64
    clang-7: error: linker command failed with exit code 1 (use -v to see invocation)
    

"___isOSVersionAtLeast"符号在arm64架构下找不到,根据以往的经验,出现这种错误的时候一般都是没有导入相关动态库(.Framework),或静态库(.a)等造成的。庆幸的是已经有人在GitHub上提交了issues并给出了解决方案:

作者的回答: You probably need to explicitly link to clang-rt, available in your LLVM Toolchain directory Sorry I mean clang-rt, at Hikari.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/libclang_rt.ios.a (or macOS suffix)

意思是说:可能是缺少某个编译器库造成的,需要手动将这个库添加到Xcode的Linked Frameworks andLibraries动态链接库目录中。并说明了此库所在的目录Hikari.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/libclang_rt.ios.a,意思是在Hikari编译器的子目录中找到文件libclang_rt.ios.a,并将他引入到Xcode项目中即可。查找路径顺序如下:

img1

img2

img3

img4

打开Show in Finder 定位到Hikari的安装目录,然后按照此路径usr/lib/clang/10.0.0/lib/darwin/libclang_rt.ios.a找到libclang_rt.ios.a文件,添加到Xcode的链接库中即可。

  1. 使用Hikari编译后,Archive 打包后,需要上传App Store 时可能会出现 “App Store” 按钮消失的问题,Archives页面右下角会出现一个提示字符:

“App Store distribution requires an Xcode Default Toolchain”

意思是:App Store 发布版需要使用Xcode 默认的Toolchain (编译工具)

如下图所示:

img5

img6

出现这个问题是因为,我们使用了Hikari编译器 Archive的包,所以需要想办法去除这个警告即可。在Hikari的wiki文档中,我们发现作者在AppStore Guideline 安装指南中已经说明了解决方案:

Alternatively, you could use Hikari’s toolchain to build normally then remove DefaultToolchainOverrideInfo from the IPA’s Info.plist

只需要在Arichive 包中的Info.plist 中找到这个值”DefaultToolchainOverrideInfo” 删除即可。可以看出此字段正是标记是否使用默认Toolchain的关键。

操作步骤为下面图示顺序,注意:记得删除字段后,一定要重启Xcode才能生效的。

img9

img7

img8

img10

删除上面红色框所示的字段即可,完了后要重启Xcode才会生效。

总结

这是iOS代码混淆系列文章的最后一篇,着重讲解了iOS编译原理相关知识,编译前端Clang和编译后端LLVM在整个编译期间各自所做的工作。后面重点讲述了如何使用开源工具Hikari 进行编译混淆、加固,在实践过程中,对遇到的坑也讲了解决方案。

希望看了这几篇文章的小伙伴,能对iOS代码混淆有个初步的学习和了解,最好能结合自身条件加以实践,想必会理解的更深刻。

最近的文章

LLVM架构与Clang

LLVM简介LLVM是一个模块化的、可重用的编译器和工具链技术的集合。最开始是由克里斯·拉特纳(Chris Lattner)在伊利诺伊大学主导开发的一个研究项目,目的是提供一个现代的、基于SSA编译策略的,能够支持任意编程语言和动态编译的编译器和工具链的集合。后来,克里斯及其他的团队被苹果雇佣了,为实现苹果系统中的各种用途而开发LLVM系统。 克里斯·拉特纳也是Swift之父,在苹果任职期间主导研发了Swift语言,编译部分也采用了LLVM工具链技术。LLVM名称最初的由来是低级虚拟机首字...…

LLVM Clang继续阅读
更早的文章

iOS代码混淆之资源替换(二)

这是iOS代码混淆系列文章的第二篇,其他两篇可以点击下方链接查看 iOS代码混淆之方法名替换(一) iOS代码混淆之编译优化(三)为什么要替换项目资源在某些公司项目开发当中 ,有时候需要通过技术手段,多次上架同一款产品。这些功能类似,且界面不同的产品也称作马甲包。为了达到将同一个包,经过较少的改动,快速更改为另一个类似的产品时,在代码混淆的基础之上还需要修改项目名称、静态资源等来达到目的。需替换的资源及注意事项 工程内部:工程名称、类名前缀、BundleId、icon、启动图、静...…

iOS 代码混淆继续阅读