在学习了上一章什么是加密解密、数字签名以及证书以后,如今咱们再来学习iOS的签名机制就事半功倍了。其实iOS签名机制的做用就是保证安装到用户手机上的App都是通过Apple官方容许的。固然,越狱设备除外。ios
在平时开发时,不论是真机调试,仍是发布App到App Store,咱们都须要通过如下几个步骤git
通过以上的一系列操做以后,咱们最终就能够拿到ios_development.cer或者ios_distribution.cer证书文件,以及mobileprovision描述文件。经过安装这些文件到Mac上就能够进行真机调试。固然,若是你在Xcode中勾选了Automatically manage signing选项,那么Xcode会自动帮咱们执行以上的全部操做。github
那么,以上操做每一步执行的做用是什么?最后得到的ios_development.cer或者ios_distribution.cer证书文件,以及mobileprovision描述文件的做用又是什么?这些文件中又包含了什么内容?bash
要想知道上述全部文件的具体做用,就须要了解iOS签名的完整流程。在使用Xcode编译、运行完项目以后,Xcode其实帮咱们作了签名操做。markdown
其实就是利用codeSign指令对.app文件进行签名操做。app
想要执行iOS签名流程,就须要有如下公钥、私钥信息iphone
iOS项目在编译完成以后会生成.app文件,App的签名操做从拿到.app文件开始ide
对.app安装包进行签名以后,压缩生成ipa安装包,而后将ipa安装包安装到iPhone上时,会进行签名验证操做。工具
在文件mobileprovision中,有devices、app id以及entitlement信息,它们的做用分别是:oop
- devices标识着哪些设备能够安装此App,若是设备不在devices中,安装会失败。
- app id,指定此标识的App才能安装,若是App的惟一标识和此app id不对应,则安装失败。
- entitlement中存放在App所具有的权限信息,若是App所使用的权限和entitlement中存放的权限不一致,也会产生问题。
上文学习了iOS签名的具体流程,如今,咱们就来一步步的执行实际的操做来对咱们所学的签名流程进行验证。同时了解ios_development.cer或者ios_distribution.cer证书文件,以及mobileprovision等文件的实际做用。
此步骤就是利用Apple的私钥,对Mac公钥进行签名,生成证书文件ios_development.cer和ios_distribution.cer
此步骤就是将devices、app id、entitlement和证书文件,经过Apple私钥进行签名,生成最后的mobileprovision文件。并且生成的mobileprovision文件就决定了当前App能够安装的设备有哪些,能够安装的App的BundleId,以及App所拥有的权限。
Apple官方验证流程以下:
当咱们逆向了一款App,为App编写了相应的插件,而且安装到了咱们本身的越狱手机上。可是,逆向过的App只能在本身越狱手机上使用,若是咱们想要将App和咱们本身编写的插件从新打包,安装到未越狱的iPhone上,那就须要学习如何对App进行重签名。
学习重签名以前,须要注意几点
生成mobileprovision文件有两种方式,第一种是经过Xcode自动生成,在编译后的App包中能够找到,第二种是到Apple官网生成,上文有详细步骤。
// 首先从embedded.mobileprovision文件中导出权限信息,存放到temp.plist中 security cms -D -i embedded.mobileprovision > temp.plist # 而后使用PlistBuddy工具将temp.plist转换成Entitlements格式的文件entitlements.plist /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist 复制代码
security find-identity -v -p codesigning
复制代码
获得的结果以下
➜ ~ security find-identity -v -p codesigning 1) D9E2802126C89BF6BF6621064FC5547F895FC25E "iPhone Developer: xxxxx@xxxx.com (KT9PJDKFVG)" 复制代码
# -fs 是 -f -s 的缩写 codesign -fs 证书ID xxx.dylib 复制代码
codesign -fs 证书ID --entitlements entitlements.plist xxx.app
复制代码
使用Xcode编译本身的项目,咱们知道源码,因此知道怎么修改Mach-O文件,可是若是咱们在逆向别人的App时,是不知作别人的源码的,因此没法直接修改Mach-O文件。
以前的文章中学习了Theos,知道了怎么经过建立Tweak项目来修改App的行为,具体流程能够查看iOS逆向学习之六(Theos实战演练)这篇文章。
建立了Tweak项目以后,经过Cydia安装到越狱手机上,而后就能够改变App的行为。具体是怎么实现的呢?
Tweak项目本质上是生成动态库,并且动态库不是存放在.app目录下,因此,想要将咱们逆向过的App安装到别人的手机上,首先须要作的就是将Tweak项目生成的动态库注入到App中的可执行文件中,也就是Mach-O文件中。
可使用insert_dylib库来将动态库注入到Mach-O文件中,能够经过insert_dylib库主页下载insert_dylib工具。在Release环境下编译,获得命令行工具,将命令行工具放在/usr/local/bin目录下。
insert_dylib的本质其实就是往Mach-O文件的Load Commands中添加了一个LC_LOAD_DYLIB或者LC_LOAD_WEAK_DYLIB。具体注入方法以下:
insert_dylib 动态库加载路径 Mach-O文件 --all-yes --weak
复制代码
查看动态库依赖信息两种方式
otool -L Mach-O文件
复制代码
在向Mach-O文件中注入动态库以后,须要更改Mach-O文件中动态库的加载地址,不然在App运行时,会由于找不到动态库报错。
可使用install_name_tool指令来修改Mach-O文件中动态库的加载地址:
install_name_tool -change 旧地址 新地址 Mach-O文件
复制代码
须要注意的是,上述指令中的新地址,必须填写全路径地址,可是咱们不知道App安装到手机上后dylib存放的具体地址,所以,可使用如下两个经常使用的环境变量:
能够点击下载iReSign源码,运行里面的Mac应用,提供.app包的路径、entitlements.plist路径和embedded.mobileprovision的路径,就能够对.app进行重签名,而后打包生成ipa文件。
能够点击下载iOS App Signer源码,选择Release环境进行编译,拿到编译后的Mac应用,就能够直接使用。只需提供.app包的路径和embedded.mobileprovision的路径
如今咱们就来使用Xcode生成.app包,而后一步一步实现重签名的过程。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *labelA; @property (weak, nonatomic) IBOutlet UILabel *labelB; @property (weak, nonatomic) IBOutlet UILabel *labelResult; @end @implementation ViewController int a = 10; int b = 20; - (void)viewDidLoad { [super viewDidLoad]; self.labelA.text = [NSString stringWithFormat:@"%d",a]; self.labelB.text = [NSString stringWithFormat:@"%d",b]; self.labelResult.text = [NSString stringWithFormat:@"%d",a + b]; } @end 复制代码
<font color=red>0A</font>转换成10进制就是10,对应着全局变量a,<font color=red>14</font>转换成10进制就是20,对应着全局变量b。
复制代码
直接修改Mach-O文件,将全局变量a的值修改为14,也就是将a的值改成20。
从新压缩生成.ipa文件,使用iFunBox将ipa安装到同一台手机上,会出现安装失败提示,缘由是.app中的Mach-O文件已经被篡改,它的签名也将会失效。因此安装在iPhone上时对App的签名验证也会失败,因此会致使安装失败。此时就须要对.app进行重签名。
拿到TestSign.app包中的embedded.mobileprovision文件,从embedded.mobileprovision文件中提取出entitlements.plist文件,指令以下:
// 首先从embedded.mobileprovision文件中导出权限信息,存放到temp.plist中 security cms -D -i embedded.mobileprovision > temp.plist # 而后使用PlistBuddy工具将temp.plist转换成Entitlements格式的文件entitlements.plist /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist 复制代码
security find-identity -v -p codesigning
复制代码
codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 --entitlements entitlements.plist TestSign.app
复制代码
出现上图效果,代表重签名成功,此时,从新压缩TestSign.app文件,获得ipa,安装到以前的手机上就能够安装成功,同时,由于全局变量a的值被咱们改为了20,因此界面上展现的是20 + 20 = 40。至此,重签名操做完成。
下面为腾讯视频开发Theos插件,而后注入到腾讯视频App,而且从新生成ipa,安装到非越狱手机上,
@interface QLHomeController - (id)presentViewController:(id)controller animated:(BOOL)animated completion:(id)completion; @end %hook QLHomeController - (void)viewDidAppear:(BOOL)animated{ %orig; UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"提示框" message:@"测试Theos插件" preferredStyle:UIAlertControllerStyleAlert]; [alertVc addAction:[UIAlertAction actionWithTitle:@"关闭" style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:alertVc animated:YES completion:nil]; } %end 复制代码
获取如下签名须要的一些文件
将test_live.dylib、CydiaSubstrate和embedded.mobileprovision文件复制到live4iphone.app包中。
向live4iphone.app包中的可执行文件中注入动态库
insert_dylib @executable_path/test_live.dylib live4iphone --all-yes --weak live4iphone
复制代码
出现如下结果代表注入成功:
➜ live4iphone.app insert_dylib @executable_path/test_live.dylib live4iphone --all-yes --weak live4iphone live4iphone already exists. Overwrite it? [y/n] y Binary is a fat binary with 2 archs. LC_CODE_SIGNATURE load command found. Remove it? [y/n] y LC_CODE_SIGNATURE load command found. Remove it? [y/n] y Added LC_LOAD_WEAK_DYLIB to all archs in live4iphone 复制代码
使用otool指令或者MachOView查看腾讯视频的可执行文件,能够发现动态库已经注入到Mach-O文件当中
- 此时发现<font color=red>CydiaSubstrate</font>的路径是<font color=red>/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate</font>,可是在非越狱手机上是没有这个路径的,因此须要经过install_name_tool指令来改变更态库的加载路径。
```
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate test_live.dylib
```
再次查看<font color=red>test_live.dylib</font>的依赖库信息,会发现<font color=red>CydiaSubstrate</font>库的路径变成了<font color=red>@loader_path/CydiaSubstrate</font>
复制代码
➜ live4iphone.app codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 test_live.dylib
test_live.dylib: replacing existing signature
➜ live4iphone.app codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 CydiaSubstrate
CydiaSubstrate: replacing existing signature
➜ live4iphone.app
复制代码