👨🏻‍💻's 博客

慢品人间烟火色,闲观万事岁月长

0%

实践篇:iOS 应用重签名(上)

环境 & 工具

 

macOS Sierra 10.12.4
Xcode 8.3.1
Jailbreak iPad 8.4
No Jailbreak iPhone 10.1.1

影响因素

 

  • _CodeSignature
  • 二进制文件
  • embedded.mobileprovision
  • entitlements

手动

Developer 环境

 

  AppStore 上下载的应用是加壳的,是不能直接用于重签名的。为什么呢? 现在的我不清楚,如果我去实现的话,可以在 codesign 在签名时可以判断代码段是否已经加密了,如果加密过证明已经处理了,就不去签名。二进制的签名依然是苹果服务器上的私钥的签名,在安装过程中,去验证二进制的签名时,无法匹配,因此安装失败。
 
  重签名需要已经脱壳的应用,可以手动/商店下载一个已经脱壳的应用。

以酷狗音乐为例

  1. 解压 .iPa
  2. cd 到 kugou.app 中
  3. 删除应用中的 _CodeSignature 目录
  4. 从自己的其他应用的 .app 文件中,拷贝一份 embedded.mobileprovision 到 kugou.app 目录下
  5. 用脱壳后的二进制文件替换掉原来的。
  6. 找到重签名的 sign 值(钥匙串)与 entitlement 文件
  7. 用 codesign 完成签名操作

entitlement 文件的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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>application-identifier</key>
<string>XXXX.包名</string>
<key>com.apple.developer.team-identifier</key>
<string>XXXX</string>
<key>get-task-allow</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>XXXX.包名</string>
</array>
</dict>
</plist>
1
2
3
➜  blog-52 /usr/bin/codesign --force --sign 签名值 --entitlements Runtrace.app.xcent --timestamp=none kugou.app
kugou.app: replacing existing signature
➜ blog-52

 
  签名完 .app 需要打包成 .ipa 文件,可以将 .app 拖入到 .iTunes 来生成 .ipa 。
  
  

 

在越狱设备上报

 

在非越狱设备上报

  
  修改 info.plist 的包名,重新制作 .ipa ,再次尝试
  
  在越狱与非越狱设备上都能正常安装,打开不闪退,表明已经过了 Apple 的签名检查了。

AdHoc 环境

 
 
  操作与 Developer 环境类似,但 embedded.mobileprovision 需要换成 AdHoc 的描述文件,同时 entitlement 文件需要处理,再 Xcode 直接 Archive 工程,照着日志中的路径查找,得到的 entitlement 还是开发环境的,在当前环境下是无效的。

下面是一个 entitlement 的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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>application-identifier</key>
<string>XXXX.包名</string>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.team-identifier</key>
<string>XXXX</string>
<key>get-task-allow</key>
<false/>
<key>keychain-access-groups</key>
<array>
<string>XXXX.包名</string>
</array>
</dict>
</plist>

 

  与上面不同之处在于 get-task-allow 为 false ,同时增加了 aps-environment 这个节点。如何找到的?主要还是通过对比工具比较出用 ios-app-signer 工具签名与 codesign 签名后,两个 .app 包的 4 个影响因素的差异,最后发现两者的决定性差异在二进制文件中。

 

小插曲

 
  在越狱设备上,用开发的 sign 签名也能成功安装,但在非越狱上无法安装,目标主要还是在非越狱设备上,越狱应该是会影响应用签名认证的这个过程。

工具

 
  关于重签名的工具还是挺多的,就说我使用过的。在非越狱设备上要过签名的认证,本质上来说应该都是依赖于 codesign 这个原生的工具的。   

ios-app-signer

Swift 开发,主界面如下

 

选签名证书 + 描述文件就可以了,操作也非常简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//MARK: Codesigning 
func codeSign(file: String, certificate: String, entitlements: String?,before:((file: String, certificate: String, entitlements: String?)->Void)?, after: ((file: String, certificate: String, entitlements: String?, codesignTask: AppSignerTaskOutput)->Void)?)->AppSignerTaskOutput{

let useEntitlements: Bool = ({
if entitlements == nil {
return false
} else {
if fileManager.fileExistsAtPath(entitlements!) {
return true
} else {
return false
}
}
})()

if let beforeFunc = before {
beforeFunc(file: file, certificate: certificate, entitlements: entitlements)
}
var arguments = ["-vvv","-fs",certificate,"--no-strict"]
if useEntitlements {
arguments.append("--entitlements=\(entitlements!)")
}
arguments.append(file)
let codesignTask = NSTask().execute(codesignPath, workingDirectory: nil, arguments: arguments)
if let afterFunc = after {
afterFunc(file: file, certificate: certificate, entitlements: entitlements, codesignTask: codesignTask)
}
return codesignTask
}

  其中 codesignPath 就是 let codesignPath = “/usr/bin/codesign” 。大致也是利用 codesign 进行签名。

fastlane sigh resign

  来自 帖子

  fastlane 是一个很棒的工具集,能辅助去解决 iOS,Mac 和 Android 一些繁琐的任务,比如生成截图处理配置文件以及发布应用程序等。

  命令行的操作也非常简单,只是一般在重签名时要传一个 .ipa 地址,这需要处理一下,不像直接用 codesign 或者 ios-app-signer 可以传 .app 文件,中间可能需要用 iTunes 处理下。

操作流程是:

  1. .ipa 地址
  2. 选择 sign
1
2
3
4
5
6
7
8
9
10
[WARNING] You are calling sigh directly. Usage of the tool name without the `fastlane` prefix is deprecated in fastlane 2.0
Please update your scripts to use `fastlane sigh resign` instead.
Path to ipa file: /Users/Jason/Music/iTunes/iTunes\ Media/Mobile\ Applications/kugou.ipa
[00:05:56]: Available identities:
iPhone Developer: xxxx xxxxx (576J77ZA38)
DE64343206CB84E95C5CF22F1C5D346664171B5A
iPhone Developer: xxx@126.com (VRZB43ZE67)
...

Signing Identity:

里面在对动态库签名时,有如下的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
for framework in "$FRAMEWORKS_DIR"/*
do
if [[ "$framework" == *.framework || "$framework" == *.dylib ]]
then
log "Resigning '$framework'"
# Must not qote KEYCHAIN_FLAG because it needs to be unwrapped and passed to codesign with spaces
# shellcheck disable=SC2086
/usr/bin/codesign ${VERBOSE} ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" "$framework"
checkStatus
else
log "Ignoring non-framework: $framework"
fi
done

总结

 
  本文主要以 codesign 指令的方式实现了重签名中比较简单的一种情况,同时介绍了几个比较有效的重签名的工具。

参考

  1. ios打包ipa的四种实用方法(.app转.ipa)
  2. iOS证书及ipa包重签名探究
  3. 最简单的重签名应用的方法
  4. iOS: Already installed app is not launching and crashing everytime in launching