SkillAgentSearch skills...

IOSbackup

A Python 3 class that reads and extracts files from a password-encrypted iOS backup created by iTunes on Mac and Windows. Compatible with iOS 26. Class works on Linux too.

Install / Use

/learn @avibrazil/IOSbackup
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

iOSbackup

A Python 3 class that reads and extracts files from a password-encrypted iOS backup created by iTunes on Mac and Windows. Initial support for unencrypted backups has been aded since version 0.9.923. Tested compatibility since iOS 10 up to current iOS 15.

You will need your backup password to decrypt the backup files, this is the password iTunes asks when it is configured to do encrypted backups. This password can be found on macOS’ Keychain Access app, under login keychain, entry iOS Backup (update: newer macOS apparently doesn’t store it in KayChain anymore).

You should always prefer encrypted backups because they are more secure and include more files from your device. Non-encrypted backups do not backup files as Health app database and other preciosities.

Donation

This software is essential for advanced device forensic activities or to anyone in need to dominate and extract full data from an iOS device.

Please consider donation of any amount in Bitcoin or Ethereum:

  • Bitcoin donation: bc1qerzyzwdnsmpfdkl3lcjgm3rhvvy7svy0p89ndj
  • Ethereum donation: 0x098dADeDDf14382F19d4F5d989fD8734376B0224

Thank you in advance

Installation

pip3 install iOSbackup --user

On macOS, get native Python 3 from Apple with command xcode-select --install. Read my guide to install Apple official Python 3 distribution for more details.

iOSbackup requires other two packages: biplist and pycryptodome that will be installed automatically by pip.

pycryptodome has an API compatible with older pycrypto, which should also work with iOSbackup. But pycryptodome is more well maintained and easier to install on Windows and macOS.

Usage

Get list of backups available on your computer

>>> from iOSbackup import iOSbackup

>>> iOSbackup.getDeviceList()
[{'udid': '00456030-000E4412342802E',
  'name': 'mobileavi',
  'ios': '13.2.3',
  'serial': 'DNPPQRS0N4RW',
  'type': 'iPhone12,3',
  'encrypted': True},
{'udid': '00654030-01234412342802E',
  'name': 'ipad',
  'ios': '13.1.3',
  'serial': 'DABCRS0N4RW',
  'type': 'iPad10,1',
  'encrypted': True}]

Open a device backup

With your password (a slow and compute-intensive task):

>>> b=iOSbackup(
	udid="00456030-000E4412342802E",
	cleartextpassword="mypassword"
)

Instead of a clear text password, use a derived key that can be seen into the instantiated object:

>>> b=iOSbackup(
	udid="00456030-000E4412342802E",
	cleartextpassword="mypassword"
)
>>> print(b)
…
decryptionKey: dd6b6123494c5dbdff7804321fe43ffe1babcdb6074014afedc7cb47f351524
…

From now on use your derived key instead of your clear text password to not expose it and because it is much faster:

>>> b=iOSbackup(
	udid="00456030-000E4412342802E",
	derivedkey="dd6b6123494c5dbdff7804321fe43ffe1babcdb6074014afedc7cb47f351524"
)

Linux virtual machine accessing iOS backup on a macOS host

Forcing a backup folder, useful when reading backups on Linux, where there is no standard for backup folders:

>>> b=iOSbackup(
	udid="00456030-000E4412342802E",
	cleartextpassword="mypassword",
	backuproot='/media/sf_username/Library/Application Support/MobileSync/Backup'
)

For this to work on a Linux virtual machine accessing a VirtualBox-shared folder, you'll have to grant full disk access to your hypervisor (VirtualBox etc). On macOS, go to System PreferencesSecurity & PrivacyPrivacyFull Disk Access and enable access to your hypervisor (VirtualBox etc). The hypervisor and VM will have to be restarted for the new setting to be effective.

You can also copy your device's backup folder, from a Windows or macOS computer, to a Linux computer, and then use this class on Linux to decrypt and read it.

iTunes default backup folders on Windows and macOS

Files app (formerly iTunes) on macOS stores backups of associated devices under ~/Library/Application Support/MobileSync/Backup. iTunes on Windows stores backups of associated devices under %HOME%\Apple Computer\MobileSync\Backup

Get some info about device on the backup

Information about device, model, serial number, its SIMs, iOS version etc can be inspected in multiple places from backup basic catalog files (plist files), even before diving into its vast amount of databases and other encrypted files.

b=iOSbackup(...)

# Device info
infoKeys=[
	# This is a non-exaustive list of interesting info, but there are more...
	'Build Version', 'Device Name', 'Display Name', 'GUID', 'ICCID', 'ICCID 2',
	'IMEI', 'IMEI 2', 'Last Backup Date', 'MEID', 'Phone Number', 'Phone Number 2',
	'Product Name', 'Product Type', 'Product Version', 'Serial Number',
	'Target Identifier', 'Target Type', 'Unique Identifier',
	'macOS Build Version', 'macOS Version'
]
for i in infoKeys:
	print(f'{i}: {b.info[i]}')


