HackingInfo

Client-Side Protections Bypass – Android

Getting protection details:
-> Debugging with Logcat, stack trace analysis
-> Analysis of classes and methods at runtime – frida/objection
-> Reverse Engineering and Code Analysis

Debugging with Logcat, stack trace analysis

-> Logcat – get the application PID and use grep

adb logcat | grep <pid>
adb logcat | findstr <pid>

-> Using StackTrace for debugging and detecting possible protections in the app

Analysis of classes and methods

-> listing classes – frida script

frida -U -f <package_name> -l listing_classes.js
'use strict'
if(Java.available){
    Java.perform(function(){
        try{
            Java.enumerateLoadedClasses({
                onMatch: function(className){
                    console.log(className);
                },
                onComplete: function(){
                    console.log("[+] done!");
                }
            });
        }catch(error){
            console.log("[-] Exception");
            console.log(error.stack);
        }
    });
}else{
    console.log("[-] Java unavailable");
}

-> listing classes – objection

objection --gadget <package_name> explore -s "android hooking list classes"

-> list methods of a class – objection

objection --gadget <package_name> explore -s "android hooking list class_methods <package_name>.<class_name>"

-> search for the code responsible for Anti-Root protection, after decompiling the dex to java class with jadx for code review

Anti-Root Bypass

