iOS逆向工程(十一):iOS签名机制

前言

想把逆向之后的APP安装到非越狱的手机上,就需要研究一下iOS的签名机制了,了解了原理之后,就可以使用codesign对APP的动态库、AppExtension、APP包进行重签名了,然后就可以安装到非越狱手机上了
一、签名基础知识 - 对称加密
    1. 对称加密,就是加密、解密使用的是同一个密钥,如下图所示,常见的对称加密算法有DES、3DES、AES,目前AES已经逐步取代DES、3DES,成为首选的对称加密算法了。
    对称加密
    1. 使用对称加密,一定会碰到密钥配送问题,例如: A将加密后的信息发给B,B想解密的话,就需要拿到密钥,但是B应该怎么在保证安全的前提下拿到密钥呢?
    1. 解决密钥配送问题的几种办法:事先共享密钥、密钥配送中心、Diffie-Hellman密钥交换、非对称加密
二、签名基础知识 - 非对称加密
    1. 非对称加密,也称公钥密码,非对称加密的密钥分为加密密钥、解密密钥两种,并不是同一个密钥,如下图所示,目前使用最广泛的非对称加密算法是:RSA非对称加密算法
      非对称加密
    1. 公钥可以公开,私钥不能公开,私钥和公钥都可以用来加密解密,公钥加密,就必须用私钥解密,私钥加密就必须用公钥解密
    1. 公钥和私钥是一一对应的,不能单独生成,一对公钥和私钥统称为密钥对
    1. 私钥加密的密文,必须用对应的公钥才能解密
    1. 公钥加密的密文,必须用对应的私钥才能解密
三、混合密码系统
    1. 对称加密不能很好的解决密钥配送问题 ,非对称加密的加密解密速度又慢,我们可以将对称加密和非对称加密混合使用,就可以解决这两个缺点,思路如下,如今网络上的密码通信所用的SSL/TLS都运用了混合密码系统
混合密码系统
    1. 消息接收者受到上述组合消息后,就可以拿出自己的私钥解密出对称密码的密钥,然后用此密钥解密消息
    1. 混合密码系统不仅解决了密钥配送问题,还解决了非对称加密解密速度慢的问题
四、签名基础知识 - 单向散列函数
    1. 单向散列函数,又被称为消息摘要函数、哈希函数,根据数据内容计算出散列值,散列值具备以下特点:
    • 对于任意长度的消息,用同一个散列函数,得出的散列值的长度是相同的

    • 计算速度快,能快速计算出散列值

    • 消息不同,散列值也不同,对数据很敏感,哪怕只有一位不同,最后得出的散列值也完全不同

    • 具备单向性,可以用消息算出散列值,但是很难从散列值回推出消息

    1. 常见的几种单向散列函数:
    • MD4、MD5,产生128bit的散列值,目前已经不安全了

    • SHA-1产生160bit的散列值,目前已经不安全了

    • SHA-2是SHA-1的继任者,包括SHA-256、SHA-384、SHA-512等等,目前还是安全的

    • SHA-3,第三代安全散列算法,目前是安全的

    1. 单向散列函数的几个应用:对比散列值防篡改、密码散列做加密
五、签名基础知识 - 数字签名
    1. 数字签名,就是消息发送者用自己的私钥,对消息的散列值进行加密,消息接受者用公钥解密,这样做,主要为了证明消息是从发送者手里发出去的,没有被篡改过,因为私钥只有消息发送者才有。
    1. 数字签名的整个流程,如下图所示:


      数字签名
    1. 数字签名的作用:确认消息的完整性和是否被篡改,防止消息发送人否认,单纯的数字签名并不能保证机密性
    1. 要想正确的使用签名,前提是验证签名的公钥必须属于发送者,如果上图中的Bob是个攻击者伪装的假Bob,那么这个攻击者就可以自己生成新的密钥对,然后将攻击者的公钥给真Bob,从而伪造信息,所以使用签名前,必须验证公钥的合法性
六、签名基础知识 - 证书
    1. 如何验证公钥的合法性呢?答案就是使用证书,证书是指:权威机构(CA)用自己的私钥对别人合法的公钥的散列值进行加密,也就是对别人的公钥进行数字签名,然后生成一个证书,来证明这个公钥是合法的,证书里面一般会包含:姓名、邮箱等个人信息;还有合法的公钥;以及CA施加的数字签名
    1. 证书的使用过程,如下图所示:


      证书的使用过程
  • 3. 基础知识总结:
    • (1). 对称加密,加密解密用的同一个密钥,加密解密速度快 ,但是无法解决密钥配送问题
    • (2). 非对称加密,加密解密用的密钥不同,用公钥加密需用私钥解密,私钥加密用公钥解密,加密解密速度慢,可以解决密钥配送问题
    • (3). 单向散列函数,根据消息生成固定长度的散列值,可以用来防止数据被篡改
    • (4). 数字签名,用私钥加密消息的散列值,生成密文,接受者用公钥解密,进行对比
    • (5). 证书,用CA的私钥,对其他人的合法公钥生成数字签名,也就是用私钥对别人的合法公钥的散列值进行加密
