The App Store
Since its initial release on July 10, 2008, the iOS App Store has amassed over 2.2 million apps. Combine that with a study by Nielsen in 2015 which shows that the average smartphone user interacts with 10 apps a day, and 30 apps a month for a total of over 35 hours spent using apps every month, it’s safe to say that we love our apps.
The way we interact with all of these apps is generally the same: download it from the App Store, find the app’s icon on your home screen, tap it and it magically opens. On the surface, there doesn’t seem much to an app. They all just sit there patiently on your home screen, icons waiting for you to tap on them and bring them to life. But have you ever wondered what actually goes on under the hood? How these apps work, and what they’re made of? Let’s take a look.
Note: throughout this post we will be looking at specific examples from an app which I wrote: RS Xchange.
The IPA file
After finding a new app which you’d like to try out on the App Store, you press the download button and wait a little while for stuff to happen. During this time, iOS is downloading the app in the form of a file with an extension of “.ipa”. So what exactly is this “.ipa” file?
“.ipa” files are actually just “.zip” files. Renaming .ipa to .zip will allow you to extract the contents of the .ipa file in much the same way you extract .zip files. After extraction, you will find a folder with the following structure:
- iTunesArtwork
- iTunesMetadata.plist
- Payload/
- META-INF/
Let’s run through this from top to bottom.
iTunesArtwork
This file is actually a .png file. Adding the “.png” extension to it will allow you to open the file with your image viewing tool of choice. Upon opening the file, you will see that this is just the app’s icon as it is shown on the App Store. This image will have a size of 1024×1024. Here is an example of an iTunesArtwork file:
iTunesMetadata.plist
This file contains lots of information about the app, its developer, when it was downloaded, and which account it was downloaded by. This is what a sample iTunesMetadata.plist file might look like:
Payload/
The Payload/ folder contains the actual app binary along with all of its resources that it needs to function. Once inside the Payoad/ folder, there will be a single file with the “.app” extension. This file is actually just another folder, and you can open it like any other folder. On MacOS, right click it and press “Show Package Contents”.
The contents of this folder will differ from app to app. This is the stuff that defines each individual app. Here is an example of some of the things you might find:
- AppIcon29x29.png
- [email protected]
- [email protected]~ipad.png
- [email protected]
- AppIcon29x29~ipad.png
- [email protected]
- [email protected]~ipad.png
- [email protected]
- AppIcon40x40~ipad.png
- [email protected]~ipad.png
- AppIcon50x50~ipad.png
- AppIcon57x57.png
- [email protected]
- [email protected]
- [email protected]
- [email protected]~ipad.png
- AppIcon72x72~ipad.png
- [email protected]~ipad.png
- AppIcon76x76~ipad.png
- Assets.car
- Base.lproj/
- Frameworks/
- Info.plist
- ItemDetailsStoryboard.storyboardc/
- LaunchScreen.storyboardc/
- OSRSItemDetailsDescriptionTableViewCell.nib
- OSRSItemDetailsHeaderView.nib
- OSRSItemDetailsWikiaTableViewCell.nib
- OSRSItemSearchTableViewCell.nib
- PkgInfo
- RS Xchange
- SC_Info/
- TSMessagesDefaultDesign.json
- _CodeSignature/
- archived-expanded-entitlements.xcent
Let’s run through them top to bottom.
AppIcon.png
First, you will notice a bunch of images named something like “AppIcon<something>.png”. These images correspond to, as you might have guessed, the app’s icon as you see it on your home screen. There are lots of various sizes of this icon, each one optimized for a different device and different place that it might be shown. For example, iPads have different app icon dimension requirements than iPhones, and the app icon as it is shown in a notification has a different dimension requirement than the app icon which is shown on the home screen.
Assets.car
This file contains some (or all) of the images which the app might use to display once you open it. The images are stored in an optimized format, and you need special tools to take them out and look at them one by one. One such tool which can do this is called the Asset Catalog Tinkerer. Upon exporting, you will get a list of image files which you can open with your image viewing tool of choice. Here is an example of some of the images which you might find inside of the Assets.car file:
Base.lproj/
This folder has to do with localization. If an app supports multiple languages, each resource which needs to be translated (strings, images, storyboards, xibs) will go into its own folder which ends in “.lproj”. For example, if your app was localized to english and french, you will have three “.lproj” folders: en.lproj, fr.lproj, and Base.lproj. The en.lproj and fr.lproj folders will contain resources which have been converted to their respective languages, and Base.lproj contains the default resources to use in the case when a user’s phone is using a language which is not supported by the app. In most cases, Base.lproj just contains the english version of the app’s resources.
Frameworks/
This folder contains all of the dynamic frameworks and libraries which the app relies on. This is just some code which was written outside of the main app, and which is used by the main app. Here is an example of some of the files which might be found in this folder:
- AFNetworking.framework/
- Blindside.framework/
- BlindsidedStoryboard.framework/
- ChameleonFramework.framework/
- Charts.framework/
- DZNEmptyDataSet.framework/
- FontAwesome_iOS.framework/
- Harpy.framework/
- HexColors.framework/
- KSDeferred.framework/
- MaryPopin.framework/
- NXTSegmentedControl.framework/
- PPiAwesomeButton.framework/
- PPiFlatSegmentedControl.framework/
- SCLAlertView_Objective_C.framework/
- SDWebImage.framework/
- TSMessages.framework/
- iRate.framework/
- libswiftContacts.dylib
- libswiftCore.dylib
- libswiftCoreGraphics.dylib
- libswiftCoreImage.dylib
- libswiftDarwin.dylib
- libswiftDispatch.dylib
- libswiftFoundation.dylib
- libswiftObjectiveC.dylib
- libswiftUIKit.dylib
Amongst these, you’ll notice that some apps contain files which start with “libswift”, and have the extension “.dylib”. These files make up the Swift runtime, and they are necessary to be included in every app which contains Swift code.
Info.plist
This file contains generic information about the app itself. Things ranging from the app’s name, to the AppIcon files we talked about above, to the permissions which the app might ask for (photos, camera, contacts, etc), and even some internal information such as the unique identifier for the app (called the bundle identifier). Here is a sample Info.plist file:
A lot of interesting information can be found in the Info.plist file. An official summary of everything this file might contain can be found here and here.
<something>.storyboardc/
Folders which end in .storyboardc contain some information related to the layout of particular screens or views within the app. The presence of these folders indicate that the app was developed using the Interface Builder tool. Within these folders, you will find several .nib files along with another Info.plist file:
- Info.plist
- UIViewController-x1L-Z2-jkR.nib
- x1L-Z2-jkR-view-7LY-9B-3EQ.nib
The Info.plist file included here is in binary format, and you need to convert it to XML format before being able to read it like normal .plist files. Run this command to convert it to XML:
1 |
plutil -convert xml1 Info.plist |
Here is what an example Info.plist file could look like inside of a .storyboardc file:
The keys/values within these Info.plist files describe some information relating to the .nib files found alongside them. In this case, the UIStoryboardDesignatedEntryPointIdentifier key is indicating that the view controller with the identifier UIViewController-x1L-Z2-jkR is to be used as the “entry point” for the application, or the first screen to be displayed when the app is opened. The UIViewControllerIdentifiersToNibNames key is mapping identifiers in the compiled .nib files to other .nib files.
<something>.nib
.nib files are the result of compiling .xib files using the ibtool utility. .xib files are XML files which define the user interface for a specific element within the app. Everything from individual buttons to entire screens can be defined in .xib files. Here is a sample .xib file:
And the corresponding user interface it produces:
It’s important to note that while developing, the XML of a .xib file is never modified directly by a person. The resulting XML is generated through the Interface Builder tool.
PkgInfo
This is an auto-generated file which contains the 4-byte package type followed by the 4-byte signature of your application. For iOS apps, the package type will be “APPL“, and the signature will be 0x3f3f3f3f.
More information about this file can be found here.
RS Xchange
This file name will be different from app to app, and the name corresponds to the value for the CFBundleExecutable in the Info.plist file. This is the app’s main executable. It contains all of the code necessary to make the app run. This is the file that gets executed when you tap on the app’s icon on your home screen.
When you download an .ipa file from the App Store, this executable is encrypted, so you can’t take a closer look at what’s inside of it. Fortunately there is a way to get the decrypted version, but we’ll cover that in a future blog post.
SC_Info/
This folder contains keys which are used for decrypting the app executables. The contents will look like this:
- Manifest.plist
- RS Xchange.sinf
- RS Xchange.supf
- RS Xchange.supp
- RS Xchange.supx
The .sinf, .supf, .supp, .supx files are used for decrypting, and the Manifest.plist file is used to list all of the relevant .sinf files which are to be used. Here is a sample Manifest.plist file:
TSMessagesDefaultDesign.json
This file is specific to the RS Xchange app which we have been inspecting throughout this post. It is just one of the additional resources which are included with the app. Apps can have all sorts of arbitrary resources which they require to function, and you will find them all in the root of the .app folder.
_CodeSignature/
This folder contains information related to code signing. When a developer decides to distribute an app via the App Store, code signing is performed on the executable and all of the other resources included within the app. The purpose of this process is to ensure that the app can not be modified by any malicious third party after the developer has chosen to distribute a version of their app.
There is a single file within this folder called CodeResources. Taking a closer look at this file, it is actually a .plist, and can be opened the same way as any other .plist file. You can find a sample CodeResources file here. (I would include it directly here, but it’s 3000+ lines long)
Each file which is eligible for code signing is included in this file, along with the corresponding hash data which should result from the process of signing each file.
If any of these files are modified after the developer has signed it, the hashes of the files will differ and the app will be unable to be run on a device.
More information about code signing can be found here and here.
archived-expanded-entitlements.xcent
This file is once again just a .plist file in disguise. It contains all of the entitlements which the app has requested, such as push notifications and access to iCloud storage. Here is a sample archived-expanded-entitlements.xcent file:
In this example, the only entitlement the app is requesting is for keychain-access-groups. You can find a complete list of the entitlements which an app may request here.
META-INF/
This folder contains some general metadata about the .ipa file. Under the META-INF/ folder, you will find two more files:
- com.apple.FixedZipMetadata.bin
- com.apple.ZipMetadata.plist
You typically don’t need to worry about this folder, and there isn’t much documentation to go with it, but let’s run through the two files found here anyway.
com.apple.ZipMetadata.plist
The com.apple.ZipMetadata.plist file contains some information about how the .ipa file was created, along with its uncompressed size. This is what a sample com.apple.ZipMetadata.plist file might look like:
Note that this .plist file is typically found in binary format, and you will need to do some work to convert it to XML format to get the output above. Converting a binary plist to an XML plist can be done with the following command:
1 |
plutil -convert xml1 com.apple.ZipMetadata.plist |
com.apple.FixedZipMetadata.bin
The next file, com.apple.FixedZipMetadata.bin, is binary file of some sort. There isn’t much documentation about what this is or how to read it, but doing a hexdump on it yields the following:
1 2 3 |
00000000 4d 64 46 78 01 10 00 00 00 00 00 00 00 00 00 00 |MdFx............| 00000010 00 00 00 00 00 00 00 |.......| 00000017 |
That’s all folks
We’ve officially gone through everything that is found within a typical App Store app file which you download and install on to your device. All of these components work together to provide you with all of the functionality you know and love, like lining up candy, browsing memes, and of course, colouring pictures of cats.