Cracking iTunes Backup Passwords with hashcat

Following the recent announcement of LUKS support in hashcat, I noticed that there have been some commits to support iTunes Backup passwords as well.

This is only useful if the backup was encrypted by setting a backup password on the iOS device. If the backup is not encrypted then all the files are in clear and there is nothing to bruteforce.

The keys used to encrypt the backup are stored in the BackupKeyBag, which can be found in the Manifest.plist file. This keybag is a binary blob, the format of which has already been documented by researchers from Sogeti ESEC Lab.

I have written a simplified script which dumps the BackupKeyBag.

Speeding up iOS Backups

iOS device backups usually take a while, depending on how much storage has been used on your device.

The iOS backup process is driven by the device itself, through the BackupAgent process. This process treats the host PC like a dumb disk store, by sending it commands like DLMessageCreateDirectory, DLMessageUploadFiles, DLMessageRemoveFiles, DLMessageGetFreeDiskSpace, etc. so that it can determine what has been backed up previously and what to send/update for incremental backups.

For password cracking, we don’t need the entire 64 GB (or God forbid, 128 GB) of data on the iOS device. We just need the Manifest.plist, which is typically less than 50 KB. But because the backup process is controlled by the device and not the PC, we can’t simply ask it to send over that single file. Sometimes when we setup a VM with libimobiledevice, we might also not have allocated such a large virtual disk. Of course when I say “we”, I really mean “I”.

To solve these issues, I created a FUSE-based filesystem called the Fake iOS Backup Filesystem, or fibfs for short. I’m particularly proud of this name because my project names are usually very unoriginal. This file system exposes a “disk” (or mount point) that reports at least 128 GB of free space, and will preserve file names and other metadata but not the file contents. It contains a hard-coded list of files, like a white list, that should have their contents preserved, Manifest.plist being one of them. Because it discards most of the backed up data, such a backup will consume less than 10 MB of real disk space.

This filesystem is to be used when specifying a backup directory for idevicebackup2. It will then lie to the iOS device that it has sufficient disk space to perform the backup, while actually discarding the backup data instead of writing them to disk.

Thus, using fibfs allows you to retrieve Manifest.plist without spending too much time or disk space for the iOS backup process.

Quick note: if your iOS 10 backups are failing due to an error removing snapshot directory, it has been fixed in the tree but just not put into a release yet. The current version with this bug is libimobiledevice 1.2.0. All the backed up data is still there anyway.

Using Hashcat

You will need the latest version of hashcat (at least 3.40), released just a few days ago.

The hash format for iTunes Backups look like this (everything is delimited by asterisks):


For iOS versions earlier than 10.2, DPIC and DPSL are not required, so just leave them blank. That means your constructed hash will look like this:


For iOS 10.2 and above, the DPIC and DPSL parameters will be required. You will see these parameters when you dump the keybag.

The hash type (or hash mode) for iOS versions < 10.2 is -m 14700. For iOS 10.2 that introduced the DPIC and DPSL parameters, you will have to use -m 14800. Setting the hash mode will instruct hashcat to use the correct OpenCL kernel.

When you dump the keybag (using the above-mentioned script or other methods), you should see something like this:

UUID: b6ed25...d71a, HMCK: 0000...0000, WRAP: 0, SALT: 2b06ba3c6281ce101a0bd0249c1203cc9c8da1a8, ITER: 10000
UUID: 3a8bcc...baaf, CLAS: 11, WRAP: 3, KTYP: 0, WPKY: c1212e8754a1db6dfddc4fc6a386795eda88c18b865742e6fbd961b13e3229efda50dc0b69bdfc2e
UUID: 47386f...58d1, CLAS: 10, WRAP: 3, KTYP: 0, WPKY: d025009b7eaa016d756d6862c71856e76b060e1ee6f69e6c805852008757f1cb25110025a2e4fcb6
UUID: 24ac76...af0c, CLAS: 9, WRAP: 3, KTYP: 0, WPKY: baa24719f865afe330b85f26468e787c0115339407ad950935070cd5e7cc27a5d6c811e716b38741

The UUID of each entry is not important, which is why the script truncates it for brevity. Only the first entry (where WRAP is 0) will contain the SALT and ITER parameters. For an iOS version 10.2 keybag, this is where you will also find the DPSL and DPIC parameters.

Subsequent keybag entries contain the encryption key for each NSFileProtection class and kSecAttrAccessible class. There's currently a total of 11 CLAS types (including undocumented classes). The actual key for each entry is stored in the WPKY attribute (wrapped key). Any WPKY value can be used, as long as the WRAP_PASSCODE bit (0x2) is set. Usually, all keys will have this bit set, so any keybag entry can be used.

