How to Mount and Analyze APFS, HFS+, and DMG Images with ipsw

Use ipsw mount to treat Apple disk images as regular filesystems, leveraging utils.MountDMG to auto-detect APFS vs HFS+ and mount via apfs-fuse or native kernel drivers.

The blacktop/ipsw toolkit provides native Go utilities to mount and inspect Apple filesystems without manual conversion. Whether you are analyzing a raw DMG from an IPSW firmware package or a standalone APFS container, ipsw abstracts the underlying complexity through a unified mounting interface.

Detecting Disk Image Types Automatically

Before mounting, ipsw identifies the filesystem type by inspecting magic numbers in the image header. The detection logic resides in internal/magic/magic.go and distinguishes between modern APFS containers and legacy HFS+ volumes.

  • APFS detection: magic.IsAPFS at internal/magic/magic.go#L253 checks for the APFS container magic (NXSB).
  • HFS+ detection: magic.IsHFSPlus at internal/magic/magic.go#L272 validates the HFS+ signature (H+ or HX).

These helpers return boolean flags that the mounting dispatcher uses to select the appropriate driver.

Mounting APFS, HFS+, and DMG Images

The central entry point for all disk image operations is utils.MountDMG in internal/utils/macos.go#L651. This function acts as a dispatcher that automatically routes APFS images to FUSE-based handlers and HFS+ images to native kernel drivers.

APFS Mounting with apfs-fuse

For APFS containers, ipsw invokes mountWithAPFSFuse at internal/utils/macos.go#L564. This requires the user-installed apfs-fuse binary to be available in $PATH. The function handles container unlocking (if encrypted) and volume selection before exposing the filesystem at a temporary mount point.

HFS+ Mounting with Native Drivers

For HFS+ volumes, mountWithHFSPlus at internal/utils/macos.go#L578 leverages the native Linux HFS+ kernel driver. On macOS hosts, this falls back to hdiutil attach for seamless integration with the host operating system.

Mount Point Management

utils.MountDMG returns three values: the mount point path, a boolean indicating if the image was already mounted (idempotent operation), and an error. This allows downstream tools to safely unmount resources when analysis completes.

CLI Commands for Image Analysis

The ipsw CLI exposes mounting functionality through several specialized commands that target specific DMG types within IPSW firmware packages.

Mounting Specific Firmware Partitions

The ipsw mount command (defined in cmd/ipsw/cmd/mount.go) supports multiple DMG types:


# Mount the Filesystem DMG (user data partition)

ipsw mount fs iPhone15,2_16.5_20F66_Restore.ipsw

# Mount the SystemOS DMG with custom mount point and detach

ipsw mount sys iPhone.ipsw --mount-point /mnt/ios-system --detach

# Mount the App DMG (pre-installed apps)

ipsw mount app iPhone.ipsw

Available types include fs (Filesystem), sys (SystemOS), app (Applications), exc (Exclave), and rdisk (Restore ramdisk).

Extracting Binaries from Mounted Images

The ipsw extract command automatically mounts DMGs to extract specific artifacts:


# Extract dyld_shared_cache from SystemOS DMG

ipsw extract iPhone.ipsw --arch arm64

Internally, this calls utils.MountDMG then walks the mount point to locate cache files (internal/search/search.go).

Diffing System Versions

The ipsw sb diff command mounts two SystemOS DMGs to compare dyld_shared_cache contents:

ipsw sb diff old.ipsw new.ipsw

This leverages pkg/dyld/extract.go to mount both images simultaneously before performing the differential analysis.

Inspecting Wallpapers

The ipsw wp command mounts the Filesystem DMG to extract wallpaper assets:

ipsw wp iPhone.ipsw --output ./wallpapers

Programmatic Usage in Go

You can integrate disk image mounting directly into Go applications using the internal/utils package.

Complete Mounting Workflow

package main

import (
    "fmt"
    "log"
    "os"
    "path/filepath"
    "strings"

    "github.com/blacktop/ipsw/internal/utils"
)

