From 36b0d456a3d7468e3651755fec4abb073eb3a063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Fri, 12 Jan 2018 10:22:10 +0800 Subject: [PATCH 01/59] 0.3.6 --- exposed-core/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 3133ea3..d2fa4f1 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,13 +23,13 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu:epic:0.3.5' // The AOP Framework - compile 'me.weishu.exposed:exposed-xposedapi:0.3.0' // The Xposed API + compile 'me.weishu:epic:0.3.6' // The AOP Framework + compile 'me.weishu.exposed:exposed-xposedapi:0.3.1' // The Xposed API compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.3.5' +version = '0.3.6' apply plugin: 'com.novoda.bintray-release' From c3f97e0cd79c23cd72271d9a0b4011dc90852e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 13 Jan 2018 12:39:46 +0800 Subject: [PATCH 02/59] [Exposed]: remove hooks for module fragment(has been done in XposedInstaller) --- .../java/me/weishu/exposed/ExposedBridge.java | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index c584d27..2d6c045 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -1,8 +1,6 @@ package me.weishu.exposed; import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.Fragment; import android.content.Context; import android.content.pm.ApplicationInfo; import android.os.Build; @@ -11,7 +9,6 @@ import android.util.Pair; import android.view.AbsSavedState; import android.view.View; -import android.widget.Toast; import com.getkeepsafe.relinker.ReLinker; import com.taobao.android.dexposed.DexposedBridge; @@ -31,7 +28,6 @@ import java.lang.reflect.Member; import java.util.HashMap; import java.util.HashSet; -import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -287,28 +283,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mPrivateFlags.set(param.thisObject, flags | 0x00020000); } }); - - // make the module reload when enter ModuleFragment - DexposedBridge.findAndHookMethod(Fragment.class, "onResume", new com.taobao.android.dexposed.XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - super.afterHookedMethod(param); - Fragment fragment = (Fragment) param.thisObject; - if ("de.robv.android.xposed.installer.ModulesFragment".equals(fragment.getClass().getName())) { - // ModulesFragment, call reload - Class moduleUtilClass = fragment.getClass().getClassLoader().loadClass("de.robv.android.xposed.installer.util.ModuleUtil"); - Object moduleUtil = XposedHelpers.callStaticMethod(moduleUtilClass, "getInstance"); - XposedHelpers.callMethod(moduleUtil, "reloadInstalledModules"); - Activity activity = fragment.getActivity(); - log("module fragment reload success, activity:" + activity); - if (activity != null) { - String tips = Locale.getDefault().toString().contains("zh") ? "勾选模块之后,需要在主界面右上角按钮 -> 重启 才能生效哦~" : - "module will take effect after Settings->Reboot!"; - Toast.makeText(activity, tips, Toast.LENGTH_SHORT).show(); - } - } - } - }); } /** From 1d89fa5189f04dd415f7c36e2a67c5da0e2aaef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Mon, 15 Jan 2018 15:55:44 +0800 Subject: [PATCH 03/59] [Exposed]: 1. fix the XSharedPreference load path bug 2. make the Xposed version 91(Just makes me happy.) 3. Add Module load observer. 4. update dependency. --- exposed-core/build.gradle | 6 +- .../java/me/weishu/exposed/ExposedBridge.java | 124 +++++++++++++++++- .../me/weishu/exposed/ModuleLoadListener.java | 11 ++ 3 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index d2fa4f1..7ec1b3c 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,13 +23,13 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu:epic:0.3.6' // The AOP Framework - compile 'me.weishu.exposed:exposed-xposedapi:0.3.1' // The Xposed API + compile 'me.weishu:epic:0.3.7' // The AOP Framework + compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.3.6' +version = '0.3.7' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 2d6c045..cf3120d 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -1,9 +1,13 @@ package me.weishu.exposed; import android.annotation.SuppressLint; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.os.Build; +import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -26,11 +30,13 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.TimeUnit; import dalvik.system.DexClassLoader; import de.robv.android.xposed.ExposedHelper; @@ -38,6 +44,7 @@ import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -63,6 +70,14 @@ public class ExposedBridge { private static Map exposedClassLoaderMap = new HashMap<>(); private static ClassLoader xposedClassLoader; + private static Context appContext; + private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { + @Override + public void onModuleLoaded(String moduleName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + // initForWeChatTranslate(moduleName, applicationInfo, appClassLoader); + } + }; + /** * Module load result */ @@ -75,8 +90,11 @@ enum ModuleLoadResult { } public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + appContext = context; ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); + XSharedPreferences.setPackageBaseDirectory(new File(applicationInfo.dataDir).getParentFile()); + initForXposedInstaller(context, applicationInfo, appClassLoader); } @@ -179,6 +197,8 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod // TODO: 17/12/1 Support Resource hook } + sModuleLoadListener.onModuleLoaded(moduleClassName, currentApplicationInfo, mcl); + return ModuleLoadResult.SUCCESS; } catch (Throwable t) { log(t); @@ -209,7 +229,7 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl Log.i(TAG, "initForXposedInstaller"); // XposedInstaller - final int fakeXposedVersion = 89; + final int fakeXposedVersion = 91; final String fakeVersionString = String.valueOf(fakeXposedVersion); final File xposedProp = context.getFileStreamPath("xposed_prop"); if (!xposedProp.exists()) { @@ -285,6 +305,108 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { }); } + + private static void initForWeChatTranslate(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + if (!"com.hkdrjxy.wechart.xposed.XposedInit".equals(moduleClassName)) { + return; + } + + if (!("com.hiwechart.translate".equals(applicationInfo.processName) || "com.tencent.mm".equals(applicationInfo.processName))) { + return; + } + + final IBinder[] translateService = new IBinder[1]; + Intent intent = new Intent(); + intent.setAction("com.hiwechart.translate.aidl.TranslateService"); + ComponentName v2 = new ComponentName("com.hiwechart.translate", "com.hiwechart.translate.aidl.TranslateService"); + intent.setComponent(v2); + appContext.bindService(intent, new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Log.i("mylog", "onServiceConnected: " + service); + translateService[0] = service; + } + + @Override + public void onServiceDisconnected(ComponentName name) { + + } + }, Context.BIND_AUTO_CREATE); + + Class serviceManager = XposedHelpers.findClass("android.os.ServiceManager", appClassLoader); + final String serviceName = Build.VERSION.SDK_INT >= 21 ? "user.wechart.trans" : "wechart.trans"; + DexposedBridge.findAndHookMethod(serviceManager, "getService", String.class, new com.taobao.android.dexposed.XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + if (serviceName.equals(param.args[0])) { + Log.i("mylog", "get service :" + translateService[0]); + param.setResult(translateService[0]); + } + } + }); + + try { + Class okHttpClient = XposedHelpers.findClass("okhttp3.OkHttpClient", appClassLoader); + DexposedBridge.findAndHookMethod(okHttpClient, "newBuilder", new com.taobao.android.dexposed.XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.afterHookedMethod(param); + Log.i("mylog", "OkHttpClient.newBuilder before:"); + } + + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + super.afterHookedMethod(param); + Log.i("mylog", "OkHttpClient.newBuilder after:" + param.getResult()); + } + }); + + Class DevicesLocation = XposedHelpers.findClass("okhttp3.OkHttpClient$Builder", appClassLoader); + DexposedBridge.hookAllConstructors(DevicesLocation, new com.taobao.android.dexposed.XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + Log.i("mylog", "OkHttpClient$Builder:" + Arrays.toString(param.args), new RuntimeException("stack")); + } + }); + + DexposedBridge.findAndHookMethod(DevicesLocation, "checkDuration", String.class, long.class, TimeUnit.class, new com.taobao.android.dexposed.XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + Log.i("mylog", "checkDuration:" + Arrays.toString(param.args)); + } + }); + + DexposedBridge.findAndHookMethod(DevicesLocation, "connectTimeout", long.class, TimeUnit.class, new com.taobao.android.dexposed.XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + super.afterHookedMethod(param); + Log.i("mylog", "connectTimeout, this: " + param.thisObject + ", args:" + Arrays.toString(param.args) + ", result:" + param.getResult()); + } + }); + } catch (Throwable e) { + Log.e("mylog", "classLoader eror", e); + } + } + +// private static void initForWeChatTranslate(final Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { +// if (!"".equals(applicationInfo.packageName)) { +// return; +// } +// DexposedBridge.findAndHookMethod(Environment.class, "getExternalStorageDirectory", new com.taobao.android.dexposed.XC_MethodHook() { +// @Override +// protected void beforeHookedMethod(MethodHookParam param) throws Throwable { +// super.beforeHookedMethod(param); +// File f = context.getFilesDir(); +// param.setResult(f); +// } +// }); +// +// } + + /** * write xposed property file to fake xposedinstaller * @param propertyFile the property file used by XposedInstaller diff --git a/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java b/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java new file mode 100644 index 0000000..5aecddd --- /dev/null +++ b/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java @@ -0,0 +1,11 @@ +package me.weishu.exposed; + +import android.content.pm.ApplicationInfo; + +/** + * author: weishu on 18/1/14. + */ + +public interface ModuleLoadListener { + void onModuleLoaded(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader); +} From 6705832b1c77c4308b8ba4ddbb22b5a0ac5a442b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Mon, 15 Jan 2018 18:40:59 +0800 Subject: [PATCH 04/59] [Exposed]: remove the dependency of Dexposed. --- exposed-core/build.gradle | 6 +- .../de/robv/android/xposed/ExposedHelper.java | 7 -- .../java/me/weishu/exposed/ExposedBridge.java | 28 ++++---- .../java/me/weishu/exposed/LogcatService.java | 3 +- .../weishu/exposed/MethodHookParamDx2X.java | 67 ------------------- .../java/me/weishu/exposed/ParamDx2X.java | 33 --------- .../me/weishu/exposed/XC_MethodHookX2Dx.java | 32 --------- 7 files changed, 19 insertions(+), 157 deletions(-) delete mode 100644 exposed-core/src/main/java/me/weishu/exposed/MethodHookParamDx2X.java delete mode 100644 exposed-core/src/main/java/me/weishu/exposed/ParamDx2X.java delete mode 100644 exposed-core/src/main/java/me/weishu/exposed/XC_MethodHookX2Dx.java diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 7ec1b3c..e7efd16 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,13 +23,15 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu:epic:0.3.7' // The AOP Framework compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API + compile ('me.weishu:epic:0.3.8') { // The AOP Framework + exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' + } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.3.7' +version = '0.3.8' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java index c13de28..fd53d16 100644 --- a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java +++ b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java @@ -16,13 +16,6 @@ public static boolean isIXposedMod(Class moduleClass) { return IXposedMod.class.isAssignableFrom(moduleClass); } - public static void beforeHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable { - methodHook.beforeHookedMethod(param); - } - - public static void afterHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable { - methodHook.afterHookedMethod(param); - } public static XC_MethodHook.Unhook newUnHook(XC_MethodHook methodHook, Member member) { return methodHook.new Unhook(member); diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index cf3120d..4fc09c0 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -15,7 +15,6 @@ import android.view.View; import com.getkeepsafe.relinker.ReLinker; -import com.taobao.android.dexposed.DexposedBridge; import java.io.BufferedReader; import java.io.Closeable; @@ -39,6 +38,7 @@ import java.util.concurrent.TimeUnit; import dalvik.system.DexClassLoader; +import de.robv.android.xposed.DexposedBridge; import de.robv.android.xposed.ExposedHelper; import de.robv.android.xposed.IXposedHookInitPackageResources; import de.robv.android.xposed.IXposedHookLoadPackage; @@ -49,7 +49,7 @@ import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; -import static com.taobao.android.dexposed.DexposedBridge.log; +import static de.robv.android.xposed.XposedBridge.log; public class ExposedBridge { @@ -216,7 +216,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod } public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callback) { - final com.taobao.android.dexposed.XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, new XC_MethodHookX2Dx(callback)); + final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback); return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); } @@ -252,16 +252,16 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl Array.set(xposed_prop_files, i, xposedPropPath); } - DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); param.setResult(fakeXposedVersion); } }); - DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); param.setResult(fakeXposedVersion); } @@ -270,7 +270,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { final Constructor fileConstructor1 = XposedHelpers.findConstructorExact(File.class, String.class); final Constructor fileConstructor2 = XposedHelpers.findConstructorExact(File.class, String.class, String.class); final String dataDir = applicationInfo.dataDir; - DexposedBridge.hookMethod(fileConstructor1, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.hookMethod(fileConstructor1, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -280,7 +280,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } } }); - DexposedBridge.hookMethod(fileConstructor2, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.hookMethod(fileConstructor2, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -293,7 +293,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // fix bug on Android O: https://github.com/emilsjolander/StickyListHeaders/issues/477 Class stickyListHeadersClass = XposedHelpers.findClass("se.emilsjolander.stickylistheaders.StickyListHeadersListView", appClassLoader); - DexposedBridge.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -335,7 +335,7 @@ public void onServiceDisconnected(ComponentName name) { Class serviceManager = XposedHelpers.findClass("android.os.ServiceManager", appClassLoader); final String serviceName = Build.VERSION.SDK_INT >= 21 ? "user.wechart.trans" : "wechart.trans"; - DexposedBridge.findAndHookMethod(serviceManager, "getService", String.class, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(serviceManager, "getService", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -348,7 +348,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { try { Class okHttpClient = XposedHelpers.findClass("okhttp3.OkHttpClient", appClassLoader); - DexposedBridge.findAndHookMethod(okHttpClient, "newBuilder", new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(okHttpClient, "newBuilder", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); @@ -363,7 +363,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { }); Class DevicesLocation = XposedHelpers.findClass("okhttp3.OkHttpClient$Builder", appClassLoader); - DexposedBridge.hookAllConstructors(DevicesLocation, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.hookAllConstructors(DevicesLocation, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -371,7 +371,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } }); - DexposedBridge.findAndHookMethod(DevicesLocation, "checkDuration", String.class, long.class, TimeUnit.class, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(DevicesLocation, "checkDuration", String.class, long.class, TimeUnit.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -379,7 +379,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } }); - DexposedBridge.findAndHookMethod(DevicesLocation, "connectTimeout", long.class, TimeUnit.class, new com.taobao.android.dexposed.XC_MethodHook() { + DexposedBridge.findAndHookMethod(DevicesLocation, "connectTimeout", long.class, TimeUnit.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); diff --git a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java index b0d8f63..9809c0d 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java +++ b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java @@ -7,13 +7,12 @@ import android.text.TextUtils; import android.util.Log; -import com.taobao.android.dexposed.DexposedBridge; - import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import de.robv.android.xposed.DexposedBridge; import de.robv.android.xposed.XposedHelpers; /** diff --git a/exposed-core/src/main/java/me/weishu/exposed/MethodHookParamDx2X.java b/exposed-core/src/main/java/me/weishu/exposed/MethodHookParamDx2X.java deleted file mode 100644 index 3c4a1c9..0000000 --- a/exposed-core/src/main/java/me/weishu/exposed/MethodHookParamDx2X.java +++ /dev/null @@ -1,67 +0,0 @@ -package me.weishu.exposed; - -import android.os.Bundle; - -import de.robv.android.xposed.XC_MethodHook; - -/** - * Created by weishu on 17/11/30. - */ - -public class MethodHookParamDx2X extends XC_MethodHook.MethodHookParam { - - private com.taobao.android.dexposed.XC_MethodHook.MethodHookParam beWrapped; - - public MethodHookParamDx2X(com.taobao.android.dexposed.XC_MethodHook.MethodHookParam beWrapped) { - this.beWrapped = beWrapped; - - this.method = beWrapped.method; - this.args = beWrapped.args; // reference, lalala - this.thisObject = beWrapped.thisObject; - } - - @Override - public synchronized Bundle getExtra() { - return beWrapped.getExtra(); - } - - @Override - public Object getObjectExtra(String key) { - return beWrapped.getObjectExtra(key); - } - - @Override - public void setObjectExtra(String key, Object o) { - beWrapped.setObjectExtra(key, o); - } - - @Override - public Object getResult() { - return beWrapped.getResult(); - } - - @Override - public void setResult(Object result) { - beWrapped.setResult(result); - } - - @Override - public Throwable getThrowable() { - return beWrapped.getThrowable(); - } - - @Override - public boolean hasThrowable() { - return beWrapped.hasThrowable(); - } - - @Override - public void setThrowable(Throwable throwable) { - beWrapped.setThrowable(throwable); - } - - @Override - public Object getResultOrThrowable() throws Throwable { - return beWrapped.getResultOrThrowable(); - } -} diff --git a/exposed-core/src/main/java/me/weishu/exposed/ParamDx2X.java b/exposed-core/src/main/java/me/weishu/exposed/ParamDx2X.java deleted file mode 100644 index ff455d0..0000000 --- a/exposed-core/src/main/java/me/weishu/exposed/ParamDx2X.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.weishu.exposed; - -import android.os.Bundle; - -import de.robv.android.xposed.callbacks.XCallback; - -/** - * Created by weishu on 17/11/30. - */ - -public class ParamDx2X extends XCallback.Param { - - private com.taobao.android.dexposed.callbacks.XCallback.Param beWrapped; - - public ParamDx2X(com.taobao.android.dexposed.callbacks.XCallback.Param beWrapped) { - this.beWrapped = beWrapped; - } - - @Override - public synchronized Bundle getExtra() { - return beWrapped.getExtra(); - } - - @Override - public Object getObjectExtra(String key) { - return beWrapped.getObjectExtra(key); - } - - @Override - public void setObjectExtra(String key, Object o) { - beWrapped.setObjectExtra(key, o); - } -} diff --git a/exposed-core/src/main/java/me/weishu/exposed/XC_MethodHookX2Dx.java b/exposed-core/src/main/java/me/weishu/exposed/XC_MethodHookX2Dx.java deleted file mode 100644 index d0338af..0000000 --- a/exposed-core/src/main/java/me/weishu/exposed/XC_MethodHookX2Dx.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.weishu.exposed; - -import de.robv.android.xposed.ExposedHelper; -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedHelpers; - -/** - * Xposed's XC_MethodHook 2 Dexposed's XC_Method. - */ -public class XC_MethodHookX2Dx extends com.taobao.android.dexposed.XC_MethodHook { - - private XC_MethodHook beWrapped; - - public XC_MethodHookX2Dx(XC_MethodHook methodHook) { - beWrapped = methodHook; - } - - @Override - protected void beforeHookedMethod(com.taobao.android.dexposed.XC_MethodHook.MethodHookParam param) throws Throwable { - ExposedHelper.beforeHookedMethod(beWrapped, new MethodHookParamDx2X(param)); - } - - @Override - protected void afterHookedMethod(com.taobao.android.dexposed.XC_MethodHook.MethodHookParam param) throws Throwable { - ExposedHelper.afterHookedMethod(beWrapped, new MethodHookParamDx2X(param)); - } - - @Override - protected void call(Param param) throws Throwable { - XposedHelpers.callMethod(beWrapped, "call", new ParamDx2X(param)); - } -} From 4dc3dd226e02526275a91a5a1bdd7d46f4d45bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Wed, 17 Jan 2018 20:03:26 +0800 Subject: [PATCH 05/59] [Exposed]: Fix the NPE caused by Android N's classloader bug. --- .../java/me/weishu/exposed/ExposedBridge.java | 73 ++----------------- 1 file changed, 6 insertions(+), 67 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 4fc09c0..98977b6 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -29,13 +29,11 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.concurrent.TimeUnit; import dalvik.system.DexClassLoader; import de.robv.android.xposed.DexposedBridge; @@ -74,7 +72,7 @@ public class ExposedBridge { private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override public void onModuleLoaded(String moduleName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { - // initForWeChatTranslate(moduleName, applicationInfo, appClassLoader); + initForWeChatTranslate(moduleName, applicationInfo, appClassLoader); } }; @@ -136,7 +134,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod return ModuleLoadResult.DISABLED; } - log("Loading modules from " + moduleApkPath); + log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName); if (!new File(moduleApkPath).exists()) { log(moduleApkPath + " does not exist"); @@ -146,7 +144,9 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod ClassLoader hostClassLoader = ExposedBridge.class.getClassLoader(); ClassLoader appClassLoaderWithXposed = getAppClassLoaderWithXposed(appClassLoader); - ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, hostClassLoader); + ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, getXposedClassLoader(hostClassLoader)); + // ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, hostClassLoader); + InputStream is = mcl.getResourceAsStream("assets/xposed_init"); if (is == null) { log("assets/xposed_init not found in the APK"); @@ -311,7 +311,7 @@ private static void initForWeChatTranslate(String moduleClassName, ApplicationIn return; } - if (!("com.hiwechart.translate".equals(applicationInfo.processName) || "com.tencent.mm".equals(applicationInfo.processName))) { + if (!("com.hiwechart.translate".equals(applicationInfo.processName) || "com.tencent.mm".equals(applicationInfo.processName))){ return; } @@ -323,7 +323,6 @@ private static void initForWeChatTranslate(String moduleClassName, ApplicationIn appContext.bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { - Log.i("mylog", "onServiceConnected: " + service); translateService[0] = service; } @@ -345,68 +344,8 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } } }); - - try { - Class okHttpClient = XposedHelpers.findClass("okhttp3.OkHttpClient", appClassLoader); - DexposedBridge.findAndHookMethod(okHttpClient, "newBuilder", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.afterHookedMethod(param); - Log.i("mylog", "OkHttpClient.newBuilder before:"); - } - - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - super.afterHookedMethod(param); - Log.i("mylog", "OkHttpClient.newBuilder after:" + param.getResult()); - } - }); - - Class DevicesLocation = XposedHelpers.findClass("okhttp3.OkHttpClient$Builder", appClassLoader); - DexposedBridge.hookAllConstructors(DevicesLocation, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - Log.i("mylog", "OkHttpClient$Builder:" + Arrays.toString(param.args), new RuntimeException("stack")); - } - }); - - DexposedBridge.findAndHookMethod(DevicesLocation, "checkDuration", String.class, long.class, TimeUnit.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - Log.i("mylog", "checkDuration:" + Arrays.toString(param.args)); - } - }); - - DexposedBridge.findAndHookMethod(DevicesLocation, "connectTimeout", long.class, TimeUnit.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - super.afterHookedMethod(param); - Log.i("mylog", "connectTimeout, this: " + param.thisObject + ", args:" + Arrays.toString(param.args) + ", result:" + param.getResult()); - } - }); - } catch (Throwable e) { - Log.e("mylog", "classLoader eror", e); - } } -// private static void initForWeChatTranslate(final Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { -// if (!"".equals(applicationInfo.packageName)) { -// return; -// } -// DexposedBridge.findAndHookMethod(Environment.class, "getExternalStorageDirectory", new com.taobao.android.dexposed.XC_MethodHook() { -// @Override -// protected void beforeHookedMethod(MethodHookParam param) throws Throwable { -// super.beforeHookedMethod(param); -// File f = context.getFilesDir(); -// param.setResult(f); -// } -// }); -// -// } - - /** * write xposed property file to fake xposedinstaller * @param propertyFile the property file used by XposedInstaller From 1116d14ab2408a56d35a6d3558d1a20e0307d180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Wed, 24 Jan 2018 10:44:06 +0800 Subject: [PATCH 06/59] [Exposed] Fix: The Xposed class in 'external' package may not found. --- .../src/main/java/me/weishu/exposed/XposedClassLoader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java b/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java index 42810dc..c9fba53 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java +++ b/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java @@ -13,7 +13,9 @@ public XposedClassLoader(ClassLoader hostClassLoader) { @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.startsWith("de.robv.android.xposed") || name.startsWith("android")) { + if (name.startsWith("de.robv.android.xposed") + || name.startsWith("android") + || name.startsWith("external")) { return mHostClassLoader.loadClass(name); } return super.loadClass(name, resolve); From 8e05eb3f5f5abd919f5b621350314b18e7cb016f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Thu, 25 Jan 2018 10:42:21 +0800 Subject: [PATCH 07/59] [Exposed] init for Xposed module. --- .../main/java/me/weishu/exposed/ExposedBridge.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 98977b6..d9f02f8 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -93,6 +93,7 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl ExposedHelper.initSeLinux(applicationInfo.processName); XSharedPreferences.setPackageBaseDirectory(new File(applicationInfo.dataDir).getParentFile()); + initForXposedModule(context, applicationInfo, appClassLoader); initForXposedInstaller(context, applicationInfo, appClassLoader); } @@ -220,6 +221,18 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); } + private static void initForXposedModule(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + InputStream inputStream = null; + + try { + inputStream = context.getAssets().open("xposed_init"); + System.setProperty("epic.force", "true"); + } catch (IOException e) { + log("initForXposedModule, ignore :" + applicationInfo.packageName); + } finally { + closeSliently(inputStream); + } + } private static void initForXposedInstaller(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { if (!XPOSED_INSTALL_PACKAGE.equals(applicationInfo.packageName)) { From 4f27d22375adc5bb02b591bceee2d7f38cdf8ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 00:05:51 +0800 Subject: [PATCH 08/59] [Exposed] tempera solution for wexposed do not show avatar. --- .../java/me/weishu/exposed/ExposedBridge.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index d9f02f8..5f213cd 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; +import android.graphics.Bitmap; import android.os.Build; import android.os.IBinder; import android.text.TextUtils; @@ -29,6 +30,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -68,6 +70,8 @@ public class ExposedBridge { private static Map exposedClassLoaderMap = new HashMap<>(); private static ClassLoader xposedClassLoader; + private static volatile boolean isWxposed = false; + private static Context appContext; private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override @@ -166,6 +170,10 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod log(" Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); + if ("com.fkzhang.wechatxposed.XposedInit".equalsIgnoreCase(moduleClassName)) { + isWxposed = true; + } + if (!ExposedHelper.isIXposedMod(moduleClass)) { log(" This class doesn't implement any sub-interface of IXposedMod, skipping it"); continue; @@ -216,7 +224,22 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod return ModuleLoadResult.FAILED; } + private static boolean ignoreHooks(Member member) { + if (isWxposed) { + if (member instanceof Method) { + if (((Method) member).getReturnType() == Bitmap.class) { + log("ignore hook: " + ((Method) member).toGenericString()); + return true; + } + } + } + return false; + } + public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callback) { + if (ignoreHooks(method)) { + return null; + } final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback); return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); } From 009adff5e73836d752baa916b449a267ca5729e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 00:54:10 +0800 Subject: [PATCH 09/59] 0.4.0 --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index e7efd16..2aaeadf 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API - compile ('me.weishu:epic:0.3.8') { // The AOP Framework + compile ('me.weishu:epic:0.4.0') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.3.8' +version = '0.4.0' apply plugin: 'com.novoda.bintray-release' From 60ee5fd444d08658027254829e95b74724b387bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 20:18:25 +0800 Subject: [PATCH 10/59] [Exposed]: fix freezing UI of wexposed. --- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 5f213cd..7e4d174 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -231,6 +231,10 @@ private static boolean ignoreHooks(Member member) { log("ignore hook: " + ((Method) member).toGenericString()); return true; } + if ("closeChatting".equalsIgnoreCase(member.getName())) { + log("ignore hook: " + ((Method) member).toGenericString()); + return true; + } } } return false; From 894637654be8a96096118419f9c13c5b0a778351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 20:39:37 +0800 Subject: [PATCH 11/59] 0.4.1 --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 2aaeadf..ceaf027 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API - compile ('me.weishu:epic:0.4.0') { // The AOP Framework + compile ('me.weishu:epic:0.4.1') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.4.0' +version = '0.4.1' apply plugin: 'com.novoda.bintray-release' From 69cfdc98cf0a96b456fbf441b292fe7a6d5c1cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 20:46:04 +0800 Subject: [PATCH 12/59] [Exposed] : collect more log. --- .../src/main/java/me/weishu/exposed/LogcatService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java index 9809c0d..72b68fb 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java +++ b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java @@ -56,7 +56,9 @@ public void run() { List cmds = new ArrayList(); cmds.add("sh"); cmds.add("-c"); - cmds.add("logcat -v time -s XposedStartupMarker:D Xposed:I appproc:I XposedInstaller:I art:F DexposedBridge:I >> " + path); + cmds.add("logcat -v time -s XposedStartupMarker:D Xposed:I appproc:I XposedInstaller:I art:F DexposedBridge:I ExposedBridge:D " + + "Runtime:I EpicNative:D VClientImpl:D " + + " >> " + path); ProcessBuilder pb = new ProcessBuilder(cmds); Process p = pb.start(); p.waitFor(); From 9290976b5b52663684c2e4ef4d498b5e4e687514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 27 Jan 2018 20:46:40 +0800 Subject: [PATCH 13/59] [Exposed] : collect more log. --- exposed-core/src/main/java/me/weishu/exposed/LogcatService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java index 72b68fb..efd6075 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java +++ b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java @@ -57,7 +57,7 @@ public void run() { cmds.add("sh"); cmds.add("-c"); cmds.add("logcat -v time -s XposedStartupMarker:D Xposed:I appproc:I XposedInstaller:I art:F DexposedBridge:I ExposedBridge:D " + - "Runtime:I EpicNative:D VClientImpl:D " + + "Runtime:I EpicNative:D VClientImpl:D VApp:I " + " >> " + path); ProcessBuilder pb = new ProcessBuilder(cmds); Process p = pb.start(); From a6ea43e6d6f26f10d2bee4869ec834f4a7c6aec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Fri, 2 Feb 2018 14:45:21 +0800 Subject: [PATCH 14/59] [Exposed] : do not load any module for XposedInstaller. --- .../main/java/me/weishu/exposed/ExposedBridge.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 7e4d174..fcf63f4 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -88,7 +88,8 @@ enum ModuleLoadResult { NOT_EXIST, INVALID, SUCCESS, - FAILED + FAILED, + IGNORED } public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { @@ -131,6 +132,10 @@ public static synchronized ClassLoader getXposedClassLoader(ClassLoader hostClas public static ModuleLoadResult loadModule(final String moduleApkPath, String moduleOdexDir, String moduleLibPath, final ApplicationInfo currentApplicationInfo, ClassLoader appClassLoader) { + if (isXposedInstaller(currentApplicationInfo)) { + return ModuleLoadResult.IGNORED; + } + final String rootDir = new File(currentApplicationInfo.dataDir).getParent(); loadModuleConfig(rootDir, currentApplicationInfo.processName); @@ -261,8 +266,12 @@ private static void initForXposedModule(Context context, ApplicationInfo applica } } + private static boolean isXposedInstaller(ApplicationInfo applicationInfo) { + return XPOSED_INSTALL_PACKAGE.equals(applicationInfo.packageName); + } + private static void initForXposedInstaller(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { - if (!XPOSED_INSTALL_PACKAGE.equals(applicationInfo.packageName)) { + if (!isXposedInstaller(applicationInfo)) { return; } From 4474641b6f32bf85d530756e7fa372bafbfcf7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Fri, 2 Feb 2018 20:27:17 +0800 Subject: [PATCH 15/59] [Exposed] : fix the notification can not show on some devices. --- .../java/me/weishu/exposed/ExposedBridge.java | 23 +++++++++++++------ .../me/weishu/exposed/ModuleLoadListener.java | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index fcf63f4..c6e0ed9 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -70,10 +70,17 @@ public class ExposedBridge { private static Map exposedClassLoaderMap = new HashMap<>(); private static ClassLoader xposedClassLoader; - private static volatile boolean isWxposed = false; + private static volatile boolean isWeChat = false; private static Context appContext; private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { + @Override + public void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + if ("com.tencent.mm".equalsIgnoreCase(applicationInfo.packageName)) { + isWeChat = true; + } + } + @Override public void onModuleLoaded(String moduleName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { initForWeChatTranslate(moduleName, applicationInfo, appClassLoader); @@ -175,9 +182,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod log(" Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); - if ("com.fkzhang.wechatxposed.XposedInit".equalsIgnoreCase(moduleClassName)) { - isWxposed = true; - } + sModuleLoadListener.onLoadingModule(moduleClassName, currentApplicationInfo, mcl); if (!ExposedHelper.isIXposedMod(moduleClass)) { log(" This class doesn't implement any sub-interface of IXposedMod, skipping it"); @@ -230,14 +235,18 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod } private static boolean ignoreHooks(Member member) { - if (isWxposed) { + if (isWeChat) { if (member instanceof Method) { if (((Method) member).getReturnType() == Bitmap.class) { - log("ignore hook: " + ((Method) member).toGenericString()); + log("i h: " + ((Method) member).toGenericString()); return true; } if ("closeChatting".equalsIgnoreCase(member.getName())) { - log("ignore hook: " + ((Method) member).toGenericString()); + log("i h: " + ((Method) member).toGenericString()); + return true; + } + if (member.getDeclaringClass().getName().contains("notification")) { + log("i h: " + ((Method) member).toGenericString()); return true; } } diff --git a/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java b/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java index 5aecddd..0f6a924 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ModuleLoadListener.java @@ -7,5 +7,6 @@ */ public interface ModuleLoadListener { + void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader); void onModuleLoaded(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader); } From d2c74d5bf1fdefd64088dd153db3f6b905d5e8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 3 Feb 2018 01:09:52 +0800 Subject: [PATCH 16/59] 0.4.4 --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index ceaf027..f839ec8 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API - compile ('me.weishu:epic:0.4.1') { // The AOP Framework + compile ('me.weishu:epic:0.4.4') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.4.1' +version = '0.4.4' apply plugin: 'com.novoda.bintray-release' From 728fb697e0d1cc6f6ae49fba902222adff86ee80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 3 Feb 2018 16:52:23 +0800 Subject: [PATCH 17/59] [Exposed] try inject the systemclassloader instead; (do not replace the app classloader) --- .../java/me/weishu/exposed/ExposedBridge.java | 64 +++++++++++++------ .../me/weishu/exposed/XposedClassLoader.java | 11 ++-- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index c6e0ed9..abdcfaa 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -65,6 +65,9 @@ public class ExposedBridge { ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; private static final String VERSION_KEY = "version"; + private static boolean SYSTEM_CLASSLOADER_INJECT = true; + + private static final String WECHAT_PACKAGE = "com.tencent.mm"; private static Pair> lastModuleList = Pair.create(null, null); private static Map exposedClassLoaderMap = new HashMap<>(); @@ -76,7 +79,7 @@ public class ExposedBridge { private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override public void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { - if ("com.tencent.mm".equalsIgnoreCase(applicationInfo.packageName)) { + if (WECHAT_PACKAGE.equalsIgnoreCase(applicationInfo.packageName)) { isWeChat = true; } } @@ -100,6 +103,8 @@ enum ModuleLoadResult { } public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); + appContext = context; ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); @@ -109,15 +114,31 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForXposedInstaller(context, applicationInfo, appClassLoader); } - public static void patchAppClassLoader(Context baseContext) { - final ClassLoader originClassLoader = baseContext.getClassLoader(); - Object mPackageInfo = XposedHelpers.getObjectField(baseContext, "mPackageInfo"); - ClassLoader appClassLoaderWithXposed = getAppClassLoaderWithXposed(originClassLoader); - XposedHelpers.setObjectField(mPackageInfo, "mClassLoader", appClassLoaderWithXposed); - Thread.currentThread().setContextClassLoader(appClassLoaderWithXposed); + private static boolean patchSystemClassLoader() { + // 1. first create XposedClassLoader -> BootstrapClassLoader + ClassLoader xposedClassLoader = new XposedClassLoader(ExposedBridge.class.getClassLoader()); + + // 2. replace the systemclassloader's parent. + ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + + try { + Field parent = ClassLoader.class.getDeclaredField("parent"); + parent.setAccessible(true); + parent.set(systemClassLoader, xposedClassLoader); + + // SystemClassLoader -> XposedClassLoader -> BootstrapClassLoader + return systemClassLoader.getParent() == xposedClassLoader; + } catch (NoSuchFieldException e) { + // todo no such field ? use unsafe. + log(e); + return false; + } catch (IllegalAccessException e) { + log(e); + return false; + } } - public static synchronized ClassLoader getAppClassLoaderWithXposed(ClassLoader appClassLoader) { + private static synchronized ClassLoader getAppClassLoaderWithXposed(ClassLoader appClassLoader) { if (exposedClassLoaderMap.containsKey(appClassLoader)) { return exposedClassLoaderMap.get(appClassLoader); } else { @@ -151,18 +172,26 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod return ModuleLoadResult.DISABLED; } - log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName); + log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT); if (!new File(moduleApkPath).exists()) { log(moduleApkPath + " does not exist"); return ModuleLoadResult.NOT_EXIST; } - ClassLoader hostClassLoader = ExposedBridge.class.getClassLoader(); - ClassLoader appClassLoaderWithXposed = getAppClassLoaderWithXposed(appClassLoader); - - ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, getXposedClassLoader(hostClassLoader)); - // ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, hostClassLoader); + ClassLoader appClassLoaderWithXposed; + ClassLoader mcl; + if (SYSTEM_CLASSLOADER_INJECT) { + // we replace the systemclassloader's parent success, go with xposed's way + appClassLoaderWithXposed = appClassLoader; + mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, XposedBridge.BOOTCLASSLOADER); + } else { + // replace failed, just wrap. + ClassLoader hostClassLoader = ExposedBridge.class.getClassLoader(); + appClassLoaderWithXposed = getAppClassLoaderWithXposed(appClassLoader); + mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, getXposedClassLoader(hostClassLoader)); + // ClassLoader mcl = new DexClassLoader(moduleApkPath, moduleOdexDir, moduleLibPath, hostClassLoader); + } InputStream is = mcl.getResourceAsStream("assets/xposed_init"); if (is == null) { @@ -226,10 +255,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod } catch (IOException e) { log(e); } finally { - try { - is.close(); - } catch (IOException ignored) { - } + closeSliently(is); } return ModuleLoadResult.FAILED; } @@ -284,8 +310,6 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl return; } - Log.i(TAG, "initForXposedInstaller"); - // XposedInstaller final int fakeXposedVersion = 91; final String fakeVersionString = String.valueOf(fakeXposedVersion); diff --git a/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java b/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java index c9fba53..ae2cdfb 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java +++ b/exposed-core/src/main/java/me/weishu/exposed/XposedClassLoader.java @@ -3,11 +3,12 @@ /** * XposedClassLoader: use to only load xposed api classes. */ -public class XposedClassLoader extends ClassLoader { +class XposedClassLoader extends ClassLoader { private ClassLoader mHostClassLoader; - public XposedClassLoader(ClassLoader hostClassLoader) { - super(ClassLoader.getSystemClassLoader()); // parent is BootClassLoader + + XposedClassLoader(ClassLoader hostClassLoader) { + super(ClassLoader.getSystemClassLoader().getParent()); // BootstrapClassLoader mHostClassLoader = hostClassLoader; } @@ -15,7 +16,9 @@ public XposedClassLoader(ClassLoader hostClassLoader) { protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (name.startsWith("de.robv.android.xposed") || name.startsWith("android") - || name.startsWith("external")) { + || name.startsWith("external") + || name.startsWith("me.weishu.epic.art") + || name.startsWith("com.taobao.android.dexposed")) { return mHostClassLoader.loadClass(name); } return super.loadClass(name, resolve); From c828edb392ad8c9a71744e742b817378ad7112a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 3 Feb 2018 16:59:54 +0800 Subject: [PATCH 18/59] [Exposed]: set the XPOSED_BRIDEGE_VERSION, becuase some plugin use it. --- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index abdcfaa..8cef890 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -64,6 +64,7 @@ public class ExposedBridge { public static final String BASE_DIR = Build.VERSION.SDK_INT >= 24 ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; + private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; private static boolean SYSTEM_CLASSLOADER_INJECT = true; @@ -104,7 +105,7 @@ enum ModuleLoadResult { public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); - + XposedBridge.XPOSED_BRIDGE_VERSION = FAKE_XPOSED_VERSION; appContext = context; ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); @@ -311,8 +312,7 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl } // XposedInstaller - final int fakeXposedVersion = 91; - final String fakeVersionString = String.valueOf(fakeXposedVersion); + final String fakeVersionString = String.valueOf(FAKE_XPOSED_VERSION); final File xposedProp = context.getFileStreamPath("xposed_prop"); if (!xposedProp.exists()) { writeXposedProperty(xposedProp, fakeVersionString, false); @@ -338,14 +338,14 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); - param.setResult(fakeXposedVersion); + param.setResult(FAKE_XPOSED_VERSION); } }); DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { @Override protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); - param.setResult(fakeXposedVersion); + param.setResult(FAKE_XPOSED_VERSION); } }); From 04835ab8c4a7c5ea590f56db0b2a5ed0d4e1e29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Sat, 3 Feb 2018 19:12:51 +0800 Subject: [PATCH 19/59] 0.4.5 --- exposed-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index f839ec8..c669116 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.4.4' +version = '0.4.5' apply plugin: 'com.novoda.bintray-release' From 8a7250f2d0d1173bc59c173f52eab6968cb7dada Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Thu, 8 Feb 2018 00:45:03 +0800 Subject: [PATCH 20/59] [Structure] revert inject system classloader. --- exposed-core/build.gradle | 2 +- .../src/main/java/de/robv/android/xposed/ExposedHelper.java | 3 +++ .../src/main/java/me/weishu/exposed/ExposedBridge.java | 5 +++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index c669116..5145128 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.4.5' +version = '0.4.7' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java index fd53d16..64747d0 100644 --- a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java +++ b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java @@ -13,6 +13,9 @@ public static void initSeLinux(String processName) { } public static boolean isIXposedMod(Class moduleClass) { + XposedBridge.log("module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass()); + XposedBridge.log("IXposedMod's classLoader : " + IXposedMod.class.getClassLoader()); + return IXposedMod.class.isAssignableFrom(moduleClass); } diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 8cef890..a041429 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -66,7 +66,7 @@ public class ExposedBridge { private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; - private static boolean SYSTEM_CLASSLOADER_INJECT = true; + private static boolean SYSTEM_CLASSLOADER_INJECT = false; private static final String WECHAT_PACKAGE = "com.tencent.mm"; @@ -104,7 +104,7 @@ enum ModuleLoadResult { } public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { - SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); + // SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); XposedBridge.XPOSED_BRIDGE_VERSION = FAKE_XPOSED_VERSION; appContext = context; ReLinker.loadLibrary(context, "epic"); @@ -127,6 +127,7 @@ private static boolean patchSystemClassLoader() { parent.setAccessible(true); parent.set(systemClassLoader, xposedClassLoader); + log("XposedBridge's BootClassLoader: " + XposedBridge.BOOTCLASSLOADER + ", parent: " + XposedBridge.BOOTCLASSLOADER.getParent()); // SystemClassLoader -> XposedClassLoader -> BootstrapClassLoader return systemClassLoader.getParent() == xposedClassLoader; } catch (NoSuchFieldException e) { From 3eb508939705ff761e907940611b28bbf1108e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Wed, 28 Feb 2018 17:38:14 +0800 Subject: [PATCH 21/59] [Misc]: Becuase of the epic improvement, remove restricts for wexposed. --- .../java/me/weishu/exposed/ExposedBridge.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index a041429..eb873a9 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -6,7 +6,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; -import android.graphics.Bitmap; import android.os.Build; import android.os.IBinder; import android.text.TextUtils; @@ -30,7 +29,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -68,21 +66,14 @@ public class ExposedBridge { private static final String VERSION_KEY = "version"; private static boolean SYSTEM_CLASSLOADER_INJECT = false; - private static final String WECHAT_PACKAGE = "com.tencent.mm"; - private static Pair> lastModuleList = Pair.create(null, null); private static Map exposedClassLoaderMap = new HashMap<>(); private static ClassLoader xposedClassLoader; - private static volatile boolean isWeChat = false; - private static Context appContext; private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override public void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { - if (WECHAT_PACKAGE.equalsIgnoreCase(applicationInfo.packageName)) { - isWeChat = true; - } } @Override @@ -263,22 +254,6 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod } private static boolean ignoreHooks(Member member) { - if (isWeChat) { - if (member instanceof Method) { - if (((Method) member).getReturnType() == Bitmap.class) { - log("i h: " + ((Method) member).toGenericString()); - return true; - } - if ("closeChatting".equalsIgnoreCase(member.getName())) { - log("i h: " + ((Method) member).toGenericString()); - return true; - } - if (member.getDeclaringClass().getName().contains("notification")) { - log("i h: " + ((Method) member).toGenericString()); - return true; - } - } - } return false; } From a6d75ff5ed6026a130d3f95c4723ef11d31e017a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=B4=E6=9C=AF?= Date: Wed, 28 Feb 2018 20:11:17 +0800 Subject: [PATCH 22/59] 0.5.0 --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 5145128..6141861 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API - compile ('me.weishu:epic:0.4.4') { // The AOP Framework + compile ('me.weishu:epic:0.5.0') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.4.7' +version = '0.5.0' apply plugin: 'com.novoda.bintray-release' From 19b536a856597080eed3aaf6f7ad1ea8cff5570d Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 12 Mar 2018 18:36:38 +0800 Subject: [PATCH 23/59] update dependency version --- exposed-core/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 6141861..58a924b 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,15 +23,15 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.3.2' // The Xposed API - compile ('me.weishu:epic:0.5.0') { // The AOP Framework + compile 'me.weishu.exposed:exposed-xposedapi:0.3.3' // The Xposed API + compile ('me.weishu:epic:0.5.3') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.5.0' +version = '0.5.3' apply plugin: 'com.novoda.bintray-release' From 939d4229d341b10ad6edc1e7baa8b4b96a91f6b5 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Tue, 13 Mar 2018 10:29:52 +0800 Subject: [PATCH 24/59] [Fix]: fix crash when use XposedInstaller below 3.1.5. --- .../main/java/me/weishu/exposed/ExposedBridge.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index eb873a9..c015ab6 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -303,11 +303,15 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl } final Class xposedApp = XposedHelpers.findClass("de.robv.android.xposed.installer.XposedApp", appClassLoader); - final Object xposed_prop_files = XposedHelpers.getStaticObjectField(xposedApp, "XPOSED_PROP_FILES"); - final int length = Array.getLength(xposed_prop_files); - String xposedPropPath = xposedProp.getPath(); - for (int i = 0; i < length; i++) { - Array.set(xposed_prop_files, i, xposedPropPath); + try { + final Object xposed_prop_files = XposedHelpers.getStaticObjectField(xposedApp, "XPOSED_PROP_FILES"); + final int length = Array.getLength(xposed_prop_files); + String xposedPropPath = xposedProp.getPath(); + for (int i = 0; i < length; i++) { + Array.set(xposed_prop_files, i, xposedPropPath); + } + } catch (Throwable ignored) { + // only support 3.1.5 and above. } DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { From 7f8a591a9881feda0b3cc8d69b2cb7f6d6057fa0 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Tue, 13 Mar 2018 20:01:36 +0800 Subject: [PATCH 25/59] [Fix]: disable tinker. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 60 +++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 58a924b..fc671c5 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.3' +version = '0.5.4' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index c015ab6..2902210 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -9,6 +9,7 @@ import android.os.Build; import android.os.IBinder; import android.text.TextUtils; +import android.util.Base64; import android.util.Log; import android.util.Pair; import android.view.AbsSavedState; @@ -104,6 +105,7 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForXposedModule(context, applicationInfo, appClassLoader); initForXposedInstaller(context, applicationInfo, appClassLoader); + initForWechat(context, applicationInfo, appClassLoader); } private static boolean patchSystemClassLoader() { @@ -408,6 +410,54 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { }); } + private static void initForWechat(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + if (applicationInfo == null) { + return; + } + final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); + + if (!WECHAT.equals(applicationInfo.packageName)) { + return; + } + if (WECHAT.equals(applicationInfo.processName)) { + // for main process + String dataDir = applicationInfo.dataDir; + + File tinker = new File(dataDir, decodeFromBase64("dGlua2Vy")); + File tinker_temp = new File(dataDir, decodeFromBase64("dGlua2VyX3RlbXA=")); + File tinker_server = new File(dataDir, decodeFromBase64("dGlua2VyX3NlcnZlcg==")); + + deleteDir(tinker); + deleteDir(tinker_temp); + deleteDir(tinker_server); + } + } + + public static boolean deleteDir(File dir) { + if (dir == null) { + return false; + } + if (dir.isDirectory()) { + String[] children = dir.list(); + for (String file : children) { + boolean success = deleteDir(new File(dir, file)); + if (!success) { + return false; + } + } + } + return dir.delete(); + } + + /** + * avoid from being searched by google. + * @param base64 + * @return + */ + private static String decodeFromBase64(String base64) { + return new String(Base64.decode(base64, 0)); + } + /** * write xposed property file to fake xposedinstaller * @param propertyFile the property file used by XposedInstaller @@ -456,20 +506,20 @@ private static String getXposedVersionFromProperty(File propertyFile) { private static boolean loadModuleConfig(String rootDir, String processName) { if (lastModuleList != null && TextUtils.equals(lastModuleList.first, processName) && lastModuleList.second != null) { - Log.d(TAG, "lastmodule valid, do not load config repeat"); + // Log.d(TAG, "lastmodule valid, do not load config repeat"); return true; // xposed installer has config file, and has already loaded for this process, return. } // load modules final File xposedInstallerDir = new File(rootDir, XPOSED_INSTALL_PACKAGE); - Log.d(TAG, "xposedInstaller Dir:" + xposedInstallerDir); + // Log.d(TAG, "xposedInstaller Dir:" + xposedInstallerDir); if (!xposedInstallerDir.exists()) { - Log.d(TAG, "XposedInstaller not installed, ignore."); + // Log.d(TAG, "XposedInstaller not installed, ignore."); return false; // xposed installer not enabled, must load all. } final File modiles = new File(xposedInstallerDir, "exposed_conf/modules.list"); - Log.d(TAG, "module file:" + modiles); + // Log.d(TAG, "module file:" + modiles); if (!modiles.exists()) { Log.d(TAG, "xposed installer's modules not exist, ignore."); return false; // xposed installer config file not exist, load all. @@ -491,7 +541,7 @@ private static boolean loadModuleConfig(String rootDir, String processName) { } lastModuleList = Pair.create(processName, moduleSet); - Log.d(TAG, "last moduleslist: " + lastModuleList); + // Log.d(TAG, "last moduleslist: " + lastModuleList); return true; } catch (IOException e) { e.printStackTrace(); From 071d59b8f745d1fca9b5a7f367925ecbd88b72f2 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Fri, 16 Mar 2018 12:34:22 +0800 Subject: [PATCH 26/59] [Fix]: toast when use external xposed installer. --- .../java/me/weishu/exposed/ExposedBridge.java | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 2902210..fecbf07 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -14,6 +14,7 @@ import android.util.Pair; import android.view.AbsSavedState; import android.view.View; +import android.widget.Toast; import com.getkeepsafe.relinker.ReLinker; @@ -312,24 +313,29 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl for (int i = 0; i < length; i++) { Array.set(xposed_prop_files, i, xposedPropPath); } + + + DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + param.setResult(FAKE_XPOSED_VERSION); + } + }); + DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + param.setResult(FAKE_XPOSED_VERSION); + } + }); } catch (Throwable ignored) { // only support 3.1.5 and above. - } - - DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - param.setResult(FAKE_XPOSED_VERSION); + try { + Toast.makeText(context, "The XposedInstaller you used is not supported.", Toast.LENGTH_SHORT).show(); + } catch (Throwable ignored2) { } - }); - DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - param.setResult(FAKE_XPOSED_VERSION); - } - }); + } final Constructor fileConstructor1 = XposedHelpers.findConstructorExact(File.class, String.class); final Constructor fileConstructor2 = XposedHelpers.findConstructorExact(File.class, String.class, String.class); From 039bfdea177c545aa30a7cf8a3abf7563b85f935 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Tue, 20 Mar 2018 11:09:03 +0800 Subject: [PATCH 27/59] [Fix]: do not hook stickylistview below android o. --- .../java/me/weishu/exposed/ExposedBridge.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index fecbf07..961ee22 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -329,6 +329,20 @@ protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Th param.setResult(FAKE_XPOSED_VERSION); } }); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // fix bug on Android O: https://github.com/emilsjolander/StickyListHeaders/issues/477 + Class stickyListHeadersClass = XposedHelpers.findClass("se.emilsjolander.stickylistheaders.StickyListHeadersListView", appClassLoader); + DexposedBridge.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + param.setResult(AbsSavedState.EMPTY_STATE); + Field mPrivateFlags = XposedHelpers.findField(View.class, "mPrivateFlags"); + int flags = mPrivateFlags.getInt(param.thisObject); + mPrivateFlags.set(param.thisObject, flags | 0x00020000); + } + }); + } } catch (Throwable ignored) { // only support 3.1.5 and above. try { @@ -361,18 +375,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } }); - // fix bug on Android O: https://github.com/emilsjolander/StickyListHeaders/issues/477 - Class stickyListHeadersClass = XposedHelpers.findClass("se.emilsjolander.stickylistheaders.StickyListHeadersListView", appClassLoader); - DexposedBridge.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); - param.setResult(AbsSavedState.EMPTY_STATE); - Field mPrivateFlags = XposedHelpers.findField(View.class, "mPrivateFlags"); - int flags = mPrivateFlags.getInt(param.thisObject); - mPrivateFlags.set(param.thisObject, flags | 0x00020000); - } - }); + } From 3597465843fd49b1e89b553b7f2bf2651fd6b428 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Sat, 24 Mar 2018 15:43:27 +0800 Subject: [PATCH 28/59] [Refactor]: do not use dexposed directly. --- exposed-core/build.gradle | 2 +- .../main/java/me/weishu/exposed/ExposedBridge.java | 12 ++++++------ .../main/java/me/weishu/exposed/LogcatService.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index fc671c5..cc789ea 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion "26.0.2" defaultConfig { - minSdkVersion 14 + minSdkVersion 19 targetSdkVersion 26 versionCode 1 versionName "1.0" diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 961ee22..ba7984f 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -315,14 +315,14 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl } - DexposedBridge.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { + XposedHelpers.findAndHookMethod(xposedApp, "getActiveXposedVersion", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); param.setResult(FAKE_XPOSED_VERSION); } }); - DexposedBridge.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { + XposedHelpers.findAndHookMethod(xposedApp, "getInstalledXposedVersion", new XC_MethodHook() { @Override protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -332,7 +332,7 @@ protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Th if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // fix bug on Android O: https://github.com/emilsjolander/StickyListHeaders/issues/477 Class stickyListHeadersClass = XposedHelpers.findClass("se.emilsjolander.stickylistheaders.StickyListHeadersListView", appClassLoader); - DexposedBridge.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new XC_MethodHook() { + XposedHelpers.findAndHookMethod(stickyListHeadersClass, "onSaveInstanceState", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -354,7 +354,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { final Constructor fileConstructor1 = XposedHelpers.findConstructorExact(File.class, String.class); final Constructor fileConstructor2 = XposedHelpers.findConstructorExact(File.class, String.class, String.class); final String dataDir = applicationInfo.dataDir; - DexposedBridge.hookMethod(fileConstructor1, new XC_MethodHook() { + XposedBridge.hookMethod(fileConstructor1, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -364,7 +364,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } } }); - DexposedBridge.hookMethod(fileConstructor2, new XC_MethodHook() { + XposedBridge.hookMethod(fileConstructor2, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); @@ -407,7 +407,7 @@ public void onServiceDisconnected(ComponentName name) { Class serviceManager = XposedHelpers.findClass("android.os.ServiceManager", appClassLoader); final String serviceName = Build.VERSION.SDK_INT >= 21 ? "user.wechart.trans" : "wechart.trans"; - DexposedBridge.findAndHookMethod(serviceManager, "getService", String.class, new XC_MethodHook() { + XposedHelpers.findAndHookMethod(serviceManager, "getService", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); diff --git a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java index efd6075..9351d6e 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java +++ b/exposed-core/src/main/java/me/weishu/exposed/LogcatService.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.List; -import de.robv.android.xposed.DexposedBridge; +import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; /** @@ -73,7 +73,7 @@ public void run() { logcatThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { - DexposedBridge.log(e); + XposedBridge.log(e); // Do nothing else. mReading = false; } From f1248a7802cf347362f88ddd238586e8b0c34862 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Tue, 10 Apr 2018 22:37:30 +0800 Subject: [PATCH 29/59] [VXP]: disable hotpatch of QQ. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index cc789ea..ddf2b34 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.4' +version = '0.5.5' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index ba7984f..b9d7748 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.os.Build; import android.os.IBinder; @@ -107,6 +108,7 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForXposedModule(context, applicationInfo, appClassLoader); initForXposedInstaller(context, applicationInfo, appClassLoader); initForWechat(context, applicationInfo, appClassLoader); + initForQQ(context, applicationInfo, appClassLoader); } private static boolean patchSystemClassLoader() { @@ -419,6 +421,22 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { }); } + @SuppressLint("ApplySharedPref") + private static void initForQQ(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + if (applicationInfo == null) { + return; + } + final String QQ = decodeFromBase64("Y29tLnRlbmNlbnQubW9iaWxlcXE="); + if (!QQ.equals(applicationInfo.packageName)) { + return; + } + if (QQ.equals(applicationInfo.processName)) { + SharedPreferences sp = context.getSharedPreferences(decodeFromBase64("aG90cGF0Y2hfcHJlZmVyZW5jZQ=="), // hotpatch_preference + Context.MODE_PRIVATE); + sp.edit().remove(decodeFromBase64("a2V5X2NvbmZpZ19wYXRjaF9kZXg=")).commit(); // key_config_patch_dex + } + } + private static void initForWechat(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { if (applicationInfo == null) { return; From 96966835cd8de2aee69bf5502a2964ecc9a5829a Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Thu, 12 Apr 2018 22:49:55 +0800 Subject: [PATCH 30/59] [VXP]: There is a bug in VA: /proc//cmdline is incorrect, but can not fix it in short, so just bypass it by hook. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 42 ++++++++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index ddf2b34..c30e7b3 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.5' +version = '0.5.6' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index b9d7748..65900fd 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -9,6 +9,7 @@ import android.content.pm.ApplicationInfo; import android.os.Build; import android.os.IBinder; +import android.os.Process; import android.text.TextUtils; import android.util.Base64; import android.util.Log; @@ -32,6 +33,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -156,7 +158,7 @@ public static synchronized ClassLoader getXposedClassLoader(ClassLoader hostClas } public static ModuleLoadResult loadModule(final String moduleApkPath, String moduleOdexDir, String moduleLibPath, - final ApplicationInfo currentApplicationInfo, ClassLoader appClassLoader) { + final ApplicationInfo currentApplicationInfo, ClassLoader appClassLoader) { if (isXposedInstaller(currentApplicationInfo)) { return ModuleLoadResult.IGNORED; @@ -360,7 +362,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); - final String path = (String)param.args[0]; + final String path = (String) param.args[0]; if (path.startsWith(BASE_DIR)) { param.args[0] = path.replace(BASE_DIR, path.equals(BASE_DIR) ? dataDir : dataDir + "/exposed_"); } @@ -370,7 +372,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); - final String path = (String)param.args[0]; + final String path = (String) param.args[0]; if (path.startsWith(BASE_DIR)) { param.args[0] = path.replace(BASE_DIR, path.equals(BASE_DIR) ? dataDir : dataDir + "/exposed_"); } @@ -386,7 +388,7 @@ private static void initForWeChatTranslate(String moduleClassName, ApplicationIn return; } - if (!("com.hiwechart.translate".equals(applicationInfo.processName) || "com.tencent.mm".equals(applicationInfo.processName))){ + if (!("com.hiwechart.translate".equals(applicationInfo.processName) || "com.tencent.mm".equals(applicationInfo.processName))) { return; } @@ -457,6 +459,31 @@ private static void initForWechat(Context context, ApplicationInfo applicationIn deleteDir(tinker); deleteDir(tinker_temp); deleteDir(tinker_server); + + final int mainProcessId = Process.myPid(); + XposedHelpers.findAndHookMethod(Process.class, "killProcess", int.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + int pid = (int) param.args[0]; + if (pid != mainProcessId) { + return; + } + // try kill main process, find stack + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + if (stackTrace == null) { + return; + } + + for (StackTraceElement stackTraceElement : stackTrace) { + if (stackTraceElement.getClassName().contains("com.tencent.mm.app")) { + XposedBridge.log("do not suicide..." + Arrays.toString(stackTrace)); + param.setResult(null); + break; + } + } + } + }); } } @@ -478,6 +505,7 @@ public static boolean deleteDir(File dir) { /** * avoid from being searched by google. + * * @param base64 * @return */ @@ -487,9 +515,10 @@ private static String decodeFromBase64(String base64) { /** * write xposed property file to fake xposedinstaller + * * @param propertyFile the property file used by XposedInstaller - * @param version to fake version - * @param retry need retry, when retry, delete file and try again + * @param version to fake version + * @param retry need retry, when retry, delete file and try again */ private static void writeXposedProperty(File propertyFile, String version, boolean retry) { Properties properties = new Properties(); @@ -528,6 +557,7 @@ private static String getXposedVersionFromProperty(File propertyFile) { /** * try read module config fules. + * * @return is need check module */ private static boolean loadModuleConfig(String rootDir, String processName) { From 0fb1f6c0829c15b2adf1c165fd85bc0956b21578 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 16 Apr 2018 11:48:15 +0800 Subject: [PATCH 31/59] ignore wechat push process's hook. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index c30e7b3..6de42a1 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.6' +version = '0.5.7' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 65900fd..ba75cbf 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -160,7 +160,7 @@ public static synchronized ClassLoader getXposedClassLoader(ClassLoader hostClas public static ModuleLoadResult loadModule(final String moduleApkPath, String moduleOdexDir, String moduleLibPath, final ApplicationInfo currentApplicationInfo, ClassLoader appClassLoader) { - if (isXposedInstaller(currentApplicationInfo)) { + if (filterApplication(currentApplicationInfo)) { return ModuleLoadResult.IGNORED; } @@ -289,6 +289,24 @@ private static boolean isXposedInstaller(ApplicationInfo applicationInfo) { return XPOSED_INSTALL_PACKAGE.equals(applicationInfo.packageName); } + private static boolean filterApplication(ApplicationInfo applicationInfo) { + if (applicationInfo == null) { + return true; + } + + if (isXposedInstaller(applicationInfo)) { + return true; + } + + if (decodeFromBase64("Y29tLnRlbmNlbnQubW06cHVzaA==").equalsIgnoreCase(applicationInfo.processName)) { + // com.tencent.mm:push + XposedBridge.log("ignore process for wechat push."); + return true; + } + + return false; + } + private static void initForXposedInstaller(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { if (!isXposedInstaller(applicationInfo)) { return; From 5258cda1d3298b91de91d2f31cbd2cdf222771db Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 16 Apr 2018 12:04:35 +0800 Subject: [PATCH 32/59] replace the hook of Application.attach with ContextWrapper.attachBaseContext for CHA. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 6de42a1..49bc804 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.7' +version = '0.5.8' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index ba75cbf..b94aa2e 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -1,8 +1,10 @@ package me.weishu.exposed; import android.annotation.SuppressLint; +import android.app.Application; import android.content.ComponentName; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; @@ -33,6 +35,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -268,10 +271,24 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb if (ignoreHooks(method)) { return null; } + + method = replaceForCHA(method); + final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback); return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); } + private static Member replaceForCHA(Member member) { + + if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { + + Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); + XposedBridge.log("replace ContextWrapper.attachBaseContext with Application.attach for CHA"); + return m; + } + return member; + } + private static void initForXposedModule(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { InputStream inputStream = null; From 046844b97584362eff739df5b945090631056559 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 16 Apr 2018 21:00:45 +0800 Subject: [PATCH 33/59] do not load module for wechat appbrand. --- .../java/me/weishu/exposed/ExposedBridge.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index b94aa2e..02f1ed5 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -70,6 +70,8 @@ public class ExposedBridge { public static final String BASE_DIR = Build.VERSION.SDK_INT >= 24 ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; + private static final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); + private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; private static boolean SYSTEM_CLASSLOADER_INJECT = false; @@ -210,6 +212,10 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod if (moduleClassName.isEmpty() || moduleClassName.startsWith("#")) continue; + if (filterModuleForApp(currentApplicationInfo, moduleClassName)) { + XposedBridge.log("ignore module: " + moduleClassName + " for application: " + currentApplicationInfo.packageName); + continue; + } try { log(" Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); @@ -324,6 +330,32 @@ private static boolean filterApplication(ApplicationInfo applicationInfo) { return false; } + private static boolean filterModuleForApp(ApplicationInfo applicationInfo, String moduleEntry) { + if (applicationInfo == null || applicationInfo.packageName == null) { + return false; + } + + final String WECHAT_JUMP_HELPER = "com.emily.mmjumphelper.xposed.XposedMain"; + + if (WECHAT.equals(applicationInfo.packageName)) { + if (applicationInfo.processName.contains("appbrand")) { + // wechat app brand + if (WECHAT_JUMP_HELPER.equals(moduleEntry)) { + // now only load module for appbrand. + return false; + } else { + return true; + } + } else { + if (WECHAT_JUMP_HELPER.equals(moduleEntry)) { + return true; + } + } + } + + return false; + } + private static void initForXposedInstaller(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { if (!isXposedInstaller(applicationInfo)) { return; @@ -478,7 +510,6 @@ private static void initForWechat(Context context, ApplicationInfo applicationIn if (applicationInfo == null) { return; } - final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); if (!WECHAT.equals(applicationInfo.packageName)) { return; From 7ac6f100addde2a7e84a7ae68f4b6426dcba4436 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 24 Apr 2018 22:50:21 +0800 Subject: [PATCH 34/59] [VXP]: yield mode. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 48 ++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 49bc804..d84914e 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.8' +version = '0.5.9' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index b94aa2e..691df79 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -70,6 +70,8 @@ public class ExposedBridge { public static final String BASE_DIR = Build.VERSION.SDK_INT >= 24 ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; + final static String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); + private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; private static boolean SYSTEM_CLASSLOADER_INJECT = false; @@ -79,6 +81,9 @@ public class ExposedBridge { private static ClassLoader xposedClassLoader; private static Context appContext; + private static String currentPackage; + private static boolean yieldMode = false; + private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override public void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { @@ -106,6 +111,8 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl // SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); XposedBridge.XPOSED_BRIDGE_VERSION = FAKE_XPOSED_VERSION; appContext = context; + initForPackage(context, applicationInfo); + ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); XSharedPreferences.setPackageBaseDirectory(new File(applicationInfo.dataDir).getParentFile()); @@ -116,6 +123,30 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForQQ(context, applicationInfo, appClassLoader); } + private static void initForPackage(Context context, ApplicationInfo applicationInfo) { + do { + if (applicationInfo == null) { + break; + } + String pkg = applicationInfo.packageName; + if (pkg == null) { + break; + } + currentPackage = pkg; + + } while (false); + + if (currentPackage == null) { + currentPackage = context.getPackageName(); + } + + String yieldModeConfig = System.getProperty("yieldMode"); + if ("true".equals(yieldModeConfig)) { + yieldMode = true; + XposedBridge.log("yield mode take effect"); + } + } + private static boolean patchSystemClassLoader() { // 1. first create XposedClassLoader -> BootstrapClassLoader ClassLoader xposedClassLoader = new XposedClassLoader(ExposedBridge.class.getClassLoader()); @@ -264,6 +295,22 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod } private static boolean ignoreHooks(Member member) { + if (member == null) { + return false; + } + + if (!yieldMode) { + return false; + } + + String name = member.getDeclaringClass().getName(); + if (WECHAT.equals(currentPackage)) { + if (name.contains("wcdb")) { + Log.i("mylog", "ignore hook for: " + name); + return true; + } + } + return false; } @@ -478,7 +525,6 @@ private static void initForWechat(Context context, ApplicationInfo applicationIn if (applicationInfo == null) { return; } - final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); if (!WECHAT.equals(applicationInfo.packageName)) { return; From 5a3c98a6c44545eb7461fa91e9938c5ce51f02a7 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 24 Apr 2018 22:53:55 +0800 Subject: [PATCH 35/59] [VXP]: add system environment for virtualxposed. --- exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java | 1 + 1 file changed, 1 insertion(+) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 691df79..a57bcfc 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -145,6 +145,7 @@ private static void initForPackage(Context context, ApplicationInfo applicationI yieldMode = true; XposedBridge.log("yield mode take effect"); } + System.setProperty("vxp", "1"); } private static boolean patchSystemClassLoader() { From c2a245d73ef38434e73d471320938c1f5670f2fb Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Wed, 25 Apr 2018 11:46:51 +0800 Subject: [PATCH 36/59] Merge branch 'master' of github.com:android-hacker/exposed # Conflicts: # exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java --- .../java/me/weishu/exposed/ExposedBridge.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index a57bcfc..d3e8947 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -70,7 +70,7 @@ public class ExposedBridge { public static final String BASE_DIR = Build.VERSION.SDK_INT >= 24 ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; - final static String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); + private static final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; @@ -242,6 +242,10 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod if (moduleClassName.isEmpty() || moduleClassName.startsWith("#")) continue; + if (filterModuleForApp(currentApplicationInfo, moduleClassName)) { + XposedBridge.log("ignore module: " + moduleClassName + " for application: " + currentApplicationInfo.packageName); + continue; + } try { log(" Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); @@ -372,6 +376,32 @@ private static boolean filterApplication(ApplicationInfo applicationInfo) { return false; } + private static boolean filterModuleForApp(ApplicationInfo applicationInfo, String moduleEntry) { + if (applicationInfo == null || applicationInfo.packageName == null) { + return false; + } + + final String WECHAT_JUMP_HELPER = "com.emily.mmjumphelper.xposed.XposedMain"; + + if (WECHAT.equals(applicationInfo.packageName)) { + if (applicationInfo.processName.contains("appbrand")) { + // wechat app brand + if (WECHAT_JUMP_HELPER.equals(moduleEntry)) { + // now only load module for appbrand. + return false; + } else { + return true; + } + } else { + if (WECHAT_JUMP_HELPER.equals(moduleEntry)) { + return true; + } + } + } + + return false; + } + private static void initForXposedInstaller(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { if (!isXposedInstaller(applicationInfo)) { return; From 38b7529f720c1b331ebe2e20a7ce3f0eff9a775c Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Tue, 1 May 2018 21:56:51 +0800 Subject: [PATCH 37/59] 0.6.0 --- exposed-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index d84914e..c18bc4b 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.5.9' +version = '0.6.0' apply plugin: 'com.novoda.bintray-release' From 4e4c93dc37ef497b9e9c77b3f9b6fd17ec62b518 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Wed, 9 May 2018 16:38:53 +0800 Subject: [PATCH 38/59] improve the compatibility with some Xposed Module. --- exposed-core/build.gradle | 4 ++-- .../java/me/weishu/exposed/ExposedBridge.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index c18bc4b..4bece09 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.3.3' // The Xposed API - compile ('me.weishu:epic:0.5.3') { // The AOP Framework + compile ('me.weishu:epic:0.5.5') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.6.0' +version = '0.6.2' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index d3e8947..bd43d7b 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -71,6 +71,7 @@ public class ExposedBridge { ? "/data/user_de/0/de.robv.android.xposed.installer/" : BASE_DIR_LEGACY; private static final String WECHAT = decodeFromBase64("Y29tLnRlbmNlbnQubW0="); + private static final String QQ = decodeFromBase64("Y29tLnRlbmNlbnQubW9iaWxlcXE="); private static final int FAKE_XPOSED_VERSION = 91; private static final String VERSION_KEY = "version"; @@ -304,14 +305,22 @@ private static boolean ignoreHooks(Member member) { return false; } + String name = member.getDeclaringClass().getName(); + if (QQ.equals(currentPackage)) { + // TODO, we just ignore this hook to avoid crash, fix it when you figure out it. (getManager) + if (name.contains("QQAppInterface")) { + // Log.i("mylog", "ignore hook for: " + member); + return true; + } + } + if (!yieldMode) { return false; } - String name = member.getDeclaringClass().getName(); if (WECHAT.equals(currentPackage)) { if (name.contains("wcdb")) { - Log.i("mylog", "ignore hook for: " + name); + // Log.i("mylog", "ignore hook for: " + member); return true; } } @@ -348,7 +357,7 @@ private static void initForXposedModule(Context context, ApplicationInfo applica inputStream = context.getAssets().open("xposed_init"); System.setProperty("epic.force", "true"); } catch (IOException e) { - log("initForXposedModule, ignore :" + applicationInfo.packageName); + log(applicationInfo.packageName + " is not a Xposed module"); } finally { closeSliently(inputStream); } From 87e1090a2d96091b36ad5117e68b539113f6b005 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Wed, 9 May 2018 16:51:13 +0800 Subject: [PATCH 39/59] replace Application.onCreate with Instrumentation.callApplicationOnCreate for CHA. --- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index bd43d7b..f660dd0 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -2,6 +2,7 @@ import android.annotation.SuppressLint; import android.app.Application; +import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; @@ -344,9 +345,16 @@ private static Member replaceForCHA(Member member) { if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); - XposedBridge.log("replace ContextWrapper.attachBaseContext with Application.attach for CHA"); + XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA"); return m; } + + if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) { + Method m = XposedHelpers.findMethodExact(Instrumentation.class, "callApplicationOnCreate", Application.class); + XposedBridge.log("replace Application.onCreate with Instrumentation.callApplicationOnCreate for CHA"); + return m; + } + return member; } From 5fb7933669dad12bee203d03fdf45eb2e1c1e184 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Wed, 9 May 2018 17:01:10 +0800 Subject: [PATCH 40/59] replace Application.onCreate with ContextWrapper.attachBaseContext for CHA. --- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index f660dd0..f0cc582 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -2,7 +2,6 @@ import android.annotation.SuppressLint; import android.app.Application; -import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; @@ -343,15 +342,14 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb private static Member replaceForCHA(Member member) { if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { - Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA"); return m; } if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) { - Method m = XposedHelpers.findMethodExact(Instrumentation.class, "callApplicationOnCreate", Application.class); - XposedBridge.log("replace Application.onCreate with Instrumentation.callApplicationOnCreate for CHA"); + Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); + XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA"); return m; } From 876e0166c3fa2c22f7f91e821e7b6cc4a6be13d6 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 14 May 2018 12:24:51 +0800 Subject: [PATCH 41/59] [Exposed]: fix the call origin exception. see exposed-xposedapi also. --- exposed-core/build.gradle | 4 ++-- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 4bece09..7399bbf 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.3.3' // The Xposed API + compile 'me.weishu.exposed:exposed-xposedapi:0.4.0' // The Xposed API compile ('me.weishu:epic:0.5.5') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.6.2' +version = '0.6.3' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index f0cc582..b3f2ffd 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -34,6 +34,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.Arrays; @@ -339,6 +340,12 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); } + public static Object invokeOriginalMethod(Member method, Object thisObject, Object[] args) + throws NullPointerException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + + return DexposedBridge.invokeOriginalMethod(method, thisObject, args); + } + private static Member replaceForCHA(Member member) { if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { From cd31c3e284039100258ed579445a3c8f7b07ce8f Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 14 May 2018 12:28:23 +0800 Subject: [PATCH 42/59] update dependency. --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 7399bbf..7c0293d 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.0' // The Xposed API - compile ('me.weishu:epic:0.5.5') { // The AOP Framework + compile ('me.weishu:epic:0.5.6') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.6.3' +version = '0.6.4' apply plugin: 'com.novoda.bintray-release' From 89410dfd15df2ba7a6ca57b29b42ff3e875d5807 Mon Sep 17 00:00:00 2001 From: "weishu.tws" Date: Mon, 14 May 2018 15:41:05 +0800 Subject: [PATCH 43/59] placeholder for X86(not implemented.) --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 7c0293d..d4434ab 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.0' // The Xposed API - compile ('me.weishu:epic:0.5.6') { // The AOP Framework + compile ('me.weishu:epic:0.5.9') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.6.4' +version = '0.6.5' apply plugin: 'com.novoda.bintray-release' From f4b2e4251c6830def11309365f464285007a2a70 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 29 May 2018 19:19:05 +0800 Subject: [PATCH 44/59] [VXP]: fix bug of MultiEntry in one module. --- exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index d3e8947..51a6c6d 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -286,10 +286,10 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod sModuleLoadListener.onModuleLoaded(moduleClassName, currentApplicationInfo, mcl); - return ModuleLoadResult.SUCCESS; } catch (Throwable t) { log(t); } + return ModuleLoadResult.SUCCESS; } } catch (IOException e) { log(e); From 510f056d51531d3b414ba974f43ea4b8e3db6222 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Wed, 30 May 2018 10:56:18 +0800 Subject: [PATCH 45/59] 0.6.6 --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index d4434ab..d2b6fb0 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.4.0' // The Xposed API + compile 'me.weishu.exposed:exposed-xposedapi:0.4.1' // The Xposed API compile ('me.weishu:epic:0.5.9') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.6.5' +version = '0.6.6' apply plugin: 'com.novoda.bintray-release' From dfcf21cccaefc35f83be17eb91f3872d68427701 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 19 Jun 2018 14:11:01 +0800 Subject: [PATCH 46/59] 1. fix the Application.attach may be hooked multi-times. 2. reduce the log of Xposed. --- exposed-core/build.gradle | 2 +- .../de/robv/android/xposed/ExposedHelper.java | 16 +++- .../java/me/weishu/exposed/CHAHelper.java | 77 +++++++++++++++++++ .../java/me/weishu/exposed/ExposedBridge.java | 33 +++----- 4 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index d2b6fb0..9015e31 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.6.6' +version = '0.6.7' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java index 64747d0..a39cfe6 100644 --- a/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java +++ b/exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java @@ -1,5 +1,7 @@ package de.robv.android.xposed; +import android.util.Log; + import java.lang.reflect.Member; /** @@ -7,14 +9,16 @@ */ public class ExposedHelper { + private static final String TAG = "ExposedHelper"; + public static void initSeLinux(String processName) { SELinuxHelper.initOnce(); SELinuxHelper.initForProcess(processName); } public static boolean isIXposedMod(Class moduleClass) { - XposedBridge.log("module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass()); - XposedBridge.log("IXposedMod's classLoader : " + IXposedMod.class.getClassLoader()); + Log.d(TAG, "module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass()); + Log.d(TAG, "IXposedMod's classLoader : " + IXposedMod.class.getClassLoader()); return IXposedMod.class.isAssignableFrom(moduleClass); } @@ -30,4 +34,12 @@ public static void callInitZygote(String modulePath, Object moduleInstance) thro param.startsSystemServer = false; ((IXposedHookZygoteInit) moduleInstance).initZygote(param); } + + public static void beforeHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{ + methodHook.beforeHookedMethod(param); + } + + public static void afterHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{ + methodHook.afterHookedMethod(param); + } } diff --git a/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java b/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java new file mode 100644 index 0000000..ff2cad6 --- /dev/null +++ b/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java @@ -0,0 +1,77 @@ +package me.weishu.exposed; + +import android.app.Application; +import android.content.Context; +import android.content.ContextWrapper; +import android.util.Log; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import de.robv.android.xposed.DexposedBridge; +import de.robv.android.xposed.ExposedHelper; +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; + +/** + * @author weishu + * @date 2018/6/19. + */ +public final class CHAHelper { + private static final String TAG = "CHAHelper"; + + static class ApplicationHookProxy extends XC_MethodHook { + + XC_MethodHook original; + + ApplicationHookProxy(XC_MethodHook original) { + this.original = original; + } + + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + super.beforeHookedMethod(param); + if (param.thisObject == null) { + throw new IllegalArgumentException("can not use static method!!"); + } + + if (param.thisObject instanceof Application) { + ExposedHelper.beforeHookedMethod(this.original, param); + } else { + Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject); + } + } + + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + super.afterHookedMethod(param); + if (param.thisObject == null) { + throw new IllegalArgumentException("can not use static method!!"); + } + + if (param.thisObject instanceof Application) { + ExposedHelper.afterHookedMethod(this.original, param); + } else { + Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject); + } + } + } + + static XC_MethodHook.Unhook replaceForCHA(Member member, final XC_MethodHook callback) { + + if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { + XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA"); + Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); + return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback)); + } + + if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) { + XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA"); + Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); + return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback)); + } + + return null; + } +} diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 42843ef..9b2191c 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -1,10 +1,8 @@ package me.weishu.exposed; import android.annotation.SuppressLint; -import android.app.Application; import android.content.ComponentName; import android.content.Context; -import android.content.ContextWrapper; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; @@ -36,7 +34,6 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; -import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -205,11 +202,11 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod loadModuleConfig(rootDir, currentApplicationInfo.processName); if (lastModuleList.second == null || !lastModuleList.second.contains(moduleApkPath)) { - log("module:" + moduleApkPath + " is disabled, ignore"); + Log.i(TAG, "module:" + moduleApkPath + " is disabled, ignore"); return ModuleLoadResult.DISABLED; } - log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT); + Log.i(TAG, "Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT); if (!new File(moduleApkPath).exists()) { log(moduleApkPath + " does not exist"); @@ -249,7 +246,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod continue; } try { - log(" Loading class " + moduleClassName); + Log.i(TAG, " Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); sModuleLoadListener.onLoadingModule(moduleClassName, currentApplicationInfo, mcl); @@ -334,7 +331,10 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb return null; } - method = replaceForCHA(method); + XC_MethodHook.Unhook replaceUnhook = CHAHelper.replaceForCHA(method, callback); + if (replaceUnhook != null) { + return ExposedHelper.newUnHook(callback, replaceUnhook.getHookedMethod()); + } final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback); return ExposedHelper.newUnHook(callback, unhook.getHookedMethod()); @@ -346,22 +346,7 @@ public static Object invokeOriginalMethod(Member method, Object thisObject, Obje return DexposedBridge.invokeOriginalMethod(method, thisObject, args); } - private static Member replaceForCHA(Member member) { - - if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { - Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); - XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA"); - return m; - } - - if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) { - Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); - XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA"); - return m; - } - return member; - } private static void initForXposedModule(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { InputStream inputStream = null; @@ -370,7 +355,7 @@ private static void initForXposedModule(Context context, ApplicationInfo applica inputStream = context.getAssets().open("xposed_init"); System.setProperty("epic.force", "true"); } catch (IOException e) { - log(applicationInfo.packageName + " is not a Xposed module"); + Log.i(TAG, applicationInfo.packageName + " is not a Xposed module, do not init epic.force"); } finally { closeSliently(inputStream); } @@ -440,7 +425,7 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl if (!fakeVersionString.equals(oldVersion)) { writeXposedProperty(xposedProp, fakeVersionString, true); } else { - log("xposed version keep same, continue."); + Log.i(TAG, "xposed version keep same, continue."); } } From ccebbd03ef296761813644875f0a9f78118d333f Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 26 Jun 2018 10:35:14 +0800 Subject: [PATCH 47/59] remove yield mode, preload native so instead. --- exposed-core/build.gradle | 2 +- .../java/me/weishu/exposed/ExposedBridge.java | 38 ++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 9015e31..e98d9ed 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.6.7' +version = '0.7.0' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 9b2191c..d1ee759 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -81,8 +81,8 @@ public class ExposedBridge { private static Context appContext; private static String currentPackage; - private static boolean yieldMode = false; + private volatile static boolean wcdbLoaded = false; private static ModuleLoadListener sModuleLoadListener = new ModuleLoadListener() { @Override public void onLoadingModule(String moduleClassName, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { @@ -139,11 +139,6 @@ private static void initForPackage(Context context, ApplicationInfo applicationI currentPackage = context.getPackageName(); } - String yieldModeConfig = System.getProperty("yieldMode"); - if ("true".equals(yieldModeConfig)) { - yieldMode = true; - XposedBridge.log("yield mode take effect"); - } System.setProperty("vxp", "1"); } @@ -312,18 +307,33 @@ private static boolean ignoreHooks(Member member) { } } - if (!yieldMode) { - return false; + return false; + } + + private static void presetMethod(Member method) { + if (method == null) { + return; } if (WECHAT.equals(currentPackage)) { - if (name.contains("wcdb")) { - // Log.i("mylog", "ignore hook for: " + member); - return true; + Class declaringClass = method.getDeclaringClass(); + if (declaringClass.getName().contains("wcdb")) { + if (!wcdbLoaded) { + ClassLoader loader = declaringClass.getClassLoader(); + Class sqliteDataBaseClass = null; + try { + sqliteDataBaseClass = loader.loadClass("com.tencent.wcdb.database.SQLiteDatabase"); + } catch (ClassNotFoundException ignored) { + XposedBridge.log("preload sqlite class failed!!!"); + } + if (sqliteDataBaseClass == null) { + return; + } + + wcdbLoaded = true; + } } } - - return false; } public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callback) { @@ -331,6 +341,8 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb return null; } + presetMethod(method); + XC_MethodHook.Unhook replaceUnhook = CHAHelper.replaceForCHA(method, callback); if (replaceUnhook != null) { return ExposedHelper.newUnHook(callback, replaceUnhook.getHookedMethod()); From bf94a6aef81d092e95c22d49887eeabc8b8d69dc Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 26 Jun 2018 10:48:38 +0800 Subject: [PATCH 48/59] update dependency. --- exposed-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index e98d9ed..fab81b5 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.4.1' // The Xposed API + compile 'me.weishu.exposed:exposed-xposedapi:0.4.2' // The Xposed API compile ('me.weishu:epic:0.5.9') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } From faa9a2c7731dc9758865a6d49445118599b9bc84 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Tue, 26 Jun 2018 16:13:13 +0800 Subject: [PATCH 49/59] fix crash of multi-user in XSharedPreference. --- exposed-core/build.gradle | 4 ++-- .../src/main/java/me/weishu/exposed/ExposedBridge.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index fab81b5..f94b1e3 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.4.2' // The Xposed API + compile 'me.weishu.exposed:exposed-xposedapi:0.4.3' // The Xposed API compile ('me.weishu:epic:0.5.9') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.7.0' +version = '0.7.1' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index d1ee759..6a05d0f 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -106,11 +106,11 @@ enum ModuleLoadResult { IGNORED } - public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { + public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader, int userId) { // SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); XposedBridge.XPOSED_BRIDGE_VERSION = FAKE_XPOSED_VERSION; appContext = context; - initForPackage(context, applicationInfo); + initForPackage(context, applicationInfo, userId); ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); @@ -122,7 +122,7 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForQQ(context, applicationInfo, appClassLoader); } - private static void initForPackage(Context context, ApplicationInfo applicationInfo) { + private static void initForPackage(Context context, ApplicationInfo applicationInfo, int userId) { do { if (applicationInfo == null) { break; @@ -140,6 +140,7 @@ private static void initForPackage(Context context, ApplicationInfo applicationI } System.setProperty("vxp", "1"); + System.setProperty("vxp_user", String.valueOf(userId)); } private static boolean patchSystemClassLoader() { From 9821a580b541a6256baf084c5fffbf3e359b8416 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Wed, 27 Jun 2018 10:31:32 +0800 Subject: [PATCH 50/59] keep api back compatible. --- exposed-core/build.gradle | 4 ++-- .../java/me/weishu/exposed/ExposedBridge.java | 20 +++++-------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index f94b1e3..f6b3510 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.4.3' // The Xposed API + compile 'me.weishu.exposed:exposed-xposedapi:0.4.4' // The Xposed API compile ('me.weishu:epic:0.5.9') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.7.1' +version = '0.7.2' apply plugin: 'com.novoda.bintray-release' diff --git a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java index 6a05d0f..3407363 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java +++ b/exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java @@ -106,11 +106,11 @@ enum ModuleLoadResult { IGNORED } - public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader, int userId) { + public static void initOnce(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) { // SYSTEM_CLASSLOADER_INJECT = patchSystemClassLoader(); XposedBridge.XPOSED_BRIDGE_VERSION = FAKE_XPOSED_VERSION; appContext = context; - initForPackage(context, applicationInfo, userId); + initForPackage(context, applicationInfo); ReLinker.loadLibrary(context, "epic"); ExposedHelper.initSeLinux(applicationInfo.processName); @@ -122,25 +122,15 @@ public static void initOnce(Context context, ApplicationInfo applicationInfo, Cl initForQQ(context, applicationInfo, appClassLoader); } - private static void initForPackage(Context context, ApplicationInfo applicationInfo, int userId) { - do { - if (applicationInfo == null) { - break; - } - String pkg = applicationInfo.packageName; - if (pkg == null) { - break; - } - currentPackage = pkg; - - } while (false); + private static void initForPackage(Context context, ApplicationInfo applicationInfo) { + currentPackage = applicationInfo.packageName; if (currentPackage == null) { currentPackage = context.getPackageName(); } System.setProperty("vxp", "1"); - System.setProperty("vxp_user", String.valueOf(userId)); + System.setProperty("vxp_user_dir", new File(applicationInfo.dataDir).getParent()); } private static boolean patchSystemClassLoader() { From 64d528d443f6b97a33f00a42a9779a2af0cc7622 Mon Sep 17 00:00:00 2001 From: weishu Date: Sun, 7 Oct 2018 19:41:20 +0800 Subject: [PATCH 51/59] Update README.md --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6f76dc4..eefa5d9 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,24 @@ # 简介 -Exposed 致力于在**非Root**环境下实现Xposed的功能。基本思路是使用沙盒机制运行APP,在沙盒环境下HOOK本进程从而实现HOOK任意APP的功能。 +exposed 致力于在**非Root**环境下实现Xposed的功能。基本思路是劫持APP进程启动的入口,加载Xposed 插件以及 非Root环境下的hook框架 [epic](https://github.com/tiann/epic) 。 -Exposed本质上是一个Xposed与沙盒之间的兼容层,它给Xposed模块提供运行环境,但不强依赖于双开宿主。不过目前的唯一实现基于[VirtualApp](https://github.com/asLody/VirtualApp),同时HOOK模块 -使用 [epic](https://github.com/tiann/epic) +exposed本质上是一个 Xposed 与 APP进程 之间的兼容层,它给Xposed模块提供运行环境(如插件加载、hook环境等)。 + +目前使用最广泛的实现是 VirtualXposed,它使用 [VirtualApp](https://github.com/asLody/VirtualApp) 来运行APP并提供进程入口劫持。但是,exposed 本身并不依赖双开宿主;甚至不需要双开。 + +另外,基于APP加固的思路,甚至直接修改APK,或者通过magisk注入进程的方式,都可以实现 免Root Xposed。 # 使用 -Exposed 是一个library,是提供给沙盒开发者使用的;如果你需要在非ROOT环境下运行Xposed,请移步项目 [VAExposed](https://github.com/android-hacker/VAExposed) +Exposed 是一个library,是提供给开发者使用的;如果你需要在非ROOT环境下运行Xposed,请移步项目 [VAExposed](https://github.com/android-hacker/VAExposed) -如果需要在沙盒中提供Xposed运行环境,在给启动沙盒进程的时候,执行如下调用即可: +如果需要在APP进程中中提供Xposed运行环境,在进程启动的入口,执行如下调用即可: ```java ExposedBridge.initOnce(context, applicationInfo, appClassLoader); ``` -同时,为了加载沙盒中的Xposed模块,需要在进程启动的时候执行模块加载: +同时,为了加载Xposed模块,需要在进程启动的时候执行模块加载: ```java ExposedBridge.loadModule(moduleApk, apkOdexDir, moduleLibDir, applicationInfo, appClassLoader); From de72b91fecae769a0c5c27a088f0c595f7093fe5 Mon Sep 17 00:00:00 2001 From: weishu Date: Tue, 8 Jan 2019 15:48:17 +0800 Subject: [PATCH 52/59] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eefa5d9..9cd6ac6 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,18 @@ # 简介 -exposed 致力于在**非Root**环境下实现Xposed的功能。基本思路是劫持APP进程启动的入口,加载Xposed 插件以及 非Root环境下的hook框架 [epic](https://github.com/tiann/epic) 。 +exposed 致力于为App提供 Xposed 运行环境。基本思路是劫持APP进程启动的入口,加载 Xposed 插件以及 hook框架 [epic](https://github.com/tiann/epic) 。 exposed本质上是一个 Xposed 与 APP进程 之间的兼容层,它给Xposed模块提供运行环境(如插件加载、hook环境等)。 目前使用最广泛的实现是 VirtualXposed,它使用 [VirtualApp](https://github.com/asLody/VirtualApp) 来运行APP并提供进程入口劫持。但是,exposed 本身并不依赖双开宿主;甚至不需要双开。 -另外,基于APP加固的思路,甚至直接修改APK,或者通过magisk注入进程的方式,都可以实现 免Root Xposed。 +另外,基于APP加固的思路,甚至直接修改APK,或者通过magisk注入进程的方式,都可以实现 Xposed。 + +目前有以下几种实现方式: + +- [VirtualXposed](https://github.com/android-hacker/VirtualXposed) :基于双开实现,通过 VirtualApp 运行目标APK,在进程启动入口加载 exposed。优势:免安装,无篡改签名问题。劣势:性能 & 稳定性受限于双开,无法与系统完全交互。 +- [太极](https://www.coolapk.com/apk/me.weishu.exp):基于修改APK实现。在 Application 类的入口织入 exposed 入口代码,从而加载 exposed。优势:可以与系统完全交互,性能好。劣势:签名改变,虽有独特技术可以绕过所有检测,但是依然有风险。部分APP调用其他会检测签名,使得所有APP必须被“太极化”,风险极高。 +- [太极·Magisk](https://mp.weixin.qq.com/s?__biz=MjM5Njg5ODU2NA==&tempkey=OTkwX0JJa0I4ZW9qcmd5bGlJSXlwQjBJOTZsWGc0TllULXVXdGVicTQxcWRyWE9McnZFQVozRGpNS21OaHEySDNHbFlfMUVudk9wbHo0akE4c29hOTZhNGs5UENXQlFISlFvQjZFSS1CT1dCa1hSZWt4XzFKNV9abEZITTJNOEJkVkotVEdrN2owcmxzeU9WVF9oaVUxdlJwd3pkcHZDWXFPOTFNVEhBeUF%2Bfg%3D%3D&chksm=25983cf012efb5e6ac3fe06bd73883139a89912fa37aee74f3b3baca9e358b2c41a260cee682#rd):通过 Magisk 修改系统文件,在 Zygote 进程启动的时候执行 exposed 入口代码,从而加载 exposed。优势:完全体,不存在上述所有问题。劣势:需要解锁Bootloader和刷机。 # 使用 From 1972a5a0bd9f95214f090f83002282d7b07edeb5 Mon Sep 17 00:00:00 2001 From: o0lwj0o <373911550@qq.com> Date: Thu, 10 Jan 2019 19:36:45 +0800 Subject: [PATCH 53/59] Suggestion : Improvement of String.equals("xxx") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi, I have found some usage of “String.equals("xxx")” in this project. When using string.equals("a") ,it will get nullpointexception if string ==null. The problem can be fixed by repalced with "a".equals(string) or Objects.equals(string,"a"). Best regards --- exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java b/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java index ff2cad6..e8ef9a3 100644 --- a/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java +++ b/exposed-core/src/main/java/me/weishu/exposed/CHAHelper.java @@ -60,13 +60,13 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { static XC_MethodHook.Unhook replaceForCHA(Member member, final XC_MethodHook callback) { - if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) { + if (member.getDeclaringClass() == Application.class && "attach".equals(member.getName())) { XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA"); Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback)); } - if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) { + if (member.getDeclaringClass() == Application.class && "onCreate".equals(member.getName())) { XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA"); Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class); return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback)); From b9ef3e3accd3a5a3950cb5d31ca5a91b5d172221 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Wed, 27 Jun 2018 10:39:50 +0800 Subject: [PATCH 54/59] make the fucking cache invalid. --- exposed-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index f6b3510..6307838 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -31,7 +31,7 @@ dependencies { } group = 'me.weishu.exposed' -version = '0.7.2' +version = '0.7.3' apply plugin: 'com.novoda.bintray-release' From 0e35cbe406ee4111afabbff5577d1b4573f648ed Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Sat, 1 Sep 2018 16:33:06 +0800 Subject: [PATCH 55/59] bump version --- exposed-core/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 6307838..599f764 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -23,15 +23,15 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'me.weishu.exposed:exposed-xposedapi:0.4.4' // The Xposed API - compile ('me.weishu:epic:0.5.9') { // The AOP Framework + compile 'me.weishu.exposed:exposed-xposedapi:0.4.5' // The Xposed API + compile ('me.weishu:epic:0.7.2') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.7.3' +version = '0.7.5' apply plugin: 'com.novoda.bintray-release' From 6f4c7fad7a5a96ac6ff341cb78aa5fbc2c4993db Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Sun, 18 Aug 2019 22:29:15 +0800 Subject: [PATCH 56/59] Update version --- exposed-core/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 599f764..f86f9b5 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 26 - buildToolsVersion "26.0.2" + compileSdkVersion 28 + buildToolsVersion "28.0.3" defaultConfig { minSdkVersion 19 - targetSdkVersion 26 + targetSdkVersion 28 versionCode 1 versionName "1.0" @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.5' // The Xposed API - compile ('me.weishu:epic:0.7.2') { // The AOP Framework + compile ('me.weishu:epic:0.6.0') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.7.5' +version = '0.7.6' apply plugin: 'com.novoda.bintray-release' From b70fed9458094d989c2514d5a80af690c619695b Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Sun, 18 Aug 2019 23:18:24 +0800 Subject: [PATCH 57/59] Update dependencies --- exposed-core/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index f86f9b5..1ea72e4 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { minSdkVersion 19 - targetSdkVersion 28 + targetSdkVersion 26 versionCode 1 versionName "1.0" @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.5' // The Xposed API - compile ('me.weishu:epic:0.6.0') { // The AOP Framework + compile ('me.weishu:epic:0.6.1-c') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.7.6' +version = '0.7.6-c' apply plugin: 'com.novoda.bintray-release' From f06e2ee63e429b0aa5a9e2a418b1ac9c3542610d Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Sun, 18 Aug 2019 23:44:55 +0800 Subject: [PATCH 58/59] Update dependencies --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 1ea72e4..9d1a206 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.5' // The Xposed API - compile ('me.weishu:epic:0.6.1-c') { // The AOP Framework + compile ('me.weishu:epic:0.6.2-c') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.7.6-c' +version = '0.7.7-c' apply plugin: 'com.novoda.bintray-release' From a593ccd970c9276bb51fb9a42889b930577e1217 Mon Sep 17 00:00:00 2001 From: tiann Date: Wed, 13 Nov 2019 21:33:28 +0800 Subject: [PATCH 59/59] Update dependencies Signed-off-by: tiann --- exposed-core/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exposed-core/build.gradle b/exposed-core/build.gradle index 9d1a206..1c2cb35 100644 --- a/exposed-core/build.gradle +++ b/exposed-core/build.gradle @@ -24,14 +24,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'me.weishu.exposed:exposed-xposedapi:0.4.5' // The Xposed API - compile ('me.weishu:epic:0.6.2-c') { // The AOP Framework + compile ('me.weishu:epic:0.8.0-c') { // The AOP Framework exclude group: 'me.weishu.exposed', module: 'exposed-xposedapi' } compile 'com.getkeepsafe.relinker:relinker:1.2.3' // for load library } group = 'me.weishu.exposed' -version = '0.7.7-c' +version = '0.8.0' apply plugin: 'com.novoda.bintray-release'