这个系列,是很早听 MJ 课程时的整理,现在分享出来。 其中一些参考资料有些有引用,有些可能忘记添加了,如果有引用部分资料,可以联系我。
iOS 逆向(一)环境搭建
iOS 逆向(二)Cycript
iOS 逆向(三)逆向工具
iOS 逆向(四)脱壳
审核中 iOS 逆向(五)Theos工具
iOS 逆向(六)动态调试
iOS 逆向(七)重签名
阅读本文前,请确保具有加密和签名的基础,可以查阅 iOS安全(二)加密与签名。
一、iOS签名机制
iOS签名机制的作用,就是保证安装到用户手机上的App都是经过Apple官方审核、认证、允许部分权限的。
不管是真机调试,还是发布APP,开发者都需要经过一系列复杂的步骤
☞ 生成CertificateSigningRequest.certSigningRequest
文件
☞ 生成并获取ios_development.cer
、ios_distribution.cer
证书文件
☞ 添加App ID、注册device
☞ 生成并获取*.mobileprovision
文件
每一步的作用是什么?
.certSigningRequest
、.cer
、.mobileprovision
文件究竟里面包含了什么?有何用处?
##1. Apple 的签名流程
下面针对三种情况下的Apple 签名流程做了一个梗概:
- 用户从App Store下载的App,是如何进行安全验证的?
- 开发者Xcode直接安装App,是如何进行安全验证的?
- 发布App,不管是发布到App Store还是第三方渠道,是如何进行安全验证的?
1.1 App Store 安装
如果APP是从AppStore下载安装的,你会发现里面是没有mobileprovision文件的
它的验证流程会简单很多,大概如下所示
1.2 Xcode安装
1.3 完整
2. iOS签名机制步骤
2.1. 生成Mac设备的公私钥
keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 就是公钥,私钥保存在本地电脑里。
2.2 生成证书
2.3 获得证书
ios_development.cer、ios_distribution.cer文件
利用Apple后台的私钥,对Mac设备的公钥进行签名后的证书文件
2.4 生成mobileprovision
2.5 安全检测
p12
本地私钥,可以导入到其他电脑,用于团队开发。
二、重签名
如果需要将破坏了签名的安装包,安装到非越狱的手机上,需要对安装包进行重签名的操作。
签名`.app`包,假如没有`.app`包,只有ipa包,那么直接解压ipa,就可以获得`.app`包。
进行重签名的包,必须是未加壳的。
再一次强调,必须未加壳。
所以,加壳应用,先进行脱壳。
重签名打包后,安装到设备的过程中,可能需要经常查看设备的日志信息:
- 程序运行过程中:Windows -> Device and Simulators -> View Device
- 程序安装过程中:Windows -> Device and Simulators -> Open Consel
1、重签.app包
首先,我们讨论最简单的情况,.app包内不包含其他动态库或者App Extension等。
只有应用主程序的Mach-O文件的情况。
1.1 准备
首先必须准备将embedded.mobileprovision
文件,必须是付费证书产生的 ,appid,device一定要匹配,并将embedded.mobileprovision
放入.app内部
- 可以通过Xcode自动生成,然后在编译后的APP包中找到;
- 可以去开发者账户中心生成下载;
1.2 查看本机证书
重签名要用到证书,所以通过下面命令查看:
$ security find-identity -v -p codesigning
1) F11EAA6593D8BBE******3AA95C19BE66CB8250 "iPhone Distribution: **** Weng (69*****F36)"
2) BC4FF0F29BD938EC****3AA5271F71D64894B60 "iPhone Developer: **** Weng (7R*****BXZ)"
1.3 生成权限文件
从embedded.mobileprovision
文件中提取出entitlements.plist
权限文件。
$ security cms -D -i embedded.mobileprovision > temp.plist
$ /usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist
1.4 签名
1)app包签名
对.app包进行签名
$ codesign -fs 证书ID或名称 --entitlements entitlements.plist xxx.app
实例:
$ codesign -fs BC4FF0F29******A5271F71D64894B60 --entitlements entitlements.plist CodesignApp.app
CodesignApp.app: replacing existing signature
2)打包ipa
新建Payload
文件夹,将.app安装包放入,压缩成zip包,并将后缀名改名为.ipa即可。
1.5 GUI工具一步达成
只需要将embedded.mobileprovision
拷贝到.app
包内。然后,采用iOS App Signer来一步达成。
-
只要在Input File中输入.app文件路径,只针对.app包签名,.app内部动态库需要单独签名。
-
iReSign 与该功能类似,但是操作比上面多。
-
签名完成之后会导出
ipa
包
2. 含动态库的.app包
包含动态库也分两种情况:
- 从App Store下载的包中包含动态库、App Extension等;
- Tweak项目中,需要加载我们自己开发的插件;
2.1 App Store下载.app包重签名
- 移除
.app
包内部_CodeSignature
文件夹。 .app
包内的所有动态库(.framework、.dylib)、App Extension(PlugIns 文件夹,拓展名为appex)、Watch App(Watch文件夹)都需要进行重新签名
查看可用证书:
$ security find-identify -v -p codesigning
签名:
$ cd .app内部目录
$ codesign -fs 证书ID或名称 xxx.dylib
- 将
embedded.mobileprovision
拷贝到.app
包内 - iOS App Signer对整个
.app
包进行重签名,得到ipa包。
2.2 tweak项目
我们在theos编译后生成的是动态库,现在需要打包到Mach-O文件,并通过签名安装到非越狱手机上。
通过Theos开发动态库插件(dylib)
- 默认都依赖于/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate
- 如果要将动态库插件打包到ipa中,也需要将CydiaSubstrate打包到ipa中,并且修改下CydiaSubstrate的加载地址。
下面均以test开头为例:
1)准备
- ①
test.app
- 假设test.app内Mach-O为
testmach
- 通过MJAppTool找到路径,拷贝到电脑
- 假如app未脱壳,先脱壳获取ipa,将ipa拷贝到电脑,得到
.app
,然后进行一下操作
- 假设test.app内Mach-O为
- ②
tweak_test.dylib
- theos开发得到的动态库插件
- /Library/MobileSubstrate/DynamicLibraries
- ③
CydiaSubstrate
- /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate
2)流程
☞ 移除.app
包内部_CodeSignature
文件夹。
☞ 将embedded.mobileprovision
拷贝到.app
包内。
☞ 将②③放入①中:直接拷贝,注意注意!!!确保①②③处于同级目录!!!
☞ 将②插入①中:利用insert_dylib
☞ 更改②中加载③的地址:利用install_name_tool
☞ 且②③需要单独签名:利用codesign
☞ 注意注意:看①中.app内是否有其他动态库,假如有,还是要!!!单独签名!!!
☞ 再给①签名:利用iOS App Signer,得到ipa包
3)insert_dylib
insert_dylib
作用就是将tweak_test.dylib
动态库插入到.app内testmach
主程序的可执行文件中。
a. 下载源码
b. 编译
源码下载后,打开工程,Edit Scheme中以Release编译,然后在Product中,找到命令行程序。
将其,移动到/usr/local/bin
即可。
c. 使用
$ insert_dylib 动态库加载路径 Mach-O文件
//or,假如新旧名称一样,就会覆盖
$ insert_dylib 动态库加载路径 原来Mach-O文件 新Mach-O文件
- --weak:以weak方式加载动态库,即使动态库找不到也不会保存。
- --all-yes:后面所有的选择都为yes
- insert_dylib的本质是往Mach-O文件的Load Commands中添加了一个LC_LOAD_DYLIB或
LC_LOAD_WEAK_DYLIB
d.实例
假如Mach-O文件Test
和tweak_test.dylib
处在同一目录下。
这里用到一个环境变量:
**@executable_path ** 代表Mach-O可执行文件目录下寻找动态库
$ cd test.app内部目录
//覆盖原来mach-o
$ insert_dylib @executable_path/tweak_test.dylib testmach testmach --weak --all-yes
4)更改动态库加载地址
可以使用install_name_tool修改Mach-O文件中动态库的加载地址,用法如下:
$ install_name_tool -change 旧地址 新地址 Mach-O文件
此处我们需要修改tweak_test.dylib
中加载CydiaSubstrate
的地址:
由于tweak_test.dylib
和CydiaSubstrate
处于同级目录,这里用到另一个环境变量:
**@loader_path ** 代表动态库所在目录
$ install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate tweak_test.dylib
修改之后:
这样一来,dylib就会从本地目录加载CydiaSubstrate
。
5)签名动态库
``.app`包内的所有动态库(.framework、.dylib)、App Extension(PlugIns 文件夹,拓展名为appex)、Watch App(Watch文件夹)都需要进行重新签名。
$ cd .app内部目录
$ codesign -fs 证书ID或名称 xxx.dylib
6)其他
- 查看Mach-O动态库依赖信息 看看我们Mach-O是否已经加载了tweak生成的动态库,或者查看动态库加载的动态库:```bash
- $ otool -L Mach-O文件(可以是动态库,动态库本身就是Mach-O文件)
- [sigh](https://github.com/fastlane/fastlane/tree/master/sigh)
[fastlane](https://github.com/fastlane/fastlane)工具之一,用于获取provisioning文件```bash
$ sudo gem install sigh
- 假如app只支持iPhone,不支持iPad,可以直接通过修改Info.plist文件中的相关配置即可,删除Support Device;
参考
工具
- AppBox
- code signing A new approach to code signing
- insert_dylib
- iOS App Signer