Remove dependency on Gson

Patch-loader might use Gson provided by the apk classLoader
This commit is contained in:
JingMatrix 2023-07-08 17:06:10 +02:00
parent 69438162cd
commit 87a765d65c
2 changed files with 24 additions and 19 deletions

View File

@ -13,15 +13,13 @@ import android.os.RemoteException;
import android.system.Os; import android.system.Os;
import android.util.Log; import android.util.Log;
import com.google.gson.Gson;
import org.lsposed.lspatch.loader.util.FileUtils; import org.lsposed.lspatch.loader.util.FileUtils;
import org.lsposed.lspatch.loader.util.XLog; import org.lsposed.lspatch.loader.util.XLog;
import org.lsposed.lspatch.service.LocalApplicationService; import org.lsposed.lspatch.service.LocalApplicationService;
import org.lsposed.lspatch.service.RemoteApplicationService; import org.lsposed.lspatch.service.RemoteApplicationService;
import org.lsposed.lspatch.share.PatchConfig;
import org.lsposed.lspd.core.Startup; import org.lsposed.lspd.core.Startup;
import org.lsposed.lspd.service.ILSPApplicationService; import org.lsposed.lspd.service.ILSPApplicationService;
import org.json.JSONObject;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -39,6 +37,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
@ -58,7 +57,7 @@ public class LSPApplication {
private static LoadedApk stubLoadedApk; private static LoadedApk stubLoadedApk;
private static LoadedApk appLoadedApk; private static LoadedApk appLoadedApk;
private static PatchConfig config; private static JSONObject config;
public static boolean isIsolated() { public static boolean isIsolated() {
return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID; return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID;
@ -78,7 +77,7 @@ public class LSPApplication {
Log.d(TAG, "Initialize service client"); Log.d(TAG, "Initialize service client");
ILSPApplicationService service; ILSPApplicationService service;
if (config.useManager) { if (config.optBoolean("useManager")) {
service = new RemoteApplicationService(context); service = new RemoteApplicationService(context);
} else { } else {
service = new LocalApplicationService(context); service = new LocalApplicationService(context);
@ -94,7 +93,7 @@ public class LSPApplication {
Log.i(TAG, "Modules initialized"); Log.i(TAG, "Modules initialized");
switchAllClassLoader(); switchAllClassLoader();
SigBypass.doSigBypass(context, config.sigBypassLevel); SigBypass.doSigBypass(context, config.optInt("sigBypassLevel"));
Log.i(TAG, "LSPatch bootstrap completed"); Log.i(TAG, "LSPatch bootstrap completed");
} }
@ -110,13 +109,13 @@ public class LSPApplication {
try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) { try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) {
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
config = new Gson().fromJson(streamReader, PatchConfig.class); config = new JSONObject(streamReader.lines().collect(Collectors.joining()));
} catch (IOException e) { } catch (Throwable e) {
Log.e(TAG, "Failed to load config file"); Log.e(TAG, "Failed to parse config file", e);
return null; return null;
} }
Log.i(TAG, "Use manager: " + config.useManager); Log.i(TAG, "Use manager: " + config.optBoolean("useManager"));
Log.i(TAG, "Signature bypass level: " + config.sigBypassLevel); Log.i(TAG, "Signature bypass level: " + config.optInt("sigBypassLevel"));
Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/"); Path originPath = Paths.get(appInfo.dataDir, "cache/lspatch/origin/");
Path cacheApkPath; Path cacheApkPath;
@ -126,7 +125,9 @@ public class LSPApplication {
appInfo.sourceDir = cacheApkPath.toString(); appInfo.sourceDir = cacheApkPath.toString();
appInfo.publicSourceDir = cacheApkPath.toString(); appInfo.publicSourceDir = cacheApkPath.toString();
appInfo.appComponentFactory = config.appComponentFactory; if (config.has("appComponentFactory")) {
appInfo.appComponentFactory = config.optString("appComponentFactory");
}
if (!Files.exists(cacheApkPath)) { if (!Files.exists(cacheApkPath)) {
Log.i(TAG, "Extract original apk"); Log.i(TAG, "Extract original apk");
@ -165,11 +166,11 @@ public class LSPApplication {
Log.i(TAG, "hooked app initialized: " + appLoadedApk); Log.i(TAG, "hooked app initialized: " + appLoadedApk);
var context = (Context) XposedHelpers.callStaticMethod(Class.forName("android.app.ContextImpl"), "createAppContext", activityThread, stubLoadedApk); var context = (Context) XposedHelpers.callStaticMethod(Class.forName("android.app.ContextImpl"), "createAppContext", activityThread, stubLoadedApk);
if (config.appComponentFactory != null) { if (config.has("appComponentFactory")) {
try { try {
context.getClassLoader().loadClass(config.appComponentFactory); context.getClassLoader().loadClass(appInfo.appComponentFactory);
} catch (ClassNotFoundException e) { // This will happen on some strange shells like 360 } catch (ClassNotFoundException e) { // This will happen on some strange shells like 360
Log.w(TAG, "Original AppComponentFactory not found: " + config.appComponentFactory); Log.w(TAG, "Original AppComponentFactory not found: " + appInfo.appComponentFactory);
appInfo.appComponentFactory = null; appInfo.appComponentFactory = null;
} }
} }

View File

@ -12,12 +12,12 @@ import android.os.Parcelable;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import org.lsposed.lspatch.loader.util.XLog; import org.lsposed.lspatch.loader.util.XLog;
import org.lsposed.lspatch.share.Constants; import org.lsposed.lspatch.share.Constants;
import org.lsposed.lspatch.share.PatchConfig; import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -46,8 +46,12 @@ public class SigBypass {
if (metaData != null) encoded = metaData.getString("lspatch"); if (metaData != null) encoded = metaData.getString("lspatch");
if (encoded != null) { if (encoded != null) {
var json = new String(Base64.decode(encoded, Base64.DEFAULT), StandardCharsets.UTF_8); var json = new String(Base64.decode(encoded, Base64.DEFAULT), StandardCharsets.UTF_8);
var patchConfig = new Gson().fromJson(json, PatchConfig.class); try {
replacement = patchConfig.originalSignature; var patchConfig = new JSONObject(json);
replacement = patchConfig.getString("originalSignature");
} catch (JSONException e) {
Log.w(TAG, "fail to get originalSignature", e);
}
} }
} catch (PackageManager.NameNotFoundException | JsonSyntaxException ignored) { } catch (PackageManager.NameNotFoundException | JsonSyntaxException ignored) {
} }