IOS逆向学习-签名机制
Posted GY-93
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOS逆向学习-签名机制相关的知识,希望对你有一定的参考价值。
1. 加密解密
encrypt
:加密decrypt
:解密plaintext
:明文ciphertext
:密文
1.0 学习流程图
1.1 学前须知
1.1.1 发送消息流程
- 为了便于学习,设计4个虚拟人物
- Alice、Bob:互相通信
- Eve: 窃听者
- Mallory:主动攻击者
1.1.2 如何防止被窃听
1.1.3 如何加密解密
1.1.4 密码的类型
- 根据密钥的使用方法,可以将密码分为2种
- 对称密码
- 公钥密码(非对称密码)
1.1.5 密码的配送问题
-
在使用对称密码时,一定会遇到密钥配送问题
-
假设, Alice将
使用对称密码加密过的消息
发给了Bob- 只有将密钥发送给Bob,Bob才能完成解密
- 在发送密钥的过程中,可能会被Eve窃取密钥,最后Eve也能完成解密
-
如何解决密钥配送问题
- 事先共享密钥
- 密钥分配中心
- Diffie-Hellman密钥交换
公钥密钥
1.2 对称密码
- 在对称密码中,加密、解密时使用的是同一个密钥
- 常见的对称密钥算法有:
DES、3DES、AES
1.2.1 DES(Data Encryption Standard)
- DES是一种将64bit明文加密成64bit密文的对称密码算法,密钥长度是56bit
- 规格上来说,密钥长度是64bit,但是每隔7bit会设置一个用于错误检查的bit,因此密钥长度实质上是56bit
- 由于DES每次只能加密64bit的数据,遇到比较大的数据,需要对DES加密进行迭代(反复)
- 目前已经可以在短时间内被破解,所以不建议使用
1.2.2 3DES
- 3DES,将DES重复3次所得到的一种密码算法,也叫做3重DES
- 目前还被一些银行等机构使用,但是处理速度不高,安全性逐渐暴露出问题
- 3个密钥都是不同的,也称为DES-EDE3
- 如果所有的密钥都使用同一个,则结果与普通的DES是等价
- 如果密钥1、密钥3相同,密钥2不同,称为DES-EDE2
1.2.3 AES(Advanced Encryiption Standard)
- 取代DES称为新标准的一种对称密码算法
- 在2000年时选择Rijindael算法作为AES的实现
- 目前AES,已经逐步取代DES、3DES,成为首选的对称密码算法
- 一般来说,我们也不应该去使用任何自制的密码算法,而是应该使用AES,它经过了全世界密码学家所进行的高品质验证工作
1.3 公钥密码
1.3.1 公钥密码简介
- 公钥密码中,密钥分为
加密密钥、解密密钥
2种,它们并不是同一个密钥 - 公钥密码也被称为
非对称密码
(Asymmetric Cryptography) - 在公钥密码中
- 加密密钥,一般是公开的,因此该密钥称为公钥(public key)
- 解密密钥,由消息接受者自己保管,不能公开,因此也称为私钥(private key)
- 公钥和私钥是一一对应的,是不能单独生成的,一对公钥和密钥统称为密钥对(key pair)
- 由公钥加密的密文,必须使用与该公钥对应的私钥才能解密
- 由私钥加密的密文,必须使用与私钥对应的公钥才能解密
1.3.2 解决密钥配送问题
- 由消息的接受者,生成一对公钥、私钥
- 将公钥发给消息的发送者
- 消息的发送者使用公钥加密消息
1.3.3 混合密码系统
- 对称密码的缺点: 不能很好的解决密钥配送问题
- 公钥密码的缺点: 加密解密速度比较慢
- 混合密码系统,是将对称密码和公钥密码的优势结合的方法
- 解决了公钥密码速度慢的问题
- 并通过公钥密码解决了对称密码的密钥配送问题
- 网络上的密码通信所用的SSL/TLS都运用了混合密码系统
1.3.3.1 混合密码-加密
- 会话密钥(session key)
- 为本次通信随机生成的临时密钥
- 作为对称密码的密钥,用于加密消息,提高速度
- 加密步骤(发送消息)
- 首先,消息发送者要拥有消息接受者的公钥
- 生成会话密钥,作为对称密码的密钥,加密消息
- 用消息接受者的公钥,加密会话密钥
- 将前2步生成的加密结果,一并发给消息接受者
- 发送出去的内容包括
- 用会话密钥加密的消息(加密方法:对称密码)
- 用公钥加密的会话密钥(加密方法:公钥密钥)
1.3.3.2 混合密码-解密
1.4 单向散列函数
1.4.1 单向散列函数简介
-
单向散列函数,可以根据消息内容计算出散列值
-
散列值的长度和消息的长度无关,无论消息是bit、10M、100G,单向散列函数都会计算出固定长度的散列值
-
单向散列函数的特点
- 根据任意长度的消息,计算出固定长度的散列值
- 计算速度快,能快速计算出散列值
- 消息不同,散列值也不同
- 具备单向性
-
单向散列函数,又被称为消息摘要函数(message digest function),哈希函数
-
输出的散列值,也被称为消息摘要(message digest)、指纹(fingerprint)
-
常见的几种单向散列函数
- MD4、MD5:产生128bit的散列值,MD就是 Message Digest的缩写,目前已经不安全,Mac终端默认可以使用MD5命令
- SHA-1: 产生160bit的散列值,目前已经不安全
- SHA-2: SHA-256、SHA-384、SHA-512,散列值长度分别为256bit、384bit、512bit
- SHA-3: 全新标准
1.4.2 如何防止数据被篡改
1.4.3 单项散列函数的应用-口令加密
2. 数字签名
- 想象一下场景
- Alice发的内容有可能是被篡改的,或者有人伪装成Alice发消息,或者就是Alice发的,但她可以否认
- 问题来了: Bod如何确定这段消息的真实性?如何识别篡改、伪装、否认?
- 解决方案: 数字签名
2.1 数字签名
-
在数字签名中,有一下两种行为:
- 生成签名: 由消息的发送者完成,通过
签名密钥
生成 - 验证签名: 由消息的接受者完成,通过
验证密钥
验证
- 生成签名: 由消息的发送者完成,通过
-
思考: 如何保证这个签名是消息发送者自己签的?
- 答案:用消息发送者的私钥进行签名
- 答案:用消息发送者的私钥进行签名
2.2 数字签名的过程
上述签名过程有一个不好的地方就是 ,既需要把明文发送过去,还要把加密之后的密文发送过去,这样可能造成传输的数据有点大
- 签名过程改造:
- 数字签名其实就是将公钥密码反过来使用
2.3数字签名的疑惑和无法解决的问题
-
思考一下:
- 如果有人篡改了文件的内容或则签名内容,会是什么结果?
- 结果是:签名验证失败。证明内容被篡改
-
数字签名不能保证机密性: 数字签名的作用不是为了保证机密性,仅仅是为了能够识别内容有没有被篡改
-
数字签名的作用:确认消息的完整性、识别消息是否被篡改、防止消息发送人否认
-
数字签名无法解决的问题:
-
要正确使用签名,前提是
用于验证签名的公钥必须属于真正的发送者
-
如果遭遇了中间人攻击,那么
公钥将是伪造的、数字签名将失败
-
所以在验证签名之前,首先得验证公钥的合法性
-
那么如何验证公钥的合法性?
证书
3. 证书
3.1 证书的简介
- 证书,联想的是驾驶证、毕业证、英语四六级证等等,都是由权威机构认证的
- 密码学中的证书,全称叫
公钥证书(Public-key Certificae, PKC)
,跟驾驶证类似- 里面有姓名、邮箱等个人信息,以及此人的公钥
- 并由机构认证(Certificate Authority, CA)施加数字签名
- CA就是能够认定公钥确实属于此人并能够生成数组签名的个人或者组织
- 有国际性组织、政府设立的组织
- 有通过提供认证服务来盈利的企业
- 个人也可以成立认证机构
3.2 证书的利用
- 证书的下载和注册
4. ios签名机制
4.1 签名简介
- IOS签名机制的作用: 保证安装到手机用户上的app都是经过Apple官方允许的
- 不管是真机调试,还是发布APP,开发者都需要进过一系列复杂的步骤
- 生成
CertificteSingingRequest.certSingingRequest
文件 - 获取
ios_development.cer\\ios_distribution.cer
证书文件 - 注册device、添加App ID
- 获取
*.moblieprovision
文件
- 生成
- 对于真机调试,现在的Xcode已经自动帮助开发者做了以上操作
我们在真机编译一个app,可以看到编译操作中一个操作是签名:
4.2 IOS签名流程
-
使用apple的私钥,便于Apple的对app的控制
-
生成Mac设备的公私钥:
CertificteSingingRequest.certSingingRequest
文件就是Mac设备的公钥
-
获取证书:把Mac的公钥上传到Apple的服务器,然后Apple使用自己
私钥签名
生成一个证书给我们该步骤对应着流程图的②步骤
-
获取证书:
ios_development.cer\\ios_distribution.cer
利用Apple后台私钥,对Mac设备的公钥进行签名后的证书文件
-
生成
moblieprovision
文件
4.3 IOS签名机制-AppStore
- 如果APP是从AppStore下载安装的,你会发现里面是没有
moblieprovision
文件的 - 它的验证流程会简单很多,大概如下所示
4.4 重签名步骤
4.4.1 常用指令介绍
- 签名被破坏的app是不能安装到用户的手机上
- 准备一个
embedded.mobileprovision
文件(必须是付费证书产生的,appid、device定需要匹配),并放入.app
包中- 可以通过Xcode自动生成,然后再编译后的APP包中找到
- 可以去开发者证书网站生成下载
- 从
embedded.mobileprovision
文件中提取出的entitlements.plist
权限文件security cms -D -i embedded.mobileprovision > temp.plist
/usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist
- 查看可用的证书
security find-identity -v -p codesigning
- 对
.app
内部的动态库、AppExtension等进行签名codesign -fs 证书ID xxx.dylib
- 对
.app
包进行签名codesign -fs 证书ID --entitlements entitlements.plist xxx.app
codesign -f -s 证书ID --entitlements entitlements.plist xxx.app
4.4.2 指令示例
- 我们可以在终端上直接输入
codesign
查看该指令的一些用法,如果codesign或则codesign --help
无法看到详细的介绍, 那么可以使用man codesign
来查看详细的用法
-
查看可用证书
-
获取
entitlements.plist
文件,然后替换.app
包内的这个文件- 该文件内包含与app匹配的
Bundle identifier
信息 - 该文件必须有你需要安装该app的
device
的信息
- 该文件内包含与app匹配的
-
抽取
entitlements.plist
文件
4.4.3 重新签名的GUI工具
-
IOS App Signer
- https://github.com/DanTheMan827/ios-app-signer
- 可以对
.app
重新签名打包成ipa - 需要再
.app
包中提供对应的embedded.mobileprovision
文件
-
iReSign
-
可以对
ipa
进行重签名 -
需要提供
entitlements.plist、embedded.mobileprovision
文件的路劲
4.4.4 tweak原理分析
-
我们编译好的
tweak
代码编写好,是动态库的形式安装到手机上, 当我们手机app启动时,会去Devcie/Library/MobileSubstrate/DynamicLibraries
路径下去加载对应的tweak动态库
, 如果我想把我们编辑好的插件工程安装到别的手机上, 那么我们应该讲这个tweak动态库
-
接下来将我们的
.app
包拷贝出来,然后将我们的编写的tweak
动态库也放到.app
的包中
也可以通过MachOview来查看可执行文件会加载的动态库
- 然后再对我们的app包进行重签名,但是启动app的时候会加载我们的动态库吗?,我们可以通过指令去查看
可执行文件
依赖的动态库 - 是不会加载的, 我们需要自己更改动态库的加载地址,让可执行文件加载的时候会加载这个动态库,这个时候我们需要在Mach-O文件插入我们自己的动态库(动态库是插入到LoadCommands 最后一条信息后面,不然会改变其它数据的位置)
4.4.5 动态库的注入
- 可以使用
insert_dylib
库将动态库注入到Mach-O文件中 - 用法
insert_dylib 动态库加载路劲 Mach-O文件
- 有两个常用参数选项:
--weak
:即使动态库找不到也不会报错,如果不使用这个参数,把动态库注入到Mach-O文件中,app启动的时候,如果找不到动态库的路径,那么app就回崩溃--all-yes
:后面所有的选择都没yes
-
可以通过otool查看Mach-O的动态库依赖信息
- otool -L Mach-O文件
- otool -L Mach-O文件
-
如果不希望生成新的文件
4.4.6 更改动态库的加载地址
-
可以使用
install_name_tool修改Mach-O文件动态库中的加载地址
install_name_tool -change 旧地址 新地址 Mach-O文件
-
通过Theos开发的动态库插件(dylib)
- 默认都依赖于
/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate
- 如果将要动态库插件打包到
ipa
中,也需要将CydiaSubstrate
打包到ipa
中,并且修改下CydiaSubstrate
的加载地址
- 默认都依赖于
-
两个常用的环境变量
@executable_path
:代表可执行文件所在的目录@loader_path
:代表动态库所在的目录
-
利用插件来修改ipa包,然后重签名步骤
- 往Mach-O文件内注入动态加载
- 把动态库依赖的动态库路径的修改
- 重新签名 (给动态库进行签名)
- 然后再对
.app
包进行签名
-
动态库中也会依赖其它动态库
-
使用指令更换动画库的路径
-
对动态库进行重签名
4.4.7重签名的注意点
-
如果希望将破坏了签名的安装包,安装到非越狱的手机上,需要对安装包进行重签名的操作
-
注意
- 安装包中的可执行文件必须是脱壳的,重签名才会有效
.app
包内部的所有动态库(.framework、.dylib)、AppExtension(PlugIns文件夹,拓展名appex)、WatchApp(Watch文件夹)都需要重新签名
-
重新签名打包后,安装到设备的过程中,可能需要经常查看设备的日志信息
- 程序运行过程中:
Window -> Devices and Simulators -> View Device Logs
- 程序安装过程中:
Window -> Devices and Simulators -> Open Console
- 程序运行过程中:
以上是关于IOS逆向学习-签名机制的主要内容,如果未能解决你的问题,请参考以下文章