How to Use the ipsw diff Command to Compare Firmware Versions Effectively

The ipsw diff command generates detailed byte-level comparisons between two IPSW files by mounting their SystemOS DMGs and running Git-style diffs on Mach-O binaries using the --fw flag.

The ipsw diff command in the blacktop/ipsw toolkit is the definitive way to analyze changes between iOS, iPadOS, or macOS firmware versions. Whether you are a security researcher tracking kernel patches or a developer auditing framework changes, this command provides granular visibility into firmware modifications by analyzing the actual Mach-O binaries extracted from IPSW archives.

How the ipsw diff Command Works

The command operates through a three-stage pipeline defined in internal/diff/diff.go. Understanding this flow helps you interpret the output and optimize performance for large firmware files.

Metadata Extraction

First, the command parses each IPSW's BuildManifest to extract version strings, build numbers, and board configurations. This logic resides in the (*Diff).getInfo method (lines 30-33 of internal/diff/diff.go), which populates the diff context before any binary analysis begins.

SystemOS DMG Mounting

Next, the command extracts and mounts the SystemOS DMG from each IPSW. If the DMG is AEA-encrypted, it is decrypted automatically. The mounting logic is handled by mountDMG and mountSystemOsDMGs (lines 25-38 of internal/diff/diff.go), which prepare the filesystem for analysis.

Firmware Parsing and Comparison

Finally, the command invokes component-specific differs. For firmware analysis, parseFirmwares (lines 11112-11124 of internal/diff/diff.go) calls mcmd.DiffFirmwares from pkg/macho/diff.go. This performs a Git-style diff on every Mach-O binary—including the kernel, kexts, and dyld shared caches—highlighting exact byte-level changes in sections you specify.

Essential Flags for Firmware Comparison

The command-line interface, defined in cmd/ipsw/cmd/diff.go (lines 35-50), provides several flags to control the firmware comparison behavior:

  • --fw – Enables firmware diffing mode, which analyzes kernelcaches, kexts, and dyld shared caches.
  • --allow-list – Restricts analysis to specific Mach-O sections (e.g., __TEXT.__text) to reduce noise.
  • --block-list – Excludes specific sections from the diff (e.g., __TEXT.__info_plist).
  • --markdown, --json, --html – Specifies the output format; Markdown is recommended for human-readable reports.
  • --output (-o) – Sets the destination directory for generated reports.
  • --low-memory – Forces the diff engine to use temporary files instead of RAM, essential for comparing large IPSWs on resource-constrained systems.

Step-by-Step Workflow for Comparing Firmware Versions

Follow this workflow to generate actionable intelligence from firmware updates:

  1. Acquire the IPSW files for both versions you want to compare (e.g., iPhone14,2_15.6_20G5023e_Restore.ipsw and iPhone14,2_15.7_20H19_Restore.ipsw).

  2. Run the basic firmware diff with Markdown output:

    ipsw diff iPhone14,2_15.6_20G5023e_Restore.ipsw \
              iPhone14,2_15.7_20H19_Restore.ipsw \
              --fw --markdown -o ./fw-diff

    This mounts the SystemOS DMGs from both IPSWs and produces a Git-style diff of all Mach-O binaries in ./fw-diff/.

  3. Filter for specific sections to focus on executable code changes only:

    ipsw diff old.ipsw new.ipsw --fw \
        --allow-list __TEXT.__text \
        --markdown -o ./kernel-text-diff
  4. Handle large firmware files on systems with limited RAM:

    ipsw diff old.ipsw new.ipsw --fw --low-memory --markdown -o ./lowmem-report
  5. Inspect the generated Markdown report. The output uses standard +/- markers to highlight added or removed symbols, modified function prologues, and altered section contents across the kernel and kexts.

Summary

  • The ipsw diff command provides byte-level firmware comparison by analyzing Mach-O binaries extracted from IPSW SystemOS DMGs.
  • The process involves three stages: metadata extraction ((*Diff).getInfo), DMG mounting (mountSystemOsDMGs), and component parsing (parseFirmwares using mcmd.DiffFirmwares).
  • Use the --fw flag to enable firmware mode, and filter output with --allow-list or --block-list to focus on specific Mach-O sections.
  • Generate human-readable reports with --markdown, --json, or --html, and use --low-memory for large IPSWs on constrained hardware.

Frequently Asked Questions

What file formats does ipsw diff support for output?

The command supports four output formats: binary (default .idiff file using gob encoding for programmatic reuse), Markdown (--markdown), JSON (--json), and HTML (--html). Markdown is recommended for security research reports because it renders Git-style diffs with + and - markers in any text editor or GitHub/GitLab interface.

How does ipsw diff handle encrypted or AEA-formatted DMGs?

The ipsw diff command automatically detects and decrypts AEA-encrypted DMGs during the mounting phase. The logic in mountDMG and mountSystemOsDMGs (defined in internal/diff/diff.go) extracts the SystemOS DMG from each IPSW, decrypts it if necessary, and mounts it to a temporary location before the Mach-O diff engine begins analysis.

Can I compare specific Mach-O sections instead of entire binaries?

Yes. Use the --allow-list flag to restrict the diff to specific sections (e.g., --allow-list __TEXT.__text to compare only executable code), or use --block-list to exclude noisy sections like __TEXT.__info_plist. These filters are passed to mcmd.DiffFirmwares in pkg/macho/diff.go, which performs the section-level comparison on the extracted firmware binaries.

What should I do if the diff fails due to memory constraints?

For large IPSW files (such as modern iOS restore images exceeding 8 GB), add the --low-memory flag. This forces the diff engine in internal/diff/diff.go to use temporary files on disk instead of loading entire Mach-O binaries into RAM. While this increases runtime slightly, it prevents out-of-memory errors on systems with limited physical RAM or when comparing multiple large firmware versions simultaneously.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →