一、基本概念
- 1.1、什么是加固?
加固是为了增加应用的安全性,防止应用被破解、盗版、二次打包、注入、反编译等 - 1.2、常见的加固方式有
- 数据加密(字符串、网络数据、敏感数据等)
- 应用加壳(二进制加密)
- 代码混淆(类名、方法名、代码逻辑等)
......(不同平台还有不同的做法)
- 1.3、iOS程序可以通过
class-dump
、Hopper
、IDA
等获取类名、方法名、以及分析程序的执行逻辑
如果进行代码混淆,可以加大别人的分析难度
二、代码混淆的实战
- 2.1、iOS的代码混淆方案
- 第一种:源码的混淆,混淆项目中下面的方面
- 类名
- 方法名
- 协议名
- 第二种:LLVM中间代码IR的混淆(容易产生BUG)
自己编写Pass
ollvm:https://github.com/obfuscator-llvm/obfuscator
- 2.2、源码的混淆 - 通过宏定义混淆方法名、类名
- 我们主要是针对,类名,方法名,属性名来进行混淆,混淆太多上架会被拒绝
- 我们使用宏定义
- .h 文件
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface JKPerson : NSObject - (void)run; - (void)setName:(NSString *)name age:(int)age; @end NS_ASSUME_NONNULL_END
- .m文件
#import "JKPerson.h" @interface JKPerson () @end @implementation JKPerson - (void)run { NSLog(@"----%s----",__func__); } - (void)setName:(NSString *)name age:(int)age { NSLog(@"----%s----%@----%d",__func__, name, age); } @end
- pch文件
#ifndef Obfuscation_pch #define Obfuscation_pch // 针对类名进行混淆 #define JKPerson rererme // 针对方法名混淆 #define run xsdfd // 针对方法名进行混淆 #define setName ahshshb // 针对方法中的参数进行混淆 #define age kkjjjo
- 2.3、源码混淆注意点
- 注意点
- 不能混淆系统方法
- 不能混淆init开头的等初始化方法
- 混淆属性时需要额外注意set方法
- 如果xib、storyboard中用到了混淆的内容,需要手动修正
- 可以考虑把需要混淆的符号都加上前缀,跟系统自带的符号进行区分
- 混淆过多可能会被AppStore拒绝上架,需要说明用途
- 建议
给需要混淆的符号加上了一个特定的前缀 - 小工具参考
MJ老师的 MJCodeObfuscation,使用方法MJ老师的 github 有说明,扫描源码
- 2.4、代码混淆工具:ios-class-guard
- 第三方工具 ios-class-guard ,多年不更新了,不建议使用,如果有能力修改源码,可以使用
- 它是基于class-dump的扩展,
扫描可执行文件
,所有的东西都进行混淆 - 用class-dump扫描出可执行文件中的类名、方法名、属性名等并做替换,会更新xib和storyboard的名字等等
- 用法
// 安装 ios-class-guard brew install ios-class-guard // 具体的使用 ios-class-guard [options] <mach-o-file>
- 具体的使用如下
ios-class-guard --sdk-root /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -X /Users/wangchong/Desktop/代码混淆/MJ老师的工具混淆/TestObfuscation/TestObfuscation/Base.lproj -O 生成文件的.h文件 symbols.json TestObfuscation
- ios-class-guard --sdk-root 模拟器路径 -X xib的路径 -O 生成文件的.h文件 symbols.json 可执行文件的路径
提示:
symbols.json
是映射文件
- 常用参数
- --sdk-root <path>:用于指定SDK路径,如果是模拟器SDK,一般路径就是:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
- --sdk-ios:相当于指定SDK路径为真机设备SDK
- -X <path>:用于指定xib、storyboard所在目录,它会递归搜索
- -O <path>:生成的混淆头文件路径
- -m <path>:符号映射表(默认是symbols.json)
三、字符串加密
- 3.1、字符串加密的简单介绍
- 很多时候,可执行文件中的字符串信息,对破解者来说,非常关键,是破解的捷径之一
- 为了加大破解、逆向难度,可以考虑对字符串进行加密
- 字符串的加密技术有很多种,可以根据自己的需要自行制定算法
- 这里举一个简单的例子
- 对每个字符进行异或(^)处理
- 需要使用字符串时,对异或()过的字符再进行一次异或(),就可以获得原字符
- 3、第三方库 MJCodeObfuscation 对字符串进行加密
- 1>、我们以下面的字符串为例: NSString *str1 = @"dcfg342";,使用工具加密如下
/* dcfg342 */ extern const MJEncryptStringData * const _2309389973; /* dcfg342 */ const MJEncryptStringData * const _2309389973 = &(MJEncryptStringData){ .factor = (char)116, .value = (char []){16,23,18,19,71,64,70,0}, .length = 7 };
- 导入
#import "MJEncryptString.h"
,使用如下
NSString *str1 = mj_OCString(_2309389973); NSLog(@"str1 = %@", str1); // 打印如下 2020-07-15 07:53:41.851045+0800 TestObfuscation[44303:841930] str1 = dcfg342
- 2>、全部扫描项目文件