How to Extract, Analyze, and Patch OTA Updates with ipsw
ipsw treats OTA updates as ZIP containers containing a post.bom manifest and encrypted payloads, providing CLI commands and Go libraries to download, inspect, extract files, and apply RSR patches using raw image diffing.
The blacktop/ipsw repository provides a comprehensive toolkit for working with Apple firmware files. Whether you need to extract, analyze, and patch OTA updates with ipsw, the tool offers both command-line interfaces and Go libraries to handle encrypted payloads, cryptex volumes, and Rapid Security Response patches.
Understanding the OTA Update Structure
Apple OTA updates are ZIP archives containing a post.bom manifest, encrypted payload files (often AEA-encrypted IMG4), and optionally cryptex volumes for Rapid Security Response patches. The ipsw tool models this structure in pkg/ota/ota.go, where the OTA type provides methods to access the ZIP contents, decrypt payloads, and parse the BOM manifest.
Downloading and Decrypting OTA Updates
The ipsw download ota command retrieves OTA files from Apple's servers. When dealing with encrypted updates, ipsw handles AEA (Apple Encrypted Archive) decryption automatically.
Handling AEA Encryption
In pkg/ota/ota.go, the Open() function creates an *ota.OTA object and calls ResolveAEAKeyFromFlags to obtain decryption keys from Apple's servers or a local ota_fcs_keys.json database. This lazy-loading approach ensures the ZIP structure is parsed before attempting decryption of the payload.
Analyzing OTA Metadata
To inspect update metadata without extracting files, use ipsw ota info. This command leverages the ota.Info() method in pkg/ota/ota.go to parse the embedded Info.plist and post.bom manifest, returning version, build numbers, supported devices, and signed components.
Extracting Files from OTA Updates
The extraction pipeline supports individual files, pattern matching, and cryptex volume handling.
Listing and Extracting Individual Files
The Files() method in pkg/ota/ota.go returns a filtered slice of zip.File entries based on the post.bom manifest. To extract a specific file, open it via o.Open(name, decompress) and copy the bytes to your destination.
Working with Cryptex Volumes
For Rapid Security Response updates, ipsw handles cryptex volumes containing cryptex-app and cryptex-system-* DMGs. The ExtractFromCryptexes method in pkg/ota/ota.go walks these volumes and extracts files matching a regex pattern. Low-level cryptex unpacking logic resides in pkg/ota/aa.go.
Pattern-Based Extraction
The RemoteExtract function (approximately lines 115-140 in pkg/ota/ota.go) enables regex-based extraction across the entire payload. This function iterates over payload files, runs Parse() (which uses Apple's aa binary when available, otherwise a Go implementation), and writes matches to the destination folder.
Patching OTA Updates with RSR (Rapid Security Response)
Rapid Security Response updates patch existing OTA files without requiring full system reinstalls. The ipsw ota patch rsr command applies these differential updates to AppOS and SystemOS cryptexes.
Understanding the RSR Patching Process
RSR patches use raw image diffing to modify existing DMG files. The process extracts the original cryptex-app and cryptex-system-* DMGs from the base OTA, applies binary diffs from the RSR update using ridiff.RawImagePatch, and writes the patched DMGs back to disk.
Applying Patches with ipsw ota patch rsr
The command implementation in cmd/ipsw/cmd/ota/ota_patch_rsr.go orchestrates the workflow. It calls ridiff.RawImagePatch (located in pkg/ota/ridiff) to perform the actual binary patching, handling both the AppOS and SystemOS cryptexes in a single operation.
Programmatic Usage with Go
The ipsw library exposes the OTA pipeline as a Go API for integration into custom tools.
Listing OTA Files
package main
import (
"fmt"
"log"
"github.com/blacktop/ipsw/pkg/ota"
)
func main() {
// Open (auto-decrypt if needed)
o, err := ota.Open("myOTA.zip", nil)
if err != nil {
log.Fatal(err)
}
// Print all entries
for _, f := range o.Files() {
if f.IsDir() {
continue
}
fmt.Println(f.Name())
}
}
The Files() method in pkg/ota/ota.go returns the filtered zip.File slice based on the post.bom manifest.
Extracting dyld_shared_cache Files
package main
import (
"log"
"path/filepath"
"github.com/blacktop/ipsw/pkg/ota"
)
func main() {
o, _ := ota.Open("myOTA.zip", nil)
info, _ := o.Info()
output := filepath.Join(".", info.GetFolder())
_ = o.ExtractFromCryptexes(`dyld_shared_cache.*`, output) // uses RIDIFF10 cryptexes
}
ExtractFromCryptexes walks cryptex volumes and extracts files matching the provided regex.
Patching RSR Updates Programmatically
package main
import (
"log"
"path/filepath"
"github.com/blacktop/ipsw/pkg/ota"
"github.com/blacktop/ipsw/pkg/ota/ridiff"
)
func main() {
basePath := "BaseOTA.zip"
rsrPath := "RSR_OTA.zip"
// Parse base OTA to locate the DMGs
baseInfo, _ := ota.ParseInfo(basePath)
appDMG, _ := baseInfo.GetAppOsDmg()
sysDMG, _ := baseInfo.GetSystemOsDmg()
// Patch app cryptex
if err := ridiff.RawImagePatch(appDMG, rsrPath, appDMG+"_patched.dmg", 0); err != nil {
log.Fatal(err)
}
// Patch system cryptex (optionally filter architectures)
if err := ridiff.RawImagePatch(sysDMG, rsrPath, sysDMG+"_patched.dmg", 0); err != nil {
log.Fatal(err)
}
}
This mirrors the CLI workflow in cmd/ipsw/cmd/ota/ota_patch_rsr.go, using ridiff.RawImagePatch to apply binary diffs.
Summary
- ipsw models OTA updates as ZIP archives containing
post.bommanifests and encrypted payloads, handling AEA decryption automatically viapkg/ota/ota.go. - The download phase retrieves updates and resolves decryption keys using
ResolveAEAKeyFromFlags, supporting both remote Apple key servers and localota_fcs_keys.jsondatabases. - Analysis commands like
ipsw ota infoleverage theInfo()method to parse metadata without extraction, reading embedded plists and BOM manifests. - Extraction supports individual files, regex patterns via
RemoteExtract, and cryptex volumes throughExtractFromCryptexes, with low-level handling inpkg/ota/aa.go. - RSR patching applies differential updates to AppOS and SystemOS cryptexes using
ridiff.RawImagePatchinpkg/ota/ridiff, enabling rapid security fixes without full OS reinstalls.
Frequently Asked Questions
How does ipsw handle AEA encryption for OTA files?
ipsw automatically detects AEA encryption headers when opening OTA files via ota.Open(). The tool calls ResolveAEAKeyFromFlags to fetch decryption keys from Apple's servers or a local ota_fcs_keys.json database, then transparently decrypts the payload during extraction operations.
What is the difference between regular OTA extraction and cryptex extraction?
Regular OTA extraction pulls files directly from the main payload ZIP using the post.bom manifest. Cryptex extraction specifically handles Rapid Security Response volumes containing cryptex-app and cryptex-system-* DMGs. The ExtractFromCryptexes method in pkg/ota/ota.go walks these specialized volumes to extract patched system files.
Can I patch an existing OTA with a newer RSR update using the Go library?
Yes, the pkg/ota/ridiff package exposes RawImagePatch for programmatic RSR patching. You parse the base OTA to locate AppOS and SystemOS DMGs, then apply the RSR diff using ridiff.RawImagePatch(baseDMG, rsrOTA, outputPath, flags). This mirrors the ipsw ota patch rsr CLI command implemented in cmd/ipsw/cmd/ota/ota_patch_rsr.go.
Where does ipsw store decryption keys for OTA files?
ipsw checks for AEA decryption keys in a local JSON database named ota_fcs_keys.json before querying Apple's remote key servers. The ResolveAEAKeyFromFlags function in pkg/ota/ota.go handles this resolution logic, caching keys locally to avoid repeated network requests for the same firmware files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →