iOS-应用安全03应用签名原理和重签名

679 阅读8分钟

iOS双层签名

在上一章我们知道:对文件的二进制数据进行hash处理,然后又进行一次非对称加密RSA,这个过程称为签名。为什么iOSapp不能向安卓那样任意的安装到任何安卓设备?我们先来分析苹果为了维护自己的生态圈有哪些需求:

1、安装包不需要上传到APP Store,可以直接安装到手机上。(eg:1.开发的日常调试 2.企业证书app的安装)

2、苹果为了保证系统的安全性,又必须对安装的APP有绝对的控制权

  • 2.1、经过苹果允许才可以安装
  • 2.2、不能被滥用导致非开发APP也能被安装

苹果为了实现上述需求,苹果给出了双层签名的方案。为了理解双层签名,先了解下面几个术语的含义:

  • 代码签名:代码签名是对可执行文件或者脚本进行数据签名。用来确认软件在签名后未被修改或者损坏过,和数字签名原理一样们只不过签名的数据是代码而已
  • 授权文件(Entitlements):app里面的iCloud/PUSH/后台运行等一系列的权限开关文件
  • 描述文件(Provisiong profile):其是对 证书、app ID、授权文件(Entitlements)、设备一个打包。为了详细说明:我这里新建了一个KTest工程,可以看到描述文件里的许多内容,
    Command + B后,如果是第一次,你应该会看到要求访问KeyChain的对话框,这其实是一次签名的过程;之后我们可以看到具体的app执行文件:
    打开包后,应该可以看到以下数据
    上图中 embedded.mobileprovision就是描述文件,_CodeSignature是资源文件(图片...)签名,而应用签名在KTest可执行文件中(相当于window系统中的.exe文件),你可以用MachO应用程序打开这里不赘述了。使用终端看描述文件内部:
