In this first blog post about tool we will see its basic uses and how it can make our life a lot easier.
ipsw is a tool that can be used for *OS research, it provides a lot of functionalities related to dyld_shared_cache, DeviceTree, kernelcache, Img4, etc. which are all of interest to security researchers.
We will go over each of command to see what it does and how to use it, but before we do that, we first need to get ipsw. We can build ipsw from the source or we can download one of the prebuilt binaries available on the GitHub .
After we have downloaded ipsw, to confirm that everything is working okay and to see the list of the options, we will type
appstore is the first command that ipsw provides and it allows us to interact with the App Store Connect API.
ipsw appstore provides:
managing bundle IDs of the created applications
management of signing certificates
listing and registering new devices
managing provisioning profiles
generating jwt token that we can use to interact with
App Store Connect API.
A lot of
ipsw commands require
App Store Connect API key and we can obtain one by visiting .
After the key is created we need to download it, by clicking on the
Path to the file will be provided with the
-p flag, Issuer ID with the
-i flag and Key ID with
-k flag respectively, both of these IDs can be copied from the webpage as can be seen on the image above.
We can list registered bundle IDs (created with Xcode) using
ipsw appstore bundle ls while providing previously acquired information (.p8 file, Issuer ID and Key ID). We could use this command in order to see all the bundle IDs that we have registered.
ipsw appstore bundle ls -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
appstore provides us with the management of signing certificates. To list the certificates we can simply call
ipsw appstore cert ls with the .p8 file, Issuer ID and Key ID. We can use this command in the cases where we would want to quickly create new signing certificate or if we want to check them.
ipsw appstore cert ls -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
Now we will see how to create new signing certificate. The first thing we need to do is to create new key using
openssl req -newkey rsa:2048 -keyout 8ksec.key -out 8ksec.csr
After filling required information we will have Certificate Signing Request inside of
8ksec.csr file and private key inside of
8ksec.key. The contents of the
8ksec.csr will be passed to the
-c flag of
ipsw appstore cert add. We need to clean it up a bit by removing newlines, we can do that with
tr -d ’\n’.
After we have obtained our
csr we will call
ipsw appstore cert add with the
ipsw appstore cert add -c CONTENTS_OF_CSR -t DEVELOPMENT -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
We can see that we successfully created a new signing certificate which got saved to the file on our system. To confirm that it is indeed created, let’s call
ipsw appstore cert ls one more time.
To remove the certificate, we simply pass the
ipsw appstore cert rm. In our case the command would look like
ipsw appstore cert rm --id Q6FAZ3K5VT -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID.
We can also manage devices using
appstore subcommand such as listing devices or registering new devices. To add new device, we need to have
UDID of the device and specify its name and platform (iOS). UDID of the device can simply be seen using
idevice_id from libimobiledevice.
To list the devices command is
ipsw appstore device ls -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
appstore subcommand provides us with
profile subcommand which allows us to manage provisioning profiles. We can do things such as listing, creating, renewing and removing provisioning profiles. Provisioning profiles allow for running apps with entitlements or signing certificates outside of the normal configuration of iOS.
To list provisioning profiles:
ipsw appstore profile ls -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
To create a new provisioning profile we need to pass the following:
the name of the provisioning profile
certificate ID for the newly created provisioning profile
finally, device ID for which device will this new provisioning profile be related
ipsw appstore profile create NAME -c CERTIFICATES_ID -d DEVICES_ID -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
If the request was successful, provisioning profile will be written to the
NAME.mobileprovision on the disk. To confirm that we have indeed created the profile, let’s issue another
To remove the profile, we simply need to pass the name of the profile to
ipsw appstore profile rm with
ipsw appstore profile rm -n 8ksec -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
Finally, we can generate JWT token to use with the App Store Connect API.
ipsw appstore token -p PATH_TO_P8_FILE -i ISSUER_ID -k KEY_ID
The second main subcommand that ipsw provides is
device-list. It allows us to see the list of all iOS devices, its architectures and the CPU inside of them.
The third main subcommand is related to diffing two
ipsw files. ipsw files are basically firmware files and we can
diff or find differences between two ipsw files. This can be useful for example if the vulnerability was patched and we don’t know the exact details, this can point us in the right direction.
We will use and ipsw files.
ipsw diff ~/Downloads/iPhone15,4_17.0.2_21A350_Restore.ipsw ~/Downloads/iPhone15,4_17.0.3_21A360_Restore.ipsw
After running the command, we can see that checks a bunch of different categories, such as dyld_shared_cache, entitlements, etc.
A couple of lines below, we can see some actual changes.
The fourth subcommand allows us to download a whole lot of different stuffs, such as OSs, IPAs, IPSW files, macOS installers and more. We can use this command to go over a bunch of different webpages to download or browse stuff, instead we can do it from the terminal.
This subcommand allows us to download IPSWs files directly from the .
ipsw download appledb --os iOS --version '17.0.3' --device iPhone15,2 --kernel
dev allows you to download IPSWs, OSs, Xcode and more from the .
ipsw download dev
Typing the command above will give you a list of what you want to download so you can easily select it.
Another useful subcommand for
ipsw download is
macos which allows you to download macOS installers.
ipsw download offers other options such as
ipa but to leave a room for the rest of the commands, we will skip those.
This command allows us to parse DeviceTree. DeviceTree is a representation of hardware used by the bootloaders to provide the kernel with a mapping of a hardware.
To parse DeviceTree, we first need to have one and to do that, we can use
ipsw extract to extract DeviceTree from the IPSW file.
Once we have extracted the DeviceTree, we can parse it with
ipsw dtree PATH_TO_DEVICE_TREE_FILE
dyld subcommand provides a lot of functionalities related to the dyld_shared_cache. Some of the functionalities are:
getting info about the dyld_shared_cache
finding which dylibs import another dylib
extracting the dyld_shared_cache
search for string inside of dyld_shared_cache
and a bunch more
dyld stands for dynamic loader and it’s job is to load the shared libraries into the memory of the process. To speed-up the loading process, these are all combined into the single file called dyld shared cache. We will cover a couple of these functionalities as there is a lot of them.
To get all information from the dyld_shared_cache we can just call
ipsw dyld info with the path to dyld_shared_cache. We also have a couple of optionals, such as printing only dylibs, dlopen closures.
ipsw dyld info PATH_TO_DYLD_SHARED_CACHE
Also, after some general information we can see dylibs inside of dyld_shared_cache as can be seen on the image below.
We can extract specific framework for further analysis from the dyld_shared_cache using
ipsw dyld extract command.
ipsw dyld extract PATH_TO_DYLD_SHARED_CACHE DYLIB
On the image below, we can see extracting
This subcommand for
ipsw dyld allows us to parse specific dylib inside of dyld_shared_cache file.
ipsw dyld macho PATH_TO_DYLD_SHARED_CACHE DYLIB
For example, to get loads commands from the Accelerate.framework, we can do:
To see which dylibs load specific dylib, we can use
ipsw dyld imports command. Lets say we have found a vulnerability inside of specific dylib and we want to check which other frameworks/dylibs import it, we can use this command.
ipsw dyld imports PATH_TO_DYLD_SHARED_CACHE DYLIB
Here we can see which dylibs are loading Accelerate.framework.
We can gather Objective C information from the dylibs using
ipsw dyld objc. We can use it to print classes, protocols, selectors or imp-caches for dyld_shared_cache. This command is useful if we want to see some classes/functionalities inside of PrivateFrameworks.
To dump all the classes, we can use
ipsw dyld objc —class PATH_TO_DYLD_SHARED_CACHE
We can split the dyld_shared_cache using
ipsw dyld split which allows us to see everything inside of dyld_shared_cache. We will go over splitting dyld_shared_cache on macOS Ventura.
On macOS Ventura, dyld_shared_cache is stored at the location of
To do that, we just need to pass the path to the dyld_shared_cache file and optional output path. As we can recall previously, our dyld_shared_cache files are stored at the
/System/Cryptexes/OS/System/Library/dyld/ and we will use
ipsw dyld split /System/Cryptexes/Os/System/Library/dyld/dyld_shared_cache_arm64e /tmp/8ksec.
A couple of seconds later, we can examine the output directory to see what is inside.
We can see a lot of interesting directories such as
Frameworks. We can now, for example, see the exported symbols from one of this frameworks, let’s say
nm -Ug followed by the path to the
CalendarWidget shared library.
ipsw dyld str allows us to search for specific string patterns inside of dyld_shared_cache files. This comes in handy when we want to check for example where is the specific string used/referenced.
ipsw str PATH_TO_DYLD_SHARED_CACHE -p “REGEX PATTERN”
As can be seen on the image above, there are quite a lot of cases where the world string is present. We can also see the name of the framework where the pattern was found.
ipsw ent allows us to search for specific entitlement inside of IPSW, make a diff of entitlements inside of two different IPSW files as well as dumping entitlements for specific MachO file. This one can be useful if we want to know every binary that contains specific entitlement, or we want to see changes between two different IPSW files.
To do search for specific entitlement, let’s say for
com.apple.developer.carplay-audio, the command would look like this:
ipsw ent -e com.apple.developer.carplay-audio PATH_TO_IPSW_FILE
Diff allows us to see difference in entitlements between two IPSW files.
ipsw ent --diff PATH_TO_FIRST_IPSW PATH_TO_SECOND_IPSW
ipsw info command allows us to see information regarding IPSW or OTA file. We could use this command if we want to see the chip or iOS version for the specific IPSW or OTA file. We can do the check for the local files, or we can pass the URL with the
-r flag to to analysis on the remote file.
command for local file:
ipsw info PATH_TO_IPSW_OTA_FILE command for remote:
ipsw info -r URL
ipsw mdevs allows us to see all mobile devices inside of specific IPSW file.
ipsw mdevs PATH_TO_IPSW
ipsw mount command allows us to mount the specific part of IPSW file. Those parts are fs (filesystem), sys (system) or app (library). We may want to use this command if we would like to see what is exactly inside of IPSW file and to do some further analysis/research on the specific part of it, e.g. specific dylib.
ipsw mount [fs|sys|app] PATH_TO_IPSW_FILE
On the next two images we can see mounting fs (filesystem) and what is inside of it.
Now, we will mount the sys (system) and we will check its content.
Finally, we will mount app.
ipsw plist command allows us to dump the .plist file as json or for example to watch for changes in plist files inside of specific directory. Let’s say that we are analyzing the application and we want to know what and when triggers writing specific option inside of plist file, we could utilise this command.
We can pass in the path to the plist file and it would get parsed as json.
ipsw plist PATH_TO_PLIST_FILE
We can also pass the output of this to
jq to get let’s say bundle identifier.
We can also use
ipsw plist to watch specific directory for changes inside of plist files. This comes in handy when we want to track what changes inside of plist file while we are working with the application.
ipsw plist -w PATH_TO_DIRECTORY
ipsw provides us with the convenient way to update it by running the
ipsw update which then allows us to download the new version for out specific OS and architecture.
After the download has finished, we can extract the archive, check our version and to see if we are indeed running the latest version by running
ipsw update inside of downloaded package.
ipsw watch is the command which is not strictly related to iOS or macOS but it is related to watching specific GitHub repository for changes. We can watch for the changed file or perhaps pattern inside of commit messages and get notified about the changes over the Discord.
In the next part, we will look at some additional uses of ipsw for *OS security research.
GET IN TOUCH
Visit our training page if you’re interested in learning more about these techniques and developing your abilities further. Additionally, you may look through our Events page and sign up for our upcoming Public trainings.
Please don’t hesitate to reach out to us through out Contact Us page or through the Button below if you have any questions or need assistance with Penetration Testing or any other Security-related Services. We will answer in a timely manner within 1 business day.
We are always looking for talented people to join our team. Visit out Careers page to look at the available roles. We would love to hear from you.