iOS代码混淆原理初探

2023-05-16

我们在手游平台SDK的iOS版本中, 除了AppStore官方支付之外还集成了第三方支付(微信支付H5和支付宝支付H5版本)。 如果用于企业签,不需要做处理,直接使用即可。 但是如果需要上架AppStore,我们需要屏蔽第三方支付。 这个我们后台设置开关,直接后台切换支付方式即可。 上架审核的时候, 切换为Appstore支付;审核通过的时候,切换为第三方支付。因为第三方支付,是H5方式,不会被机审检测到。 同时,防止被抽查,后台也可以设置,将每次前多少次支付,设置为AppStore支付,之后用第三方支付,降低被抽查到的风险。

但是只是做到这个还不够, 如果需要用这套SDK上多个游戏,或者多个马甲包。 防止一样的代码被4.3的风险或者被代码标记的风险,我们需要对SDK的代码进行混淆, 每次出一个马甲SDK。
关于iOS代码的混淆, 查阅了网上很多文章,混淆的原理性文章都是多年之前的了纯字符随机替换,这种按照目前的机审政策,已经很难过审了。另外也有一些混淆工具,不过是按时间收费的。

所以,我们这里就U8SDK下面的XSDK(手游平台SDK)这个项目,来谈一谈iOS中的代码混淆。

如果在开发之初, 开发者经验丰富, 或者运营经验丰富, 提前将混淆这个事情重视起来, 那么混淆就会很简单。 可以事先指定代码编写规则,尽量保证类方法变量等的唯一性。 比如所有的类以X开头,所有的方法函数以F开头,所有的属性以P开头, 所有的内部变量以S开头等等这样的规则。 那么在后续写混淆的时候,几行代码就可以搞定了。

但是我相信多数项目和XSDK一样,可能都是事后诸葛亮,等到需要做这件事情的时候,才发现代码命名随心所欲带来的代价。 但是,为了方便混淆来重写框架是不可能的了,程序也不愿意呀。

所以,我们就只能来费些心思来写混淆脚本了。 我们采用python来写混淆脚本,用python来干这个事情,还是很合适的。

首先,我们确定一下混淆目标:

列出了混淆目标, 我们来设计混淆思路了。

一、词汇替换

混淆,也就是替换, 将老的名称替换为新的名称。 之前网上很多都是使用纯随机字符来替换,但是目前这个方式风险很大,很容易被苹果检测出来有隐藏功能的意图。

所以,我们采用双词库的形式来进行混淆。 我们准备两套词库。 一套是常用的单词词库(词汇量大概1000个);一套是程序常用单词词库(词汇量大概100个)。

在生成混淆后的新名称的时候, 我们根据需要, 从两套词库中随机单词,进行拼接。

比如混淆类名称的时候, 当前有一个类名是AppStorePay。 我们先从常用词库中随机单词进行拼接,直到长度大于等于AppStorePay长度的时候为止。 然后再从程序词库中随机一个单词作为后缀。 这样混淆后的名称可能是OneForTestListener这样的形式。 看起来就接近了正常的类名命名。

另外混淆的时候, 我们记录一个已经生成的新的名称的列表, 如果生成的新名称已经存在,那么重新生成。 防止生成的新名称重复导致问题。

二、混淆思路

混淆的时候, 我们可以逐行混淆, 但是这种方式, 误差可能会很大。 我们希望执行混淆之后, 一次性编译通过, 不需要再手动修改某些混淆失败的地方。 所以我们放弃了逐行混淆的方式。采用一种更加精细化的混淆方式。

另外混淆的方式,我们希望尽可能地符合语法通用的规则,而不简简单单地适应XSDK这个项目。 (防止后续我们其他项目也需要做混淆)

首先,我们将代码目录下所有的代码文件加载进来, 于是我们设计一个符合代码结构的层级:

图中我们可以看到, 我们首先设计了四个类。

XFolder代表一个代码目录;

XClass类代表一个类文件;

XFunction类代表一个类中的一个函数;

XProperty类代表一个类中的一个属性。

设计好了这个之后,我们就可以调用XFolder中的load方法,加载XFolder对应目录下的所有class文件,以及所有Class文件中的函数和属性。

三、混淆实现

