代码混淆实践
这张图是反编译后的代码,图上可以看到类名和方法名清楚的很,这会为破解者提供很清晰的流程和思路,找到相应的代码做些什么。
代码混淆的好处:
1、增加安全性,防破解,防泄漏,通过反编译工具不再能看到代码裸奔
2、审核,降低代码的一致性,遇到的的自然懂
这是两个最基本的实用点,本文将从类名混淆这一个维度讲述一些心得,并提供相应的混淆工具,混淆中需要做的事情还很多,希望起到抛砖引玉。
注:1、本文混淆使用的工具是python脚本,依赖python3环境,python环境为3.7.1。
2、如果不想了解其中逻辑,可直接下载脚本,依次执行完成后,重新运行项目检查是否顺利编译和运行。安装完python环境后再命令行输入python 空格 脚本文件路径即可执行,例:
python3 /Users/mac/pythonscript.py
3、脚本仓库:https://github.com/360fengdai/obscure_oc.git
4、脚本实现语言是Python,混淆测试代码是Object-C的类名,其他语言也是如法炮制,无有不能用
欢迎提出建议,共同进步。
核心思路:
第一步:搜索目标字符串:
1、最好的方式就是正则表达式,匹配类名生成的地方,因为此时特征比较明显,例如oc中声明类@interface ClassA,@interface在类名前边就是它的特征,由此生成正则表达式即可,暂时也没有找到更好的方式。遍历工程目录下文件.h和.m文件,指定一些过滤文件,例如静态库对应的头文件,这种头文件中声明的类在.a文件中使用到了,.a文件已不能更改,所有需要过滤,再例如framework中的.h中声明的类,通过正则表达式提取出类名,生成需要混淆的类名列表
2、遍历系统方法库,扫描系统类名列表,系统framework默认路径为/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks,遍历framework下的.h文件执行第1步逻辑,提取类名,生成系统系统类名列表,生成后可存文件缓存,避免每次都遍历系统方法库,脚本库中也提供了遍历系统类名的脚本供参考。
3、第1步中生成的类名列表,删除其中的系统类名,注意不能遍历到就立即删除,for循环是迭代器,立即删除后可能会导致内存地址变更,之后的for循环出错或者crash,先用缓存数组存储待删除的索引,再按索引大小从大到小排序逆向删除。
到此即得到了待混淆的目标字符串数组
第二步:
生成混淆映射表:
待混淆的字符串为key,生成一个随机字符串为value,即混淆后的值,由此生成映射表即可
{'ClassA':'abcdefg','ClassB':'ABCDEFG'...}
第三步 :
使用第二步生成的映射表,遍历所有目标类型文件,替换所有key为混淆后的value,例如之前的所有使用到类名为ClassA的地方都替换成abcdefg
此步还是不太好做的,需要精确匹配确实是类名的地方,还要不匹配例如xxClassAxx这种带ClassA的字符串,目前我的做法是匹配类名前后一个或者多个字符,因为类名前后的字符必是特定的某些,例如oc使用类名生成对象时,
[[ClassA alloc] init]
ClassA前边需要是[,后边需要是空格。这就精准匹配了此种情况的所有类名,还有其他一些有限的引用方式,如法即可。
脚本做混淆,没有完美的脚本,不同语言的项目需要匹配的规则都不大一致,但核心思路都一致,能做出适用自己项目的就可以了。