欢迎阅读iOS逆向系列(按序阅读食用效果更加)
写在前面
应用重签名(本文涉及)无风险,但某信有检测BundId机制,建议不要大号登录
一、代码签名
代码签名是对可执行文件或脚本进行数字签名,用来确认软件在签名后未被修改或损坏的措施。和数字签名原理一样,只不过签名的数据是代码而已
1.简单的代码签名
-
苹果官方生成一对非对称加密的公私钥,在iOS的系统中内置一个公钥,私钥由苹果后台保存;
-
开发者上传App到App Store时,苹果后台用私钥对App数据进行签名(即先进行Hash得到hash值,再用私钥加密hash值得到“RSAHash”);
-
iOS系统下载这个App后,用内置的公钥验证这个签名,若签名正确,那么这个App肯定是由苹果后台认证的,并且没有被修改过,也就达到了苹果的需求:保证安装的每一个APP都是经过苹果官方允许的。(公钥解密“RSAHash”得到hash1,再对应用包进行相同hash算法得到hash2,验证两次hash值是否相同)
但是还有很多需求是不能通过App Store下载这一途径满足的
2.苹果的市场需求
- 安装包不需要上传到App Store,可以直接安装到手机上
- 开发App时直接真机调试安装
- 企业内部分发的渠道企业证书签名的APP也是需要顺利安装的
- 苹果为了保证系统的安全性,又必须对安装的APP有绝对的控制权
- 经过苹果允许才可以安装
- 不能被滥用导致非开发APP也能被安装
为了实现这些需求,iOS签名的复杂度也就开始增加了,苹果这里给出的方案是双层签名
3.双层签名
这里简单梳理了一下iOS的双层签名流程,当然这不是最终的流程,苹果爸爸在这个基础流程上还要加点东西。这个流程中有两个基础角色:Mac电脑、iPhone手机,因为iOS的APP开发环境在Mac系统下,所以这个依赖关系成为了苹果双层签名的基础
-
苹果自己有固定的一对公私钥,跟之前App Store原理一样,私钥存储在苹果后台,公钥放在每个iOS系统中。这里称为
公钥A
、私钥A
;在Mac系统中创建CSR
文件时生成非对称加密算法的一对公钥/私钥,这里称为公钥M
、私钥M
;A=Apple M = Mac -
开发者通过
CSR
文件向开发者中心申请证书
-
苹果服务器生成
证书
,也就是我们平时所说的开发者证书
,其原理就是用私钥A
对公钥M
非对称加密。请求到证书
之后,钥匙串访问
就会将证书
与本地私钥M
( 就是我们所熟知的p12
) 进行相关联 -
当我们
Command+B
生成一个应用时,Xcode就会用本地的私钥M
对这个应用进行签名,同时将证书放到app里面打包成ipa包 -
iPhone手机安装ipa包
-
iOS系统里的
公钥A
对证书进行验证 -
验证通过拿到
证书
中的公钥M
-
公钥M
验证app的签名。这里就间接验证了这个APP的安装行为是否经过苹果官方允许(这里只验证安装行为,不验证APP是否被改动,因为开发阶段 APP 内容总是不断变化的,苹果不需要管)
-
一次签名:私钥A->公钥M=>证书
-
二次签名:私钥M->app=>app
-
一次验证:公钥A->证书=>公钥M
-
二次验证:公钥M->私钥M=>结果
当CSR文件创建的时候,会自动生成一对私钥和公钥,私钥存储在Mac上,私钥存储默认存储在登录钥匙串中,可以在钥匙串的分类钥匙下查看,请求到的证书会包含公钥部分
图中还有一大坨东西是什么?接下来就来介绍它
4.描述文件
苹果为了解决应用滥用的问题,所以苹果又加了两个限制
- 在苹果后台注册过的设备才可以安装
- 签名只能针对某一个具体的App,并且苹果还想控制App里面的iCloud/PUSH/后台运行/调试器附加这些权限,所以苹果把这些权限开关统一称为Entitlements(授权文件)
因此才有了Provisioning Profile(描述文件)
描述文件一般包括证书、AppID、设备。当我们在真机运行或者打包一个项目的时候,证书用来证明我们程序的安全性和合法性
描述文件是在AppleDevelop网站创建的(在Xcode中填上AppleID它会进行创建),Xcode运行时会打包进入App内。所以我们使用CSR申请证书时,我们还要申请一个东西!!就是描述文件!
在开发时,编译完一个App后,用本地的私钥M对这个App进行签名,同时把从苹果服务器得到的 Provisioning Profile文件打包进APP里,文件名为embedded.mobileprovision,把 APP 安装到手机上,最后系统进行验证
前往描述文件目录
$ /Users/**用户名**/Library/MobileDevice/Provisioning Profiles
查看描述文件
$ security cms -Di xxx.mobileprovision
二、重签名
1.重签名前期准备
-
PP助手下载微信(越狱版本)
-
解压缩ipa包
-
终端进入如图目录查看应用签名信息
$ codesign -vv -d WeChat.app
//注意这里要选择iPhone Developer证书
$ security find-identity -v -p codesigning
- 查看MachO文件是否加密(步骤3显示包内容后进入当前目录)
//读取MachO信息
$ otool -l WeChat
//读取MachO信息并
$ otool -l WeChat > ~/Desktop/123.txt
//读取MachO中"cry"开头的信息
$ otool -l WeChat | grep cry
2.重签名步骤
1.删除插件和带有插件的.app包(比如Watch,PlugIns)
因为普通账号不能对插件进行签名,所以需要删除
在包内容
路径中找到Watch
和PlugIns
文件夹直接删除
2.重签framework
// 进入FrameWork目录
$ cd Frameworks
// 列举当前FrameWork
$ ls
// 覆盖签名
// codesign -fs "(证书名称)" (FrameWork名称)
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" mars.framework
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" marsbridgenetwork.framework
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" matrixreport.framework
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" OpenSSL.framework
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" ProtobufLite.framework
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" andromeda.framework
3.给MachO上可执行权限
在包内容
路径下执行$ Chmod +x WeChat
4.添加描述文件
新建工程,真机运行即可得到描述文件
将ipa包中的描述文件
放到微信的包内容
中去
5.修改应用包的bundid
修改微信包内容
中的info.plist->BundleId,改为与描述文件
的BundleId一致
6.授权文件重签app包
查看原先的描述文件
embedded.mobileprovision并复制相应内容
$ security cms -Di embedded.mobileprovision
利用Xcode新建一个plist文件
以代码形式打开plist文件(open As->Source code)并粘贴相应内容
复制一份与目标.app放于同一目录下
最后一步命令行签名app包
$ codesign -fs "iPhone Developer: 840385400@qq.com (NZJQGFWAYE)" --no-strict --entitlements=ent.plist WeChat.app
7.安装.app包
Xcode界面下shift+cmd+2
调出手机设备
app运行后利用Xcode附加进程
点击“登录”按钮就可以打印对应信息了
接下来再介绍个操作——利用Xcode来使以上繁琐的步骤略微减少
3.xcode重签名
必须是与MachO文件同名工程(工程名相同,BundId无所谓),否则进程不是微信进程
1.运行app,装描述文件
新建WeChat
工程,同上Command+Run
,将描述文件生成一下
2.替换掉app包
复制一个新的越狱包,覆盖掉到原来的ipa包
3.删除插件
同本文2-1
4.重签framework
同本文2-2
5.run
由于是Xcode直接运行,可以通过Debug View查看界面
写在结尾
本来想写的简洁点,但为了让看这篇文章的人有所收获,我还是一步步操作尽可能讲解的详细点。我觉得写博客的目的一半是为了积累,另一半是送人玫瑰,手留余香,希望对重签名原理这块没怎么接触过的同学能有个初步认识乃至能够上手操作