Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Verified Commit bb232f2a authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Remove xposed specific bits, spoof even moar

parent 03d6444d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ dependencies {
    compile 'com.squareup.wire:wire-runtime:1.6.1'
    compile ':droidguasso:@jar'
    compile ':arthook:@aar'
    provided 'de.robv.android.xposed:api:82'
    compile project(':remote-droid-guard-lib')
}

+1 −11
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
          xmlns:tools="http://schemas.android.com/tools">

    <uses-sdk
        android:minSdkVersion="9"
        android:minSdkVersion="19"
        android:targetSdkVersion="24"
        tools:overrideLibrary="de.larma.arthook"/>

@@ -24,16 +24,6 @@
                <action android:name="org.microg.gms.droidguard.REMOTE"/>
            </intent-filter>
        </service>

        <meta-data
            android:name="xposedmodule"
            android:value="true"/>
        <meta-data
            android:name="xposeddescription"
            android:value="Support module for DroidGuard Helper, required when XPosed is installed"/>
        <meta-data
            android:name="xposedminversion"
            android:value="54"/>
    </application>

</manifest>
+0 −1
Original line number Diff line number Diff line
org.microg.gms.droidguard.SysHook
 No newline at end of file
+99 −75
Original line number Diff line number Diff line
@@ -16,41 +16,38 @@

package org.microg.gms.droidguard;

import android.content.ContextWrapper;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
import android.util.Log;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NavigableMap;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.larma.arthook.$;
import de.larma.arthook.ArtHook;
import de.larma.arthook.BackupIdentifier;
import de.larma.arthook.Hook;
import de.larma.arthook.OriginalMethod;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

import static org.microg.gms.droidguard.Constants.GMS_PACKAGE_NAME;

public class SysHook implements IXposedHookLoadPackage {
public class SysHook {
    private static final String TAG = "SysHook";

    private static boolean done = false;
    private static String odexArch = "arm"; // or "arm64"
    private static String checksum;
    static boolean done = false;
    static String odexArch = "arm"; // or "arm64"
    static String checksum;

    // From TelephonyManager
    private static String deviceId;
    private static String subscriberId;
    static String deviceId;
    static String subscriberId;

    public synchronized static void activate(String odexArch, String checksum, String deviceId, String subscriberId) {
        SysHook.odexArch = odexArch;
@@ -62,76 +59,102 @@ public class SysHook implements IXposedHookLoadPackage {
        ArtHook.hook(SysHook.class);
    }

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("org.microg.gms.droidguard"))
            return;

        XposedHelpers.findAndHookMethod(TelephonyManager.class, "getSubscriberId", new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
    @Hook("android.telephony.TelephonyManager->getSubscriberId")
    public static String TelephonyManager_getSubscriberId(TelephonyManager tm) {
        Log.d(TAG, "Set subscriber id: " + SysHook.subscriberId);
        return subscriberId;
    }
        });

