From 85a05bbbd1b064ed79cc6199c79a7c17d52fc87b Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sat, 16 Apr 2022 12:04:20 +0800 Subject: [PATCH] Avoid creating the LoadedApk from ourselves (#1852) Fix #1843 --- .../java/org/lsposed/lspd/core/Startup.java | 9 +-- .../lspd/hooker/HandleBindAppHooker.java | 77 ------------------- ...trHooker.java => LoadedApkCtorHooker.java} | 22 ++---- .../lspd/hooker/LoadedApkGetCLHooker.java | 36 ++++----- 4 files changed, 28 insertions(+), 116 deletions(-) delete mode 100644 core/src/main/java/org/lsposed/lspd/hooker/HandleBindAppHooker.java rename core/src/main/java/org/lsposed/lspd/hooker/{LoadedApkCstrHooker.java => LoadedApkCtorHooker.java} (79%) diff --git a/core/src/main/java/org/lsposed/lspd/core/Startup.java b/core/src/main/java/org/lsposed/lspd/core/Startup.java index 3192e0f9..3232c95b 100644 --- a/core/src/main/java/org/lsposed/lspd/core/Startup.java +++ b/core/src/main/java/org/lsposed/lspd/core/Startup.java @@ -29,9 +29,8 @@ import com.android.internal.os.ZygoteInit; import org.lsposed.lspd.deopt.PrebuiltMethodsDeopter; import org.lsposed.lspd.hooker.CrashDumpHooker; -import org.lsposed.lspd.hooker.HandleBindAppHooker; import org.lsposed.lspd.hooker.HandleSystemServerProcessHooker; -import org.lsposed.lspd.hooker.LoadedApkCstrHooker; +import org.lsposed.lspd.hooker.LoadedApkCtorHooker; import org.lsposed.lspd.service.ILSPApplicationService; import org.lsposed.lspd.util.Utils; @@ -48,14 +47,10 @@ public class Startup { XposedBridge.hookAllMethods(ZygoteInit.class, "handleSystemServerProcess", new HandleSystemServerProcessHooker()); } - XposedHelpers.findAndHookMethod(ActivityThread.class, - "handleBindApplication", - "android.app.ActivityThread$AppBindData", - new HandleBindAppHooker()); XposedHelpers.findAndHookConstructor(LoadedApk.class, ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class, ClassLoader.class, boolean.class, boolean.class, boolean.class, - new LoadedApkCstrHooker()); + new LoadedApkCtorHooker()); } public static void bootstrapXposed() { diff --git a/core/src/main/java/org/lsposed/lspd/hooker/HandleBindAppHooker.java b/core/src/main/java/org/lsposed/lspd/hooker/HandleBindAppHooker.java deleted file mode 100644 index 686ce0e6..00000000 --- a/core/src/main/java/org/lsposed/lspd/hooker/HandleBindAppHooker.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of LSPosed. - * - * LSPosed is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LSPosed is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LSPosed. If not, see . - * - * Copyright (C) 2020 EdXposed Contributors - * Copyright (C) 2021 - 2022 LSPosed Contributors - */ - -package org.lsposed.lspd.hooker; - -import android.app.ActivityThread; -import android.app.LoadedApk; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; -import android.content.res.XResources; - -import org.lsposed.lspd.util.Hookers; -import org.lsposed.lspd.util.Utils; - -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; - -// normal process initialization (for new Activity, Service, BroadcastReceiver etc.) -public class HandleBindAppHooker extends XC_MethodHook { - - @Override - protected void beforeHookedMethod(MethodHookParam param) { - try { - Hookers.logD("ActivityThread#handleBindApplication() starts"); - ActivityThread activityThread = (ActivityThread) param.thisObject; - Object bindData = param.args[0]; - final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo"); - // save app process name here for later use - String appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); - String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; - - // Note: packageName="android" -> system_server process, ams pms etc; - // packageName="system" -> android pkg, system dialogues. - Utils.logD("processName=" + appProcessName + ", packageName=" + reportedPackageName); - - CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo"); - if (appInfo.sourceDir == null) { - return; - } - XposedHelpers.setObjectField(activityThread, "mBoundApplication", bindData); - XposedInit.loadedPackagesInProcess.add(reportedPackageName); - LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo); - - if (!XposedInit.disableResources) { - XResources.setPackageNameForResDir(appInfo.packageName, loadedApk.getResDir()); - } - - String processName = (String) XposedHelpers.getObjectField(bindData, "processName"); - - LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, reportedPackageName, - processName, true); - hook.setUnhook(XposedHelpers.findAndHookMethod( - LoadedApk.class, "getClassLoader", hook)); - - } catch (Throwable t) { - Hookers.logE("error when hooking bindApp", t); - } - } -} diff --git a/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCstrHooker.java b/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCtorHooker.java similarity index 79% rename from core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCstrHooker.java rename to core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCtorHooker.java index b3fe4db8..e8b98910 100644 --- a/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCstrHooker.java +++ b/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCtorHooker.java @@ -20,7 +20,6 @@ package org.lsposed.lspd.hooker; -import android.app.AndroidAppHelper; import android.app.LoadedApk; import android.content.res.XResources; import android.util.Log; @@ -32,7 +31,7 @@ import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedInit; // when a package is loaded for an existing process, trigger the callbacks as well -public class LoadedApkCstrHooker extends XC_MethodHook { +public class LoadedApkCtorHooker extends XC_MethodHook { @Override protected void afterHookedMethod(MethodHookParam param) { @@ -49,8 +48,12 @@ public class LoadedApkCstrHooker extends XC_MethodHook { } if (packageName.equals("android")) { - Hookers.logD("LoadedApk# is android, skip: " + mAppDir); - return; + if (XposedInit.startsSystemServer) { + Hookers.logD("LoadedApk# is android, skip: " + mAppDir); + return; + } else { + packageName = "system"; + } } // mIncludeCode checking should go ahead of loadedPackagesInProcess added checking @@ -59,11 +62,6 @@ public class LoadedApkCstrHooker extends XC_MethodHook { return; } - if (XposedInit.loadedPackagesInProcess.isEmpty()) { - Hookers.logD("First LoadedApk should be called by handleBindApplication, skip: " + mAppDir); - return; - } - if (!XposedInit.loadedPackagesInProcess.add(packageName)) { Hookers.logD("LoadedApk# has been loaded before, skip: " + mAppDir); return; @@ -76,11 +74,7 @@ public class LoadedApkCstrHooker extends XC_MethodHook { return; } - LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, packageName, - AndroidAppHelper.currentProcessName(), false); - hook.setUnhook(XposedHelpers.findAndHookMethod( - LoadedApk.class, "getClassLoader", hook)); - + new LoadedApkGetCLHooker(loadedApk); } catch (Throwable t) { Hookers.logE("error when hooking LoadedApk.", t); } diff --git a/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkGetCLHooker.java b/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkGetCLHooker.java index 05df199d..1607bbc3 100644 --- a/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkGetCLHooker.java +++ b/core/src/main/java/org/lsposed/lspd/hooker/LoadedApkGetCLHooker.java @@ -22,6 +22,8 @@ package org.lsposed.lspd.hooker; import static org.lsposed.lspd.core.ApplicationServiceClient.serviceClient; +import android.app.ActivityThread; +import android.app.AndroidAppHelper; import android.app.LoadedApk; import android.os.IBinder; @@ -41,17 +43,11 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage; public class LoadedApkGetCLHooker extends XC_MethodHook { private final LoadedApk loadedApk; - private final String packageName; - private final String processName; - private final boolean isFirstApplication; - private Unhook unhook; + private final Unhook unhook; - public LoadedApkGetCLHooker(LoadedApk loadedApk, String packageName, String processName, - boolean isFirstApplication) { + public LoadedApkGetCLHooker(LoadedApk loadedApk) { this.loadedApk = loadedApk; - this.packageName = packageName; - this.processName = processName; - this.isFirstApplication = isFirstApplication; + unhook = XposedHelpers.findAndHookMethod(LoadedApk.class, "getClassLoader", this); } @Override @@ -63,7 +59,17 @@ public class LoadedApkGetCLHooker extends XC_MethodHook { } try { - Hookers.logD("LoadedApk#getClassLoader starts: isFirst=" + isFirstApplication); + Hookers.logD("LoadedApk#getClassLoader starts"); + + String packageName = ActivityThread.currentPackageName(); + String processName = ActivityThread.currentProcessName(); + boolean isFirstApplication = packageName != null && processName != null && packageName.equals(loadedApk.getPackageName()); + if (!isFirstApplication) { + packageName = loadedApk.getPackageName(); + processName = AndroidAppHelper.currentProcessName(); + } else if (packageName.equals("android")) { + packageName = "system"; + } Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir"); ClassLoader classLoader = (ClassLoader) param.getResult(); @@ -86,15 +92,13 @@ public class LoadedApkGetCLHooker extends XC_MethodHook { hookNewXSP(lpparam); } + Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstApplication=" + isFirstApplication + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo); XC_LoadPackage.callAll(lpparam); } catch (Throwable t) { Hookers.logE("error when hooking LoadedApk#getClassLoader", t); } finally { - if (unhook != null) { - unhook.unhook(); - unhook = null; - } + unhook.unhook(); } } @@ -132,8 +136,4 @@ public class LoadedApkGetCLHooker extends XC_MethodHook { }); } } - - public void setUnhook(Unhook unhook) { - this.unhook = unhook; - } }