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
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
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 screencap –p /sdcard/download/print.png
adb exec-out screencap –p > 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...");
}
})