The reason this works is because we are not cracking the key itself, but rather the backup password that protects these keys. Each key is "wrapped" using AES and a successful unwrapping can be verified by checking the IV for a known value (A6A6A6A6A6A6A6A6). This allows hashcat to know when it has found the right password.

So to summarize, these parameters are used to construct a hash for hashcat to crack:

  • a WPKY from any entry
  • SALT and ITER parameters from the first entry
  • DPSL and DPIC parameters (only for iOS 10.2 and later)


Note that this is not a hashcat tutorial; I assume you already know how to use it.

Here's a worked example for cracking the password to the keybag above. In this case, the backup is from an iOS version 9.x device, and we are using the key for the CLAS 11 entry.

> hashcat64 -m 14700 -a 3 "$itunes_backup$*9*c1212e8754a1db6dfddc4fc6a386795eda88c18b865742e6fbd961b13e3229efda50dc0b69bdfc2e*10000*2b06ba3c6281ce101a0bd0249c1203cc9c8da1a8**" pa?l?l?l?l?l?l



Session..........: hashcat
Status...........: Cracked
Hash.Type........: iTunes Backup < 10.0
Hash.Target......: $itunes_backup$*9*c1212e8754a1db6dfddc4fc6a386795eda88c18b865742e6fbd961b13e3229efda50dc0b69bdfc2e*10000*2b06ba3c6281ce101a0bd0249c1203cc9c8da1a8**
Time.Started.....: Thu Mar 02 22:16:09 2017 (9 secs)
Time.Estimated...: Thu Mar 02 22:16:18 2017 (0 secs)
Input.Mask.......: pa?l?l?l?l?l?l [8]
Input.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:    55659 H/s (6.43ms)
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 540672/308915776 (0.18%)
Rejected.........: 0/540672 (0.00%)
Restore.Point....: 360448/308915776 (0.12%)
Candidates.#1....: paydbfer -> panpjurd
HWMon.Dev.#1.....: Temp: 47c Fan: 33% Util: 92% Core:1100Mhz Mem:1500Mhz Lanes:16

If you do get some "separator unmatched" error, check that the "iTunes version" in the hash matches the hash mode being used.


To give you an idea of the performance of cracking iTunes Backup passwords, here's a comparison against other well-known algorithms that have been long supported by hashcat:

Chart of hashcat cracking speeds

Note that the graph has a logarithmic scale. These measurements were taken using my Radeon HD 7900; your mileage may vary.

There’s no cause for concern here. The security measures in place to protect the iTunes Backup password are in line with current practices. Apple has taken steps to further secure iOS 10 backups by introducing an additional layer of 10,000,000 rounds (yes, that’s 10 million!) of SHA-256. That is why the new iTunes 10.2 backups now take at least 3 orders of magnitude longer to crack.

This is also a reminder to use a sufficiently strong password for your encrypted iOS backups.

Further Reading

If you are interested in reading more about the security architecture for iOS backups, you can check out the following links:


6 comments on “Cracking iTunes Backup Passwords with hashcat

  1. Damien2678 says:


    Thanks for this interesting Post. I’m trying to follow it, but block at the first step using the Python script to dump the BackupKeyBag.

    May you specify which “plist” module you are using please? I could not find one making your script working.

    Thanks ahead!

    Note: it seems “StringIO” module has been replaced by module “io” (using Python 3.6 (64 bit) on Windows 7)


  2. Tommy says:

    Mr. Tan,

    This was incredibly useful for me! I’m examining an iPhone 6 for a forensics case and the need to access an encrypted backup arose. I also had a few issues running your script to dump the BackupKeyBag, but after some tinkering I got it working. I was only able to achieve 28K H/s with my GTX 750Ti, but it was enough to crack it in a reasonable amount of time.

    Thanks again!


    • -Jack says:

      What error? No matter what I try, I get “global name Structure not defined” and I’m not smart enough to figure it out…

  3. darkgilder says:

    Hi iḿ having trouble with the script, iḿ a python newbie so i can’t figure out the solution here is the shell output
    $ python Manifest.plist
    Traceback (most recent call last):
    File “”, line 99, in
    File “”, line 93, in main
    stream = getKeybagFile(sys.argv[1])
    File “”, line 26, in getKeybagFile
    pl = Structure.from_bin(data) if data.startswith(‘bplist’) \
    NameError: global name ‘Structure’ is not defined

    best regards

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s