func analyzeDMG(dmgPath string) error {
    // Mount the image (auto-detects APFS vs HFS+)
    mountPoint, alreadyMounted, err := utils.MountDMG(dmgPath, "")
    if err != nil {
        return fmt.Errorf("mount failed: %w", err)
    }
    
    status := "newly mounted"
    if alreadyMounted {
        status = "already mounted"
    }
    fmt.Printf("Image %s at %s\n", status, mountPoint)

    // Walk the filesystem to find dynamic libraries
    err = utils.Walk(mountPoint, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if strings.HasSuffix(path, ".dylib") {
            relPath := strings.TrimPrefix(path, mountPoint)
            fmt.Println("Found:", relPath)
        }
        return nil
    })
    if err != nil {
        return fmt.Errorf("filesystem walk failed: %w", err)
    }

    // Cleanup: unmount when done
    if err := utils.Unmount(mountPoint, true); err != nil {
        return fmt.Errorf("unmount failed: %w", err)
    }
    
    return nil
}

func main() {
    if err := analyzeDMG("System.dmg"); err != nil {
        log.Fatal(err)
    }
}

Type Detection Helpers

For applications that need to inspect images before mounting, use the magic number detectors:

import "github.com/blacktop/ipsw/internal/magic"

// Check if file is APFS
if isAPFS, _ := magic.IsAPFS(imagePath); isAPFS {
    fmt.Println("APFS container detected")
}

// Check if file is HFS+
if isHFS, _ := magic.IsHFSPlus(imagePath); isHFS {
    fmt.Println("HFS+ volume detected")
}

Key Source Files and Architecture

Understanding the codebase structure helps when extending ipsw or debugging mount issues.

Path Function
internal/utils/macos.go#L651 MountDMG – Central dispatcher that routes to APFS or HFS+ handlers
internal/magic/magic.go#L253 IsAPFS – Magic number detection for APFS containers
internal/magic/magic.go#L272 IsHFSPlus – Magic number detection for HFS+ volumes
internal/utils/macos.go#L564 mountWithAPFSFuse – APFS mounting via apfs-fuse binary
internal/utils/macos.go#L578 mountWithHFSPlus – HFS+ mounting via native kernel driver
cmd/ipsw/cmd/mount.go CLI implementation for ipsw mount subcommands
pkg/dyld/extract.go dyld_shared_cache extraction from mounted SystemOS DMGs
internal/search/search.go DMG scanning and filesystem walking utilities
internal/diff/diff.go SystemOS DMG comparison logic
api/server/routes/ipsw/ipsw.go HTTP API endpoints for remote DMG mounting

Summary

  • Automatic detection: ipsw identifies APFS vs HFS+ via magic numbers in internal/magic/magic.go before attempting to mount.
  • Flexible mounting: The utils.MountDMG dispatcher at internal/utils/macos.go#L651 routes APFS images to apfs-fuse and HFS+ images to native kernel drivers.
  • CLI integration: Commands like ipsw mount, ipsw extract, and ipsw sb diff abstract the mounting lifecycle, automatically cleaning up resources after analysis.
  • Programmatic access: Go developers can import github.com/blacktop/ipsw/internal/utils to mount images, walk filesystems, and extract specific file types with full control over mount points and cleanup.

Frequently Asked Questions

What dependencies are required to mount APFS images with ipsw?

Mounting APFS containers requires the apfs-fuse binary to be installed and available in your system $PATH. ipsw does not bundle this dependency; it shells out to the external binary at internal/utils/macos.go#L564. HFS+ images do not require external tools on Linux systems with the native HFS+ kernel driver loaded.

Can ipsw mount encrypted DMG files?

Yes, ipsw supports mounting encrypted DMG files when the necessary keys are available. The mountWithAPFSFuse function handles container unlocking before mounting. For IPSW firmware packages, ipsw can automatically extract keys from the manifest for certain DMG types, though manual key provision may be required for custom encrypted images.

How does ipsw handle already-mounted images?

The utils.MountDMG function returns a boolean flag indicating whether the image was already mounted at the requested path. If already mounted, ipsw skips the mount operation and proceeds with analysis, preventing duplicate mount entries. During cleanup, the unmount logic checks this state to avoid unmounting images that were mounted by other processes before ipsw ran.

Is it possible to mount DMG images via the ipsw HTTP API?

Yes, the web server implementation in api/server/routes/ipsw/ipsw.go exposes HTTP endpoints that trigger DMG mounting operations remotely. This allows automated analysis pipelines to mount firmware images on a server instance, extract specific files via the API, and unmount resources programmatically without direct shell access to the host system.

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 →