前言
一个项目中的明文字符串不计其数,但是有一些是程序的敏感信息的话如果不进行加密和混淆处理,反编译者就会很容易找到我们的敏感信息。拿到这些敏感信息之后就很容易分析我们的程序,业务逻辑进而做一些可能对我们不是很友好的事情,所以一些敏感明文字符串还是有必要做一下加密,让敏感信息更加安全。特别是对于我们金融类的APP开发。
反编译工具
这里介绍几个常用的:
(1)class-dump
主要用来反编译一个库文件或者app的方法名、属性等声明(即.h文件,强大的是反编译出来的.h不仅仅包含头文件中的声明,.m中的function方法名称也同样能够反编译出来)。
(2)IDA
主要用来反编译库文件的实现(当然方法声明同样能够反编译出来,用class-dump主要是更加形象,有针对性),这个反编译工具非常强大能够将函数的实现及逻辑关系、流程统统显示出来,弊端就是反编译出来的内容为汇编语言,需要一定汇编基础的才能看懂。看起来比较头疼。
(3)Hopper Disassembler
与IDA功能相似,主要功能都是反编译查看方法的实现,这个软件的功能相对于IDA来说,可读性要强很多,反编译出来的内容类似于汇编与OC的运行时的结合体,相对比较容易看出方法的具体实现。本次也是采用此工具进行验证。
代码混淆
在探索明文字符串加密之前先来了解一下代码混淆:
- 方法名混淆(对关键的类、方法,命名成与真实意图无关的名称)
- 创建shell脚本
- 声明要替换的方法名列表
- 生成对应的转义之后的无序字符串
- 逻辑混淆(添加无用又不影响逻辑的代码片段,迷糊逆向人员)
- 类名方法名混淆(例如:ios-class-guard)
Warning!!! 前方高能
Guideline 2.3.1 - Performance
We discovered that your app contains hidden features. Specifically, It would be appropriate to remove all code obfuscation and selector mangling or to explain in detail the purpose of its inclusion before resubmitting for review.
据说从17年开始苹果拒审代码混淆的APP。所以项目整体代码的混淆目前感觉意义不大。
第三方加固
第三方的服务(例如:网易云易盾)这类的加固成效如何不太清楚,这里拿出来给个参考,毕竟没用过,可能是否选用要看公司的决策了。
第三方明确说明了加固中使用了代码混淆,不知道是使用什么黑科技混淆的,肯定不是跑脚本的方式,好奇宝宝可以研究一下~~
字符串加密调研和尝试
对于被砸壳的二进制文件,逆向分析人员分析代码有一条重要线索,也就是被硬编码的明文字符串。比如说,你的 app 被人抓包了,某些数据请求接口也被人发现了,那么很简单,逆向人员可以直接拷贝特征比较明显的字符串到 hopper 中搜索,通过查看该字符串被引用的地方,可以很快的找到相应的逻辑代码。对于这一步的防范,需要做的就是对硬编码的明文进行加密。
使用静态内连 C 函数
- inline函数避免了普通函数的,在汇编时必须调用call的缺点。
- 取消了函数的参数压栈,减少了调用的开销,提高效率。所以执行速度确比一般函数的执行速度要快。
定义:
UIKIT_STATIC_INLINE NSString *testScheme() {
return @"testtesttesttest";
}
static inline NSString * testName() {
return @"test";
}
使用:
@"appId": testRrd(),
@"scheme" : testScheme()
结果:
很明显明文字符串还是很容易暴露出来~~
方案PASS!
Swift 安全性更高
- 越狱开源社区对反编译 Swift 的支持也不是很即时。
- 一些反编译工具并不支持反编译含有 Swift 的二进制文件(例如:class-dump)。
- 能够反编译 Swift 的工具也表现出 Swift 更安全的一面。
我对同样逻辑的同样代码(只是语法不同)的 OC 和 Swift 方法(方法中包含明文字符串)进行了测试:
上面对比明显可以看出 OC 经过反编译之后暴露出来的信息更能多,并且明文字符串显而易见。
但是如果 Swift 方法添加了对 OC 的支持(@objc)也会使安全性降低。
现阶段 Swift 相对 OC 来说更安全一些,等 Swift 日趋稳定,以及越狱开源社区的逐渐支持,可能这一点优势可能就不明显了。
UAObfuscatedString
有个开源代码可以用,UAObfuscatedString,这个开源混淆代码写出来的字符串是以点语法的方式连接起来。
语法:
@"url" : NSMutableString.string.w.w.w.dot.b.a.i.d.u.dot.c.o.m
测试混淆结果:
UAObfuscatedString 是通过 Category 和 Extension 来实现这种点语法拼接字符串,存在比较明显的规律,外加它是开源的可能安全性不是很高,如单从加密的角度去使用这个开源库感觉意义不大。
使用异或加密
原理:通过位运算的 ^ 异或运算符把字符串与一个指定的值进行运算,从而改变字符串中每个字符的值,这样就可以得到一个加密后的字符串;当把加密后的字符串作为程序输入内容后,异或运算会把加密后的字符串还原为原有字符串的值。
使用:
@"key" : testMethod()
// Key 可以是0~255的Int
#define XORKEY 0xC9
static void XOREncrypt(unsigned char *str, unsigned char key) {
unsigned char *p = str;
while (((*p) ^= key) != '\0') {
p++;
}
}
static id testMethod(void) {
unsigned char str[] = {(XORKEY ^ 'e'), (XORKEY ^ 'n'), (XORKEY ^ 'c'), (XORKEY ^ 'r'),
(XORKEY ^ 'y'), (XORKEY ^ 'p'), (XORKEY ^ 't'), (XORKEY ^ '\0')};
XOREncrypt(str, XORKEY);
static unsigned char result[7];
memcpy(result, str, 7);
return [[NSString alloc] initWithFormat:@"%s", result];
}
这里将字符用函数指针成员的形式存储,反编译后,只留下了地址,去掉了明文字符串直接暴露的风险。