-> After discovering the class, method and expected return of the protection you can create a script in frida (Creating Scripts in Frida) or use known scripts for this (https://codeshare.frida.re/)
-> Note: stack trace collection, possible errors, debugging with logcat are also appreciated to discover the class, method and expected return of the Anti-Root

-> Root Detection Example

public boolean checkRoot() {
        String[] path = {"/sbin/", "/system/bin/", "/system/xbin/", "/data/local/xbin/", "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/"};
        for (int i2 = 0; i2 < 8; i2++) {
            if (new File(<somefunction>(path[i2], "su")).exists()) {
                return true;
            }
        }
        return false;
    }

-> Example frida script

'use strict'

if(Java.available){
    Java.perform(function(){
        try{
            var target = Java.use("<package_name>.<class_name>");
            target.isDeviceRooted.implementation = function() {
            return false;
            };
        }catch(error){
            console.log("[-] An exception occured");
            console.log(String(error.stack));
        }
    });
}else{
    console.log("[-] Java unavailable");
}

-> execute

frida -U -f <package_name> -l bypass_root_detection.js

Since Android is based on the Linux architecture, we can directly connect to libc.so when the access function is called when checking a root file:

Interceptor.attach(Module.findExportByName("libc.so","access"), {
    onEnter: function(args) {
        this.path = args[0].readUtf8String()
        this.mode = args[1]
    },
    onLeave: function (retval) {
        var paths = [
            "/system/app/Superuser.apk",
            "/sbin/su",
            "/system/bin/su",
            "/system/xbin/su",
            "/data/local/xbin/su",
            "/data/local/bin/su",
            "/system/sd/xbin/su",
            "/system/bin/failsafe/su",
            "/data/local/su",
        ]
        
        for(var i = 0; i < paths.length; i++) {
            if(this.path.includes(paths[i])) {
                console.log(`access(${this.path}, ${this.mode})`)
                retval.replace(-1)
            }
        }
    }
})

Reverse engineering example for Anti-Root bypass

-> decompile the apk to smali

apktool d app.apk -o app

-> Look for references related to root protection and edit

grep -r -i '"su"' ./app
vim <path>.<file>.smali

-> reference to root validation identified “const-string v5, “su””

-> change to

const-string v5, "anything"

-> Recompile the app

apktool b app

-> Sign the app
Creating a Keystore

keytool -genkey -v -keystore mysigning.keystore -alias <app_alias> -keyalg RSA -keysize 2048 --validity 10000

Using the created keystore and sign the apk

jarsigner --verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mysigning.keystore <app.apk> <app_alias>

Anti-Root Bypass with Objection

-> bypassing Anti-Root

objection --gadget <package_name> explore -s "android root disable"

-> Another example

objection --gadget <package_name> explore -s "android hooking set return_value <package_name>.<class_name>.<method_name> false"

Anti-Root Bypass with Frida Scripts

frida -U -f <package_name> -l <script>.js

https://codeshare.frida.re/@fdciabdul/frida-multiple-bypass

Broken JailMonkey Detection

If you have found JailMonkey in your tests, you can use this Frida script to bypass Android

/*
by F0x - Mateus Tesser
*/
console.log("----------------------");
console.log('> JailMonkey Bypass!!!');
console.log("----------------------");

Java.perform(function() {
	var HookDetect = Java.use("com.gantix.JailMonkey.HookDetection.HookDetectionCheck");
	HookDetect.hookDetected.implementation = function() {
		console.log("[+] Hook Detect bypassed!")
		return true;
	}
	HookDetect.advancedHookDetection.implementation = function() {
		console.log("[+] Advanced Hook Detect bypassed!");
		return true;
	}
	HookDetect.checkFrida.implementation = function() {
		console.log("[+] Anti-Frida Bypassed!");
		return false;
	}

	const adb_check = Java.use("com.gantix.JailMonkey.AdbEnabled.AdbEnabled");
	adb_check.AdbEnabled.implementation = function() {
		console.log("[+] AdbEnabled bypassed!!!");
		return false;
	}

	const jail_proc = Java.use("com.gantix.JailMonkey.JailMonkeyModule");
	const hashmap_proc = Java.use("java.util.HashMap");
	const false_obj = Java.use("java.lang.Boolean").FALSE.value;

	jail_proc.getConstants.implementation = function() {
		var h = hashmap_proc.$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;
		console.log("[+] JailMonkey Protection bypassed!");
	}

	jail_proc.isDevelopmentSettingsMode.implementation = function() {
		return false;
	}
	jail_proc.isDebbugedMode.implementation = function() {
		return false;
	}
});

Anti-Emulator Bypass

​Among the ways that anti-emulator protections use to detect emulated access on Android are:

-> Runtime execution​
It consists of creating a new instance at runtime and executing commands such as getprop to check information from the android.os.SystemProperties class, analyzing whether the application is running on an emulated device.​

​-> Java reflection​
Using accessor methods within the android.os.SystemProperties class to return values ​​that indicate that the application is running in an emulated environment.

-> After discovering the class, method and expected return of the protection you can create a script in frida (Creating Scripts in Frida) or use known scripts for this (https://codeshare.frida.re/)
-> Note: stack trace collection, possible errors, debugging with logcat are also appreciated to discover the class, method and expected return of the Anti-Root

Anti-Emulator Bypass with Frida Scripts

frida -U -f <package_name> -l <script>.js

SSL Pinning Bypass

-> Frida
-> Objection
-> Reverse engineering with apktool and Replacing Hard-Coded Certificate, Sha 256 Hash, etc

SSL Pinning Bypass with Frida Scripts

frida -U -f <package_name> -l <script>.js --no-pause

image
https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/ ​
https://github.com/httptoolkit/frida-interception-and-unpinning
https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/

SSL Pinning Bypass with Objection

objection --gadget <package_name> explore -s 'android sslpinning disable'

Bypassing NetworkSecurityConfig Android >=7 & targetSdkVersion >= 24 only system certificates are trusted

-> decompiling

apktool d app.apk

-> AndroidManifest.xml Analysis

cat AndroidManifest.xml  

-> identified that exists “android:networkSecurityConfig=“xml/network_security_config”

-> Edit Network Security Configuration File:

vim /res/xml/network_security_config.xml

-> Add in network_security_config.xml (instruct the application to accept user-added certificates during SSL/TLS verification. This is a commonly used technique to bypass SSL pinning because it allows custom certificates to be trusted independently of the original application-defined certificates.)

<certificates src="user" />

-> recompiling

apktool b app

-> Sign the app
Creating a Keystore

keytool -genkey -v -keystore mysigning.keystore -alias <app_alias> -keyalg RSA -keysize 2048 --validity 10000

Using the created keystore and sign the apk

jarsigner --verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mysigning.keystore <app.apk> <app_alias>

End-to-End Encryption Bypass

image

It is responsible for preventing the visualization of parameters in the request in clear text,
Data sent is encrypted before leaving the device and can only be decrypted by the server.

Understand how the application is encrypting the data and decrypting it to obtain their encryption keys and tamper with the decrypted data.
If end-to-end encryption is used, even if the certificate is installed, and bypassing the SSL pinning, and managing to intercept the traffic using a proxy (burp), we will not be able to see clear text data during the interception of HTTP /HTTPS traffic , end-to-end encryption prevents request tampering.

-> Static analysis
-> Perform at runtime tracing
Case:
-> AES 256 being used for encrypt/decrypt data
-> Client and server with the same encryption key

objection --gadget explore -s "android hooking watch class <package_name>.<AESclass> --dump-args --dump-return

endtoend.js

'use strict'
if(Java.available){
    Java.perform(function(){
        try{
            var aes_class = Java.use("<package_name>.<class_name>");
            aes_class.<method_name>.overload("[B").implementation = function (gk) {
                var key_value = this.bytesToHex(gk);
                console.log(returnvalue);
                return key_value;
            };
        }catch(error){
            console.log("[-] Exception");
            console.log(String(error.stack));
        }
    });
}else{
    console.log("[-] Java unavailable");
}

frida -U -f <package_name> -l bypass_root_decetion.js -l endtoend.js

There are more complex cases in which asymmetric cryptography will also be used to transfer the key and data.

Anti-Debugging Bypass

Debuggers can be useful for our analysis of the application, in order to increase our attack surface during a Pentest.
An anti-debug mechanism will block our debugging.

or you can run the command below as root (It’s bypass Anti-Debugging and USB Debugging detection):

settings put global adb_enabled 2

Script Anti-Debugging Bypass

-> script universal-android-debugging-bypass
https://codeshare.frida.re/@meerkati/universal-android-debugging-bypass/
https://codeshare.frida.re/@Raphkitue/android-debug-mode-bypass/
https://codeshare.frida.re/@voker2311/android-common-security-bypasses/

Anti-Frida Bypass

The anti-frida performs the blockade by detecting:

  • Changes of Instructions;
  • Port used by frida;
  • Named pipes and threads used by Frida;
  • Comparison of the text section in memory with the text section in disk for libc and native library.
    Keep in mind that you need to analyze the code to find out how to better bypass the anti-frida used by the app.

Script Anti-Frida Bypass

https://codeshare.frida.re/@fdciabdul/frida-multiple-bypass/
https://codeshare.frida.re/@enovella/anti-frida-bypass/

Port detection bypass

-> bypass for change port

./frida-server -l 0.0.0.0:19991

-> communicating with Frida on a different port

frida -H 192.168.0.22:19991 -f <package_name> -l <script>.js

Flag Secure Bypass

-> check if it is possible to print critical information in the app

adb shell screencapp /sdcard/download/print.png
adb exec-out screencapp > print.png

-> check if you can view this critical data with the application in the background

-> perform bypass with script in Frida to see the application even in the background and take screenshots

frida -U -f <package-name> -l screenshot.js

-> perform bypass with Objection to see the application even in the background and take screenshots

-> See the application even in the background and take screenshots

objection -g <package_name> explore -s "android ui FLAG_SECURE false"

Exploring activity/application termination control methods

Many applications react to suspicious activity, such as root detection, use of emulators or debugging mode, by closing themselves automatically using specific shutdown methods.

However, it is possible to take advantage of these methods used when running hooking to prevent the application from not closing and remaining running.

Java.perform(function() {
    let System = Java.use("java.lang.System")
    let exit = System.exit.overload('int');
    exit.implementation = function() {
        console.log("Bypass...");
    }
})

fdciabdul

i love code and pentesting, i'm not hacker, but i love to learn it

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *