Detection of Xposed Framework

Keywords: Android Java Mobile

Reference article: http://d3adend.org/blog/?p=589

Xposed and Cydia Substrate are two commonly used hook frameworks. Xposed can hook the java layer, CydiaSubstrate can hook the java layer and the native layer. How do we detect that the current mobile phone has installed the corresponding framework and determine whether the current process is hooked? There is only one method to collect the information left in the system by hook framework installation and running.

I. Package Name Detection

We can first use the PakageManager class to detect the package name to determine whether the Xposed framework and the CydiaSubstrate framework are installed.

PackageManager packageManager=getApplicationContext().getPackageManager();
        List<ApplicationInfo> appliacationInfoList=packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
        for(ApplicationInfo item:appliacationInfoList ){
            if(item.packageName.equals("de.robv.android.xposed.installer")){
                Log.wtf("HookDetection","Xposeded fonund on device");
            }
            if(item.packageName.equals("com.saurik.substrate")){
                Log.wtf("HookDetection","Xposeded fonund on device");
            }
        }

Bypass method: hook package manager. getInstalledApplications

2. Check suspicious methods in call stack

When the Xposed framework is used in hook applications, the following suspicious methods are generated in stack trace:
1. When the framework starts, the de.robv.android.xposed.XposedBridge.main method is called in the dalvik.system.NativeStart.main method call.
2. When the Xposed framework hook s a specific method, the de.robv.android.xposed.XposedBridge.handleHookedMethod and de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative methods are called.
3. The hook ed method will appear twice in the call stack.

The Substrate framework generates the following suspicious methods when hook ing methods:
1. When the Substrate gy framework is activated, the com.android.internal.os.ZygoteInit.main method is called twice.
2. When the Substrate framework hook s a specific method, com. saurik. substrate. MS $2 - > invoked is invoked, the com.saurik.substrate.MS$MethodPointer.invoke method and an extended method are invoked.
3. The hook ed method will appear twice in the call stack.

Knowing the difference between the normal call stack and the hook call stack, we can use java code to detect the existence of the hook framework.

try {

            throw new Exception("Deteck hook");

        } catch (Exception e) {

            int zygoteInitCallCount = 0;
            for (StackTraceElement item : e.getStackTrace()) {
                // Check if "com.android.internal.os.ZygoteInit" occurs twice, and if it occurs twice, it indicates that the Substrate gy framework has been installed.
                if (item.getClassName().equals("com.android.internal.os.ZygoteInit")) {
                    zygoteInitCallCount++;
                    if (zygoteInitCallCount == 2) {
                        Log.wtf("HookDetection", "Substrate is active on the device.");
                    }
                }

                if (item.getClassName().equals("com.saurik.substrate.MS$2") && item.getMethodName().equals("invoke")) {
                    Log.wtf("HookDetection", "A method on the stack trace has been hooked using Substrate.");
                }

                if (item.getClassName().equals("de.robv.android.xposed.XposedBridge")
                        && item.getMethodName().equals("main")) {
                    Log.wtf("HookDetection", "Xposed is active on the device.");
                }
                if (item.getClassName().equals("de.robv.android.xposed.XposedBridge")
                        && item.getMethodName().equals("handleHookedMethod")) {
                    Log.wtf("HookDetection", "A method on the stack trace has been hooked using Xposed.");
                }

            }

        }

Bypass method: hook getStackTrace()

3. The method of detecting native should not be native

The Xposed framework converts the hook method into a native method and replaces it with its own code (calling the hooked MethodCallback method instead). You can look at the XposedBridge_hookMethodNative method in the app_process file to see how it works.

The Substrate framework works in a similar way by changing the attributes of the method to hook. In ART mode, the Xposed framework does not need to make related transformations because the method is already a native method.

Suppose we declare a common method

public class DoStuff {
    public static String getSecret() {
        return "ChangeMePls!!!";
    }
}

When the method is hook ed, the runtime classes are the same as the following

public class DoStuff {
    public static String getSecret() {
        return "ChangeMePls!!!";
    }
}

This abnormal behavior can be detected in our packages

1. Find the location of the application DEXfile
2. Enumerate all classes in DEXfile file
3. For DEX files, use reflection to check natvie methods that should not be native methods

4. Use / proc/[pid]/maps to detect suspicious objects and JARs objects in memory.

Set<String> libraries=new HashSet<String>();
        String mapsFilename="/proc/"+android.os.Process.myPid()+"/maps";
        try {
            BufferedReader reader = new BufferedReader(new FileReader(mapsFilename));
            String line;
            while((line=reader.readLine())!=null){
                if(line.endsWith(".so")||line.endsWith(".jar")){
                    int n = line.lastIndexOf(" ");
                    libraries.add(line.substring(n+1));
                }


            }
            for(String library:libraries){
                if(library.contains("com.saurik.substrate")) {
                    Log.wtf("HookDetection", "Substrate shared object found: " + library);
                }
                if(library.contains("XposedBridge.jar")) {
                    Log.wtf("HookDetection", "Xposed JAR found: " + library);
                }
            }

            reader.close();
        } catch (Exception e) {
            Log.wtf("HookDetection", e.toString());
        }

Bypass method: hook files open method returns / dev/null

Posted by Aethaellyn on Wed, 03 Apr 2019 17:48:29 -0700