Chapters

Hide chapters

Advanced Apple Debugging & Reverse Engineering

Fourth Edition · iOS 16, macOS 13.3 · Swift 5.8, Python 3 · Xcode 14

Section I: Beginning LLDB Commands

Section 1: 10 chapters
Show chapters Hide chapters

Section IV: Custom LLDB Commands

Section 4: 8 chapters
Show chapters Hide chapters

19. Code Signing
Written by Walter Tyree

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Ah, code signing: an iOS developer’s nemesis. Code signing is hardly at the top of every iOS developer’s agenda, but a strong knowledge of how code signing works can be extremely useful for solving problems, as well as establishing yourself as a linchpin in your development team. There’s nothing more “ask-for-a-raise-worthy” than a developer who can re-sign an outdated Swift 2.2 iOS app, instead of having to fix the potentially thousands of Swift compiler errors when time is against you.

This chapter will give you a basic overview of how code signing works by having you pick apart the open-source iOS Wordpress v10.9 application.

You’ll explore the stages of the app’s code signature before being sent to App Store Connect. In addition, you’ll re-sign the Wordpress app so it can run on your very own iOS device!

Setting Up

In order to complete everything in this chapter, you’ll need a number of items. First, you’ll need a proper iOS Apple Developer account to generate Provisioning Profiles. You’ll also need a physical iOS device to install the Wordpress iOS application.

Terminology

To really appreciate how code signing works, you need to understand three key components: public/private keys, entitlements, and provisioning profiles. You’ll start with a breadth-first look, then dive into a depth-first look at each.

Public/Private Keys

This is probably the hardest thing to understand when learning about the code signing process, since public/private keys introduce cryptography, which quickly becomes a rabbit hole of knowledge, formats, formatting, and gotchas.

security find-identity -p codesigning -v
4) 61940D752C3E5CDD3C20FFE498B86E5B78D0078F "Apple Development: walter@tyreeapps.com (78L6PC9H2P)"

security find-certificate -c "Apple Development: walter@tyreeapps.com (78L6PC9H2P)" -p
security find-certificate  -c "Apple Development: walter@tyreeapps.com (78L6PC9H2P)"  -p > /tmp/public_cert.cer
cat /tmp/public_cert.cer
-----BEGIN CERTIFICATE-----
MIIFnDCCBISgAwIBAgIIFMKm2AG4HekwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
...
openssl x509 -in /tmp/public_cert.cer -inform PEM -text -noout

Entitlements

Embedded in (almost) every compiled application is a set of entitlements: again, this is an XML string embedded in the application saying what an app can and can’t do. Other programs will check for permissions (or lack thereof) in the entitlements and grant or deny a request accordingly. Think of the capabilities section found in Xcode.

codesign -d --entitlements :- /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder

Provisioning Profiles

Finally, the provisioning profiles are up for discussion. A provisioning profile includes the public x509 certificate, the list of approved devices, as well as the entitlements all embedded into one file.

