Avoid creating the LoadedApk from ourselves (#1852)

Fix #1843
This commit is contained in:
LoveSy 2022-04-16 12:04:20 +08:00 committed by GitHub
parent 81448c3958
commit 85a05bbbd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 116 deletions

View File

@ -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() {

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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);
}
}
}

View File

@ -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#<init> is android, skip: " + mAppDir);
return;
if (XposedInit.startsSystemServer) {
Hookers.logD("LoadedApk#<init> 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#<init> 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.<init>", t);
}

View File

@ -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;
}
}