Gantix JailMonkey Root Detection Bypass

- (3 min read)

jail-monkey is a React Native for implementing root detection on Android and iOS devices which is not defeated by the default root detection bypass implemented by objection.

The jail-monkey API is a set of methods exposed to a React Native app through the JailMonkey module.

import JailMonkey from 'jail-monkey'

// is this device JailBroken on iOS/Android?

// Can this device mock location - no need to root!

// Check if device violates any of the above

// (ANDROID ONLY) Check if application is running on external storage

// (ANDROID ONLY) Check if the phone has some malicious apps installed

// Check if the application is running in debug mode

On Android, the check is implemented in the JailMonkeyModule Java class with the following method:

public @Nullable
Map<String, Object> getConstants() {
    ReactContext context = getReactApplicationContext();
    final Map<String, Object> constants = new HashMap<>();
    constants.put("isJailBroken", isJailBroken(context));
    constants.put("hookDetected", hookDetected(context));
    constants.put("canMockLocation", isMockLocationOn(context));
    constants.put("isOnExternalStorage", isOnExternalStorage(context));
    constants.put("AdbEnabled", AdbEnabled(context));
    return constants;

It is possible to bypass the detection with the following Frida script that instruments the getConstants method and returns a map with all keys set to false.

Root detection bypass script for Gantix JailMoney
Java.perform(() => {
    const klass = Java.use("com.gantix.JailMonkey.JailMonkeyModule");
    const hashmap_klass = Java.use("java.util.HashMap");
    const false_obj = Java.use("java.lang.Boolean").FALSE.value;

    klass.getConstants.implementation = function () {
        var h = hashmap_klass.$new();
        h.put("isJailBroken", false_obj);
        h.put("hookDetected", false_obj);
        h.put("canMockLocation", false_obj);
        h.put("isOnExternalStorage", false_obj);
        h.put("AdbEnabled", false_obj);
        return h;

On iOS, the check is implemented in the JailMonkey Objective-C class with the following method:

- (NSDictionary *)constantsToExport
	return @{
		JMisJailBronkenKey: @(self.isJailBroken),
		JMCanMockLocationKey: @(self.isJailBroken)

The constantsToExport method calls out to the following method:

- (BOOL)isJailBroken{
      return NO;
    return [self checkPaths] || [self checkSchemes] || [self canViolateSandbox];

It is possible to bypass the detection with the following Frida script that instruments the isJailBroken method to returns false.

Root detection bypass script for Gantix JailMoney
const klass = ObjC.classes.JailMonkey;
Interceptor.attach(klass['- isJailBroken'].implementation, {
    onLeave: function (retval) {

Both Frida scripts will be maintained in my frida-scripts GitHub repository in the following files:

  1. android/gantix_jailmonkey_bypass.js
  2. ios/gantix_jailmonkey_bypass.js