前言
想把逆向之后的APP安装到非越狱的手机上,就需要研究一下iOS的签名机制了,了解了原理之后,就可以使用codesign
对APP的动态库、AppExtension、APP包进行重签名了,然后就可以安装到非越狱手机上了
一、签名基础知识 - 对称加密
-
-
对称加密,就是加密、解密使用的是同一个密钥,如下图所示,常见的对称加密算法有
DES、3DES、AES
,目前AES
已经逐步取代DES、3DES
,成为首选的对称加密算法了。
-
对称加密,就是加密、解密使用的是同一个密钥,如下图所示,常见的对称加密算法有
- 使用对称加密,一定会碰到密钥配送问题,例如: A将加密后的信息发给B,B想解密的话,就需要拿到密钥,但是B应该怎么在保证安全的前提下拿到密钥呢?
- 解决密钥配送问题的几种办法:事先共享密钥、密钥配送中心、Diffie-Hellman密钥交换、非对称加密
二、签名基础知识 - 非对称加密
-
非对称加密,也称公钥密码,非对称加密的密钥分为
加密密钥、解密密钥
两种,并不是同一个密钥,如下图所示,目前使用最广泛的非对称加密算法是:RSA非对称加密算法
-
非对称加密,也称公钥密码,非对称加密的密钥分为
- 公钥可以公开,私钥不能公开,私钥和公钥都可以用来加密解密,公钥加密,就必须用私钥解密,私钥加密就必须用公钥解密
- 公钥和私钥是一一对应的,不能单独生成,一对公钥和私钥统称为密钥对
- 由
私钥
加密的密文,必须用对应的公钥
才能解密
- 由
- 由
公钥
加密的密文,必须用对应的私钥
才能解密
- 由
三、混合密码系统
-
对称加密
不能很好的解决密钥配送问题 ,非对称加密
的加密解密速度又慢,我们可以将对称加密和非对称加密混合使用,就可以解决这两个缺点,思路如下,如今网络上的密码通信所用的SSL/TLS
都运用了混合密码系统
-
- 消息接收者受到上述组合消息后,就可以拿出自己的
私钥
解密出对称密码的密钥
,然后用此密钥解密消息
- 消息接收者受到上述组合消息后,就可以拿出自己的
- 混合密码系统不仅解决了密钥配送问题,还解决了非对称加密解密速度慢的问题
四、签名基础知识 - 单向散列函数
-
- 单向散列函数,又被称为消息摘要函数、哈希函数,根据数据内容计算出散列值,散列值具备以下特点:
对于任意长度的消息,用同一个散列函数,得出的散列值的长度是相同的
计算速度快,能快速计算出散列值
消息不同,散列值也不同,对数据很敏感,哪怕只有一位不同,最后得出的散列值也完全不同
具备单向性,可以用消息算出散列值,但是很难从散列值回推出消息
-
- 常见的几种单向散列函数:
MD4、MD5,产生128bit的散列值,目前已经不安全了
SHA-1产生160bit的散列值,目前已经不安全了
SHA-2
是SHA-1的继任者,包括SHA-256、SHA-384、SHA-512等等,目前还是安全的SHA-3
,第三代安全散列算法,目前是安全的
- 单向散列函数的几个应用:对比散列值防篡改、密码散列做加密
五、签名基础知识 - 数字签名
-
数字签名,就是
消息发送者用自己的私钥,对消息的散列值进行加密
,消息接受者用公钥解密,这样做,主要为了证明消息是从发送者手里发出去的,没有被篡改过,因为私钥只有消息发送者才有。
-
数字签名,就是
-
数字签名的整个流程,如下图所示:
-
- 数字签名的作用:确认消息的完整性和是否被篡改,防止消息发送人否认,单纯的数字签名并不能保证机密性
- 要想正确的使用签名,前提是验证签名的公钥必须属于发送者,如果上图中的Bob是个攻击者伪装的假Bob,那么这个攻击者就可以自己生成新的密钥对,然后将攻击者的公钥给真Bob,从而伪造信息,所以使用签名前,必须验证公钥的合法性
六、签名基础知识 - 证书
- 如何验证公钥的合法性呢?答案就是使用证书,证书是指:
权威机构(CA)用自己的私钥对别人合法的公钥的散列值进行加密
,也就是对别人的公钥进行数字签名,然后生成一个证书,来证明这个公钥是合法的,证书里面一般会包含:姓名、邮箱等个人信息;还有合法的公钥;以及CA施加的数字签名
- 如何验证公钥的合法性呢?答案就是使用证书,证书是指:
-
证书的使用过程,如下图所示:
-
-
3. 基础知识总结:
-
(1). 对称加密,加密解密用的同一个密钥,加密解密速度快 ,但是无法解决密钥配送问题
-
(2). 非对称加密,加密解密用的密钥不同,用公钥加密需用私钥解密,私钥加密用公钥解密,加密解密速度慢,可以解决密钥配送问题
-
(3). 单向散列函数,根据消息生成固定长度的散列值,可以用来防止数据被篡改
-
(4). 数字签名,用私钥加密消息的散列值,生成密文,接受者用公钥解密,进行对比
-
(5). 证书,用CA的私钥,对其他人的合法公钥生成数字签名,也就是用私钥对别人的合法公钥的散列值进行加密
-
七、iOS签名机制
- 基础知识学完了,我们正式开始学习iOS的签名机制,iOS签名机制的作用就是:保证安装到用户手机上的APP,都是经过苹果官方允许的
-
- 真机调试和打包应用的时候,都会经历以下步骤:
生成
.certSigningRequest
文件获得
ios_development.cer \ ios_distribution.cer
证书文件注册
device
、添加App ID
获得
*.mobileprovision
文件
-
- 上述的步骤每一步都做了什么事情呢?生成的这些文件包含了什么呢?听我娓娓道来:
-
CertificateSigningRequest.certSigningRequest
文件,其实就是Mac设备的公钥
-
ios_development.cer、ios_distribution.cer
文件,其实就是用Apple后台的私钥,对Mac设备的公钥进行签名后的证书文件
.mobileprovision文件
就是把.cer、devices设备ID、App ID、entitlements权限文件
放在一起,用Apple的私钥做了一次数字签名
-
iOS签名机制的整个流程如下:(每台iPhone上都会有Apple的公钥)
-
iOS签名机制的整个流程如下:(每台iPhone上都会有Apple的公钥)
- 如果App是通过打包或者真机调试安装到手机上的话,都会经历以下的安全检测,如果有一项不匹配,就无法安装
- 如果App是通过打包或者真机调试安装到手机上的话,都会经历以下的安全检测,如果有一项不匹配,就无法安装
- 如果App是从
AppStore
下载安装的,你会发现里面是没有mobileprovision文件
的,它的验证流程会简单很多,如下所示:
- 如果App是从
八、iOS重签名
-
- 我们使用
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
-
- 除了使用命令行重签名以外,我们还可以使用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
库,所以要把CydiaSubstrate
与WeChatTest.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包
重新签名
-
9. 使用iFunBox工具把签好名的ipa包,安装到非越狱手机上,如果安装失败,可以打开控制台,查看安装失败的日志找原因
十、总结一下
整个逆向、重签名过程的原理,其实非常简单,如下所示,假设我们要为微信开发插件
- 通过
Theos
生成一个dylib动态库: A.dylib
(为了方便叙述,我们称它为A.dylib动态库)
- 通过
- 通过
insert_dylib
将A.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
- 修改
A.dylib
中CydiaSubstrate库
的加载路径,把绝对路径改成相对路径
- 修改
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate WeChatTest.dylib
- 将
WeChat.app
包中的Info.plist
文件里的设备列表UISupportedDevices
删掉,并保存,主要为了防止安装时报不支持设备的错误
- 将
- 将
WeChat.app
包中的所有Info.plist
文件里的com.tencent.xin
都改成你想改的BundleID,例如我就改成:com.test888.888
,包括插件、扩展里的。(大部分的com.tencent.xin
都需要改,要是不知道作用的话,建议你全改)
- 将
- 从苹果开发者网站准备一个
embedded.mobileprovision
文件,必须是付费证书产生的,appid、device一定要匹配,准备好后,放入WeChat.app包中
- 从苹果开发者网站准备一个
- 使用
codesign
命令对A.dylib
和CydiaSubstrate库
进行重签名
- 使用
查看所有可用证书,选择合适的证书,进行重签名
security find-identity -v -p codesigning
先对CydiaSubstrate进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 CydiaSubstrate
再对WeChatTest.dylib进行重签名
codesign -fs 2E377710143F8F007535CA3791B29FBDBF173BB9 A.dylib
- 使用iOS App Signer对WeChat.app包进行重签名,证书一定要选择对,然后通过
iFunBox
安装到手机即可,遇到错误查看控制台
日志 (由于上面已经改过了BundleID,这里就不需要再改了)
- 使用iOS App Signer对WeChat.app包进行重签名,证书一定要选择对,然后通过
- 以上这么多步骤,就是为了模拟真机调试的过程,为啥描述文件要命名为
embedded.mobileprovision
呢,因为真机调试的时候,苹果就把描述文件命名为embedded.mobileprovision
,你可以在真机调试的.app包
中查看,通过这些步骤,让苹果设备误以为你是真机调试,就可以把逆向的App安装到非越狱的手机上啦。
- 以上这么多步骤,就是为了模拟真机调试的过程,为啥描述文件要命名为