解析embedded.mobileprovision 和LC_CODE_SIGNATURE 来验证证书

问题描述

我的目标是执行类似于 How to get access to iOS Developer Certificate from code 的操作:验证我的库没有在重新打包的 IPA 中使用。那里的答案建议解析 embedded.mobileprovision 文件以查看有关证书和配置文件的信息。

embedded.mobileprovision 文件中,我可以找到一个很长的嵌入 plist,我看到的 XML 有两个相关字段:

<?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>
…
  <key>application-identifier</key>
  <string>ABCDEFGHIJ.com.example.ObjCExample</string>
…
  <key>UUID</key>
  <string>00000000-0000-0000-0000-000000000000</string>
…
  <key>Version</key>
  <integer>1</integer>
</dict>
</plist>

(出于显而易见的原因,我用 ABCDEFGHIJ 替换了真正的 DEVELOPMENT_TEAM ID,用零替换了 UUID)

在键 <data> 下还有一个 listDeveloperCertificates 条目数组,但我不知道如何使用这些数据。例如,我不知道我是否可以始终选择这些证书之一。但是我在这文件中没有看到签名证书 ID,而且我也没有一个可靠的程序来解析 embedded.mobileprovision 文件

不过,这对于我的目的来说可能已经足够了,但我还有另一种更强大的方法。我可以解析我的二进制文件mach_header,按照 exampleDave DeLong 并基于 earlier answerCédric LuthiLC_CODE_SIGNATURE 的格式似乎比 embedded.mobileprovision 文件的格式更好。

具体来说,EMbedDED_ENTITLEMENTS blob(魔术0xfade7171)包含一个简短的纯文本 plist:

<?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>ABCDEFGHIJ.com.example.ObjCExample</string>
    <key>com.apple.developer.team-identifier</key>
    <string>ABCDEFGHIJ</string>
    <key>get-task-allow</key>
    <true/>
    <key>keychain-access-groups</key>
    <array>
        <string>ABCDEFGHIJ.com.example.ObjCExample</string>
    </array>
</dict>
</plist>

到目前为止一切顺利,但我不确定相同的 XML 将如何查找来自 AppStore 的应用程序。例如,有一个新的 EMbedDED_ENTITLEMENTS_DER blob (0xfade7172) 似乎包含相同的 plist,但采用二进制格式( 是否有一个示例说明如何解析它?).

此外,我在 Apple Development: alexcohn@mycompany.com (KLMnopQRST) blob(魔术 REQUIREMENTS)中看到签名证书 ID 0xfade0c01,并且按照 go package 的流程,我可以找到此 ID以编程方式在我的可执行文件中。

哪个证书 ID 对我来说更可靠

要求很简单:

  • 当应用退出时,这个 ID 应该改变,即使它没有为 App Store 退出
  • 此 ID 应存在于调试版本和发布版本中(它们可能是不同的 ID)。
  • 此 ID 应该稳定,即当开发者重新构建应用、切换构建机器或将新设备添加到 adHoc 配置文件时,它不应更改。
  • 此 ID 应该很容易找到(就像签名证书在钥匙串应用中可见一样)。

解决方法

好的,所以我在 github 上找到了 this repo,现在我可以提取(并验证)签名证书的正确 SHA256 签名,该签名以标准 PKCS7 格式存储在 - blob 中0xfade0b01 命令。

缺点是我只是为此导入了整个 openssl library。有没有办法在内置 SecCertificate 类的帮助下解析这个 blob?另一个悬而未决的问题,也许嵌入式 openssl lib 比系统框架更能抵御逆向工程和 Frida 式注入攻击?