AIR ARMOR is a security solution of AIR; AIR is a component of the LINE GAME PLATFORM.
You can refer to Seunghoon’s posting on AIR GO and APK Signing for information on the APK signature scheme. For this posting, I’ll explain about iOS code signing, one of Apple’s security mechanism. Code signing is to verify the integrity of the software code and confirm the signer (who wrote the code). I’ll also cover checking the integrity of iOS Mach-O binaries later using the code signature struct. Let me first give you some ideas about iOS code signing.
What is iOS code signing?
iOS devices only run apps that are code signed with the certificate issued by Apple, whether it is an app downloaded from App Store or app built for the purpose of testing. This code signing must be done with a certificate issued by Apple.
Apps downloaded from App Store are code signed with Apple’s certificate as follows:
Those apps under development for distribution or testing by developers are signed with the development certificate issued by Apple.
The following is a sample of development certificate for ad hoc distribution.
To install an app signed with an Apple’s Development Certificate, you must have a provisioning profile on your device. You need to have a provisioning profile installed on the device specified in the provisioning profile. Only then can you install and run an iOS app signed with the developer certificate.
What is provisioning profile?
Apple defines a provisioning profile as “a type of system profile used to launch one or more apps on devices and use certain services”. You can create a provisioning profile in Xcode by enabling automatic signing (personally recommended) or go for manual signing at Apple Developer Program.
The following window appears for ad hoc distribution of a sample app.
When you select the Automatically manage signing option in the window above, Xcode will automatically generate a provisioning profile during the build. You can check automatically generated profiles in the following path:
$ ls ~/Library/MobileDevice/Provisioning\ Profiles 1axxxx49-xxxx-xxxx-xxxx-c2xxxxxxxxff.mobileprovision a8xxxxec-xxxx-xxxx-xxxx-5cxxxxxxxx22.mobileprovision
If you select the Manually manage signing option, you need to choose a provisioning profile you created manually with your developer account, as shown below. However, you cannot make changes to automatically generated provisioning profiles and save them as custom provisioning profiles.
What does a provisioning profile contain?
You can find the provisioning profile in the app package file (
.ipa file). When you unzip the
.ipa file, you will see a file named
embedded.mobileprovision in the
Payload folder (e.g.
Payload/sample.app/embedded.mobileprovision). This is your provisioning profile. You can use the following command to inspect the provisioning profile or just open the profile in a text editor.
$ security cms -D -i embedded.mobileprovision
Provisioning profiles have information on development certificates, provisioned devices, entitlements, and expiration dates. If where you launch the app doesn’t match the information in the provisioning profile, your app won’t be launched.
When you take a look at the
DeveloperCertificates key in a provisioning profile, you will find a string encoded in base64.
openssl command cannot interpret data encoded in base64, you need to convert this into PEM (Privacy-Enhanced Mail) format so that the command can understand the data. You can do this by copying the string, adding
-----BEGIN CERTIFICATE----- at the top and
-----END CERTIFICATE----- at the bottom, and saving the file. (For this posting, I saved the file as “
openssl command, you can check the information of the certificate saved in
sample.txt as follows:
$ openssl x509 -in sample.txt -text Certificate: Data: Version: 3 (0x2) Serial Number: XXXXXX... (XXXXXX... ) Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, O = Apple Inc., OU = Apple Worldwide Developer Relations, CN = Apple Worldwide Developer Relations Certification Authority Validity Not Before: Oct 26 09:45:00 2018 GMT Not After : Oct 26 09:45:00 2019 GMT Subject: UID = XXXXXXXX, CN = iPhone Developer: XXXXXX (XXXXXXXX), OU = XXXXXXXX, O = XXXXXX, C = US Subject Public Key Info: ...
After checking the certificate information, you can find entitlements information, as shown below, right underneath the certificate information.
Entitlements specify which services the app is allowed to use and under what situation. For your information, as this provisioning profile sample is a debug build, the
get-task-allow option is set as
true to allow process debugging.
What is listed in the
<array> above depends on what capabilities you selected in the Xcode Capabilities tab. Let me enable Access WiFi Information and Apple Pay capabilities as follows:
When you create a provisioning profile with the configurations above, you can see these capabilities are added to the
Entitlements as keys with respective values.
You can check the expiration date of a provisioning profile with the
ExpirationDate key. Your app will not launch after this expiration date.
You can view a list of registered devices for this provisioning profile under the
ProvisionedDevices key. Your app will only run on these devices.
A provisioning profile that allows an app to run on any device, for such as ad hoc distribution, will have the
ProvisionsAllDevices key as
Verifying the integrity of binaries
Code signed Mach-O binaries have a code signature struct, which is used to verify the integrity of the Mach-O binaries.
What is a Mach-O binary file?
Before we take a deep dive, let me briefly explain about Mach-O binary files. Apps that run on iOS (
.ipa files) have a Mach-O binary file. Mach-O is a standard executable format in iOS and macOS. iOS executes a Mach-O binary file to launch an app.
$ file sample sample: Mach-O 64-bit executable x86_64 $ ./sample sample!
How to find a Mach-O binary file
This is how you find a Mach-O binary file. First, you need to unzip the
ipa file, and you will find the
Info.plist file in the
Payload folder (e.g.
Payload/sample.app/Info.plist). When you open
Info.plist, you will find the Executable file element, which is the Mach-O file executed to launch an app. The following is how the
Info.plist file looks like.
The following diagram shows a high-level description of the structure of our sample Mach-O binary file.
Now, let’s dive a little bit further into Mach-O binaries by looking at its components.
You can check whether the file is a Mach-O file or not by looking at the
magic value of the
The following table shows a brief description of each member of the Mach-O Header struct.
|magic||Indicates whether the file is a Mach-O file and determines the byte order.||<mach-o/loader.h>|
|cpu_type||Indicates a type of CPU||<mach/machine.h>|
|cpu_subtype||Indicates a subtype of CPU||<mach/machine.h>|
|file_type||Indicates a type of file for this header||<mach-o/loader.h>|
|num_load_commands||Indicates the number of load commands.||–|
|size_of_load_commands||Indicates the total size of load commands in bytes.||–|
|flags||Indicates what optional features of the Mach-O file format this binary file is using.||–||<mach-o/loader.h>|
machHeader struct is directly followed by a list of load commands (
LoadCommand). If the result of parsing the
machHeader struct indicates that the file is a Mach-O file, then the load command list is parsed. Load commands have a lot of information including the location of segments, the name of dynamic libraries and the location of symbol table. Among other things, I’ll focus on the code signing related load command, which is
You can see the
LoadCommand related to code signing information of the Mach-O file.
You can look up the information on
LC_CODE_SIGNATURE, using the
$ otool -l Payload/iOSSample-mobile.app/iOSSample-mobile | grep LC_CODE_SIGNATURE -A3 cmd LC_CODE_SIGNATURE cmdsize 16 dataoff 3188480 datasize 59808
dataoff indicates the offset of
CodeSignature. When you follow this information one by one, you can find all of code signing related information. I’ll not go into further detail about how to find this information.
The following shows a high-level structure of
Let’s take a closer look at the following items that compose the CodeSignature struct:
CodeSignature struct, you can find the
CodeDirectory, which has the hash values of a specific file or executable binary file pieces. When you look at the
CodeDirectory struct of our sample app binary file, you can find HashSlot codeHash and HashSlot specialHash at the bottom of the list.
codeHash has the hash values of the binary file for each
0x1000). The following diagram represents the
codeHash of our sample app.
When the code is modified, the hash value of the page corresponding to the code modifications will change. Since this hash value will not match to the hash value in the
codeHash, iOS will know that the code has been modified.
Now, let’s take a look at
specialHash. We got the values of each element in the
specialHash array by parsing the Mach-O file. The elements and each element value is as follows.
|Array index||Contains||Description||Hash (of our sample app)|
|0||Entitlement||Bound in code signature||4b255acb014ab5dc8cd63f5120baeef19309e340|
|1||Application Specific||Application Specific is not currently used as indicated by the code related to the Apple Mach-O code signing.||0000000000000000000000000000000000000000|
|2||Resource Directory||Resource directory indicates _CodeSignature/CodeResources file in the ||35b65bb61f6b617e9a944cdada31cb78b47ab393|
|3||Internal requirements||Internal requirements indicate Requirements in the file.||cdbf07382a5a26998e34dc9d80070fc5db8c9230|
|4||Bound Info.plist (Manifest)||Bound Info.plist indicates the ||5108d83c00eb7f294fb73914abdb0a1c977b92f2|
The resource directory points to the
_CodeSignature/CodeResources file (e.g.
Payload/sample.app/_CodeSignature/CodeResources) in the
ipa file. The
CodeResources file lists up the checksum of the resource files in the app file. You can see the content of the
CodeResources file of our sample app below.
We can check the hash value of sha-1 by using the
shasum command. The hash value retrieve by the command is identical to the sample value identified in
$ shasum Payload/iOSSample-mobile.app/_CodeSignature/CodeResources 35b65bb61f6b617e9a944cdada31cb78b47ab393 Payload/iOSSample-mobile.app/_CodeSignature/CodeResources
The “Bound Info.plist” indicates the
Info.plist file in the
.app directory. The
Info.plist file has basic information on the app such as the name, version and filepath of the app icon. The value returned is identical to the sample value identified in
$ shasum Payload/iOSSample-mobile.app/Info.plist 5108d83c00eb7f294fb73914abdb0a1c977b92f2 Payload/iOSSample-mobile.app/Info.plist
Requirements and Requirement
Requirement is a set of rules used to verify code signing. The number of Requirement is defined by the count member of the Requirements struct. You can check out the information on Requirements, using the codesign command as shown below.
$ codesign --display -r- Payload/iOSSample-mobile.app/iOSSample-mobile Executable=Payload/iOSSample-mobile.app/iOSSample-mobile designated => identifier "armor.sdk.sample.cocos2dx.ios" and anchor apple generic and certificate leaf[subject.CN] = "iPhone Distribution: XXXXXXX (XXXXXXX)" and certificate 1[field.1.2.840.1136220.127.116.11.1] /* exists */
To verify the checksum, we will copy all of
Requirements andRequirement fields and save it as a file, called
Let’s check the checksum of the requirements.txt file, using the
shasum command as below. The value returned is identical to the sample value identified in
$ shasum requirements.txt cdbf07382a5a26998e34dc9d80070fc5db8c9230 requirements.txt
CodeDirectory has the hash value for
Entitlement in the binary file. You can find
Entitlement in the
CodeSignature struct, as shown below.
Let’s copy the
Entitlement struct, including the field
data, into a file. Save the file with the name,
And run the
shasum command with file containing the
Entitlement struct. The value returned is identical to the sample value identified in
$ shasum entitlement.txt 4b255acb014ab5dc8cd63f5120baeef19309e340 entitlement.txt
$ jtool --sig -v Payload/iOSSample-mobile.app/iOSSample-mobile ... Blob 4: Type: 10000 @41788: Blob Wrapper (4802 bytes) (0x10000 is CMS (RFC3852) signature)
BlobWrapper has data on the code signing of the
CodeDirectory as mentioned earlier and certificates used for code signing of such data. If you want to view the content of Certificates, extract the data of
BlobWrapper from the binary file and save it as a file. In our exercise, let’s name it
You cannot open this text file with a text editor, but you can check overall content using the
openssl command, as shown below.
$ openssl pkcs7 -inform der -in blobwrapper.txt -print -noout PKCS7: type: pkcs7-signedData (1.2.840.113518.104.22.168) d.sign: version: 1 md_algs: algorithm: sha256 (2.16.822.214.171.124.4.2.1) parameter: NULL contents: type: pkcs7-data (1.2.840.1135126.96.36.199) d.data: <ABSENT> cert: cert_info: version: 2 serialNumber: 134752589830791184 signature: algorithm: sha1WithRSAEncryption (1.2.840.1135188.8.131.52) parameter: NULL issuer: C=US, O=Apple Inc., OU=Apple Certification Authority, CN=Apple Root CA validity: notBefore: Feb 7 21:48:47 2013 GMT notAfter: Feb 7 21:48:47 2023 GMT subject: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority key: algor: algorithm: rsaEncryption (1.2.840.1135184.108.40.206) parameter: NULL public_key: (0 unused bits) 0000 - 30 82 01 0a 02 82 01 01-00 ca 38 54 a6 cb 0.........8T.. ...
When you change the content of the
CodeDirectory, the CMS signature will change even if you use the same certificate for code signing. So even if an attacker changes the code and updates the content of the
CodeDirectory in line with the changed code, you can ensure the integrity of your app by verifying the CMS signature with your key.
iOS does not stop at verifying the hash value of the files related to the binary file, but goes further to ensure the integrity of the app by verifying code signing. This process allows iOS to prevent a manipulated app from running on a device of random users.
AIR ARMOR provides additional security features on top of the basic security feature using the code signing principles of a Mach-O binary file. Please check out its security features here.