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

> Mount and analyze APFS, HFS+, and DMG images easily with ipsw. Use ipsw mount to treat disk images as filesystems and discover disk formats automatically.

- Repository: [blacktop/ipsw](https://github.com/blacktop/ipsw)
- Tags: how-to-guide
- Published: 2026-02-26

---

**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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/cmd/ipsw/cmd/mount.go)) supports multiple DMG types:

```bash

# 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:

```bash

# 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`](https://github.com/blacktop/ipsw/blob/main/internal/search/search.go)).

### Diffing System Versions

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

```bash
ipsw sb diff old.ipsw new.ipsw

```

This leverages [`pkg/dyld/extract.go`](https://github.com/blacktop/ipsw/blob/main/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:

```bash
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

```go
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:

```go
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`](https://github.com/blacktop/ipsw/blob/main/cmd/ipsw/cmd/mount.go) | CLI implementation for `ipsw mount` subcommands |
| [`pkg/dyld/extract.go`](https://github.com/blacktop/ipsw/blob/main/pkg/dyld/extract.go) | dyld_shared_cache extraction from mounted SystemOS DMGs |
| [`internal/search/search.go`](https://github.com/blacktop/ipsw/blob/main/internal/search/search.go) | DMG scanning and filesystem walking utilities |
| [`internal/diff/diff.go`](https://github.com/blacktop/ipsw/blob/main/internal/diff/diff.go) | SystemOS DMG comparison logic |
| [`api/server/routes/ipsw/ipsw.go`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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.