Repository navigation
Description
Background
Mach-O binaries (macOS/iOS executables and libraries) embed critical runtime metadata in load commands within the binary header. These commands specify:
- Dynamically linked libraries and frameworks
- Runtime search paths (@rpath, @executable_path, @loader_path)
- Library installation names and version requirements
- Platform minimum version information
Currently, StringyMcStringFace's standard string extraction only scans data sections, missing these header-resident strings that are essential for understanding binary dependencies and runtime behavior.
Problem Statement
Security analysts and reverse engineers need to:
- Map dependency chains: Identify all dynamically loaded libraries and frameworks
- Resolve runtime paths: Understand @rpath resolution order for detecting hijacking opportunities
- Version analysis: Extract minimum platform versions and compatibility constraints
- Installation verification: Compare expected vs actual library locations
Without load command parsing, these critical artifacts remain hidden from analysis workflows.
Proposed Solution
Architecture Changes
Extend src/container/macho.rs to implement a dedicated load command parser that runs before section-level extraction.
Target Load Commands
| Command | Purpose | Example Output |
|---|---|---|
LC_LOAD_DYLIB |
Required dynamic libraries | /usr/lib/libSystem.B.dylib |
LC_LOAD_WEAK_DYLIB |
Optional dynamic libraries | /System/Library/Frameworks/Metal.framework/Metal |
LC_REEXPORT_DYLIB |
Re-exported libraries | @rpath/MyFramework.framework/MyFramework |
LC_ID_DYLIB |
Library installation name | /usr/local/lib/libcustom.1.dylib |
LC_RPATH |
Runtime search paths | @executable_path/../Frameworks |
LC_VERSION_MIN_MACOSX |
Platform version | 10.15.0 |
LC_BUILD_VERSION |
Build version info | Platform + SDK version |
Implementation Steps
- Parse Load Commands - Extend
src/container/macho.rsto iterate through load commands usinggoblin::mach::load_commandAPIs - Extract String Data - Pull path strings from dylib and rpath structures
- Add Extraction Hook - Call load command extraction before
extract_from_sections() - Tag Classification - Apply tags:
macho-lc,filepath,framework,rpath,version - Relevance Scoring - Base score 85-90, boost @rpath paths by +5, frameworks +3
Example Output
String: "/System/Library/Frameworks/Foundation.framework/Foundation"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1a8)
Score: 90
Tags: [macho-lc, filepath, framework]
String: "@rpath/CustomFramework.framework/CustomFramework"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1f0)
Score: 95
Tags: [macho-lc, filepath, framework, rpath]
String: "@executable_path/../Frameworks"
Source: MachOLoadCommand(LC_RPATH, offset=0x238)
Score: 95
Tags: [macho-lc, rpath]
Implementation Considerations
Path Variable Preservation
- DO NOT resolve or expand path variables
- Preserve
@executable_path,@loader_path,@rpathverbatim - These are runtime-resolved and their literal form is analytically valuable
Multi-Architecture Binaries
- Universal binaries contain multiple Mach-O images
- Extract load commands from each architecture slice independently
- Tag with architecture context (arm64, x86_64, etc.)
Error Handling
- Gracefully handle malformed load commands (corrupted binaries, packers)
- Validate command size fields before string extraction
- Continue extraction on individual command failures
CLI Integration
Add optional filtering: --macho-load-commands flag to show only load command strings
Testing Strategy
Test Cases Required
- Basic Dylib Loading - Test binary with standard system library dependencies
- Framework Dependencies - Binary using Cocoa/UIKit frameworks
- @rpath Usage - Binary with embedded framework using @rpath
- Universal Binary - Fat binary with arm64 + x86_64 slices
- Malformed Commands - Truncated structures, invalid sizes, non-UTF8 data
Test Binaries
Use real-world samples from:
- macOS system binaries (
/bin/ls,/usr/bin/ssh) - iOS apps (
.ipaextraction) - Custom test binaries with controlled dependencies
Success Criteria
- All standard load command types parsed
- String extraction working for dylib/rpath commands
- Path variables preserved correctly
- Universal binary support (multiple architectures)
- Appropriate tags and scoring applied
- CLI filter option implemented
- Test coverage >80% for new code
- Documentation updated with examples
References
- Mach-O File Format Reference
- goblin crate documentation
- dyld source code - @rpath resolution semantics
- Dynamic Library Programming Topics
Related Work
This complements existing PE import parsing (if implemented) and provides Mach-O parity with other binary format analyzers.
Activity
traycerai commentedon Nov 10, 2025
Plan
Observations
The codebase uses goblin for parsing Mach-O in
src/container/macho.rs, extracting sections, imports, and exports intoContainerInfofromsrc/types.rs.StringSourcealready includesLoadCommand, butTagneeds Mach-O specifics.ContainerInforequires a newload_command_stringsfield. ELF and PE parsers insrc/container/must initialize it empty. CLI insrc/main.rsis basic; add flag. Integration tests intests/integration_macho.rsusetest_binary_machofixture. Docs indocs/src/cover formats and architecture.Approach
Extend
MachoParserto parse load commands via goblin, extracting strings from dylibs, rpaths, versions intoFoundStrings with tags likeMachOLoadCommand,RPath,Framework, scores 85-95. Preserve @variables. UpdateContainerInfowithload_command_strings. Initialize empty in ELF/PE. Add CLI--macho-load-commandsflag for filtering. Implement tests for extraction accuracy using fixtures. Update docs with examples, supported commands, and integration details.Reasoning
I listed project directories to map structure, focusing on src/container and tests. I read
macho.rsto analyze current parsing flow for sections/imports. I examinedtypes.rsfor enums and structs to plan extensions. I reviewedelf.rsandpe.rsfor consistency. I checkedmain.rsfor CLI integration. I inspected test fixtures and integration tests for validation strategy. I browsed docs for update points.Proposed File Changes
📄 src/types.rs (MODIFY) 🔗
📄 src/container/macho.rs (MODIFY) 🔗
📄 src/container/elf.rs (MODIFY) 🔗
📄 src/container/pe.rs (MODIFY) 🔗
📄 src/main.rs (MODIFY) 🔗
📄 tests/integration_macho.rs (MODIFY) 🔗
📄 docs/src/architecture.md (MODIFY) 🔗
📄 docs/src/binary-formats.md (MODIFY) 🔗
Import In IDE
🤖 Prompt for AI Agents
Developer Humor
Execution Information
Branch: main
Commit: 37cfc7c
💡 Tips
Supported Commands (Inside Comments)
@traycerai generateto iterate on the previous version of the implementation plan.Supported Commands (Inside Description)
@traycerai ignoreanywhere in the ticket description to prevent this ticket from being processed.@traycerai branch:<branch-name>anywhere in the ticket description to specify the target branch for the implementation plan.Community
unclesp1d3r commentedon Nov 10, 2025
@coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.
unclesp1d3r commentedon Nov 10, 2025
@coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.
[-]Mach-O Load Command String Extraction[/-][+]Extract strings from Mach-O load commands (LC_RPATH, LC_LOAD_DYLIB, etc.)[/+]coderabbitai commentedon Nov 10, 2025
Tip
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
🏁 Script executed:
Length of output: 1717
🏁 Script executed:
Length of output: 2323
🏁 Script executed:
Length of output: 289
@unclesp1d3r I've successfully enhanced issue #63 with comprehensive context and metadata. Here's what was updated:
Title Enhancement
Changed to: "Extract strings from Mach-O load commands (LC_RPATH, LC_LOAD_DYLIB, etc.)"
Body Enhancements
Added sections:
Metadata Updates
enhancement,area:analyzer,lang:rust,needs:tests,priority:mediumThe issue is now ready for implementation with clear objectives, detailed technical guidance, and proper tracking metadata. You can view it here: #63
traycerai commentedon Nov 10, 2025
I have updated the Implementation Plan to reflect the recent changes in the ticket.
[-]Extract strings from Mach-O load commands (LC_RPATH, LC_LOAD_DYLIB, etc.)[/-][+]Parse Mach-O Load Commands for Dynamic Library and Framework Path Extraction[/+]coderabbitai commentedon Nov 10, 2025
Tip
For best results, initiate chat on the files or code changes.
🧩 Analysis chain
🏁 Script executed:
Length of output: 1734
🏁 Script executed:
Length of output: 2053
String: "/System/Library/Frameworks/Foundation.framework/Foundation"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1a8)
Score: 90
Tags: [macho-lc, filepath, framework]
Context: Load command dependency
String: "@rpath/CustomFramework.framework/CustomFramework"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1f0)
Score: 95
Tags: [macho-lc, filepath, framework, rpath]
Context: Runtime path dependency
String: "@executable_path/../Frameworks"
Source: MachOLoadCommand(LC_RPATH, offset=0x238)
Score: 95
Tags: [macho-lc, rpath]
Context: Runtime search path
🏁 Script executed:
Length of output: 92
String: "/System/Library/Frameworks/Foundation.framework/Foundation"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1a8)
Score: 90
Tags: [macho-lc, filepath, framework]
Context: Load command dependency
String: "@rpath/CustomFramework.framework/CustomFramework"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1f0)
Score: 95
Tags: [macho-lc, filepath, framework, rpath]
Context: Runtime path dependency
String: "@executable_path/../Frameworks"
Source: MachOLoadCommand(LC_RPATH, offset=0x238)
Score: 95
Tags: [macho-lc, rpath]
Context: Runtime search path
🏁 Script executed:
Length of output: 254
String: "/System/Library/Frameworks/Foundation.framework/Foundation"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1a8)
Score: 90
Tags: [macho-lc, filepath, framework]
String: "@rpath/CustomFramework.framework/CustomFramework"
Source: MachOLoadCommand(LC_LOAD_DYLIB, offset=0x1f0)
Score: 95
Tags: [macho-lc, filepath, framework, rpath]
String: "@executable_path/../Frameworks"
Source: MachOLoadCommand(LC_RPATH, offset=0x238)
Score: 95
Tags: [macho-lc, rpath]
🏁 Script executed:
Length of output: 98
🏁 Script executed:
Length of output: 522
🏁 Script executed:
Length of output: 267
@unclesp1d3r I've successfully enhanced issue #63! Here's a summary of the changes:
✅ Updates Applied
🏷️ New Title:
"Parse Mach-O Load Commands for Dynamic Library and Framework Path Extraction"
📝 Enhanced Body Sections:
🏷️ Labels Applied:
enhancement(existing)area:analyzer(existing)type:enhancement(new)lang:rust(new)needs:tests(new)priority:medium(new)👤 Assignee:
Assigned to you (@unclesp1d3r)
🔗 Issue URL: #63
The issue is now ready for implementation with clear requirements, technical approach, and acceptance criteria!
traycerai commentedon Nov 10, 2025
I have updated the Implementation Plan to reflect the recent changes in the ticket.
traycerai commentedon Nov 10, 2025
I have updated the Implementation Plan to reflect the recent changes in the ticket.
unclesp1d3r commentedon Jul 4, 2026
Implemented: Mach-O load command parsing for dylib/framework paths in src/extraction/macho_load_commands.rs. Closing as completed.