dylex
A high-performance dyld shared cache extractor for macOS and iOS, written in Rust.
dylex extracts individual Mach-O binaries from Apple's dyld shared cache with full symbol table reconstruction, pointer rebasing, and proper LINKEDIT optimization. Extracted binaries are suitable for reverse engineering, analysis, and research.
Features
- Fast Extraction - Memory-mapped I/O and parallel processing for maximum speed
- Automatic Cache Discovery - Finds system caches automatically on macOS
- Architecture Selection - Support for arm64, arm64e, and x86_64 caches
- Symbol Table Reconstruction - Rebuilds standalone LINKEDIT with proper symbol tables
- Pointer Rebasing - Handles slide info v3/v5 for correct pointer values
- ObjC Metadata Fixing - Clears optimization flags for standalone operation
- Directory Structure Preservation - Optionally preserves full framework paths
- Batch Extraction - Extract multiple images with filters and parallel processing
Installation
From crates.io
From Source
Pre-built Binaries
Download pre-built binaries from the releases page.
Quick Start
# List available architectures in the system cache
# Show cache information
# List all images containing "UIKit"
# Extract a single library
# Extract all MapKit-related frameworks with preserved paths
Commands
dylex extract
Extract images from the dyld shared cache.
Usage: dylex extract [OPTIONS] [CACHE]
Arguments:
[CACHE] Path to the dyld shared cache (file or directory).
If not specified, searches default system locations.
Options:
-i, --image <IMAGE> Image to extract (e.g., "UIKit" or full path)
-f, --filter <FILTER> Filter images by substring match
-a, --arch <ARCH> Architecture (arm64e, arm64, x86_64)
-o, --output <OUTPUT> Output path (file or directory)
--preserve-paths <BOOL> Preserve directory structure [default: auto]
-v, --verbosity <LEVEL> Verbosity (0=quiet, 1=warn, 2=info, 3=debug)
-j, --jobs <N> Parallel jobs (default: CPU count)
-h, --help Print help
Examples
# Extract single image to specific file
# Extract by full path
# Extract all Foundation-related images
# Extract everything (warning: large!)
# Extract with verbose output
# Use custom cache path
dylex list
List images in the cache.
Usage: dylex list [OPTIONS] [CACHE]
Options:
-a, --arch <ARCH> Architecture to use
-f, --filter <FILTER> Filter images by name
-A, --addresses Show virtual addresses
-b, --basenames Show only basenames (not full paths)
-h, --help Print help
Examples
# List all images
# List with addresses
# Filter and show basenames
# Count images matching filter
|
dylex info
Display detailed cache information.
Usage: dylex info [OPTIONS] [CACHE]
Options:
-a, --arch <ARCH> Architecture to use
-h, --help Print help
Example Output
Dyld Shared Cache Information
==============================
Path: /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e
Architecture: arm64e
Images: 3554
Mappings: 22
Subcaches: 2
Total size: 5307.38 MB
Mappings:
[ 0] 0x0000000180000000 - 0x00000001e6660000 ( 1.6G) r-x
[ 1] 0x00000001e6660000 - 0x00000001e8874000 ( 34.1M) r-- [slide]
...
Subcaches:
[ 1] dyld_shared_cache_arm64e.01 (2543.53 MB)
[ 2] dyld_shared_cache_arm64e.02 (196.12 MB)
dylex arches
List available cache architectures.
Usage: dylex arches [PATH]
Arguments:
[PATH] Directory to search. If not specified, uses system default.
Example Output
Available architectures in /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld:
arm64e - dyld_shared_cache_arm64e
x86_64 - dyld_shared_cache_x86_64
dylex lookup
Find which image contains a specific address.
Usage: dylex lookup [OPTIONS] <ADDRESS> [CACHE]
Arguments:
<ADDRESS> Address to lookup (hex, e.g., 0x180000000)
Options:
-a, --arch <ARCH> Architecture to use
-h, --help Print help
Default Cache Locations
When no cache path is specified, dylex searches these locations in order:
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld(macOS Ventura+)/System/Library/dyld(older macOS)/var/db/dyld
Architecture Selection
The --arch flag uses substring matching:
| Flag | Matches |
|---|---|
-a arm64e |
arm64e only |
-a arm64 |
arm64 and arm64e |
-a x86 |
x86_64 and x86_64h |
If multiple architectures match, you'll be prompted to be more specific.
Output Structure
Single Image Extraction
By default, single images are extracted to the current directory with their basename:
# Creates: ./libobjc.A.dylib
Batch Extraction with Filter
When using -f/--filter, directory structure is preserved by default:
# Creates:
# ./extracted/System/Library/Frameworks/MapKit.framework/Versions/A/MapKit
# ./extracted/System/Library/Frameworks/_MapKit_SwiftUI.framework/Versions/A/_MapKit_SwiftUI
# ./extracted/usr/lib/swift/libswiftMapKit.dylib
# ...
Use --preserve-paths false to flatten:
# Creates:
# ./flat/MapKit
# ./flat/_MapKit_SwiftUI
# ./flat/libswiftMapKit.dylib
What dylex Does
When extracting an image, dylex performs these operations:
- Copies Segment Data - Extracts __TEXT, __DATA, __LINKEDIT, etc.
- Rebases Pointers - Applies slide info to fix pointer values
- Rebuilds LINKEDIT - Creates standalone symbol table, string table, and other metadata (replaces ~600MB shared LINKEDIT)
- Fixes ObjC Metadata - Clears
OBJC_IMAGE_OPTIMIZED_BY_DYLDflag - Updates Load Commands - Adjusts offsets for standalone operation
- Optimizes File Layout - Removes unnecessary padding
Library Usage
dylex can be used as a library:
use ;
Performance
dylex is designed for speed:
- Memory-mapped I/O - No unnecessary copying
- Parallel extraction - Uses all CPU cores for batch operations
- Efficient data structures - FxHashMap for fast lookups
- LTO-optimized release builds - Maximum binary performance
Typical extraction times on Apple M1:
- Single library: ~0.3s
- 100 libraries: ~5s
- Full cache (~3500 images): ~3-5 minutes
Limitations
- macOS/iOS only - dyld caches are Apple-specific
- Read-only - Cannot modify or repack caches
- No code signing - Extracted binaries need re-signing for execution
- Stub fixing - Some inter-library stubs may not be fully resolved
Comparison with Other Tools
| Feature | dylex | dsc_extractor | DyldExtractor |
|---|---|---|---|
| Language | Rust | C++ | Python |
| Speed | Fast | Medium | Slow |
| LINKEDIT rebuild | Yes | Partial | Yes |
| Slide info v5 | Yes | Yes | Yes |
| Parallel extraction | Yes | No | No |
| Library API | Yes | No | Yes |
Troubleshooting
"No dyld shared caches found"
The default cache locations may not exist on your system. Specify the path explicitly:
"Multiple caches match"
Be more specific with the architecture:
# Instead of -a arm64 (matches arm64 and arm64e)
Extracted binary won't run
Extracted binaries are not code-signed. For research/analysis only:
# Re-sign for local execution (macOS)
Large extracted file sizes
Some libraries (like libobjc) include large shared ObjC metadata segments. This is expected behavior.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
Acknowledgments
- Inspired by DyldExtractor
- Apple's dyld source code for format documentation
- The reverse engineering community