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代码混淆原理初探 的相关文章

  • iOS 自定义滑块删除两端的最小和最大空间

    我正在尝试使用自定义滑块 class MySlider UISlider override func trackRect forBounds bounds CGRect gt CGRect let customBounds CGRect o
  • NSCalendar 返回明年第一周上周一的错误日期

    我使用下面的代码使用随机日期来计算上周一 哪个工作文件但我的代码在明年日期中断 下面是相同的代码 NSDate date NSDate dateWithTimeIntervalSince1970 1483620311 228 NSLog c
  • 无法验证包:721772200.itmsp

    我写这篇文章是因为我有一个严重的问题 我在cartoonsmart 网站上购买了Commander Cool 游戏 然而 一个严重的问题发生了 iTune Connect 验证无法接受该申请 我尝试从两个不同的开发者帐户发布它 但错误仍然发
  • 如何在 Swift 中使用indexesOfObjectsPassingTest:

    IndexOfObjectsPassingTest 的声明在 Swift 中看起来像这样 func indexesOfObjectsPassingTest predicate AnyObject Int CMutablePointer
  • 如何正确创建迦太基 cartfile?

    我正在研究购物车文件 迫不及待地想 简单地创建一个购物车文件 就像所有说明所说的那样 只是 如何 简单地 创建一个 Cartfile 我创建了一个纯文本文档 将其命名为 cartfile 并在其中复制了一些依赖项 Ran carthage
  • 使用 NSString 进行 UTF8 解码

    我是 Objective C 新手 尝试使用以下示例将格式错误的 UTF8 编码 NSString 转换为格式良好的字符串苹果文档 http developer apple com library mac documentation Coc
  • Cordova 2.4.0 或 2.5.0 或 2.6.0 和 requirejs

    Cordova 2 4 0 及更高版本支持 AMD 加载到 javascript 中 我特别希望将 Cordova 2 5 0 与最新版本的 RequireJS backbone jquery jquery mobile 一起使用 我还没有
  • 无法连接到 iTunes Store(获取应用内购买列表)

    我正在尝试从我的应用程序的应用程序内购买项目商店中获取列表 这是我所做的 安装了新的配置文件并启用了应用内购买 替换配置文件很棘手 但我认为我的设置是正确的 验证税务和银行信息是否正常 该应用程序已在商店出售 创建测试用户 在测试设备上以测
  • 如何在iOS中处理1到3个手指的滑动手势

    我使用以下代码来处理代码中的 1 根手指滑动 UISwipeGestureRecognizer swipe UISwipeGestureRecognizer alloc initWithTarget self action selector
  • 将自定义数据包含到 iOS 故障转储中

    你好 堆栈溢出 有一个简单的问题要问您 当我的应用程序在用户的设备上崩溃时 是否可以将自定义错误数据嵌入到自动生成的 iOS 故障转储中 例如 我的 SQlite 数据库由于某种原因无法运行 例如 数据库文件已损坏 我无法从这个错误中恢复
  • iOS:生成pdf时绘制文本时如何设置字体?

    我在ios应用程序中使用drawpdf函数生成pdf 同时调用nsobject类中的drawtext函数 它根据我指定的框架和字符串清楚地绘制文本 我的代码是 void drawText NSString textToDraw inFram
  • Swift,以编程方式更改 UICollectionViewCell 和 UILabel(单元格内)的宽度

    我已将单元格 UICollectionViewCell 的宽度设置为等于 UICollectionView 的宽度 并且我尝试对该单元格中包含的 UILabel 执行完全相同的操作 我认为下面的代码准确地解释了我想要实现的目标 所以我在这里
  • 使用未解析的标识符“FlurryAdInterstitial”

    我正在尝试整合Flurry Interstitial Ads使用cocoapods in Swift and Xcode 7 1 1 我正在关注开发人员雅虎网站上的此文档 https developer yahoo com flurry d
  • 用户验证 Facebook 后未调用应用程序打开 Url 方法

    我已将 ios 应用程序中的 facebook 升级到 3 0 并使用提供的代码https developers facebook com docs howtos login with facebook using ios sdk http
  • UIViewControllerAnimatedTransitioning:旋转更改后黑屏片段

    我已经创建了一个视图控制器转换 只要我不更改设备方向 一切都正常 图 1 显示了应有的屏幕 然后我切换到下一个视图控制器 在其中更改方向 现在我回到第一个视图控制器并再次切换方向 然后我得到的结果如图 2 所示 出现黑色边框 请不要介意屏幕
  • ReactiveCocoa 将 SignalProducers 合二为一

    我正在使用 ReactiveCocoa 并且我有几个 SignalProducers let center NSNotificationCenter defaultCenter let signalProducer1 center rac
  • 访问目标 c 中的类方法。使用 self 还是类名?

    我正在学习 iOS 编程 并且对以下有关关键字 self 的使用的代码感到困惑 据我了解 self就像Java的this 它指的是当前实例 当我想调用类方法时 通常的方式应该是这样 PlayingCard validSuits 但是侵入实例
  • 如何在代码中编辑约束

    我有一个以 100 开始宽度限制的网页 当用户单击按钮时 我想将约束更改为 200 我试过这个 NSLayoutConstraint constrain NSLayoutConstraint constraintWithItem self
  • 在 UIWebView 中播放 Facebook 视频

    有谁知道如何在 Facebook 上播放视频UIWebView 我的应用程序将视频上 传到 Facebook 并检索视频的网址 我想将此网址嵌入到UIWebView播放 我已经为 youtube 解决了这个问题 但没有为 Facebook
  • TableViewController 的 viewDidLoad 未触发

    我一直在关注这个tutorial http www appcoda com ios programming sidebar navigation menu 有一个滑出式菜单 我添加了一个 TableViewController 它将显示文章

随机推荐