Skip to main content

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标签使用流程文档

操作指引#

根据自己环境要求,界面操作和命令行操作方式任选其一即可。

编译app#

1.修改编译选项,编译的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类名下的方法均会被混淆。

注意

  1. 每个程序的函数名都不一样,根据自己的需求指定对应的函数名;
  2. 一个函数名不能同时指定代码混淆和代码虚拟化两种保护方式;
  3. 函数选项过多代码虚拟化后可能会影响程序性能,建议对关键函数进行设置代码虚拟化。

上架应用#

若加固后的程序需上架App Store,则可使用Xcode或Transporter工具进行提交(也可使用其他工具进行提交,以下不在列举)。

Xcode工具#

1.将xcarchive包里的原程序app删除或移动备份到其他位置;

2.再将protected/***.app移动到原程序app的位置上,并删除.ssp配置文件;

3.修改完后,在返回Archives页面,点击Distribute APP对程序进行提交。

Transporter工具#

1.将加固后生成的ipa直接拖入到Transporter工具中;

2.点击验证,等待程序验证完成;

3.程序验证完成后,可选择交付即可。

问题#

Xcode环境下加固app#

Xcode16以下版本

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打包成ipa#

1、创建一个文件夹,名称为Payload;

2、将保护后的.app文件放入该文件夹中;

3、将Payload文件夹进行压缩(默认压缩为.zip);

4、将后缀名.zip改名为.ipa;