无源 iOS 加固详解

小夏 科技 更新 2024-01-29

导读:在移动安全中,客户端层的安全性非常重要,因为移动应用通常在客户端设备上执行,并处理敏感的用户数据。通过强化您的应用程序,您可以有效地防御逆向工程和恶意攻击,并保护应用程序的机密信息和知识产权。 加固通过混淆、加密保护、反调试等方式为应用提供强大的安全层,使攻击者更难破解和修改应用。

1. iOS加固方案

目前主流的加固方案有三种:

源码加固:直接基于源码工程混淆,这种模式一般只能在开发者环境中部署加固工具,需要一些额外的环境配置。

Bitcode 加固:因为 BitCode 本质上是 IPA 编译过程的中间部分,其加固原理与源码没有太大区别,主要区别在于对接模式,通过用 BitCode 上传包,可以在加固厂商处进行加固过程,降低对接和环境部署的成本。

无源加固:基于IPA包的加固,由于作用于二进制文件,功能控制不如源码灵活,但访问成本低。

在新的 Xcode 15 发布后,BitCode 生成开关已被正式移除。

因此,iOS 客户端强化最终可能只有两个选项:源代码强化和无源代码。 由于源码加固方案是开源的,原则上有参考依据,这里就不多说了,下面简单介绍一下源码加固的一些原理。

2. iOS无源码加固

任何平台的源代码强化都无法解壳文件格式,iOS 也不例外。 与Android下的ELF文件一样,iOS的可执行文件是一种猛男格式文件。 从程序加载和操作的角度来看,男子气概和精灵有以下相似之处和不同之处。

相似之处:两者都使用段来描述内存加载范围和权限,并使用段来更详细地划分 ** 和数据。

两者都包含符号表和字符串表,用于记录函数和变量信息。

两者都有重新定位的概念。

区别:iOS 部分的含义更明确,尤其是 OBJC 和 SWIFT 相关信息。

iOS 支持延迟加载。

iOS 对符号进行了更严格的分类和排序。

iOS 中的 Load Command 更类似于 ELF 中 dynamic 和 PHDR 的组合,是对程序结构和依赖关系的描述。

要了解平台程序是如何强化的,首先需要了解加载和执行程序的过程。

负荷。 加载过程包括内存映射、内存修复和初始化过程。

从文件内容来看,男子气概包含三大数据结构。

Macho Header:包含 mach-o 文件的基本信息,如文件类型、CPU 类型、加载命令数等。

load 命令:每个 load 命令都包含一个标头和数据。 标头包含加载命令的类型、大小和其他相关信息。

segment:用于描述mach-o文件中的segment、data segment和loader所需的数据信息。

通过解析命令结构,可以读取与load命令关联的所有数据,并且数据必须在上述数据范围内。 整个男子气概文件大小等于上述三个数据大小的总和。

在程序的编译过程中有一些约定,一些自实现的变量或函数的调用使用了相对地址,可以简单理解为与程序加载的第一个地址的偏移量,而不是实际地址。 但是,当程序加载到内存中时,第一个地址通常是随机的,并且这些地址需要在运行之前进行修复,这个过程称为变基。

在程序开发过程中,如果使用动态库中的函数或变量,生成的二进制产品会识别出这些需要导入的函数或变量,并将函数地址保留在地址区(得到的表)中。 动态链接的过程是将函数地址或变量值固定在这些位置,这个过程称为绑定。

程序加载过程很容易理解,可以分为以下三个过程。

根据分段设置的地址分配数据存储和权限。

根据 rebase 中的规则,对编译生成的相对地址进行修复并转换为真实地址。

根据 bind 中的规则,固定编译所依赖的其他函数和变量的地址,以保证程序可以正常调用。

由于 iOS 版本的迭代,rebase 和 bind 的描述以及数据的存储方式因版本而异。

在 iOS 14 下,您可以通过解析 lc dyld info 或仅解析 lc dyld info 来变基和绑定操作。

rebase 和 bind 操作都是根据 ios 自定义的一组操作码进行解析的,可以参考 dyld 源码了解操作码的处理过程。

