Root Detection and Bypass (2)
Root Detection and Bypass (2)
Java.perform(function() {
varDebugClass= Java.use("android.os.Debug");
DebugClass.isDebuggerConnected.implementation= function() {
returnfalse; // Always return false};
});
Anti-Hooking Bypass:
o Modifying the application logic to neutralize anti-hooking checks (e.g., detecting
Frida processes).
o Using Magisk modules to hide hooking frameworks like Xposed.
Code Example:
privatebooleancheckRootFiles(){
String[] paths = {
"/system/app/Superuser.apk",
"/system/bin/su",
"/system/xbin/su",
"/data/local/bin/su",
"/data/local/xbin/su",
"/sbin/su",
"/system/sd/xbin/su"};
for(String path : paths) {
Filefile=newFile(path);
if(file.exists()) {
returntrue;
}
}
returnfalse;
}
Improvements:
Obfuscate file paths to prevent bypass by simple string replacement.
Randomize the file check logic to make reverse engineering harder.
Code Example:
privatebooleancheckSystemProperties(){
StringbuildTags=Build.TAGS;
if(buildTags != null&& buildTags.contains("test-keys")) {
returntrue;
}
returnSystem.getProperty("ro.debuggable").equals("1");
}
Improvements:
Combine multiple property checks and verify them dynamically.
Encrypt or obfuscate property names in the code.
Command Execution Checks
Detect suspicious commands being executed on the device.
Code Example:
privatebooleanexecuteSuCommand(){
try{
Processprocess=Runtime.getRuntime().exec("which su");
BufferedReaderin=newBufferedReader(newInputStreamReader(process.getInputStream()));
returnin.readLine() != null;
} catch(Exception e) {
returnfalse;
}
}
Improvements:
Use native libraries (JNI) for command execution to make bypass harder.
Monitor system command usage patterns dynamically.
BusyBox
BusyBox binaries are commonly used in rooted environments for advanced command-line utilities:
/system/bin/busybox
/system/xbin/busybox
/data/local/busybox
/sbin/busybox
Xposed Framework
Xposed is widely used for modifying app behavior:
/system/framework/XposedBridge.jar
/data/data/de.robv.android.xposed.installer/
/data/dalvik-cache/xposed/
/magisk/xposed/
Temporary Directories
Rooting processes often leave files in temporary or cache directories:
/data/local/tmp/root/
/cache/.root/
/data/.root/
Magisk-Related Paths
/dev/magisk/
/magisk/
/sbin/magisk/
/init.magisk.rc
Code Example:
privatebooleanverifySignature(){
try{
PackageInfopackageInfo=getPackageManager().getPackageInfo(getPackageName(),
PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
for(Signature signature : signatures) {
if(!isValidSignature(signature)) {
returnfalse;
}
}
returntrue;
} catch(Exception e) {
returnfalse;
}
}
privatebooleanisValidSignature(Signature signature){
StringvalidSignature="YOUR_VALID_SIGNATURE_HASH";
returnvalidSignature.equals(signature.toCharsString());
}
Improvements:
Validate signatures server-side to avoid tampering with client logic.
Implement a checksum to verify app resources.
Checksum Verification
Verify the integrity of critical app files.
Code Example:
privatebooleanverifyChecksum(String filePath, String expectedHash){
try{
MessageDigestmd=MessageDigest.getInstance("SHA-256");
FileInputStreamfis=newFileInputStream(filePath);
byte[] buffer = newbyte[1024];
intbytesRead;
while((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
fis.close();
byte[] hashBytes = md.digest();
StringBuildersb=newStringBuilder();
for(byteb : hashBytes) {
sb.append(String.format("%02x", b));
}
returnexpectedHash.equals(sb.toString());
} catch(Exception e) {
returnfalse;
}
}
Code Example:
privatebooleandetectHooking(){
returnnewFile("/data/data/de.robv.android.xposed.installer").exists() ||
newFile("/system/framework/XposedBridge.jar").exists();
}
JNI Example:
#include<jni.h>#include<string.h>JNIEXPORT jboolean JNICALL
Java_com_example_RootDetection_nativeCheck(JNIEnv *env, jobject obj){
FILE *file = fopen("/system/bin/su", "r");
if(file) {
fclose(file);
returnJNI_TRUE;
}
returnJNI_FALSE;
}
Integration Example:
SafetyNet.getClient(this).attest(requestNonce, API_KEY)
.addOnSuccessListener(response -> {
StringresponseJson=response.getJwsResult();
// Validate response on server})
.addOnFailureListener(e -> {
// Handle failure});
Anti-Debugging Checks
Prevent runtime debugging to stop analysis or tampering.
Code Example:
privatebooleanisBeingDebugged(){
returnandroid.os.Debug.isDebuggerConnected() || BuildConfig.DEBUG;
}