将代码类文件都加载到内存之后, 现在我们就需要对混淆目标中的各个目标的混淆进行实现了。 我们设计一系列混淆实现类,来进行混淆:

1、PCHCodeMixer: 对XSDK.pch文件中定义的全局变量进行混淆,同时对源码中所有引用的地方进行替换

2、PropertyCodeMixer: 对每个类中定义的属性进行混淆, 同时对源码目录中所有引用的地方进行替换

3、FunctionCodeMixer: 对每个类中定义的函数进行混淆,同时对源码目录中所有引用的地方进行替换

4、FunctionCodePostMixer: 对函数内部定义的属性进行混淆,同时在合适的地方插入垃圾代码。

5、ClassCodeMixer:对类名称进行混淆,同时对源码目录以及xcode工程文件中所有引用的地方进行替换

6、ResourceMixer:对资源进行混淆, 对所有图片文件进行md5变更,对所有图片名称进行混淆,对所有源码目录以及xcode工程文件中所有引用的地方进行替换

7、GlobalNameMixer: 对目录,对框架名称,对Bundle名称等全局名称进行混淆。 同时对所有文件和xcode工程文件中所有引用的地方进行替换

有了以上这些组件,就可以完成对框架代码和资源进行混淆和替换。另外还有两个辅助的mixer类,主要完成对demo工程和文档内容的替换:

8、DemoMixer: 对demo工程中的引用进行替换。

9、DocMixer:对文档中对应的引用进行替换。

另外注意下,混淆的时候, 通过正则表达式来解析对应的函数和属性, 但是因为iOS的特殊性, 函数中有中括号,而且函数的地方可以无限嵌套。 所以,在对函数进行处理的时候,可以采用栈结构来解析和匹配。
另外解析函数体内容的时候, 我们也是采用栈结构来解析。 也就是先解析出了类中所有的函数名称, 然后从后往前解析函数体内容。这样解析也方便很多。 其他地方的混淆,基本用正则表达式就可以完成,只是写正则的时候或者用正则匹配替换的时候, 尽可能的精细化规则,严谨地匹配。替换的时候, 按照被替换串的长度,优先替换长串,再替换短串。

目前XSDK代码经过混淆工具混淆之后, 无需再手动替换, 直接xcode打开,编译重新生成XSDK的framework和bundle文件,然后替换到XSDK的Demo工程中的SDK目录下,然后直接运行XSDK Demo就可以了。