# Other ways to get device info
b.manifest['Lockdown']['DeviceName'] # device name or hostname
b.manifest['Lockdown']['ProductVersion'] # iOS version as 14.0.1, see Version column of https://en.wikipedia.org/wiki/IOS_version_history#Version_history
b.manifest['Lockdown']['BuildVersion'] # iOS version as 18A393, see Build column of https://en.wikipedia.org/wiki/IOS_version_history#Version_history
b.manifest['Lockdown']['SerialNumber'] # device serial number
b.manifest['Lockdown']['ProductType'] # device type as iPhone12,3, see columns Identifier of https://www.theiphonewiki.com/wiki/Models
b.udid # UDID of the device
b.uuid.hex() # UUID of device

# Backup info
b.backupRoot # backup root folder
b.date # UTC date and time of this backup
b.getDecryptionKey() # password-derived key of backup
b.manifest['IsEncrypted'] # is it an encrypted backup?
b.manifest['WasPasscodeSet'] # backup has a passcode?
b.status


# Basic list of installed apps, probably used by iTunes to easily display things to users
b.info['Applications'].keys()

# Apps icons
png_data=b.info['Applications']['com.burbn.instagram']['PlaceholderIcon']

# Dive into device content
b.manifest['ManifestKey'].hex() # manifest DB decryption key
b.manifest['Applications'] # list of installed apps
b.manifestDB # decrypted copy of Manifest.db SQLite database

Get a list of backed-up files:

Info available in the Manifest.db which relates backup file hash to semi-full path of file into the device, plus file backup domain, plus some file metadata.

>>> b.getBackupFilesList()
[{'name': '',
  'backupFile': 'abfbc8747bfbb373e2b08ce67b1255ffda4e1b91',
  'domain': 'AppDomain-4GU63N96WE.com.p5sys.jumpdesktop',
  'relativePath': '',
  'flags': 2,
  'file': b'bplist00\xd4...'
  },
 {'name': 'Documents',
  'backupFile': 'ec0c1b379560bb5ccc81ee783538fd51cfd97461',
  'domain': 'AppDomain-4GU63N96WE.com.p5sys.jumpdesktop',
  'relativePath': 'Documents',
  'flags': 2,
  'file': b'bplist00\xd4...'
  },
 {'name': 'Documents/Servers',
  'backupFile': 'a735380eade71b48f0fe27d38a283aacd8ed8372',
  'domain': 'AppDomain-4GU63N96WE.com.p5sys.jumpdesktop'},
 {'name': 'Documents/extensions',
  'backupFile': 'c08f725cc39ec819ab7ced3b056f4e0630ead09f',
  'domain': 'AppDomain-4GU63N96WE.com.p5sys.jumpdesktop'},
 {'name': 'Library',
  'backupFile': 'e60a6345697594c735e5a6ed86c0d57dad6a2176',
  'domain': 'AppDomain-4GU63N96WE.com.p5sys.jumpdesktop'},
 ...]

backupFile is the file name on your computer. Basically SHA1([Domain]/[FilePath]).

name is the original semi-complete path of file name in the device.

domain is the file group this file is member, see bellow list of domains.

file is binary plist content with some file metadata.

Or put it directly into a Pandas DataFrame for easier manipulation and searching:

>>> import pandas as pd
>>> backupfiles=pd.DataFrame(b.getBackupFilesList(), columns=['backupFile','domain','name'])

With Pandas, display only list of files in HomeDomain group:

>>> backupfiles[backupfiles['domain']=='HomeDomain']

Get a decrypted copy of the call history SQLite database:

The getFileDecryptedCopy() method creates a decrypted copy of requested file on targetFolder/targetName. If targetFolder and targetName aren't given, a temporary file will be created. The name of decrypted file (temporary or not) can be found in the decryptedFilePath item of returned dict, as seen below.

>>> file=b.getFileDecryptedCopy(relativePath="Library/CallHistoryDB/CallHistory.storedata")
>>> file
{'decryptedFilePath': 'HomeDomain~Library--CallHistoryDB--CallHistory.storedata',
 'domain': 'HomeDomain',
 'originalFilePath': 'Library/CallHistoryDB/CallHistory.storedata',
 'backupFile': '5a4935c78a5255723f707230a451d79c540d2741',
 'size': 1228800}

Fetch call records from the decrypted copy of call history database, using a SQL query.

>>> calls = sqlite3.connect(file['decryptedFilePath'])
>>> calls.row_factory=sqlite3.Row
>>> calllog = calls.cursor().execute(f"SELECT * FROM ZCALLRECORD ORDER BY ZDATE DESC").fetchall()

Restore Entire Folder Containing Photos and their Metadata

This content is located in the Media folder of CameraRollDomain domain. This example will exclude videos from restoration.

>>> b.getFolderDecryptedCopy(
	'Media',
	targetFolder='restored-photos',
	includeDomains='CameraRollDomain',
	excludeFiles='%.MOV'
)

Restore an entire domain

Here we restore all files of WirelessDomain in a hierarchy starting at local directory:

>>> b.getFolderDecryptedCopy(
	includeDomains='WirelessDomain',
)

Here we restore all files of HomeDomain in a hierarchy starting at folder my-folder:

>>> b.getFolderDecryptedCopy(
	includeDomains='HomeDomain',
	targetFolder='my-folder',
)

To restore all backed up data files of an app, search for its domain name (see below) and use this technique.

Get List of All Installed Apps

>>> apps=list(b.manifest[

Related Skills

View on GitHub
GitHub Stars270
CategoryData
Updated4d ago
Forks41

Languages

Python

Security Score

85/100

Audited on Mar 25, 2026

No findings