refactor: clean up de.rebv.android.xposed linkage

This commit is contained in:
ACh Sulfate
2024-07-22 14:06:18 +08:00
parent deed89ab18
commit 768d55bf9e
8 changed files with 116 additions and 47 deletions

View File

@@ -66,9 +66,9 @@ public class StartupAgent {
// I don't know... What happened?
return;
}
StartupInfo.modulePath = modulePath;
StartupInfo.loaderInfo = loaderInfo;
StartupInfo.hookBridge = hookBridge;
StartupInfo.setModulePath(modulePath);
StartupInfo.setLoaderInfo(loaderInfo);
StartupInfo.setHookBridge(hookBridge);
// bypass hidden api
ensureHiddenApiAccess();
// we want context

View File

@@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.github.qauxv.loader.hookapi.IHookBridge;
import io.github.qauxv.loader.hookapi.ILoaderInfo;
import java.util.Objects;
public class StartupInfo {
@@ -33,11 +34,11 @@ public class StartupInfo {
throw new AssertionError("No instance for you!");
}
/* package */ static String modulePath;
private static String modulePath;
/* package */ static ILoaderInfo loaderInfo;
private static ILoaderInfo loaderInfo;
/* package */ static IHookBridge hookBridge;
private static IHookBridge hookBridge;
@NonNull
public static String getModulePath() {
@@ -62,4 +63,18 @@ public class StartupInfo {
return hookBridge;
}
public static void setHookBridge(@Nullable IHookBridge hookBridge) {
StartupInfo.hookBridge = hookBridge;
}
public static void setLoaderInfo(@NonNull ILoaderInfo loaderInfo) {
Objects.requireNonNull(loaderInfo);
StartupInfo.loaderInfo = loaderInfo;
}
public static void setModulePath(@NonNull String modulePath) {
Objects.requireNonNull(modulePath);
StartupInfo.modulePath = modulePath;
}
}

View File

@@ -24,7 +24,8 @@ package io.github.qauxv.poststartup;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit;
import com.github.kyuubiran.ezxhelper.init.InitFields;
import com.github.kyuubiran.ezxhelper.utils.Log;
import io.github.qauxv.core.MainHook;
import io.github.qauxv.core.NativeCoreBridge;
import io.github.qauxv.util.HostInfo;
@@ -50,13 +51,11 @@ public class StartupRoutine {
*/
public static void execPostStartupInit(Context ctx, Object step, String lpwReserved, boolean bReserved) {
// init all kotlin utils here
EzXHelperInit.INSTANCE.setHostPackageName(ctx.getPackageName());
EzXHelperInit.INSTANCE.setEzClassLoader(ctx.getClassLoader());
// resource injection is done somewhere else, do not init it here
EzXHelperInit.INSTANCE.initAppContext(ctx, false, false);
EzXHelperInit.INSTANCE.setLogTag("QAuxv");
HostInfo.init((Application) ctx);
Initiator.init(ctx.getClassLoader());
InitFields.ezXClassLoader = ctx.getClassLoader();
// resource injection is done somewhere else, do not init it here
Log.INSTANCE.getCurrentLogger().setLogTag("QAuxv");
Natives.load(ctx);
overrideLSPatchModifiedVersionCodeIfNecessary(ctx);
NativeCoreBridge.initNativeCore(ctx.getPackageName(), Build.VERSION.SDK_INT,

View File

@@ -21,17 +21,25 @@
*/
package io.github.qauxv.util;
import androidx.annotation.Nullable;
import io.github.qauxv.loader.hookapi.IHookBridge;
import io.github.qauxv.poststartup.StartupInfo;
public class LspObfuscationHelper {
private static String sObfuscatedPackageName = null;
public static final String CMD_GET_XPOSED_BRIDGE_CLASS = "GetXposedBridgeClass";
private static String sProbeLsposedNativeApiClassName = "Lorg/lsposed/lspd/nativebridge/NativeAPI;";
public static void setObfuscatedXposedApiPackage(String packageName) {
sObfuscatedPackageName = packageName;
private LspObfuscationHelper() {
}
public static String getObfuscatedXposedApiPackage() {
return sObfuscatedPackageName;
@Nullable
public static Class<?> getXposedBridgeClass() {
IHookBridge hookBridge = StartupInfo.getHookBridge();
if (hookBridge == null) {
return null;
}
return (Class<?>) hookBridge.queryExtension(CMD_GET_XPOSED_BRIDGE_CLASS);
}
public static String getObfuscatedLsposedNativeApiClassName() {
@@ -39,12 +47,11 @@ public class LspObfuscationHelper {
}
public static String getXposedBridgeClassName() {
if (sObfuscatedPackageName == null) {
return "de.robv.android.xposed.XposedBridge";
Class<?> xposedBridgeClass = getXposedBridgeClass();
if (xposedBridgeClass != null) {
return xposedBridgeClass.getName();
} else {
var sb = new StringBuilder(sObfuscatedPackageName);
sb.append(".XposedBridge");
return sb.toString();
return "de.robv.android.xposed.XposedBridge";
}
}

View File

@@ -32,9 +32,9 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cc.ioctl.util.HostInfo;
import de.robv.android.xposed.XposedBridge;
import io.github.qauxv.BuildConfig;
import io.github.qauxv.R;
import io.github.qauxv.util.LspObfuscationHelper;
import io.github.qauxv.util.SyncUtils;
import io.github.qauxv.util.NonUiThread;
import java.io.File;
@@ -145,16 +145,22 @@ public class HookStatus {
}
private static void initHookStatusImplInHostProcess() throws LinkageError {
boolean dexObfsEnabled = !"de.robv.android.xposed.XposedBridge".equals(XposedBridge.class.getName());
Class<?> xposedClass = LspObfuscationHelper.getXposedBridgeClass();
boolean dexObfsEnabled = false;
if (xposedClass != null) {
dexObfsEnabled = !"de.robv.android.xposed.XposedBridge".equals(xposedClass.getName());
}
String hookProvider = null;
if (dexObfsEnabled) {
HookStatusImpl.sIsLsposedDexObfsEnabled = true;
hookProvider = "LSPosed";
} else {
String bridgeTag = null;
try {
bridgeTag = (String) XposedBridge.class.getDeclaredField("TAG").get(null);
} catch (ReflectiveOperationException ignored) {
if (xposedClass != null) {
try {
bridgeTag = (String) xposedClass.getDeclaredField("TAG").get(null);
} catch (ReflectiveOperationException ignored) {
}
}
if (bridgeTag != null) {
if (bridgeTag.startsWith("LSPosed")) {

View File

@@ -24,7 +24,11 @@ package io.github.qauxv.util.hookstatus;
import android.app.Application;
import android.os.Build;
import androidx.annotation.NonNull;
import io.github.qauxv.BuildConfig;
import io.github.qauxv.core.NativeCoreBridge;
import io.github.qauxv.loader.hookapi.ILoaderInfo;
import io.github.qauxv.poststartup.StartupInfo;
import io.github.qauxv.util.HostInfo;
import io.github.qauxv.util.Natives;
import org.lsposed.hiddenapibypass.HiddenApiBypass;
@@ -44,5 +48,49 @@ public class ModuleAppImpl extends Application {
}
NativeCoreBridge.initNativeCore(getPackageName(), Build.VERSION.SDK_INT,
HostInfo.getHostInfo().getVersionName(), HostInfo.getHostInfo().getVersionCode());
initStartupInfo();
// for fail-safe purpose
com.github.kyuubiran.ezxhelper.utils.Log.INSTANCE.getCurrentLogger().setLogTag("QAuxv");
}
private void initStartupInfo() {
final String apkPath = getApplicationInfo().sourceDir;
ILoaderInfo loaderInfo = new ILoaderInfo() {
@NonNull
@Override
public String getEntryPointName() {
return "ActivityThread";
}
@NonNull
@Override
public String getLoaderVersionName() {
return BuildConfig.VERSION_NAME;
}
@Override
public int getLoaderVersionCode() {
return BuildConfig.VERSION_CODE;
}
@NonNull
@Override
public String getMainModulePath() {
return apkPath;
}
@Override
public void log(@NonNull String msg) {
android.util.Log.i("QAuxv", msg);
}
@Override
public void log(@NonNull Throwable tr) {
android.util.Log.e("QAuxv", tr.toString(), tr);
}
};
StartupInfo.setModulePath(apkPath);
StartupInfo.setLoaderInfo(loaderInfo);
}
}

View File

@@ -44,9 +44,7 @@ public class Xp51HookEntry implements IXposedHookLoadPackage, IXposedHookZygoteI
Class<?> kXposedBridge = XposedBridge.class;
switch (lpparam.packageName) {
case PACKAGE_NAME_SELF: {
Class<?> kHookStatusInit = Class.forName("io.github.qauxv.util.hookstatus.HookStatusInit");
Method init = kHookStatusInit.getDeclaredMethod("init", ClassLoader.class);
init.invoke(null, lpparam.classLoader);
Xp51HookStatusInit.init(lpparam.classLoader);
break;
}
case PACKAGE_NAME_TIM:

View File

@@ -1,42 +1,38 @@
/*
* QAuxiliary - An Xposed module for QQ/TIM
* Copyright (C) 2019-2022 qwq233@qwq2333.top
* Copyright (C) 2019-2024 QAuxiliary developers
* https://github.com/cinit/QAuxiliary
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* This software is an opensource software: you can redistribute it
* and/or modify it under the terms of the General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version and our eula as published
* version 3 of the License, or any later version as published
* by QAuxiliary contributors.
*
* This software 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
* Affero General Public License for more details.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
* You should have received a copy of the General Public License
* along with this software.
* If not, see
* <https://github.com/cinit/QAuxiliary/blob/master/LICENSE.md>.
*/
package io.github.qauxv.util.hookstatus;
package io.github.qauxv.loader.sbl.xp51;
import androidx.annotation.Keep;
import de.robv.android.xposed.XposedBridge;
import java.lang.reflect.Field;
/**
* Called in handleLoadPackage, NO KOTLIN, NO ANDROIDX
**/
@Keep
public class HookStatusInit {
public class Xp51HookStatusInit {
private HookStatusInit() {
private Xp51HookStatusInit() {
}
@Keep
public static void init(ClassLoader classLoader) throws Throwable {
public static void init(ClassLoader classLoader) throws ReflectiveOperationException {
Class<?> kHookStatusImpl = classLoader.loadClass("io.github.qauxv.util.hookstatus.HookStatusImpl");
Field f = kHookStatusImpl.getDeclaredField("sZygoteHookMode");
f.setAccessible(true);