1、加固
加固是为了增加应用的安全性,防止应用被破解、盗版、二次打包、注入、反编译等。常见的加固方式有数据加密(字符串、网络数据、敏感数据等)、应用加壳(二进制加密)、代码混淆(类名、方法名、代码逻辑等)。
2、代码混淆
iOS程序可以通过class-dump、Hopper、IDA等获取类名、方法名、以及分析程序的执行逻辑。如果进行代码混淆,可以加大别人分析难度。
iOS的代码混淆方案有:
源码混淆:混淆类名、方法名、协议名等。
LLVM中间代码IR的混淆:自己编写Pass或使用 ollvm 来实现,但是容易产生Bug。
3、源码混淆
可以通过宏定义的方式来进行代码混淆:
@interface Person : NSObject- (void)run;- (void)setupName:(NSString *)name age:(int)age no:(int)no;@end
在.pch文件中添加类名、方法名和参数名的宏定义:
#ifndef PrefixHeader_pch#define PrefixHeader_pch#define Person alfjaskl#define run fasdf#define setupName gsdh#define age alfja#define no flasjdf#endif
编译后通过Hopper分析可执行文件,看到的就是混淆后的代码:
源码混淆有以下注意点:
1、不能混淆系统方法
混淆后系统方法调用时会因为找不到方法实现而报错
2、不能混淆init开头的初始化方法
例如混淆下面的初始化方法
-(instancetype)asdfas:(NSString *)name {if (self = [super init]) {}return self;}
会报错: ! Cannot assign to ‘self’ outside of a method in the init family ,原因是对self赋值必须在init开头的方法中进行。
3、混淆属性是需要额外的注意set方法
#define age alfja@property (nonatomic, assign) int age;- (void)setAlfja:(int)alfja {}
4、如果xib、storyboard中用到了混淆的内容,需要手动修正
xib不会自动替换宏定义内容,需要手动修改。
5、可以考虑把混淆的符号都加上前缀,跟系统自带的符号进行区分
@interface XLPerson : NSObject- (void)xl_run;- (void)xl_setupName:(NSString *)name xl_age:(int)age xl_no:(int)no;
#define XLPerson alfjaskl#define xl_run fasdf#define xl_setupName gsdh#define xl_age alfja#define xl_no flasjdf
6、添加无用代码
do {// 源码break;} while(1);
添加无用代码可以增加阅读源码的难度。
建议:
给需要混淆的符号加上一个特定的前缀。不要对整个项目进行混淆,审核会被拒。
小工具:
MJCodeObfuscation,可以对指定文件夹、指定前缀代码进行混淆。
4、ios-class-guard
ios-class-guard,是基于class-dump的扩展,用class-dump扫描出可执行文件的类名、方法名、属性名等并做替换,会更新xib和storyboard的名字等等。
它会对可执行文件进行扫描,把所有代码都进行混淆,生成混淆头文件(宏定义)和符号映射表。但是由于长时间未更新,已经不适用最新的iOS项目,所以不推荐使用。
5、字符串加密
源代码中的字符串很容易被破解:
- (void)viewDidLoad {[super viewDidLoad];NSString *str = @"abcdefg123";NSLog(@"str = %@", str);}

很多时候,可执行文件中的字符串信息,对破解者来说,非常关键,是破解的捷径之一。为了加大破解、逆向难度,可以考虑对字符串进行加密。字符串的加密技术有很多种,可以根据自己的需要自行制定算法。
通过异或( ^ )的方式对字符串进行加密解密:
const char *str = "abc123";// 进行异或操作for (int i = 0; i < strlen(str); i++) {NSLog(@"%d", str[i] ^ 7);}// 102 101 100 54 53 52
char strNew[] = {102, 101, 100, 54, 53, 52, 0};NSMutableString *str1 = [NSMutableString string];for (int i = 0; i < strlen(strNew); i++) {[str1 appendFormat:@"%c", strNew[i] ^ 7];}NSLog(@"str1 = %@", str1);
小工具:
MJCodeObfuscation,可以对指定字符串进行加密。
用法一:输入字符串,点击“加密”,得到加密后的字符串。导入MJEncryptString文件夹。 用法二:点击“选择目录”,会自动扫描目录下的所有字符串进行加密,得到字符串加密文件,导入即可使用。
