diff --git a/app/build.gradle b/app/build.gradle index 9667815..d2b4a48 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,6 +21,12 @@ android { } } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + } buildTypes { debug { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f79a64d..81d756b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,19 +6,22 @@ - + + + - \ No newline at end of file + diff --git a/app/src/main/assets/xposed_init b/app/src/main/assets/xposed_init index 441393b..dfc7ee8 100644 --- a/app/src/main/assets/xposed_init +++ b/app/src/main/assets/xposed_init @@ -1 +1 @@ -org.lsposed.lspatch.tester.Hook \ No newline at end of file +org.lsposed.org.lsposed.org.lsposed.lspatch.tester.Hook diff --git a/app/src/main/java/de/robv/android/xposed/XposedHelper.java b/app/src/main/java/de/robv/android/xposed/XposedHelper.java index 3ba39ad..6536513 100644 --- a/app/src/main/java/de/robv/android/xposed/XposedHelper.java +++ b/app/src/main/java/de/robv/android/xposed/XposedHelper.java @@ -1,9 +1,5 @@ package de.robv.android.xposed; -import de.robv.android.xposed.IXposedHookZygoteInit; -import de.robv.android.xposed.IXposedMod; -import de.robv.android.xposed.XC_MethodHook; - import java.lang.reflect.Member; public class XposedHelper { diff --git a/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java b/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java new file mode 100644 index 0000000..a3b4e9c --- /dev/null +++ b/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java @@ -0,0 +1,36 @@ +package org.lsposed.lspatch.appstub; + +import android.app.Application; +import android.content.Context; + +import java.io.ByteArrayOutputStream; + +public class LSPApplicationStub extends Application { + + private static byte[] dex = null; + + static { + try (var is = LSPApplicationStub.class.getClassLoader().getResourceAsStream("assets/lsp"); + var os = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int n; + while (-1 != (n = is.read(buffer))) { + os.write(buffer, 0, n); + } + dex = os.toByteArray(); + } catch (Throwable e) { + android.util.Log.e("LSPatch", "load dex error", e); + } + System.loadLibrary("lspd"); + } + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + } +} diff --git a/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java b/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java index 2621519..5ecff1c 100644 --- a/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java +++ b/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java @@ -17,6 +17,7 @@ import org.lsposed.lspatch.loader.util.FileUtils; import org.lsposed.lspatch.loader.util.XLog; import org.lsposed.lspatch.loader.util.XpatchUtils; import org.lsposed.lspatch.share.Constants; +import org.lsposed.lspd.deopt.PrebuiltMethodsDeopter; import org.lsposed.lspd.nativebridge.SigBypass; import org.lsposed.lspd.yahfa.hooker.YahfaHooker; @@ -40,7 +41,8 @@ import de.robv.android.xposed.XposedInit; public class LSPApplication { private static final String ORIGINAL_APPLICATION_NAME_ASSET_PATH = "original_application_name.ini"; private static final String ORIGINAL_SIGNATURE_ASSET_PATH = "original_signature_info.ini"; - private static final String TAG = LSPApplication.class.getSimpleName(); + private static final String TAG = "LSPatch"; + private static String originalApplicationName = null; private static String originalSignature = null; private static Application sOriginalApplication = null; @@ -49,51 +51,43 @@ public class LSPApplication { private static int TRANSACTION_getPackageInfo_ID = -1; - final static public int FIRST_ISOLATED_UID = 99000; - final static public int LAST_ISOLATED_UID = 99999; final static public int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; - final static public int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; - final static public int SHARED_RELRO_UID = 1037; final static public int PER_USER_RANGE = 100000; - static Context context; + final static private LSPApplication instance = new LSPApplication(); static public boolean isIsolated() { - int uid = android.os.Process.myUid(); - uid = uid % PER_USER_RANGE; - return (uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID) || (uid >= FIRST_APP_ZYGOTE_ISOLATED_UID && uid <= LAST_APP_ZYGOTE_ISOLATED_UID); + return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID; } - static { + static public void onLoad() { cacheSigbypassLv = -1; if (isIsolated()) { XLog.d(TAG, "skip isolated process"); + return; } - else { - context = XpatchUtils.createAppContext(); - if (context == null) { - XLog.e(TAG, "create context err"); - } - else { - System.load(context.getApplicationInfo().nativeLibraryDir + "/liblspd.so"); - YahfaHooker.init(); - XposedInit.startsSystemServer = false; + Context context = XpatchUtils.createAppContext(); + if (context == null) { + XLog.e(TAG, "create context err"); + return; + } + YahfaHooker.init(); + XposedBridge.initXResources(); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote + XposedInit.startsSystemServer = false; - originalApplicationName = FileUtils.readTextFromAssets(context, ORIGINAL_APPLICATION_NAME_ASSET_PATH); - originalSignature = FileUtils.readTextFromAssets(context, ORIGINAL_SIGNATURE_ASSET_PATH); + originalApplicationName = FileUtils.readTextFromAssets(context, ORIGINAL_APPLICATION_NAME_ASSET_PATH); + originalSignature = FileUtils.readTextFromAssets(context, ORIGINAL_SIGNATURE_ASSET_PATH); - XLog.d(TAG, "original application class " + originalApplicationName); - XLog.d(TAG, "original signature info " + originalSignature); + XLog.d(TAG, "original application class " + originalApplicationName); + XLog.d(TAG, "original signature info " + originalSignature); - try { - doHook(); - initAndLoadModules(context); - } - catch (Exception e) { - e.printStackTrace(); - } - } + try { + doHook(context); + initAndLoadModules(context); + } catch (Throwable e) { + Log.e(TAG, "Do hook", e); } } @@ -106,12 +100,7 @@ public class LSPApplication { } private static boolean isApplicationProxied() { - if (originalApplicationName != null && !originalApplicationName.isEmpty() && !("android.app.Application").equals(originalApplicationName)) { - return true; - } - else { - return false; - } + return originalApplicationName != null && !originalApplicationName.isEmpty() && !("android.app.Application").equals(originalApplicationName); } private static ClassLoader getAppClassLoader() { @@ -122,14 +111,13 @@ public class LSPApplication { Object mBoundApplication = XposedHelpers.getObjectField(getActivityThread(), "mBoundApplication"); Object loadedApkObj = XposedHelpers.getObjectField(mBoundApplication, "info"); appClassLoader = (ClassLoader) XposedHelpers.callMethod(loadedApkObj, "getClassLoader"); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "getAppClassLoader", e); } return appClassLoader; } - private static void byPassSignature() throws ClassNotFoundException, IllegalAccessException { + private static void byPassSignature(Context context) throws ClassNotFoundException, IllegalAccessException { Field[] pmStubFields = Class.forName("android.content.pm.IPackageManager$Stub").getDeclaredFields(); for (Field field : pmStubFields) { if (!Modifier.isStatic(field.getModifiers()) || field.getType() != int.class) { @@ -203,25 +191,26 @@ public class LSPApplication { // reset pos out.setDataPosition(0); } - } - catch (Throwable err) { + } catch (Throwable err) { err.printStackTrace(); } } }); } - private static void doHook() throws IllegalAccessException, ClassNotFoundException, IOException { + private static void doHook(Context context) throws IllegalAccessException, ClassNotFoundException, IOException { if (isApplicationProxied()) { hookContextImplSetOuterContext(); hookInstallContentProviders(); hookActivityAttach(); hookServiceAttach(); } - if (fetchSigbypassLv() >= Constants.SIGBYPASS_LV_PM) { - byPassSignature(); + hookApplicationStub(); + int bypassLv = fetchSigbypassLv(context); + if (bypassLv >= Constants.SIGBYPASS_LV_PM) { + byPassSignature(context); } - if (fetchSigbypassLv() >= Constants.SIGBYPASS_LV_PM_OPENAT) { + if (bypassLv >= Constants.SIGBYPASS_LV_PM_OPENAT) { File apk = new File(context.getCacheDir(), "lspatchapk.so"); if (!apk.exists()) { try (InputStream inputStream = context.getAssets().open("origin_apk.bin"); @@ -241,7 +230,7 @@ public class LSPApplication { private static int cacheSigbypassLv; - private static int fetchSigbypassLv() { + private static int fetchSigbypassLv(Context context) { if (cacheSigbypassLv != -1) { return cacheSigbypassLv; } @@ -249,48 +238,82 @@ public class LSPApplication { try (InputStream inputStream = context.getAssets().open(Constants.CONFIG_NAME_SIGBYPASSLV + i)) { cacheSigbypassLv = i; return i; - } - catch (IOException ignore) { + } catch (IOException ignore) { } } - throw new IllegalStateException(Constants.CONFIG_NAME_SIGBYPASSLV + " err"); + return 0; + } + + private static void hookApplicationStub() { + try { + Class appStub = XposedHelpers.findClass("org.lsposed.lspatch.appstub.LSPApplicationStub", getAppClassLoader()); + XposedHelpers.findAndHookMethod(appStub, "onCreate", new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + instance.onCreate(); + } + }); + XposedHelpers.findAndHookMethod(appStub, "attachBaseContext", Context.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + instance.attachBaseContext((Context) param.args[0]); + } + }); + } catch (Throwable e) { + Log.e(TAG, "hookApplicationStub"); + } } private static void hookContextImplSetOuterContext() { - XposedHelpers.findAndHookMethod("android.app.ContextImpl", getAppClassLoader(), "setOuterContext", Context.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - replaceApplicationParam(param.args); - // XposedHelpers.setObjectField(param.thisObject, "mOuterContext", sOriginalApplication); - } - }); + try { + XposedHelpers.findAndHookMethod("android.app.ContextImpl", getAppClassLoader(), "setOuterContext", Context.class, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + replaceApplicationParam(param.args); + } + }); + } catch (Throwable e) { + Log.e(TAG, "hookContextImplSetOuterContext", e); + } } private static void hookInstallContentProviders() { - XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.ActivityThread", getAppClassLoader()), "installContentProviders", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - replaceApplicationParam(param.args); - } - }); + try { + XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.ActivityThread", getAppClassLoader()), "installContentProviders", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + replaceApplicationParam(param.args); + } + }); + } catch (Throwable e) { + Log.e(TAG, "hookInstallContextProviders", e); + } } private static void hookActivityAttach() { - XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Activity", getAppClassLoader()), "attach", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - replaceApplicationParam(param.args); - } - }); + try { + XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Activity", getAppClassLoader()), "attach", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + replaceApplicationParam(param.args); + } + }); + } catch (Throwable e) { + Log.e(TAG, "hookActivityAttach", e); + } } private static void hookServiceAttach() { - XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Service", getAppClassLoader()), "attach", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - replaceApplicationParam(param.args); - } - }); + try { + XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Service", getAppClassLoader()), "attach", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + replaceApplicationParam(param.args); + } + }); + } catch (Throwable e) { + Log.e(TAG, "hookServiceAttach", e); + } } private static void replaceApplicationParam(Object[] args) { @@ -309,9 +332,8 @@ public class LSPApplication { try { Class activityThreadClass = Class.forName("android.app.ActivityThread"); activityThread = XposedHelpers.callStaticMethod(activityThreadClass, "currentActivityThread"); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "getActivityThread", e); } } return activityThread; @@ -328,29 +350,23 @@ public class LSPApplication { private void attachOrignalBaseContext(Context base) { try { XposedHelpers.callMethod(sOriginalApplication, "attachBaseContext", base); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "attachOriginalBaseContext", e); } } private void setLoadedApkField(Context base) { - // mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; try { Class contextImplClass = Class.forName("android.app.ContextImpl"); Object contextImpl = XposedHelpers.callStaticMethod(contextImplClass, "getImpl", base); Object loadedApk = XposedHelpers.getObjectField(contextImpl, "mPackageInfo"); XposedHelpers.setObjectField(sOriginalApplication, "mLoadedApk", loadedApk); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "setLoadedApkField", e); } } public void onCreate() { - // setLoadedApkField(sOriginalApplication); - // XposedHelpers.setObjectField(sOriginalApplication, "mLoadedApk", XposedHelpers.getObjectField(this, "mLoadedApk")); - if (isApplicationProxied()) { // replaceApplication(); replaceLoadedApkApplication(); @@ -371,18 +387,16 @@ public class LSPApplication { // replace LoadedApk.java makeApplication() mApplication = app; XposedHelpers.setObjectField(loadedApkObj, "mApplication", sOriginalApplication); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "replaceLoadedApkApplication", e); } } private void replaceActivityThreadApplication() { try { XposedHelpers.setObjectField(getActivityThread(), "mInitialApplication", sOriginalApplication); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "replaceActivityThreadApplication", e); } } @@ -390,9 +404,8 @@ public class LSPApplication { if (sOriginalApplication == null) { try { sOriginalApplication = (Application) getAppClassLoader().loadClass(originalApplicationName).newInstance(); - } - catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "createOriginalApplication", e); } } return sOriginalApplication; @@ -404,9 +417,8 @@ public class LSPApplication { Object applicationInfoObj = XposedHelpers.getObjectField(mBoundApplication, "appInfo"); // info XposedHelpers.setObjectField(applicationInfoObj, "className", originalApplicationName); - } - catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + Log.e(TAG, "modifyApplicationInfoClassName", e); } } } diff --git a/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java b/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java index a58cb20..4996239 100644 --- a/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java +++ b/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java @@ -158,12 +158,6 @@ public class LSPLoader { appContext = context; - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { - if (!FileUtils.isSdcardPermissionGranted(context)) { - XLog.e(TAG, "File permission is not granted, can not control xposed module by file " + XPOSED_MODULE_FILE_PATH); - } - } - initSELinux(context); ClassLoader originClassLoader = context.getClassLoader(); @@ -195,7 +189,7 @@ public class LSPLoader { if (!app.enabled) { continue; } - if (app.metaData != null && (app.metaData.containsKey("xposedmodule"))) { + if (app.metaData != null && app.metaData.containsKey("xposedminversion")) { String apkPath = pkg.applicationInfo.publicSourceDir; String apkName = context.getPackageManager().getApplicationLabel(pkg.applicationInfo).toString(); if (TextUtils.isEmpty(apkPath)) { @@ -211,27 +205,24 @@ public class LSPLoader { final List> installedModuleListFinal = installedModuleList; - new Thread(new Runnable() { - @Override - public void run() { - List savedPackageNameList = loadPackageNameListFromFile(false); - if (savedPackageNameList == null) { - savedPackageNameList = new ArrayList<>(); - } - List> addPackageList = new ArrayList<>(); - for (Pair packgagePair : installedModuleListFinal) { - if (!savedPackageNameList.contains(packgagePair.first)) { - XLog.d(TAG, "append " + packgagePair + " to " + XPOSED_MODULE_FILE_PATH); - addPackageList.add(packgagePair); - } - } - try { - appendPackageNameToFile(addPackageList); - } - catch (IOException e) { - e.printStackTrace(); + new Thread(() -> { + List savedPackageNameList = loadPackageNameListFromFile(false); + if (savedPackageNameList == null) { + savedPackageNameList = new ArrayList<>(); + } + List> addPackageList = new ArrayList<>(); + for (Pair packgagePair : installedModuleListFinal) { + if (!savedPackageNameList.contains(packgagePair.first)) { + XLog.d(TAG, "append " + packgagePair + " to " + XPOSED_MODULE_FILE_PATH); + addPackageList.add(packgagePair); } } + try { + appendPackageNameToFile(addPackageList); + } + catch (IOException e) { + e.printStackTrace(); + } }).start(); return modulePathList; } diff --git a/app/src/main/java/org/lsposed/lspatch/tester/Hook.java b/app/src/main/java/org/lsposed/lspatch/tester/Hook.java index e88a44d..a71052a 100644 --- a/app/src/main/java/org/lsposed/lspatch/tester/Hook.java +++ b/app/src/main/java/org/lsposed/lspatch/tester/Hook.java @@ -8,7 +8,7 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage; public class Hook implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { - XposedHelpers.findAndHookMethod("org.lsposed.lspatch.tester.MainActivity", lpparam.classLoader, "checkXposed2", new XC_MethodHook() { + XposedHelpers.findAndHookMethod("org.lsposed.org.lsposed.org.lsposed.lspatch.tester.MainActivity", lpparam.classLoader, "checkXposed2", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { param.setResult(true); diff --git a/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java b/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java index ea75e87..525a0a1 100644 --- a/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java +++ b/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java @@ -26,12 +26,6 @@ public class MainActivity extends Activity { param.setResult(true); } }); - XposedHelpers.findAndHookMethod(this.getClass(), "checkXposed2", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - param.setResult(true); - } - }); TextView textView = findViewById(R.id.msg); if (checkXposed() && checkXposed2()) { diff --git a/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java b/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java deleted file mode 100644 index c3f7628..0000000 --- a/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.lsposed.lspatch.tester; - -import android.app.Application; -import android.content.Context; - -import org.lsposed.lspatch.loader.LSPLoader; -import org.lsposed.lspd.yahfa.hooker.YahfaHooker; - -import de.robv.android.xposed.XposedInit; - -// you can run this app to test hook framework -public class XposedTestApplication extends Application { - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - } - - static { - System.loadLibrary("lspd"); - YahfaHooker.init(); - XposedInit.startsSystemServer = false; - LSPLoader.initAndLoadModules(); - } -} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 27011cb..820b4f2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="org.lsposed.lspatch.tester.MainActivity"> + tools:context="org.lsposed.org.lsposed.tester.MainActivity"> - \ No newline at end of file + diff --git a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java index 6ea482f..a3b4e9c 100644 --- a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java +++ b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java @@ -1,120 +1,36 @@ package org.lsposed.lspatch.appstub; -import android.app.ActivityThread; import android.app.Application; import android.content.Context; -import android.util.Log; import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; - -import dalvik.system.InMemoryDexClassLoader; public class LSPApplicationStub extends Application { - final static String TAG = LSPApplicationStub.class.getSimpleName(); - static Object realLSPApplication = null; + private static byte[] dex = null; static { - // load real lsp loader from asset - Context context = createAppContext(); - if (context == null) { - throw new IllegalStateException("create context err"); - } - else { - try (InputStream inputStream = context.getAssets().open("lsp.dex"); - ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { - - int nRead; - byte[] data = new byte[16384]; - - while ((nRead = inputStream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - // loader can load it's own so from app native library dir - String libraryDir = context.getApplicationInfo().nativeLibraryDir; - - Log.d(TAG, "LSPApplicationStub cl: " + LSPApplicationStub.class.getClassLoader()); - Log.d(TAG, "NativePath : " + libraryDir); - - InMemoryDexClassLoader loaderClassLoader = new InMemoryDexClassLoader(ByteBuffer.wrap(buffer.toByteArray()), - LSPApplicationStub.class.getClassLoader()); - Class lspa = loaderClassLoader.loadClass("org.lsposed.lspatch.loader.LSPApplication"); - realLSPApplication = lspa.newInstance(); - } - catch (Exception e) { - throw new IllegalStateException("wtf", e); + try (var is = LSPApplicationStub.class.getClassLoader().getResourceAsStream("assets/lsp"); + var os = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int n; + while (-1 != (n = is.read(buffer))) { + os.write(buffer, 0, n); } + dex = os.toByteArray(); + } catch (Throwable e) { + android.util.Log.e("LSPatch", "load dex error", e); } + System.loadLibrary("lspd"); } @Override public void onCreate() { super.onCreate(); - - try { - realLSPApplication.getClass().getDeclaredMethod("onCreate").invoke(realLSPApplication); - } - catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - throw new IllegalStateException("wtf", e); - } } @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); - - try { - Method method = realLSPApplication.getClass().getDeclaredMethod("attachBaseContext", Context.class); - method.setAccessible(true); - method.invoke(realLSPApplication, base); - } - catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - throw new IllegalStateException("wtf", e); - } - } - - // copy from app project - public static Context createAppContext() { - try { - Class activityThreadClass = Class.forName("android.app.ActivityThread"); - Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread"); - currentActivityThreadMethod.setAccessible(true); - - Object activityThreadObj = currentActivityThreadMethod.invoke(null); - - Field boundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication"); - boundApplicationField.setAccessible(true); - Object mBoundApplication = boundApplicationField.get(activityThreadObj); // AppBindData - if (mBoundApplication == null) { - Log.e(TAG, "mBoundApplication null"); - return null; - } - Field infoField = mBoundApplication.getClass().getDeclaredField("info"); // info - infoField.setAccessible(true); - Object loadedApkObj = infoField.get(mBoundApplication); // LoadedApk - if (loadedApkObj == null) { - Log.e(TAG, "loadedApkObj null"); - return null; - } - Class contextImplClass = Class.forName("android.app.ContextImpl"); - Method createAppContextMethod = contextImplClass.getDeclaredMethod("createAppContext", activityThreadClass, loadedApkObj.getClass()); - createAppContextMethod.setAccessible(true); - - Object context = createAppContextMethod.invoke(null, (ActivityThread) activityThreadObj, loadedApkObj); - - if (context instanceof Context) { - return (Context) context; - } - } - catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) { - throw new IllegalStateException("wtf", e); - } - return null; } } diff --git a/core b/core index 90b37a6..9e47e90 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 90b37a68aa32e79ea2dc58048f7657ba66abed89 +Subproject commit 9e47e9027c4244317085cce2a95ddcbb7b579ee0 diff --git a/patch/src/main/java/org/lsposed/patch/LSPatch.java b/patch/src/main/java/org/lsposed/patch/LSPatch.java index cda1fc9..3cc0684 100644 --- a/patch/src/main/java/org/lsposed/patch/LSPatch.java +++ b/patch/src/main/java/org/lsposed/patch/LSPatch.java @@ -254,7 +254,7 @@ public class LSPatch { } try (var is = getClass().getClassLoader().getResourceAsStream("assets/dex/lsp.dex")) { - zFile.add("assets/lsp.dex", is); + zFile.add("assets/lsp", is); } catch (Throwable e) { throw new PatchError("Error when add assets: " + e); }