~/Library/MobileDevice/Provisioning Profiles/
ls ~/Library/MobileDevice/Provisioning\ Profiles/
PP_FILE=$(ls ~/Library/MobileDevice/Provisioning\ Profiles/*mobileprovision | head -1)
security cms -D -i "$PP_FILE"

Exploring the WordPress App

Just like your typical debugging workflow on your iOS device, before an app is sent up to the Apple AppStore Connect mothership, you must compile an app with a provisioning profile. This provisioning profile is included in every pre-App Store .app under the name embedded.mobileprovision. It’s this provisioning profile that tells iOS the application is valid and came from you.

WORDPRESS="/full/path/to/WordPress.app/"

The Provisioning Profile

Find the embedded.mobileprovision provisioning profile inside of the WordPress application and use the security command on it.

security cms -D -i "$WORDPRESS/embedded.mobileprovision"
CERT_DATA=MIIFozCCBIu...
echo "$CERT_DATA" | base64 -D > /tmp/wordpress_cert.cer
openssl x509 -in /tmp/wordpress_cert.cer -inform DER -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 786948871528664923 (0xaebcdd447dc4f5b)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority
        Validity
            Not Before: Jan 17 13:26:41 2018 GMT
            Not After : Jan 17 13:26:41 2019 GMT
        Subject: UID=PZYM8XX95Q, CN=iPhone Distribution: Automattic, Inc. (PZYM8XX95Q), OU=PZYM8XX95Q, O=Automattic, Inc., C=US
... truncated ...

Embedded Executables

Provided an application contains extensions (i.e. share extension, today widgets, or others), there will be even more signed packaged bundles found in the ./Plugins directory that contain their own application identifier and embedded.mobileprovision provisioning profile.

The _CodeSignature Directory

Included in a real iOS application bundle (but not in the Simulator) is a folder named _CodeSignature that includes a single file named CodeResources. This is an XML plist file which is a checksum of every non-executable file found in this directory.

cat "$WORDPRESS/_CodeSignature/CodeResources"  | head -10
openssl sha1 -binary "$WORDPRESS/AboutViewController.nib"  | base64

Resigning the WordPress App

Time for some codesigning fun!

(Optional) Generate a Valid Provisioning Profile

If you don’t have a provisioning profile that met the above requirements (UDID, not expired), you’ll need to head on over to the Developer Portal and create a new one.

security find-certificate -c "Apple Development: walter@tyreeapps.com (78L6PC9H2P)" -p > /tmp/public_cert.PEM
openssl x509 -in /tmp/public_cert.PEM -inform pem -noout -text | grep OU=
Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority

Subject: UID=V969KV7V2B, CN=Apple Development: walter@tyreeapps.com (78L6PC9H2P), OU=K75NL9T9H7, O=Derek Selander, C=US

Copying the Provisioning Profile

At this point, you should have a valid provisioning profile, which you’ll use to resign the WordPress application either by creating a new provisioning profile or by using an existing provisioning profile. Assign the PP_PATH Terminal variable to the fullpath of the provisioning profile you expect to use for this experiment.

PP_PATH=~/Downloads/Code_Signing_Example_ProvisProfile_92618.mobileprovision
cp "$PP_PATH" "$WORDPRESS/embedded.mobileprovision"

Deleting the Plugins

The WordPress application has several extension applications embedded into the main app found in the ./Plugins directory. Each of these contains a unique provisioning profile with a unique application identifier. You could sign each of these extensions itself with a unique provisioning profile, but that will get way too complicated for this demo.

Modifying the Info.plist

I hope you’ve remembered the name of the App ID of the provisioning profile! You’ll need to plug that into the Info.plist’s key CFBundleIdentifier If you don’t remember it, you can query it from the provisioning profile.

security cms -D -i "$PP_PATH" | grep application-identifier -A1
<key>application-identifier</key>
<string>H4U46V6494.com.selander.code-signing</string>
plutil -replace CFBundleIdentifier -string H4U46V6494.com.selander.code-signing "$WORDPRESS/Info.plist"
plutil -replace CFBundleDisplayName -string "Woot" "$WORDPRESS/Info.plist"

Extracting the Entitlements

You’re almost there!

codesign -d --entitlements :/tmp/ent.xml "$WORDPRESS/WordPress"
cat /tmp/ent.xml
security cms -D -i "$PP_PATH" > /tmp/scratch
xpath -e '//*[text() = "Entitlements"]/following-sibling::dict' /tmp/scratch | pbcopy
<?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>keychain-access-groups</key>
    <array>
        <string>H4U46V6494.*</string>       
    </array>
    <key>get-task-allow</key>
    <true />
    <key>application-identifier</key>
    <string>H4U46V6494.com.selander.code-signing</string>
    <key>com.apple.developer.team-identifier</key>
    <string>H4U46V6494</string>
</dict>
</plist>

Finally, Signing the WordPress App

You now have performed all the setup. You have a valid signing identity; you have a valid provisioning profile embedded in the WordPress application at embedded.mobileprovision; you have removed the Plugins directory; and you have the entitlements of the new provisioning profile found at /tmp/ent.xml.

codesign -f -s "Apple Development: walter@tyreeapps.com (78L6PC9H2P)" "$WORDPRESS"/Frameworks/*
codesign --entitlements /tmp/ent.xml -f -s "Apple Development: walter@tyreeapps.com (78L6PC9H2P)" "$WORDPRESS"

Did It Succeed?

Provided you have followed the steps exactly, you’ll see a new app with the WordPress logo with the name “Woot” underneath it!

Key Points

  • Use the PEM format for displaying certificate information in a human-readable way.
  • Query a certificate using the openssl command line tool or using the GUI Keychain Utility on your Mac.
  • Entitlements specify what permissions your app has. The get-task-allow entitlement is required if you want to attach with LLDB.
  • Normally, Xcode handles the codesigning and provisioning profiles for you automatically, but you can go to the Developer portal to make your own.
  • When working with .xml files the xpath utility queries for data while maintaining the structure.

Where to Go From Here?

This chapter has only scratched the surface of code signing. There is a lot more great content out there that focuses on other components to code signing.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now