iOS逆向学习之十二(iOS签名机制)

iOS签名机制的做用

在学习了上一章什么是加密解密、数字签名以及证书以后,如今咱们再来学习iOS的签名机制就事半功倍了。其实iOS签名机制的做用就是保证安装到用户手机上的App都是通过Apple官方容许的。固然,越狱设备除外。ios

在平时开发时,不论是真机调试,仍是发布App到App Store,咱们都须要通过如下几个步骤git

  • 首先,在Mac上生成CertificateSigningRequest.certSigningRequest文件
  • 而后在Apple开发者网站上获取到ios_development.cer或者ios_distribution.cer证书文件,前者是开发证书,后者是发布证书
  • 在Apple开发者网站上注册device,添加App ID。
  • 选择device、App ID以及开发证书或者生产证书,生成mobileprovision文件

通过以上的一系列操做以后,咱们最终就能够拿到ios_development.cer或者ios_distribution.cer证书文件,以及mobileprovision描述文件。经过安装这些文件到Mac上就能够进行真机调试。固然,若是你在Xcode中勾选了Automatically manage signing选项,那么Xcode会自动帮咱们执行以上的全部操做。github

那么,以上操做每一步执行的做用是什么?最后得到的ios_development.cer或者ios_distribution.cer证书文件,以及mobileprovision描述文件的做用又是什么?这些文件中又包含了什么内容?bash

iOS签名流程

要想知道上述全部文件的具体做用,就须要了解iOS签名的完整流程。在使用Xcode编译、运行完项目以后,Xcode其实帮咱们作了签名操做。markdown

其实就是利用codeSign指令对.app文件进行签名操做。app

准备

想要执行iOS签名流程,就须要有如下公钥、私钥信息iphone

  • Mac设备的公钥和私钥,通常是Mac设备本身生成
  • Apple官方的私钥,保存在Apple的后台
  • Apple官方的公钥,每一台iPhone出厂以后都会保存Apple官方的公钥信息

签名流程分析

iOS项目在编译完成以后会生成.app文件,App的签名操做从拿到.app文件开始ide

  • 第一步,拿到.app文件以后,使用Mac私钥对.app文件进行签名操做,生成的签名文件存放在.app目录下的_CodeSignature/CodeResources

  • 第二步,使用Apple私钥对Mac公钥进行签名,生成证书文件

  • 第三步,将第二步获取到的证书文件和devices、app id以及entitlement一块儿使用Apple私钥再次进行签名,生成mobileprovision文件,也就是描述文件。

  • 第四步,将第一步签名事后的.app文件和第三步生成的mobileprovision文件一块儿压缩生成ipa安装包。

  • 最后,完整的签名打包过程以下

验证流程

对.app安装包进行签名以后,压缩生成ipa安装包,而后将ipa安装包安装到iPhone上时,会进行签名验证操做。工具

  • 第一步,使用iPhone上存放的Apple公钥验证mobileprovision文件中的签名。
  • 第二步,签名验证成功以后,拿到mobileprovision中存放的devices、app id以及entitlement信息。同时拿到证书文件。而后使用Apple公钥对证书中的签名进行验证。验证成功以后拿到Mac公钥。
  • 第三步,拿到Mac公钥以后,使用Mac公钥对App的签名文件进行验证,若是验证成功,则代表当前的App的源码没有被篡改过。而后此App就能安装到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等文件的实际做用。

  • 第一步,在Mac上生成CertificateSigningRequest.certSigningRequest文件,其实这个文件就是Mac设备的公钥。

  • 第二步,登陆Apple开发者网站,获取证书,安装到Mac设备。
    • 建立certificates

- 选择证书类型,有开发证书和发布证书。

- 上传CertificateSigningRequest.certSigningRequest文件,也就是Mac公钥信息。

- 下载证书,安装到Mac设备上

此步骤就是利用Apple的私钥,对Mac公钥进行签名,生成证书文件ios_development.cer和ios_distribution.cer

  • 第三步,生成mobileprovision
    • 建立mobileprovision,能够选择开发环境或者生产环境

- 选择App ID

- 选择设备devices

- 选择证书certificates

- 生成mobileprovision文件,下载到Mac上进行安装

此步骤就是将devices、app id、entitlement和证书文件,经过Apple私钥进行签名,生成最后的mobileprovision文件。并且生成的mobileprovision文件就决定了当前App能够安装的设备有哪些,能够安装的App的BundleId,以及App所拥有的权限。

Apple官方验证流程

Apple官方验证流程以下:

重签名

当咱们逆向了一款App,为App编写了相应的插件,而且安装到了咱们本身的越狱手机上。可是,逆向过的App只能在本身越狱手机上使用,若是咱们想要将App和咱们本身编写的插件从新打包,安装到未越狱的iPhone上,那就须要学习如何对App进行重签名。

