0

My goal is to perform something similar to How to get access to iOS Developer Certificate from code: verify that my library is not used in a re-packaged IPA. The answer there suggests to parse the embedded.mobileprovision file to see information about the certificates and provisioning profile.

In the embedded.mobileprovision file, I can find a long embedded plist, and the XML I see there has two relevant fields:

<?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>

(for obvious reasons I replaced the true DEVELOPMENT_TEAM ID with ABCDEFGHIJ and the UUID with zeros).

There is also a list array of long <data> entries under the key DeveloperCertificates, but I have no idea how I can use this data. For example, I don't know if I can consistently choose one of these certificates. But I don't see the signing certificate ID in this file, and also I don't have a reliable procedure to parse the embedded.mobileprovision file.

Still, this may be enough for my purposes, but I have another, more robust approach. I can parse the mach_header of my binary, following the example by Dave DeLong and based on an earlier answer by Cédric Luthi. The format of LC_CODE_SIGNATURE seems to be better documented than that of the embedded.mobileprovision file.

Specifically, the EMBEDDED_ENTITLEMENTS blob (magic 0xfade7171) contains a short plain-text 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>

So far so good, but I am not sure how the same XML will look for an app that comes from the AppStore. For example, there is the new EMBEDDED_ENTITLEMENTS_DER blob (0xfade7172) which seems to hole the same plist, but in binary format (is there an example that shows how this should be parsed?).

Also, I see the signing certificate ID Apple Development: alexcohn@mycompany.com (KLMNOPQRST) in REQUIREMENTS blob (magic 0xfade0c01), and by following the flow of a go package, I can find this ID in my executable programmatically.

Which certificate ID will be more reliable for my purposes?

The requirements are simple:

  • this ID should change when the app is resigned, even if it is not resigned for the App Store.
  • this ID should be present in both debug builds and release builds (these may be different IDs).
  • this ID should be stable, i.e. it should not change when the developer rebuilds the app, or switches the build machine, or new devices are added to the adHoc provisioning profile.
  • this ID should be easy to find (like the signing certificate is visible in the keychain app).
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307

1 Answers1

1

OK, so I found this repo on github, and now I can extract (and verify) the proper SHA256 signature of the signing certificate, which is stored in the standard PKCS7 format in the 0xfade0b01 blob of LC_CODE_SIGNATURE command.

The drawback is that I am importing the whole openssl library just for that. Isn't there a way to parse this blob with the help of the built-in SecCertificate class? Another open question, maybe embedded openssl lib is more resilient to reverse engineering and Frida-style injection attacks than the system framework?

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307