如果提供给研发那边的话, 只需要将上面替换过的XSDK Demo和文档提供给研发那边即可。 经过混淆工具混淆之后, Demo工程和文档中都会被替换,无需手动替换操作。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS代码混淆原理初探 的相关文章

  • UITableView 无法一直滚动到底部[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我只是好奇 我做了一些UITable
  • 永远不会在 ios 的 google API 中获取上传数据进度

    我在我的应用程序中使用 Google Drive API 从我的应用程序上传文件 到目前为止 我成功了 并找到了上传所有类型文件的良好结果 我跟着谷歌示例 https developers google com drive examples
  • iOS 视频压缩 Swift iOS 8 损坏的视频文件

    我正在尝试压缩用户相机从 UIImagePickerController 拍摄的视频 不是现有视频 而是动态视频 以上传到我的服务器 并花费少量时间来完成此操作 因此较小的尺寸是理想的选择 而不是 30 较新质量的相机为 45 mb 这是在
  • prepareForSegue 和 PerformSegueWithIdentifier 发送方

    我想知道标题中的函数如何工作以及发送者参数 假设单击按钮调用了performSegue方法 那么这是否也调用了prepareSegue方法 是否在performSegue方法之前但在按下按钮之后调用prepareSegue方法 另外 这两个
  • 在集合视图单元格中播放视频,就像在 Facebook 应用程序时间轴中播放的视频一样

    我想在集合视图单元格中播放视频 要求就像 Instagram 时间线 播放视频就像在 facebook 时间线中播放视频 为此 我使用了 UICollectionViewCell 我有一些图像 没有视频 现在我是来自画廊的图像 我正在使用相
  • 自定义 OpenVPN iOS 客户端 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在开发一个自定义 iOS OpenVPN 客户端 我找到了这个原生 OpenVPN 客户端核心源码https staging op
  • 解包可选值时意外发现 nil - 使用 ALAMOFIRE

    我正在尝试使用 Alamofire 获取 JSON 格式的数据 当我使用一个 URL 时 它工作正常 当我使用另一个 URL 时 我在解包可选值时收到错误 我似乎无法追踪错误来自哪里 我已采取将代码放入 ViewDidLoad 来跟踪错误
  • ios Facebook 添加 FBNativeAdView 作为子视图

    我想使用预建视图FBNativeAdView 不想自定义 FBNative 广告 如link https developers facebook com docs reference ios current class FBNativeAd
  • 从 AVAudioRecorder 获取分贝

    我正在尝试从 AVAudio 录音机获取分贝值 这是我目前的代码 我有一个启动录音机的方法 然后是一个读取分贝值的方法 var recorder AVAudioRecorder 全局定义的记录器 然后在此处使用 func init reco
  • 使用 iPhone 控制蓝牙音频设备

    我正在寻找为 iPhone 编写应用程序 它将能够控制汽车中的收音机和 CD 播放器 收音机和播放器具有可用的蓝牙连接 我开始这个问题是为了获得这个地方所需的所有信息 我有几个问题 但如果您发现任何我没有要求的对我开始开发此应用程序不重要的
  • 在 SwiftUI 中,如何执行手势但将手势转发到其后面的视图?

    我正在创建一个工具提示系统 如果用户触摸工具提示之外的任何地方 我想关闭工具提示 我希望这样在工具提示之外的触摸既可以消除工具提示 又可以激活用户点击的任何控件 因此 您可以打开一个工具提示 然后仍然单击工具提示外部的按钮 并在第一次点击时
  • 如何在 Safari 上打开本地 html 文件?

    我想打开本地 html 文件Safari集成到我的Swift 3应用 我知道如何使用网址来做到这一点 这是我用来执行此操作的代码 let encodedString url addingPercentEncoding withAllowed
  • Mapkit 在 IOS 13 中使用过多的 CPU

    最近 在一些用户更新到 iOS 13 x 后 我的 iOS 应用程序开始频繁崩溃 在 iOS 12 x 中没有出现该问题 我正在使用 Mapkit 渲染一些 MKPolygons 和 MKPolylines MKPolylines 被删除并
  • 将 UIRefreshControl 用于 UIWebView

    我在 iOS 6 中看到了 UIRefreshControl 我的问题是是否可以通过下拉来刷新 WebView 而不是像在邮件中那样让它弹出 我使用 rabih 的代码是 WebView UIRefreshControl refreshCo
  • ExpandableLabel iOS 中的“少看”

    我正在使用第三方库可扩展标签 https github com apploft ExpandableLabel实施一个see more特征 我正在寻找仅快速的解决方案 其中包含标签中的文本而不是按钮中的文本 因此这可以完美地工作 添加库并更
  • 如何避免 NSNumberFormatter 中的四舍五入

    我试图拥有一个最大精度为 2 位小数的数字字符串 而其余小数只是被修剪掉而不是四舍五入 例如 I have 123456 9964 I want 123456 99 gt Just want to trim rest of the deci
  • 尝试注册 RCTBridgeModule 类 RCTFileReaderModule

    尝试为名称 FileReaderModule 注册 RCTBridgeModule 类 RCTFileReaderModule 但该名称已由类 FileReaderModule 注册 尝试使用命令react native run ios在i
  • TableView 中图像的大小不正确

    我正在使用来自 URL 的图像创建一个表视图 但图像不会调整到所有视图的大小 直到我将其按入行中 知道为什么会发生这种情况吗 这是一个自定义的表格视图 我的代码是 UITableViewCell tableView UITableView
  • 使用 NSFileHandle 覆盖数据

    使用 NSFileHandle 使用 truncateFileAtOffset 从文件末尾删除 n 个字符非常容易 void removeCharacters int numberOfCharacters fromEndOfFile NSF
  • 如何像谷歌日历一样将单元格的内容滚动到表格视图中的另一个单元格中?

    我希望用户界面像谷歌日历那样进入桌面视图 它在不同的行中显示相同的日期事件 但是当您向上或向下滚动时 左侧的日期也会向上向下滚动 Can you please help me how to achieve this Please take

随机推荐