七、iOS签名机制
    1. 基础知识学完了,我们正式开始学习iOS的签名机制,iOS签名机制的作用就是:保证安装到用户手机上的APP,都是经过苹果官方允许的
    1. 真机调试和打包应用的时候,都会经历以下步骤:
    • 生成.certSigningRequest文件

    • 获得ios_development.cer \ ios_distribution.cer证书文件

    • 注册device、添加App ID

    • 获得*.mobileprovision文件

    1. 上述的步骤每一步都做了什么事情呢?生成的这些文件包含了什么呢?听我娓娓道来:
    • CertificateSigningRequest.certSigningRequest文件,其实就是Mac设备的公钥
      .certSigningRequest.png
  • ios_development.cer、ios_distribution.cer文件,其实就是用Apple后台的私钥,对Mac设备的公钥进行签名后的证书文件

    证书.png

  • .mobileprovision文件就是把.cer、devices设备ID、App ID、entitlements权限文件放在一起,用Apple的私钥做了一次数字签名

mobileprovision文件
    1. iOS签名机制的整个流程如下:(每台iPhone上都会有Apple的公钥)
      iOS签名机制流程图
    1. 如果App是通过打包或者真机调试安装到手机上的话,都会经历以下的安全检测,如果有一项不匹配,就无法安装
      安全检测.png
    1. 如果App是从AppStore下载安装的,你会发现里面是没有mobileprovision文件的,它的验证流程会简单很多,如下所示:
      AppStore下载的验证流程.png
八、iOS重签名
    1. 我们使用codesign命令,对App进行重签名,步骤如下:
    • (1). 准备一个embedded.mobileprovision文件,必须是付费证书产生的,appid、device一定要匹配,准备好后,放入.app包中
      • 可以通过Xcode自动生成,然后再编译后的APP包中找到
      • 也可以通过开发者证书网站生成下载
    • (2). 从embedded.mobileprovision文件中提取出entitlements.plist权限文件,命令如下:
security cms -D -i embedded.mobileprovision > temp.plist
/usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist  > entitlements.plist
  • (3). 通过以下命令,查看可用的证书,并拿到证书ID
security find-identity -v -p codesigning
  • (4). 对.app内部的动态库、AppExtension等进行签名
codesign -fs 证书ID xxx.dylib
  • (5). 对.app包进行重签名
codesign -fs 证书ID --entitlements entitlements.plist  xxx.app
    1. 除了使用命令行重签名以外,我们还可以使用GUI图形化工具进行重签名,这里推荐两个比较好用的工具:
    • iOS App Signer,可以对.app重签名打包成.ipa,需要再.app包中提供对应的embedded.mobileprovision文件

    • iReSign,可以对ipa进行重签名,需要提供entitlements.plist、embedded.mobileprovision文件的路径

九、对tweak项目进行重签名
  • 1. 准备好tweak项目的App包,还有通过tweak生成的dylib库
    • (1). 拿到脱壳后的ipa文件,具体脱壳方法可以看这里,一键脱壳,以便后续使用

    • 也通过MJAppTools工具的MJAppTools -l命令,找到微信的Mach-O可执行文件路径 ,通过iFunBox将其拖出来,然后用class-dump进行脱壳,以便后续使用

    • (2). 通过iFunBox,在手机的Device/Library/MobileSubstrate/DynamicLibraries目录中,找到通过tweak生成的WeChatTest.dylib库,拖出来以便后续使用

    • (3). 将App包中的Info.plist文件里的设备列表UISupportedDevices删掉,并保存,主要为了防止安装时报不支持设备的错误

  • 2. 从苹果开发者网站准备一个embedded.mobileprovision文件,必须是付费证书产生的,appid、device一定要匹配,准备好后,放入App包中
  • 3. 使用insert_dylib库将dylib动态库注入到Mach-O文件中
    • (1). 将下载好的insert_dylib库进行编译,拿到release版本的insert_dylib库,将其放入到mac的/usr/local/bin目录下,这样就可以在命令行里使用insert_dylib命令了

    • (2). 命令格式是:insert_dylib 动态库加载绝对路径 Mach-O文件,这个命令有两个常用的参数:--weak,及时动态库找不到也不会报错;--all-yes,后面的所有选项都是yes

@executable_path代表可执行文件所在的目录
@loader_path代表动态库所在的目录