XXXXX@MacBook-Pro ~ % cd /Users/XXXX/Library/Developer/Xcode/DerivedData/KTest-aljwhltjgylwbnayiwdyysnxrrny/Build/Products/Debug-iphoneos/KTest.app
XXXXX@MacBook-Pro KTest.app % ls -a
.				KTest
..				PkgInfo
Base.lproj			_CodeSignature
Info.plist			embedded.mobileprovision
XXXXX@MacBook-Pro KTest.app % security cms -Di embedded.mobileprovision 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>AppIDName</key>
	<string>XC riceFun KTest</string>
	<key>ApplicationIdentifierPrefix</key>
	<array>
	<string>TM6D7482ZM</string>
	</array>
	<key>CreationDate</key>
	<date>2020-02-27T09:11:45Z</date>
	<key>Platform</key>
	<array>
		<string>iOS</string>
	</array>
	<key>IsXcodeManaged</key>
	<true/>
	<key>DeveloperCertificates</key>
	<array>
		<data>MIIFlzCCBH+gAwIBAgIIJJmsMK8vs2kwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTkwOTI1MDEyMDU0WhcNMjAwOTI0MDEyMDU0WjCBijEaMBgGCgmSJomT8ixkAQEMCk00U0c5NThaMkUxODA2BgNVBAMML2lQaG9uZSBEZXZlbG9wZXI6IDk5NTA2NTIyNUBxcS5jb20gKDhGNDgzNks4NzQpMRMwEQYDVQQLDApUTTZENzQ4MlpNMRAwDgYDVQQKDAfluIYg6bKNMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ4n37M35IxjSN3IjDYdi65PANwoQJhTZVsP2H8q43pg5Dt3uEa0qLG1zy0u6HdyYabzufggUIbRX+kDOBY55vByPJrqg+lvWepMCTDPRdmwXsMqajkj+dicdT0Q1gZtqAKe7Ozx0yqyMSuMQ9l+TrDPcXhvzLPuPjDswhf5I4KdmHuTgGQu0jcb8Sbma9tpEsQs9MXrqLY54W9uITCdCySeLPQs2wE1FYeh2dFQXbxBt/8NE2mfAVQ1fhlKkdM66UZKGphP9QwnE08Brsm+AWRp6a7HRNPiueBCCQaFgHXsxKYzXSdQE5qjGVETBOn2BrSQ18tXQ/jAcyj7oEDZt18CAwEAAaOCAfEwggHtMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUiCcXCam2GGCL7Ou69kdZxVJUo7cwPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLXd3ZHIwMTCCAR0GA1UdIASCARQwggEQMIIBDAYJKoZIhvdjZAUBMIH+MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS8wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFLwz0fDMcctZMtx8I6cfKDHBxa2WMA4GA1UdDwEB/wQEAwIHgDATBgoqhkiG92NkBgECAQH/BAIFADANBgkqhkiG9w0BAQsFAAOCAQEAD9L5F2jYtIDQvXZVgeJL6O7MDK4j3lUzkga+Erss4ZVlGjByInDLEE2EAPIiubtmXCUjggg4YMHfVc/QRDilyu8UM9sp6+60aI4+zHseO65TYiyNuvkjN/kGxd9LXEfwlVAHZA7DX8lJY4xFQTUt16TXZfYRob/aC120Nz5SjNHySaiJVAmTy+Wka2rMpNYzxTDmgODyfCATzoblLcWkHw3PhdUsl/30IAupWPa7qZDUto1aQhLNuLuBT/DmQmzRUO22F8KgQt4jBuI/8RBcQ46OxKHhtSnrKDQzCuyg1Becyxb+UKck+w0ib4xvmX6sg9VqWdWvKxPZERHgNP+f4A==</data>
		<data>MIIFrTCCBJWgAwIBAgIIJZxJAUUW2HcwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMjAwMjI3MDkwMTQzWhcNMjEwMjI2MDkwMTQzWjCBizEaMBgGCgmSJomT8ixkAQEMCk00U0c5NThaMkUxOTA3BgNVBAMMMEFwcGxlIERldmVsb3BtZW50OiA5OTUwNjUyMjVAcXEuY29tICg4RjQ4MzZLODc0KTETMBEGA1UECwwKVE02RDc0ODJaTTEQMA4GA1UECgwH5biGIOmyjTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDr1tktqaSMj0kZdluli1/RvR04nJJuDLvAMqAM/aN5d66UZBy58mX27sgNs5GyqJ0SGSknw4ECuc9/CONY0cfjj1KR/5b4DArn1BKMRDgv5lpnWLqer/SxUvPEaXS7KWSDMfbdT+Xo6IUMjhS6my1A2foVP6Kg4f6lG1xgP7A7tdQ35/XGYKe/JaDli/QABVTV8gqMx3YZe+10PjheuLjpbaTwqixP9/gjfXv1Mj2yBlsJuDoODjy6EZBtzGAy2o2ehshk3ItZOQZ0cs/FdMKeb+EQEnTj08g4dGPsklDtUVmoSbJZjtzdbTvVPxUwBDJjJC/UNsgAFJneXpkwBNHNAgMBAAGjggIGMIICAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy13d2RyMTkwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBS9kxkEzB9qDZzmlH1eyCcGnfID2DAOBgNVHQ8BAf8EBAMCB4AwEwYKKoZIhvdjZAYBAgEB/wQCBQAwEwYKKoZIhvdjZAYBDAEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAB1AFRan1RVQrtHsmmLFBDmbupfdf0zhELtUPR6NMeMQSRZt0NaPl26wwsp+NpiAIo+I6xMlgTPrdTab2tnYu5L2/Hz7lNy8ZvodPmYP4vA31pq183fzWlt0rVzFFkckB7lqtSMSZiPXrF0x9t929wZKhEV5KYeN8hBi6/Ow3lVqDUzouGcxxqzdvY/arCZFj0E/44pCrvH9CL/IojtfogN/2Olm8h4qXVue5qMdINo3LTcNLuloGx0YCozP4eGHhbiCCw0zo+DIn7/kbQ0wevEywxCuxal/XKuoIOD9RS4syLZAs96UcbX49RkPNUIDxkAyPbAhJLk6AJJUCiGyg48=</data>
	</array>

								
	<key>Entitlements</key>
	<dict>
				
				<key>application-identifier</key>
		<string>TM6D7482ZM.riceFun.KTest</string>
				
				<key>keychain-access-groups</key>
		<array>
				<string>TM6D7482ZM.*</string>
		</array>
				
				<key>get-task-allow</key>
		<true/>
				
				<key>com.apple.developer.team-identifier</key>
		<string>TM6D7482ZM</string>

	</dict>
	<key>ExpirationDate</key>
	<date>2020-03-05T09:11:45Z</date>
	<key>Name</key>
	<string>iOS Team Provisioning Profile: riceFun.KTest</string>
	<key>ProvisionedDevices</key>
	<array>
		<string>8d8f30d089c0920d4ab49c473da130ad4bb36b72</string>
	</array>
	<key>LocalProvision</key>
	<true/>
	<key>TeamIdentifier</key>
	<array>
		<string>TM6D7482ZM</string>
	</array>
	<key>TeamName</key>
	<string>三 张</string>
	<key>TimeToLive</key>
	<integer>7</integer>
	<key>UUID</key>
	<string>92d1831f-ac22-4300-b1ee-07c3c025b631</string>
	<key>Version</key>
	<integer>1</integer>