学习重签名以前,须要注意几点

  • 第一,安装包中的可执行文件必须是进行过脱壳操做的,重签名才会生效,否则会安装失败
  • 第二,重签名所须要的mobileprovision文件必须是付费开发者帐号申请的才能够,免费开发者帐号没法进行重签名。
  • 第三,.app包中的全部动态库(.framework,.dylib)、AppExtension(PlugIns文件夹,拓展名是appex)、WatchApp(Watch文件夹)等都须要进行重签名操做

CodeSign指令重签名

具体步骤

  • 首先,须要准备一个embedded.mobileprovision文件(必须是付费开发者帐号生成的,里面的appid、device等须要匹配),而后将此文件放入.app包中

生成mobileprovision文件有两种方式,第一种是经过Xcode自动生成,在编译后的App包中能够找到,第二种是到Apple官网生成,上文有详细步骤。

  • 从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
复制代码
  • 查看Mac上可使用的证书,获取到证书的Identity,后续签名须要使用,具体指令以下
security find-identity -v -p codesigning
复制代码

获得的结果以下

➜  ~ security find-identity -v -p codesigning
  1) D9E2802126C89BF6BF6621064FC5547F895FC25E "iPhone Developer: xxxxx@xxxx.com (KT9PJDKFVG)"
复制代码
  • 对.app包中的全部动态库、AppExtension等进行重签名,前提是修改过这些动态库或者AppExtension,若是没有修改的动态库或者AppExtension,能够跳过此步骤。指令以下:
# -fs 是 -f -s 的缩写
codesign -fs 证书ID xxx.dylib
复制代码
  • 对.app包进行签名,须要使用到以前生成的entitlements.plist文件,指令以下:
codesign -fs 证书ID --entitlements entitlements.plist xxx.app
复制代码

Theos插件重签名

使用Xcode编译本身的项目,咱们知道源码,因此知道怎么修改Mach-O文件,可是若是咱们在逆向别人的App时,是不知作别人的源码的,因此没法直接修改Mach-O文件。

以前的文章中学习了Theos,知道了怎么经过建立Tweak项目来修改App的行为,具体流程能够查看iOS逆向学习之六(Theos实战演练)这篇文章。

Tweak加载方式

建立了Tweak项目以后,经过Cydia安装到越狱手机上,而后就能够改变App的行为。具体是怎么实现的呢?

  • 首先,Tweak项目通过编译生成的是一个dylib动态库文件,存放在Tweak项目目录.theos/obj/debug/目录下。
  • 执行make package打包以后生成对应的deb文件,存放在packages目录下。
  • 执行make install以后,会经过Cydia安装到手机上,dylib文件存放在~/Library/MobileSubstrate/DynamicLibraries/目录下。
  • 在App启动以后,会同时将dylib加载到内存中,App中若是访问被咱们hook的类中的方法,会直接执行dylib中的方法。

动态库的注入

Tweak项目本质上是生成动态库,并且动态库不是存放在.app目录下,因此,想要将咱们逆向过的App安装到别人的手机上,首先须要作的就是将Tweak项目生成的动态库注入到App中的可执行文件中,也就是Mach-O文件中。

可使用insert_dylib库来将动态库注入到Mach-O文件中,能够经过insert_dylib库主页下载insert_dylib工具。在Release环境下编译,获得命令行工具,将命令行工具放在/usr/local/bin目录下。

insert_dylib库用法

insert_dylib的本质其实就是往Mach-O文件的Load Commands中添加了一个LC_LOAD_DYLIB或者LC_LOAD_WEAK_DYLIB。具体注入方法以下:

insert_dylib 动态库加载路径 Mach-O文件 --all-yes --weak
复制代码
  • --weak选项表示,即便当前注入的动态库找不到,App也不会报错
  • --all-yes选项表示,后面全部的选项都选yes
查看Mach-O的动态库依赖信息

查看动态库依赖信息两种方式

  • 经过otool查看Mach-O的动态库依赖信息
otool -L Mach-O文件
复制代码

  • 经过MachOView查看Mach-O的动态库依赖信息

更改动态库的加载地址

在向Mach-O文件中注入动态库以后,须要更改Mach-O文件中动态库的加载地址,不然在App运行时,会由于找不到动态库报错。

可使用install_name_tool指令来修改Mach-O文件中动态库的加载地址:

install_name_tool -change 旧地址 新地址 Mach-O文件
复制代码

须要注意的是,上述指令中的新地址,必须填写全路径地址,可是咱们不知道App安装到手机上后dylib存放的具体地址,所以,可使用如下两个经常使用的环境变量:

  • @executable_path表明可执行文件所在的目录,也就是Mach-O文件所在目录。咱们将dylib和可执行文件放在同一个目录下,而后将地址修改成@executable_path/dylib名称。这就表示在加载动态库时,到可执行文件所在的目录下去寻找动态库。
  • @loader_path表明动态库所在的目录,此环境变量通常在动态库依赖其它动态库的状况下使用,若是咱们须要注入的动态库还依赖其它动态库,那么就须要将所依赖的动态库和原动态库存放在同一目录下,而后更改动态库的加载地址为@loader_path/动态库名称。这表示到原动态库所在目录下加载须要依赖的动态库。

