Introduction
No Escape is an iOS lab from MobileHackingLab where you need to bypass jailbreak detection in order to access restricted content in the application.
Methodology
- Explore the application
- Review source code
- Create bypass script
- Execute bypass script
- Final thoughts
Explore the application
When we open the app the first time, we are greeted with a message stating that we are using a jailbroken device and that the app will exit now for security reasons.

There is nothing more to explore in the app for now; we will need to bypass these restrictions in order to see the rest of the functionality the app offers.
Review source code
We will be using Ghidra to reverse engineer the binary and search for the jailbreak detection.
In Ghidra, we navigate to the Symbol Tree and search for the word “Jail” to see if there are any results.
You will notice that it found a few results, the bottom isJailbroken
is the one that we want to check.

/* No_Escape.isJailbroken() -> Swift.Bool */
bool No_Escape::isJailbroken(void)
{
bool bVar1;
uint uVar2;
uint local_18;
uint local_14;
uVar2 = $$No_Escape.(checkForJailbreakFiles_in__BCE8F13474E5A52C60853EA803F80A81)()_->_Swift.Bool
();
if ((uVar2 & 1) == 0) {
local_14 = $$No_Escape.(checkForWritableSystemDirectories_in__BCE8F13474E5A52C60853EA803F80A81)( )_->_Swift.Bool
();
}
else {
local_14 = 1;
}
if ((local_14 & 1) == 0) {
local_18 = $$No_Escape.(canOpenCydia_in__BCE8F13474E5A52C60853EA803F80A81)()_->_Swift.Bool();
}
else {
local_18 = 1;
}
if ((local_18 & 1) == 0) {
bVar1 = $$No_Escape.(checkSandboxViolation_in__BCE8F13474E5A52C60853EA803F80A81)()_->_Swift.Bool
();
}
else {
bVar1 = true;
}
return bVar1 != false;
}
As we can see, this function performs various tests to determine if a device is jailbroken:
- Check if some common jailbreak binaries are located on the device
- Check if the app can write to system directories
- Check if the Cydia app is installed and can be opened
- Check if the app can write to directories outside its sandbox
Based on these checks, it will return a final result, as a boolean, to indicate whether the device is jailbroken or not.
From here we have two options to bypass the hooking:
- We can hook and bypass each of the individual checks and return false for each one
- We can ignore all the other checks and only hook the final result and change its value before it returns it to the sender
For this specific case, we are going with the latter solution.
Create bypass script
Since Ghidra demangles the Swift function names we need to use Frida to find the mangled name of the function that we want to hook:
[iPhone::com.mobilehackinglab.No-Escape ]-> Module.enumerateExportsSync("No Escape").filter((module) => module.name.includes("Jail"));
[
{
"address": "0x10058e068",
"name": "$s9No_Escape12isJailbrokenSbyF",
"type": "function"
}
]
[iPhone::com.mobilehackinglab.No-Escape ]->
Now that we have the function name we can write a hook to intercept it, modify the return value, and then let it continue:
var isJailBroken = Module.findExportByName(
"No Escape",
"$s9No_Escape12isJailbrokenSbyF"
);
if (isJailBroken) {
console.log("Hooking success!");
Interceptor.attach(isJailBroken, {
onEnter: function (args) {
console.log("Entered isJailBroken!");
},
onLeave: function (retval) {
// Modify the return value to always return 0x0 (false)
retval.replace(0x0);
console.log("Exited isJailBroken, retval:" + retval);
},
});
} else {
console.log("Hooking failed!");
}
Our hook modifies the return value of the function to always return 0x0 (false)
Execute bypass script
Now we launch the app using Frida and include our hooking script and observe the results:
frida -U -f "com.mobilehackinglab.No-Escape" -l no-escape-bypass-jailbreak.js
Spawning `com.mobilehackinglab.No-Escape`...
Hooking success!
Spawned `com.mobilehackinglab.No-Escape`. Resuming main thread!
[iPhone::com.mobilehackinglab.No-Escape ]-> Entered isJailBroken!
Exited isJailBroken, retval:0x0
Entered isJailBroken!
Exited isJailBroken, retval:0x0

We have successfully bypassed the jailbreak detection and can see the flag in the application!
Final thoughts
In this lab we saw multiple checks that work great in combination with each other to detect jailbroken devices.
The only problem is that it lacked some checks to prevent hooking and thus was bypassed altogether.
Security checks are only as strong as your weakest check.