变基通过一系列操作码执行特定操作,其结果是确保在加载应用和随机化内存基址时可以固定与程序关联的内部地址。

bind 使用一组不同的编码,bind 进程用于绑定符号,例如当程序使用其他库中的变量函数时,需要将地址信息写入程序内存中,以保证这些函数和变量的正常访问和使用。

iOS 14 及以上版本兼容 14 以下的格式,但提供了新格式(修复链)以完成动态链接。 编译应用程序时,如果选择仅支持 iOS 14 或更高版本,则 Macho 文件中不再有 LC Dyld Info 或 LC Dyld Info Only,并且 Dyld Chained Fixups 和 Dyld Exports Trie 将替换为 Dyld Chained Fixups 和 Dyld Exports Trie。

Dyld 链式修复对应于旧版本的 bind 和 rebase,其中删除了惰性绑定机制,但 bind 和弱绑定之间仍然存在区别。

Dyld Exports Trie 对应于旧版本的导出符号。

dyld 链式修复的数据图如下:

上面的 iOS 重新定义了一组重新定位数据的方法,Fixup Chains 有两个关键功能:

初始化导入表,该表是一个包含符号信息和 lib 信息的链表或数组,指向符号的 **,其数组索引与绑定数据相关联。

引导 dyld 在 segment 数据中找到 dyld 链式的起始位置,计算出数据中真正需要修复的地址,通常在 got 表或者一些引用的局部变量中。

在数据部分,初始化方法与以前的版本不同。

在旧格式中,您可以指定哪些地址需要变基,哪些地址需要绑定。 在真正要修复的地址中,默认值可能是 0 或相对地址。

新版格式 fixupchains 只获取数据的第一个地址,需要通过 chainedfixuppointerondisk 的结构以链表的形式对数据进行解析,并根据结构类型进行相应的修复操作。

新版本的 macho 增加了格式的复杂性,但在大量重定位的程序中,数据量可以减少很少。

执行。 执行过程涉及一些默认情况下在程序中执行的接口。 在这里,我们更多地关注 main 函数在启动之前的行为。

在类和类扩展中加载和注册方法。

调用 objc 的 +load 函数。

在 mod init func 中执行函数,包括但不限于以下规则中声明的函数。

声明为属性(构造函数)的 C 函数)。

已在全局变量中初始化的对象。

执行 main 函数。

关注启动过程的目的是在做加固时,在合适的时间初始化加固相关的功能,比如在负载中初始化,或者插入init进行初始化。 您需要确保初始化时间在加固函数生效之前。

场景和效果。

在确认了程序的加载和执行过程后,我们可以对程序进行数据加密、混淆转换、功能对抗等操作,以达到所需的保护效果。 二进制密码混淆几乎总是基于汇编和文件处理,这比源代码更难,但如果处理得当,其分析难度并不比源代码加固差,相反,由于汇编和文件处理的灵活性,修改特征会更容易。

以下是保护作用之一:

从效果上看,不像普通的混淆,表面有一层抽取,而真正的**次级混淆,不仅无法分析函数体,甚至连参数类型都无法正常解析。

三、结语

在本文中,我们详细介绍了一些 iOS 应用程序强化的工作原理。 希望能帮助一些需要了解强化的朋友了解一些原理知识。 在当今的数字时代,应用程序安全至关重要。 为了保障用户数据和业务的安全,我们不断完善iOS加固产品,为开发者提供全面的应用防护解决方案。

如果您对我们的加固产品感兴趣或想了解更多信息,请访问网易盾**。 我们很乐意为您提供定制的解决方案,以满足您的安全需求。

相似文章

    Dynamic Dock 无障碍权限详解,打造无障碍用户体验

    在当今的数字世界中,辅助功能权限变得越来越重要。无论是出于法律要求,还是为了提供更好的用户体验,Dynamic Dock 无障碍权限的开放都成为了很多人关注的焦点。本文将仔细介绍如何打开 Dynamic Dock 的辅助功能权限,以帮助您更好地理解和应用此功能。.Dynamic Dock 的辅助功能...