</dict>
</plist>%                                                                       baofan@MacBook-Pro KTest.app % 

重点关注Entitlements内部的东西,在下面的内容中会用到。

了解上面几个术语之后,再看流程图:

双向签名

1.在iphone和苹果appstore上面分别有一个钥公A和私钥A(天生就有)

2.app在申请证书的时候,本地电脑会先生成一对非对称加密的公钥M私钥M

3.公钥M会被电脑包装成CSR文件向苹果服务器

4.苹果收到CSR文件后会用私钥ACSR文件又进行一次签名,签名后得到就是描述文件描述文件Provisiong profile,这个描述文件内部包含了设备ids,appid,权限文件...还有一个证书,而这个证书包含了用私钥A加密后的公钥M和公钥M的hash值

5.当本地电脑拿到这个描述文件Provisiong profile后会取出里面的证书进行钥匙串访问,将证书和私钥M进行关联;

6.当app在安装的时候(或者Command + B),本地的私钥M会对app进行签名,签名的内容包括MachO文件还有刚才的从苹果服务器上申请描述文件Provisiong profile。然后将这些东西打包成一个app包,安装到iPhone手机上

7.iPhone手机拿到app包开始安装的时候,会进行验证,如果验证成功就能安装成功

  • 7.1用公钥A验证描述文件Provisiong中的证书,如果验证成功就证明这个行为是苹果服务器允许的,即验证证书签名
  • 7.2用公钥A解密证书拿到公钥M,然后公钥M又去解密私钥M,。一步就是验证app签名
  • 7.3通过上述两步验证,到达双层签名的目的,app也就能安装了。

以上就是app双层签名的全过程。我们去看看钥匙串

第一个就是我们重苹果服务器上请求的证书,而下面的.p12就是流程图中的和证书进行绑定的私钥M,所以当把.p12文件给别人时,别人也可以进行签名调试;

注意:上述的双层签名是为了满足日常的调试和企业级的分发;如果是app store上下载,其实只需要用到私钥A和公钥A一层签名就可以了;

iOS 应用重签名

应用重签名,首先你得有一个砸过壳的app,你可以下载pp助手,在pp助手中下载你需要重签名的app;下面我将以微信.ipa为例子

Xcode应用重签名

1.新建一个你要重签名的app同名的app,如何知道app的名字?

1.1 使用The Unarchiver 这个解压缩软件解压微信.ipa,找到app包

1.2找到app包,右键显示包内容
1.3包内容下目录里找到info.plist文件,双击打开
1.4找到info.plist中的Bundle name 对应的名字就是你需要新建工程的名字
1.5新建同名工程
1.5 run一次同名工程,使之安装到手机上

2.获取同名工程app证书名字

2.1查看证书名字

2.2从keyChain(钥匙串)中找到同名的证书,并复制证书名字我这里是Apple Development: xxxxxxx@qq.com (8F4836K874)后面会用到

3.删除app包中的不可签名的插件(Plugins)及应用(Watch),因为这些插件和内部的小应用无法重签名;重签名内部的库 3.1删除

3.2重签名Frameworks文件夹下面的库
用终端重签名,需要用到2.2复制的证书名字,终端命令codesign -fs

  XXX $: cd /Users/xxxxx/Library/Developer/Xcode/DerivedData/WeChat-hihupndjuikezabwgfipnoypmvtp/Build/Products/Debug-iphoneos/WeChat.app/Frameworks
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXXXXX@qq.com (8F4836K874)" andromeda.framework
  andromeda.framework: replacing existing signature
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" mars.framework
  mars.framework: replacing existing signature
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" marsbridgenetwork.framework
  marsbridgenetwork.framework: replacing existing signature
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" matrixreport.framework
  matrixreport.framework: replacing existing signature
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" OpenSSL.framework
  OpenSSL.framework: replacing existing signature
  XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" ProtobufLite.framework
  ProtobufLite.framework: replacing existing signature

4.替换工程包

4.1复制上面1.2的app包

4.2在同名工程中找到app包的位置

4.3将上面4.1复制的包替换该包
4.重新run同名工程;你将会看到微信已经安装成功,并且能看到视图层级。到这里app重签名就完成了

脚本重签名

脚本重签需要用到shell脚本,将在下一章继续说明