        XposedHelpers.findAndHookMethod(TelephonyManager.class, "getDeviceId", new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
    @Hook("android.telephony.TelephonyManager->getDeviceId")
    public static String TelephonyManager_getDeviceId(TelephonyManager tm) {
        Log.d(TAG, "Set device id: " + SysHook.deviceId);
        return deviceId;
    }
        });

        XposedHelpers.findAndHookMethod(TelephonyManager.class, "getDeviceId", int.class, new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
    @Hook("android.telephony.TelephonyManager->getDeviceId")
    public static String TelephonyManager_getDeviceId(TelephonyManager tm, int slot) {
        Log.d(TAG, "Set device id 2: " + SysHook.deviceId);
        return deviceId;
    }
        });

        XposedHelpers.findAndHookMethod(ContextWrapper.class, "getPackageName", XC_MethodReplacement.returnConstant(GMS_PACKAGE_NAME));

        XposedHelpers.findAndHookMethod(ContextWrapper.class, "getClassLoader", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                param.setResult(createModifiedClassLoader((ClassLoader) param.getResult()));
    @Hook("android.net.ConnectivityManager->getActiveNetworkInfo")
    public static NetworkInfo ConnectivityManager_getActiveNetworkInfo(ConnectivityManager cm) {
        return null; // null is a valid response
    }
        });

        XposedHelpers.findAndHookMethod(TreeSet.class, "iterator", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                NavigableMap map = (NavigableMap) XposedHelpers.getObjectField(param.thisObject, "m");
                if (map == null)
                    map = (NavigableMap) XposedHelpers.getObjectField(param.thisObject, "backingMap");
                if (map == null)
                    return;
                if (detectMapsSet(map.navigableKeySet().iterator())) {
                    param.setResult(createMapsReplacementSet().iterator());
    @Hook("java.util.regex.Pattern->matcher")
    @BackupIdentifier("PatternMatcher")
    public static Matcher Pattern_matcher(Pattern pattern, CharSequence cs) {
        OriginalMethod method = OriginalMethod.by("PatternMatcher");
        if (cs instanceof String) {
            String s = (String) cs;
            if (s.contains("Xposed") || s.contains("xposed") || s.contains("XPosed") || s.contains("XPOSED"))
                return method.invoke(pattern, "");
            if (s.contains("org.microg.gms.droidguard"))
                return method.invoke(pattern, s.replace("org.microg.gms.droidguard", "com.google.android.gms"));
        }
        return method.invoke(pattern, cs);
    }
        });

        SysHook.done = true;
    @Hook("android.content.ContextWrapper->getPackageName")
    public static String ContextWrapper_getPackageName(Object o) {
        Log.d(TAG, "Set package name: " + GMS_PACKAGE_NAME);
        return GMS_PACKAGE_NAME;
    }

    @Hook("android.telephony.TelephonyManager->getSubscriberId")
    public static String TelephonyManager_getSubscriberId(TelephonyManager tm) {
        return subscriberId;
    @Hook("android.os.SystemProperties->getInt")
    @BackupIdentifier("SystemPropertiesGetInt")
    public static int SystemProperties_getInt(String key, int def) {
        if (key.equals("ro.debuggable") || key.equals("service.adb.root"))
            return 0;
        if (key.equals("ro.secure"))
            return 1;
        return OriginalMethod.by("SystemPropertiesGetInt").invokeStatic(key, def);
    }

    @Hook("android.telephony.TelephonyManager->getDeviceId")
    public static String TelephonyManager_getDeviceId(TelephonyManager tm) {
        return deviceId;
    @Hook("java.util.Arrays->asList")
    @BackupIdentifier("ArraysAsList")
    public static List Arrays_asList(Object[] objs) {
        Log.d(TAG, "Arrays->asList: "+Arrays.toString(objs));
        if (detectLibrariesList(objs))
            return OriginalMethod.by("ArraysAsList").invoke(null, new Object[]{getModifiedSystemSharedLibraries()});
        return OriginalMethod.by("ArraysAsList").invoke(null, new Object[]{objs});
    }

    @Hook("android.telephony.TelephonyManager->getDeviceId")
    public static String TelephonyManager_getDeviceId(TelephonyManager tm, int slot) {
        return deviceId;
    static boolean detectLibrariesList(Object[] list) {
        boolean isList = false;
        boolean wasModified = false;
        for (int i = 0; i < list.length; i++) {
            if (!(list[i] instanceof String))
                return false;
            if ("com.android.location.provider".equals(list[i]) || "android.test.runner".equals(list[i]))
                isList = true;
            if ("com.google.widevine.software.drm".equals(list[i]))
                wasModified = true;
        }
        return isList && !wasModified;
    }

    @Hook("android.content.ContextWrapper->getPackageName")
    public static String ContextWrapper_getPackageName(Object o) {
        return GMS_PACKAGE_NAME;
    @Hook("android.app.ApplicationPackageManager->getSystemSharedLibraryNames")
    @BackupIdentifier("PackageManagerGetSystemSharedLibraryNames")
    public static String[] PackageManager_getSystemSharedLibraryNames(Object o) {
        Log.d(TAG, "Modified SystemSharedLibraries");
        return getModifiedSystemSharedLibraries();
    }

    static String[] getModifiedSystemSharedLibraries() {
        return new String[]{"android.test.runner",
                "com.android.future.usb.accessory",
                "com.android.location.provider",
                "com.android.media.remotedisplay",
                "com.android.mediadrm.signer",
                "com.google.android.maps",
                "com.google.widevine.software.drm",
                "com.qualcomm.qcrilhook",
                "com.qualcomm.qti.rcsservice",
                "com.quicinc.cneapiclient",
                "javax.obex",
                "org.apache.http.legacy"};
    }

    @Hook("android.content.ContextWrapper->getClassLoader")
@@ -140,7 +163,7 @@ public class SysHook implements IXposedHookLoadPackage {
        return createModifiedClassLoader((ClassLoader) OriginalMethod.by("ContextWrapperClassLoader").invoke(o));
    }

    private static ClassLoader createModifiedClassLoader(ClassLoader original) {
    static ClassLoader createModifiedClassLoader(ClassLoader original) {
        return new URLClassLoader(new URL[0], original) {
            @Override
            public String toString() {
@@ -158,22 +181,23 @@ public class SysHook implements IXposedHookLoadPackage {
        return originalMethod.invoke(set);
    }

    private static boolean detectMapsSet(Iterator iterator) {
    static boolean detectMapsSet(Iterator iterator) {
        boolean hasDgCache = false;
        boolean hasFrameworkRes = false;
        while (iterator.hasNext()) {
            Object o = iterator.next();
            if (!(o instanceof String)) {
                return false;
            }
            String s = (String) o;
            if (s.contains("org.microg.gms") && s.contains(".apk")) {
                Log.d(TAG, "Detected maps set");
                return true;
            Log.d(TAG, "mapdetect: " + s);
            if (s.contains("app_dg_cache")) hasDgCache = true;
            if (s.contains("framework-res.apk")) hasFrameworkRes = true;
        }
        }
        return false;
        return hasDgCache && hasFrameworkRes;
    }

    private static Set<String> createMapsReplacementSet() {
    static Set<String> createMapsReplacementSet() {
        Set<String> replacement = new TreeSet<>();
        replacement.add("/data/app/com.google.android.gms-1/base.apk");
        replacement.add("/data/app/com.google.android.gms-1/oat/" + odexArch + "/base.odex");