iOS应用保护最佳实践
#
iOS程序介绍iOS程序是运行在苹果公司开发的iOS操作系统上的应用程序,iOS应用的可执行程序是MachO文件格式。
温馨提示
- 为了方便对应用进行签名,建议在 macOS系统上对 iOS程序加密
#
安全性问题虽然从AppStore下载安装的iOS App都是苹果加壳后的,但是苹果对程序内的可执行文件只进行了简单的加密处理,随着市面上的脱壳工具(比如Clutch等)逐渐成熟,可以通过解密算法对iOS app进行脱壳处理,进而使用class-dump
工具导出App的MachO文件所有头文件、Hopper或ida等工具分析App的MachO文件代码,并将代码高度还原,对于高安全性需要的场景,不经过保护很容易被逆向破解。
#
功能介绍Virbox Protector
工具(简称加壳工具)通过对iOS app或ipa程序进行加固,支持函数级保护和基础保护,可以有效的防逆向、防调试、防篡改以及防二次打包等操作。
#
基础功能#
内存校验内存校验,可以在程序加载时校验自身完整性,如果发现程序被篡改,则会退出进程。
如果需要在运行时动态进行校验,可以使用SDK标签
在代码中调用。
#
OC名称混淆OC名称混淆,可以将类名混淆成无意义的字符串名称,可以无法直观的找到类名的调用关系。
注意:1)该功能目前只能混淆类名,不能混淆方法名,调用到其他资源的类名也不会进行混淆。2)若程序代码里涉及到跨模块反射调用这种情况,则OC名称混淆可能会导致程序界面功能无法正常使用的情况。
原程序的类名反编译,如图所1示:
OC名称混淆后类名反编译,如图所示:
#
调试器检测调试是逆向分析时的重要手段,可以在庞大的二进制指令中迅速定位到相关的逻辑。
调测调试器,可以检测当前模块的进程是否被 IDA Pro/lldb等工具调试,被调试则退出阻止运行。
#
移除调试信息IPA程序中可执行程序有时会包含Debug节,静态符号表,其中包含了函数名、函数地址等信息,对外发布时如果携带会降低程序的安全性。
移除调试信息,会将程序中的 .debug 节,静态符号表移除。
原程序的符号,如图所示:
勾选移除调试信息
后程序的符号,如图所示:
#
签名校验校验ipa中的开发者签名证书(Team id),防止ipa被第三方二次打包重签名。
1)若想使用签名校验功能,则必须要启用签名;2)若启用签名,则签名校验选项可选可不选。
#
签名设置若勾选启用签名,签名证书选择和Xcode编译xcarchive时的证书一致,则程序保护生成的app默认已签名;
若不勾选启用签名,则程序保护生成的app默认不签名,需自行在对加固后的app手动签名(比如使用codesign、iOS App Signer工具等);
#
函数功能#
代码混淆代码混淆是将函数中原始的指令,通过等价变换、立即数加密、间接跳转、虚假分支、花指令加扰、指令切片等手段,将原始指令转换为难以阅读的随机的指令片段。
原程序反编译效果,如图所示:
代码混淆后反编译效果,如图所示:
#
代码虚拟化代码虚拟化,是保护过程中将函数中原始的汇编指令,转换为自定义的虚拟指令,运行时在自定义的虚拟机中执行,模拟了汇编指令中的内存访问、条件判断、寄存器状态等。
代码虚拟化后反编译效果,如图所示:
#
SDK标签参考SDK标签使用流程文档。
#
操作指引根据自己环境要求,界面操作和命令行操作方式任选其一即可。
#
编译app1.修改编译选项,编译的xcarchive包内带有dSYM文件,如图所示:
操作:
Xcode->TARGETS->Build Setting->Build Options->Debug Information Format
选择DWARF with dSYM File
选项;目的:加壳工具解析app时可以解析出函数名称,否则,函数将会只会显示地址;
2.加壳工具暂不支持bitcode,Xcode15编辑器已经没有bitcode选项,所以若是Xcode15以上的编译器则可忽略该操作;
若是Xcode15以下的编译器,则编译程序时需关闭bitcode的编译选项,操作Xcode->TARGETS->Build Setting->Build Options->Enable Bitcode->no
关闭bitcode;
3.以上选项配置完后,选择Xcode->Prodcut->Archive
进行编译程序,如图所示;
4.编译成功后进入到Archives页面;
5.选中编译好的程序,右键在Finder里打开该程序;
6.找到编译好的xcarchive,右键显示包内容;
7.进入包内容后,在Products\Applications目录下为待保护的app程序。
#
界面操作1.将app和ipa程序拖入加壳工具界面;
2.点击按钮函数选项->添加函数
可以选择要保护的函数;
3.可以选择想要保护的函数,将其设置为代码混淆或代码虚拟化;
注意
1.若是使用OC或Swift语言编译的iOS程序,则其本身自带了符号,所以有无dSYM文件,加壳工具均可识别函数名;
2.若是iOS程序中调用了C/C++语言编译的库,则编译后的app或ipa文件里不带符号,此时若想显示C/C++库里的函数名,则需要dSYM文件;
4.在加密选项处选择所需的功能并勾选,启用签名选择证书,点击保护选中项目
,等待保护完成即可。
5.保护完成后,默认在protected目录下生成加固后的程序。
***.app.ssp:指配置文件,主要存储Virbox Protector界面选择的函数和加密所选的选项,该配置文件和原程序在同目录且名称一致,即
Virbox Protector
再次保护程序时可不用重新配置;protected/***.ipa:指加固后的app程序打包成ipa的包;
protected/***.app:指加固后生成的程序;
#
命令行操作#
命令行工具Virbox Protector
的命令行工具 virboxprotector_con
的默认路径位于:
Windows:C:\Program Files\senseshield\Virbox Protector 3\bin
Linux:/usr/share/virboxprotector/bin
macOS:/Applications/Virbox Protector 3.app/Contents/MacOS/bin
使用配置文件保护
使用工具界面进行保护,在被保护的程序旁边会生成 .ssp
文件,然后调用virboxprotector_con
:
virboxprotector_con <input_file> -o <output_file>
virboxprotector_con
会自动查找 <input_file>.ssp 作为配置文件开始保护。
无配置文件保护
如果没有配置文件,virboxprotector_con
会使用默认参数保护,可以传入具体参数覆盖默认选项,参考命令行选项。
以上两种方式任选其一即可。
#
命令行选项加密选项
选项 | 参数 | 默认选项 |
---|---|---|
内存校验 | --mem-check= | 0 |
调试器检测 | --detect-dbg= | 0 |
OC名称混淆 | --objc-rename= | 0 |
签名校验(仅iOS) | --sign-check= | 0 |
指定app内的frameworks | --frameworks=<.framework> | 无 |
移除调试信息 | --strip-dbginfo= | 1 |
举例
对ipa保护,勾选内存校验、调试器检测和移除调试信息选项,不启用签名,命令参考如下:virboxprotector_con test.ipa --mem-check=1 --detect-dbg=1 --strip-dbginfo=1 -o protector/test.ipa
签名选项
选项 | 参数 |
---|---|
启用签名 | --sign= |
证书名称 | --identity= |
ipa包输出 | --ipa= |
举例
1.使用命令行查看系统上的证书security find-identity -v -p codesigning2.对ipa保护,勾选内存校验、调试器检测和签名校验选项,并启用签名,命令参考如下:virboxprotector_con test.ipa --mem-check=1 --detect-dbg=1 --sign-check=1 --sign=1 --identity="证书id" -o protector/test.ipa
1.macOS app保护,参考示例:
开启内存校验、调试器检测和移除调试信息功能,并启用签名,命令参考如下:virboxprotector_con test.app --mem-check=1 --detect-dbg=1 --strip-dbginfo=1 --sign=1 --identity="Apple Development:ceshi@123.com" -o protected/test.app
2.iOS app保护,参考示例:
开启内存校验、调试器检测和移除调试信息功能,并启用签名,输出ipa,命令参考如下:virboxprotector_con test.app --mem-check=1 --detect-dbg=1 --strip-dbginfo=1 --sign=1 --identity="Apple Development:ceshi@123.com" --ipa=protected/test.ipa
3.若app中的有framework框架,使用--frameworks=<.framework>
参数保护app内的framework框架,其中<.framework>
是指app内嵌套的framework的文件名,参考示例:
virboxprotector_con test.app --mem-check=1 --detect-dbg=1 --strip-dbginfo=1 --frameworks="test.framework" --sign=1 --identity="Apple Development:ceshi@123.com" --ipa=protected/test.ipa
函数选项
选项 | 参数 |
---|---|
代码虚拟化 | -v |
代码混淆 | -m |
忽略不支持的函数 | --ignore-unsupported= |
支持指定函数名称或规则保护,使用 ;
号隔开,支持通配符 *
,举例:
-m "function1;function2" -v "function3;function4" --ignore-unsupported=1
举例
1)对指定的方法名进行混淆和虚拟化,参考示例:
virboxprotector_con test.app -v "-[ViewController setDetectResults:];-[ViewController timer]" -m "-[ViewController setTableView:];-[ViewController detectResults]" --detect-dbg=0 --sign-check=0 --sign=1 --identity="Apple Development: XXXX@qq.com" --ipa=protected/test.ipa
2)对某个类名进行混淆和虚拟化,参考示例:
virboxprotector_con AppProtectDemo.app -v "-[ViewController *]" -m "-[SecondViewController *]" --detect-dbg=0 --sign-check=0 --sign=1 --identity="Apple Development: XXXX@qq.com" --ipa=protected/test.ipa
上面命令表示:ViewController类名下的方法均会被虚拟化,SecondViewController类名下的方法均会被混淆。
注意
- 每个程序的函数名都不一样,根据自己的需求指定对应的函数名;
- 一个函数名不能同时指定代码混淆和代码虚拟化两种保护方式;
- 函数选项过多代码虚拟化后可能会影响程序性能,建议对关键函数进行设置代码虚拟化。
#
上架应用若加固后的程序需上架App Store
,则可使用Xcode或Transporter工具进行提交(也可使用其他工具进行提交,以下不在列举)。
#
Xcode工具1.将xcarchive包里的原程序app删除或移动备份到其他位置;
2.再将protected/***.app移动到原程序app的位置上,并删除.ssp配置文件;
3.修改完后,在返回Archives页面,点击Distribute APP
对程序进行提交。
#
Transporter工具1.将加固后生成的ipa直接拖入到Transporter工具中;
2.点击验证
,等待程序验证完成;
3.程序验证完成后,可选择交付
即可。
#
问题#
Xcode环境下加固appXcode16以下版本
1.在Target->Build Phases->New Run Script Phases创建Run Script;
2.在Run Script添加如下脚本;
3.然后进行build,则默认在原app目录下生成一个protected文件夹,目录里即为加固后的app或ipa。
Xcode16以上版本
1.在Xcode 16版本创建新的项目;
2.在Edit Scheme->Build->Post-actions新建Run Script;
3.在Run Script添加脚本;
4.然后进行build,则默认在原app目录下生成一个protected文件夹,目录里即为加固后的app或ipa。
脚本示例,参考如下:
echo "开始执行加固命令,根据需求添加命令参数,参考如下""/Users/sense/Desktop/Virbox Protector 3 Trial.app/Contents/MacOS/bin/virboxprotector_con" "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app" --detect-dbg=1 --sign-check=0 --sign=1 --identity="Apple Development: 27XXXXXX7@qq.com" --ipa="${TARGET_BUILD_DIR}/protected/${PRODUCT_NAME}.ipa"
#
非越狱手机上安装ipa【注】这种情况只在个人测试时才会出现这个问题,如果程序正常上架后,在app store里下载,就不会区分手机是越狱还是非越狱。
问题:若加壳时文件签名证书选择和Xcode编译xcarchive时的证书不一致,程序重新签名,如何在非越狱手机上安装程序?
解决1:重新签名时,证书用一致的。
解决2:
1、下载爱思助手,并打开
2、连接设备
3、点击爱思助手的工具箱,选择”IPA签名“,选择使用“Apple ID签名”
4、点击“添加Apple ID”,输入开发者账号,选择设备UDID,点击添加。
4、选择ipa文件,选择对应的Apple ID,点击开始签名
5、签名成功后,点击“打开已签名IPA位置”,可以看到重签后的IPA
6、在非越狱手机上可以安装成功(注:这种情况下签名的ipa只能在该设备ID上安装)。
#
崩溃信息若程序加壳后在手机上运行崩溃,需要将崩溃信息提供给Virbox人员,如何获取崩溃信息?
1、手机连接电脑,保证手机ip地址要和电脑IP地址在同一网段内。
2、打开Xcode ,选择Window->Devices and Simulators选项;
2、点击View Device Logs选项;
3、若手机ip地址要和电脑IP地址在同一网段内,在手机上运行的app崩溃后,日志会自动同步到此页面;
4、选中Type为Crash,点击右键Export log,将该日志保存到本地。
#
如何用命令给app签名1、使用该命令查询电脑上的证书
security find-identity -v -p codesigning
2、使用该命令对app进行签名
codesign -fs <证书信息> ***.app
#
如果将app打包成ipa1、创建一个文件夹,名称为Payload;
2、将保护后的.app文件放入该文件夹中;
3、将Payload文件夹进行压缩(默认压缩为.zip);
4、将后缀名.zip改名为.ipa;