JailMonkeyEraser: Bypassing iOS Jailbreak Detection
A comprehensive analysis of jailbreak detection mechanisms and how to bypass them using dynamic instrumentation. This research explores the technical implementation of popular detection libraries and demonstrates practical bypass techniques.
Overview
JailMonkeyEraser is a Frida script designed to bypass jailbreak and dynamic instrumentation detection in iOS applications. This tool specifically targets popular detection libraries including JailMonkey, DetectFrida, and JailBrokenHelper, which are commonly used by developers to prevent their apps from running on jailbroken devices or when being analysed with dynamic analysis tools.
What Does This Mean?
Think of it like this: Many iOS apps have built-in "security guards" that check if your device has been modified (jailbroken) or if someone is trying to analyse the app (using tools like Frida). If these guards detect anything suspicious, they shut down the app. JailMonkeyEraser essentially tells these guards "everything is fine" even when it's not, allowing security researchers and developers to analyse apps that would otherwise refuse to run.
Why Is This Useful?
- Security Research: Allows researchers to analyse apps for vulnerabilities
- Penetration Testing: Enables security testing of mobile applications
- Development: Helps developers test their apps on jailbroken devices
- Education: Provides insights into how mobile security works
Background: Jailbreak Detection Landscape
Why Apps Detect Jailbreaks
iOS applications often implement jailbreak detection mechanisms for several reasons:
- Security: Prevent unauthorised modifications to the app's behaviour
- Compliance: Meet enterprise security requirements
- Anti-Analysis: Deter reverse engineering and dynamic analysis
- DRM Protection: Protect digital rights management systems
Common Detection Libraries
Three popular libraries are frequently used for jailbreak detection:
1. JailMonkey
A React Native library that provides comprehensive jailbreak detection capabilities. It checks for:
- Common jailbreak file paths
- Jailbreak-related URL schemes
- Dynamic library injections
- Sandbox violations
2. DetectFrida
Specifically designed to detect Frida dynamic instrumentation framework. It looks for:
- Frida-specific processes
- Frida-related environment variables
- Frida server connections
3. JailBrokenHelper
A native iOS library that performs low-level system checks:
- Package manager detection (Cydia, Sileo, etc.)
- Suspicious application detection
- System file modification checks
- Dynamic library injection detection
Technical Analysis
Reverse Engineering Process
To understand how these detection mechanisms work, we need to analyse the compiled binaries. Here's the detailed process:
1. Binary Extraction and Analysis
# Extract the app binary
cp /path/to/app.ipa /tmp/
cd /tmp
unzip app.ipa
cd Payload/AppName.app
# Analyse linked libraries
otool -L AppName
# View Objective-C class information
otool -ov AppName | grep -A 5 -B 5 "JailMonkey\|DetectFrida\|JailBrokenHelper"
# Extract strings for analysis
strings AppName | grep -i "jail\|frida\|cydia\|sileo"
2. Hopper Disassembler Analysis
Load the binary into Hopper Disassembler for detailed analysis:
- Import the binary and let Hopper analyse the Objective-C runtime
- Navigate to the "Objective-C" tab to see all classes
- Search for JailMonkey, DetectFrida, and JailBrokenHelper classes
- Examine method implementations and control flow
- Map the detection logic and identify key decision points
3. Method Analysis Results
Based on the reverse engineering analysis, here's what each detection method does:
JailMonkey Detection Methods
// Primary detection method - orchestrates all checks
- (BOOL)isJailBroken;
// Returns YES if device is jailbroken, NO otherwise
// Internally calls checkPaths, checkDyLibs, checkSymLinks
// Individual detection methods
- (BOOL)checkPaths; // Scans for common jailbreak files
- (BOOL)checkDyLibs; // Dynamic library injection detection
- (BOOL)checkSymLinks; // Symbolic link detection
- (BOOL)canViolateSandbox; // Sandbox violation tests
- (BOOL)isDebugged; // Debugger detection
- (BOOL)canFork; // Process forking capability
// Common jailbreak files checked:
// /Applications/Cydia.app
// /Library/MobileSubstrate/MobileSubstrate.dylib
// /bin/bash, /usr/sbin/sshd
// /etc/apt, /private/var/lib/apt/
// /private/var/lib/cydia
// /private/var/mobile/Library/SBSettings/Themes
DetectFrida Detection Methods
// Main Frida detection method
- (BOOL)isJailBroken;
// Returns YES if Frida is detected, NO otherwise
// Implementation checks for:
// 1. Frida processes: frida-server, frida-helper
// 2. Frida environment variables: FRIDA_DNS_SERVER
// 3. Frida-related files: /usr/lib/frida/
// 4. Frida network connections on port 27042
// 5. Frida-specific strings in memory
// 6. Frida gadget injection detection
JailBrokenHelper Detection Methods
// Package manager detection methods
+ (BOOL)hasCydiaInstalled; // Checks for Cydia.app
+ (BOOL)hasUndecimusInstalled; // Checks for unc0ver jailbreak
+ (BOOL)hasSileoInstalled; // Checks for Sileo package manager
+ (BOOL)hasZbraInstalled; // Checks for Zebra package manager
// System-level detection methods
+ (BOOL)isContainsSuspiciousApps; // Scans for jailbreak apps
+ (BOOL)canEditSystemFiles; // Tests system file write access
+ (BOOL)checkDYLD; // Checks DYLD_INSERT_LIBRARIES
+ (BOOL)checkSuspiciousObjCClasses; // Scans for jailbreak classes
// Suspicious apps scanned:
// - Filza File Manager, iFile, NewTerm
// - PreferenceLoader, RocketBootstrap
// - Activator, iCleaner Pro
4. Control Flow Analysis
Understanding how these methods work together:
Detection Logic Flow
// JailMonkey detection flow
isJailBroken() {
if (checkPaths() == YES) return YES;
if (checkDyLibs() == YES) return YES;
if (checkSymLinks() == YES) return YES;
if (canViolateSandbox() == YES) return YES;
if (isDebugged() == YES) return YES;
if (canFork() == YES) return YES;
return NO;
}
// DetectFrida detection flow
isJailBroken() {
if (findProcess("frida-server")) return YES;
if (getenv("FRIDA_DNS_SERVER")) return YES;
if (fileExists("/usr/lib/frida/")) return YES;
if (hasConnectionOnPort(27042)) return YES;
return NO;
}
5. Analysis Tools and Techniques
The analysis utilised several specialised tools and techniques:
Static Analysis Tools
# Binary analysis with otool
otool -L AppName # List linked libraries
otool -ov AppName # View Objective-C classes
otool -tv AppName # Disassemble text section
# String extraction
strings AppName | grep -i "jail" # Extract jailbreak-related strings
strings AppName | grep -i "frida" # Extract Frida-related strings
strings AppName | grep -i "cydia" # Extract Cydia-related strings
# File analysis
file AppName # Determine file type
lipo -info AppName # Check architecture support
codesign -d AppName # View code signing info
Implementation: JailMonkeyEraser
Development Approach
The development of JailMonkeyEraser involved a systematic approach to understanding and bypassing detection mechanisms:
Phase 1: Research and Analysis
- Library Documentation: Studied JailMonkey, DetectFrida, and JailBrokenHelper source code
- Binary Analysis: Used Hopper Disassembler to understand method implementations
- Runtime Analysis: Used Frida to trace method calls and understand execution flow
- String Analysis: Extracted and analysed detection strings from binaries
Phase 2: Method Identification
Using the reverse engineering analysis, I identified the key methods to hook:
// JailMonkey methods to bypass
isJailBroken() // Primary detection method
checkPaths() // File system scans
checkDyLibs() // Dynamic library injection detection
checkSymLinks() // Symbolic link detection
canViolateSandbox() // Sandbox violation tests
isDebugged() // Debugger detection
canFork() // Process forking capability
// DetectFrida methods to bypass
isJailBroken() // Single main method for Frida detection
// JailBrokenHelper methods to bypass
hasCydiaInstalled() // Package manager detection
hasUndecimusInstalled() // unc0ver jailbreak detection
hasSileoInstalled() // Sileo package manager detection
hasZbraInstalled() // Zebra package manager detection
isContainsSuspiciousApps() // Jailbreak app detection
canEditSystemFiles() // System file write access
checkDYLD() // DYLD_INSERT_LIBRARIES check
checkSuspiciousObjCClasses() // Jailbreak class detection
Phase 3: Frida Script Development
The script development followed an iterative approach:
Step 1: Basic Method Hooking
// First attempt - basic hooking
if (ObjC.available) {
var JailMonkey = ObjC.classes.JailMonkey;
if (JailMonkey && JailMonkey['isJailBroken']) {
Interceptor.attach(JailMonkey['isJailBroken'].implementation, {
onLeave: function(retval) {
console.log('[Bypass] JailMonkey.isJailBroken() -> false');
retval.replace(0);
}
});
}
}
Step 2: Comprehensive Method Coverage
// Expanded to cover all JailMonkey methods
var jailMonkeyMethods = [
'isJailBroken',
'canViolateSandbox',
'isDebugged',
'canFork',
'checkPaths',
'checkDyLibs',
'checkSymLinks'
];
jailMonkeyMethods.forEach(function(method) {
if (JailMonkey[method]) {
Interceptor.attach(JailMonkey[method].implementation, {
onLeave: function(retval) {
console.log('[Bypass] JailMonkey.' + method + '() -> false');
retval.replace(0);
}
});
}
});
Final Frida Script Implementation
Here's the complete, production-ready implementation:
if (ObjC.available) {
// === JailMonkey methods ===
var JailMonkey = ObjC.classes.JailMonkey;
if (JailMonkey) {
[
'isJailBroken',
'canViolateSandbox',
'isDebugged',
'canFork',
'checkPaths',
'checkDyLibs',
'checkSymLinks',
'checkPathsMessage',
'checkDyLibsMessage',
'checkSymLinksMessage',
'jaiBrokenMessage'
].forEach(function(method) {
if (JailMonkey[method]) {
Interceptor.attach(JailMonkey[method].implementation, {
onLeave: function(retval) {
console.log('[Bypass] JailMonkey.' + method + '() -> false');
retval.replace(0); // false/NO
}
});
}
});
}
// === DetectFrida methods ===
var DetectFrida = ObjC.classes.DetectFrida;
if (DetectFrida) {
if (DetectFrida['isJailBroken']) {
Interceptor.attach(DetectFrida['isJailBroken'].implementation, {
onLeave: function(retval) {
console.log('[Bypass] DetectFrida.isJailBroken() -> false');
retval.replace(0);
}
});
}
}
// === JailBrokenHelper methods ===
var JailBrokenHelper = ObjC.classes.JailBrokenHelper;
if (JailBrokenHelper) {
[
'hasCydiaInstalled',
'hasUndecimusInstalled',
'hasSileoInstalled',
'hasZbraInstalled',
'isContainsSuspiciousApps',
'isContainsSuspiciousSystemPathsExists',
'canEditSystemFiles',
'checkDYLD',
'checkSuspiciousObjCClasses'
].forEach(function(method) {
if (JailBrokenHelper[method]) {
Interceptor.attach(JailBrokenHelper[method].implementation, {
onLeave: function(retval) {
console.log('[Bypass] JailBrokenHelper.' + method + '() -> false');
retval.replace(0);
}
});
}
});
}
console.log("Jailbreak/Frida detection bypass hooks installed!");
} else {
console.log("Objective-C runtime is not available!");
}
How the Bypass Works
The script operates by intercepting method calls at the Objective-C runtime level:
- Method Hook: Uses Frida's Interceptor.attach() to hook method implementations
- Return Value Manipulation: Forces all detection methods to return false (0)
- Logging: Provides visibility into which methods are being bypassed
- Runtime Execution: Works without modifying the original binary
Key Design Decisions
Several important decisions were made during development:
1. Return Value Strategy
All detection methods return 0
(false/NO) instead of 1
(true/YES):
- Consistency: All methods return the same "not detected" value
- Simplicity: Single return value for all bypassed methods
- Reliability: Avoids potential issues with different return value types
2. Method Coverage Strategy
Comprehensive coverage of all detection methods:
- Primary Methods: Hook main detection methods (isJailBroken, etc.)
- Secondary Methods: Hook individual check methods for thorough coverage
- Message Methods: Hook reporting methods to prevent detailed detection logs
3. Error Handling
Robust error handling for different scenarios:
- Class Availability: Check if classes exist before hooking
- Method Availability: Verify methods exist before attaching hooks
- Runtime Availability: Ensure Objective-C runtime is available
Usage Guide
What Does This Look Like in Practice?
Here's a real-world scenario: You're a security researcher trying to analyse a banking app that refuses to run on jailbroken devices. Without JailMonkeyEraser, the app would detect your jailbroken device and immediately crash. With JailMonkeyEraser, the app runs normally, allowing you to perform security analysis.
Prerequisites
- Jailbroken iOS device
- Frida server running on the device
- Frida client installed on your computer
- Target app's bundle identifier
Step-by-Step Instructions
1. Install Frida
# On your computer
pip install frida-tools
# On the jailbroken device (via Cydia/Sileo)
# Add Frida repository and install frida-server
2. Start Frida Server
# On the device
frida-server
3. Launch Target App
# On your computer
frida -U -f com.example.app -l jailmonkeyeraser.js
Expected Output
Spawning `com.example.app`...
Jailbreak/Frida detection bypass hooks installed!
Spawned `com.example.app`. Resuming main thread!
[iPhone::com.example.app ]-> [Bypass] JailBrokenHelper.hasCydiaInstalled() -> false
[Bypass] JailBrokenHelper.hasUndecimusInstalled() -> false
[Bypass] JailBrokenHelper.hasSileoInstalled() -> false
[Bypass] JailBrokenHelper.hasZbraInstalled() -> false
[Bypass] JailBrokenHelper.isContainsSuspiciousApps() -> false
[Bypass] JailBrokenHelper.checkDYLD() -> false
[Bypass] JailBrokenHelper.checkSuspiciousObjCClasses() -> false
[Bypass] JailBrokenHelper.canEditSystemFiles() -> false
What the Output Means
Each line starting with [Bypass]
shows that the script successfully intercepted a detection method and forced it to return false
. This means the app thinks everything is normal and continues running, even though it's actually on a jailbroken device with Frida running.
Technical Deep Dive
How Does the Bypass Work?
At its core, JailMonkeyEraser works by intercepting function calls. When an app tries to check if the device is jailbroken, our script steps in and says "nope, everything is normal" regardless of what the actual check would find. It's like having a translator that always gives the "safe" answer to security questions.
Method Hooking Mechanism
The script uses Frida's powerful hooking capabilities to intercept method calls:
Interceptor.attach() Breakdown
Interceptor.attach(JailMonkey[method].implementation, {
onLeave: function(retval) {
console.log('[Bypass] JailMonkey.' + method + '() -> false');
retval.replace(0); // false/NO
}
});
Key Components:
JailMonkey[method].implementation
- Gets the native function pointeronLeave
- Callback executed when the method returnsretval.replace(0)
- Forces return value to false
Objective-C Runtime Integration
The script leverages Frida's Objective-C runtime integration:
- Accesses
ObjC.classes
to get class references - Uses method name strings to locate implementations
- Works with both instance (-) and class (+) methods
Defence Evasion Techniques
Detection Avoidance
To avoid being detected by the very tools we're bypassing:
- Runtime Hooking: No binary modification required
- Selective Bypass: Only targets specific detection methods
- Logging Control: Can disable console output for stealth
Advanced Techniques
For more sophisticated bypass scenarios:
- Hook system calls directly
- Intercept file system access
- Bypass code signing checks
- Override environment variables
Limitations and Considerations
Technical Limitations
- Requires jailbroken device
- Frida server must be running
- May not work with obfuscated binaries
- Some apps may have additional detection layers
Legal and Ethical Considerations
Important: This tool is intended for educational and authorised security testing purposes only. Always ensure you have explicit permission before testing on any applications or devices.
Conclusion
What We Accomplished
In this research, we:
- Analysed how popular jailbreak detection libraries work by reverse engineering their code
- Identified the specific methods these libraries use to detect jailbreaks and Frida
- Developed a Frida script that intercepts these detection methods
- Created a tool that allows security researchers to bypass these protections
Key Technical Achievement
The main technical accomplishment was understanding that jailbreak detection works by calling specific methods that return true
if they detect something suspicious. By intercepting these method calls and forcing them to return false
, we can make any app think it's running on a normal, non-jailbroken device.
JailMonkeyEraser demonstrates the power of dynamic instrumentation in bypassing security controls. By understanding the underlying detection mechanisms and leveraging Frida's capabilities, we can effectively neutralise jailbreak detection systems.
This research highlights the importance of:
- Understanding adversary capabilities
- Implementing defence-in-depth strategies
- Regular security testing and validation
- Staying current with bypass techniques