将tweak_xxx.dylib注入到MachO_XXX文件中,命令如下 :
insert_dylib @executable_path/tweak_xxx.dylib MachO_XXX  --weak --all-yes

将WeChatTest.dylib注入到WeChat可执行文件中,命令如下:
insert_dylib @executable_path/WeChatTest.dylib WeChat --weak --all-yes
  • 4. 使用在mac命令行,输入otool -L Mach-O可执行文件命令,查看dylib库的依赖文件,我们发现tweak生成的dylib库依赖CydiaSubstrate库,所以想要在非越狱手机上安装,就必须把CydiaSubstrate库也注入到Mach-O文件中
使用otool命令,找到WeChatTest.dylib的依赖库
otool -L WeChatTest.dylib

输出了下面这个,证明WeChatTest.dylib依赖CydiaSubstrate
/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)
  • 5. 在手机上的Device/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate,找到CydiaSubstrate库,拖出来,以便后续使用
  • 6. 由于非越狱设备中没有CydiaSubstrate库,所以要把CydiaSubstrateWeChatTest.dylib放在同一个目录下,并且更改WeChatTest.dylib中的CydiaSubstrate库的加载地址,命令是:install_name_tool -change 旧地址 新地址 Mach-O文件
更改WeChatTest.dylib中的CydiaSubstrate库的加载地址
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate  WeChatTest.dylib
  • 7. 对动态库进行重签名,命令是:codesign -fs 证书ID xxx.dylib
查看所有可用证书,选择合适的证书,进行重签名
security find-identity -v -p codesigning

先对CydiaSubstrate进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 CydiaSubstrate

再对WeChatTest.dylib进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 WeChatTest.dylib
  • 8. 用iOS App Signer对.app包进行重签名,需要将CydiaSubstrate、WeChatTest.dylib都放入.app包中,在进行重签名,iOS App Signer会自动给Framework、dylib、AppExtension、WatchApp、.app包重新签名
image.png
  • 9. 使用iFunBox工具把签好名的ipa包,安装到非越狱手机上,如果安装失败,可以打开控制台,查看安装失败的日志找原因
十、总结一下

整个逆向、重签名过程的原理,其实非常简单,如下所示,假设我们要为微信开发插件

    1. 通过Theos生成一个dylib动态库: A.dylib(为了方便叙述,我们称它为A.dylib动态库)
    1. 通过insert_dylibA.dylib注入到脱壳后微信的可执行文件中,把A.dylib和它依赖的CydiaSubstrate库一起放到WeChat.app包中,也就是跟微信可执行文件同一个目录下 (一键脱壳的方法)
寻找A.dylib库
在手机的Device/Library/MobileSubstrate/DynamicLibraries目录中,可以找到通过tweak生成的A.dylib库

寻找CydiaSubstrate库
在手机上的Device/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate,可以找到CydiaSubstrate库

注入A.dylib到WeChat可执行文件
insert_dylib @executable_path/A.dylib WeChat --weak --all-yes WeChat
    1. 修改A.dylibCydiaSubstrate库的加载路径,把绝对路径改成相对路径
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate  WeChatTest.dylib
    1. WeChat.app包中的Info.plist文件里的设备列表UISupportedDevices删掉,并保存,主要为了防止安装时报不支持设备的错误
    1. WeChat.app包中的所有Info.plist文件里的com.tencent.xin都改成你想改的BundleID,例如我就改成:com.test888.888,包括插件、扩展里的。(大部分的com.tencent.xin都需要改,要是不知道作用的话,建议你全改)
    1. 从苹果开发者网站准备一个embedded.mobileprovision文件,必须是付费证书产生的,appid、device一定要匹配,准备好后,放入WeChat.app包中
    1. 使用codesign命令对A.dylibCydiaSubstrate库进行重签名
查看所有可用证书,选择合适的证书,进行重签名
security find-identity -v -p codesigning

先对CydiaSubstrate进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 CydiaSubstrate

再对WeChatTest.dylib进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 A.dylib
    1. 使用iOS App Signer对WeChat.app包进行重签名,证书一定要选择对,然后通过iFunBox安装到手机即可,遇到错误查看控制台日志 (由于上面已经改过了BundleID,这里就不需要再改了)
      iOS App Signer会给包里的所有动态库、插件、扩展进行签名.png
    1. 以上这么多步骤,就是为了模拟真机调试的过程,为啥描述文件要命名为embedded.mobileprovision呢,因为真机调试的时候,苹果就把描述文件命名为embedded.mobileprovision,你可以在真机调试的.app包中查看,通过这些步骤,让苹果设备误以为你是真机调试,就可以把逆向的App安装到非越狱的手机上啦。

你可能感兴趣的:(iOS逆向工程(十一):iOS签名机制)