Theos开发的动态库插件注意事项

  • 咱们使用Theos开发的动态库插件(dylib)由于使用过Cydia安装的,因此它默认是依赖CydiaSubstrate插件的。CydiaSubstrate插件存放目录为iPhone的/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate。
  • 若是想要将咱们开发的动态库插件打包到ipa中, 就须要同时将CydiaSubstrate一块儿打包到ipa中,而且须要修改CydiaSubstrate的加载地址。

重签名GUI工具

iReSign

能够点击下载iReSign源码,运行里面的Mac应用,提供.app包的路径、entitlements.plist路径和embedded.mobileprovision的路径,就能够对.app进行重签名,而后打包生成ipa文件。

iOS App Signer

能够点击下载iOS App Signer源码,选择Release环境进行编译,拿到编译后的Mac应用,就能够直接使用。只需提供.app包的路径和embedded.mobileprovision的路径

重签名练习

练习1、使用codesign指令对Xcode生成.app文件进行重签名

如今咱们就来使用Xcode生成.app包,而后一步一步实现重签名的过程。

  • 首先,建立iOS项目TestSign,在ViewController中增长以下代码
#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
复制代码
  • 运行项目在界面上能够看到10 + 20 = 30的效果,此时,拿到编译Product目录下生成的.app包TestSign.app
  • 此时,建立PayLoad文件夹,将TestSign.app放到文件夹中,压缩PayLoad文件夹,修改压缩文件的后缀为.ipa,将PayLoad.ipa直接安装到手机上,是能够直接安装成功的,由于编译的时候就是选择的是真机编译,并且mobileprovision文件也是由Xcode自动生成,包含当前设备。
  • 经过以前的学习咱们知道,在Mach-O文件中,全局变量存放的位置是__DATA段,使用MachOView打开estSign.app中的可执行文件,以下

<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

复制代码
  • 经过如下指令获取到证书ID,要与embedded.mobileprovision文件中的证书保持一致:
security find-identity -v -p codesigning
复制代码
  • 使用codesign指令对.app包进行重签名
codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 --entitlements entitlements.plist TestSign.app 
复制代码

出现上图效果,代表重签名成功,此时,从新压缩TestSign.app文件,获得ipa,安装到以前的手机上就能够安装成功,同时,由于全局变量a的值被咱们改为了20,因此界面上展现的是20 + 20 = 40。至此,重签名操做完成。

练习2、Theos开发插件,注入腾讯视频App,安装到非越狱手机

下面为腾讯视频开发Theos插件,而后注入到腾讯视频App,而且从新生成ipa,安装到非越狱手机上,

  • 首先,下载腾讯视频App,能够经过爱思助手、PP助手下载已经进行过脱壳的App,或者经过App Store下载,而后使用Clutch工具进行脱壳操做。注意,必需要是脱壳后的App才能进行重签名,不然签名无效。
  • 链接手机,使用Reveal查看腾讯视频的页面,找到主界面QLHomeController。具体流程可参考iOS逆向学习之二(Mac远程操控iPhone)和iOS逆向学习之三(Cycript)
  • 建立Tweak项目。使用nic.pl指令建立Tweak项目,按步骤填写所须要的信息。注意MobileSubstrate Bundle filter填写腾讯视频App的bundle ID,经过Cycript获取到bundle ID为com.tencent.live4iphone。
  • 在Tweak.x文件中添加以下代码,效果是在腾讯视频首页弹出一个Alert弹框。
@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

复制代码
  • 执行make package && make install,对Tweak项目进行打包,打包完成后经过Cydia安装到iPhone上,等待iPhone重启,而后打开腾讯视频,在首页就能够看到咱们写的弹框了。

  • 获取如下签名须要的一些文件

    • 在iPhone上的/var/mobile/Containers/Bundle/Application/目录下找到live4iphone.app安装包。
    • 在/Library/MobileSubstrate/DynamicLibraries/目录下找到咱们编写的插件所生成的动态库test_live.dylib。
    • 在/Library/Frameworks/CydiaSubstrate.framework/目录下找到test_live.dylib依赖的动态库CydiaSubstrate。
    • 获取以前练习中使用的embedded.mobileprovision文件。
  • 将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文件当中

  • 修改CydiaSubstrate库的路径
    • 经过otool查看test_live.dylib的依赖库信息。

- 此时发现<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>
复制代码
  • 分别对test_live.dylib和CydiaSubstrate进行重签名
➜  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
复制代码
  • 使用iOS App Signer对live4iphone.app进行重签名,生成ipa安装包

  • 将live4iphone.ipa安装到非越狱手机上,能够发现安装成功,而且进入以后出现弹框。

相关文章
相关标签/搜索