From b83152323adabb90153bf9180729079078f7b149 Mon Sep 17 00:00:00 2001 From: xihan123 Date: Thu, 21 Nov 2024 02:38:48 +0800 Subject: [PATCH] Allow uers to chose if inject loader dex (#19) If we always inject loader dex, then modules with third party libraries might fail to find library classes since the default class loader is alway used before the the loader of the module package. Therefore, it is better to treat packages with isolated services as special cases. --- core | 2 +- .../main/java/org/lsposed/lspatch/Patcher.kt | 3 +++ .../lsposed/lspatch/ui/page/NewPatchScreen.kt | 9 +++++++ .../lspatch/ui/viewmodel/NewPatchViewModel.kt | 2 ++ .../ui/viewmodel/manage/AppManageViewModel.kt | 2 +- .../src/main/res/values-zh-rCN/strings.xml | 2 ++ .../src/main/res/values-zh-rTW/strings.xml | 2 ++ manager/src/main/res/values/strings.xml | 2 ++ .../main/java/org/lsposed/patch/LSPatch.java | 24 ++++++++++++------- 9 files changed, 38 insertions(+), 10 deletions(-) diff --git a/core b/core index 1db3217..6575c44 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 1db3217d2e7b0986b0ad1f0e7581601c759a39c0 +Subproject commit 6575c443f09693244a72e5cd5dcf41f6cba0f9a2 diff --git a/manager/src/main/java/org/lsposed/lspatch/Patcher.kt b/manager/src/main/java/org/lsposed/lspatch/Patcher.kt index 1bf2d64..15e6d35 100644 --- a/manager/src/main/java/org/lsposed/lspatch/Patcher.kt +++ b/manager/src/main/java/org/lsposed/lspatch/Patcher.kt @@ -11,10 +11,12 @@ import org.lsposed.lspatch.share.PatchConfig import org.lsposed.patch.LSPatch import org.lsposed.patch.util.Logger import java.io.IOException +import java.util.Collections.addAll object Patcher { class Options( + private val injectDex: Boolean, private val config: PatchConfig, private val apkPaths: List, private val embeddedModules: List? @@ -31,6 +33,7 @@ object Patcher { embeddedModules?.forEach { add("-m"); add(it) } + if(injectDex) add("--injectdex") if (!MyKeyStore.useDefault) { addAll(arrayOf("-k", MyKeyStore.file.path, Configs.keyStorePassword, Configs.keyStoreAlias, Configs.keyStoreAliasPassword)) } diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchScreen.kt b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchScreen.kt index 3c8473d..a1dc27e 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchScreen.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchScreen.kt @@ -337,6 +337,15 @@ private fun PatchOptionsBody(modifier: Modifier, onAddEmbed: () -> Unit) { title = stringResource(R.string.patch_override_version_code), desc = stringResource(R.string.patch_override_version_code_desc) ) + + SettingsCheckBox( + modifier = Modifier.clickable { viewModel.injectDex = !viewModel.injectDex }, + checked = viewModel.injectDex, + icon = Icons.Outlined.Code, + title = stringResource(R.string.patch_inject_dex), + desc = stringResource(R.string.patch_inject_dex_desc) + ) + var bypassExpanded by remember { mutableStateOf(false) } AnywhereDropdown( expanded = bypassExpanded, diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt index d170a91..be17f4b 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt @@ -38,6 +38,7 @@ class NewPatchViewModel : ViewModel() { var debuggable by mutableStateOf(false) var overrideVersionCode by mutableStateOf(false) var sigBypassLevel by mutableStateOf(2) + var injectDex by mutableStateOf(false) var embeddedModules = emptyList() lateinit var patchApp: AppInfo @@ -90,6 +91,7 @@ class NewPatchViewModel : ViewModel() { Log.d(TAG, "Submit patch") if (useManager) embeddedModules = emptyList() patchOptions = Patcher.Options( + injectDex = injectDex, config = PatchConfig(useManager, debuggable, overrideVersionCode, sigBypassLevel, null, null), apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()), embeddedModules = embeddedModules.flatMap { listOf(it.app.sourceDir) + (it.app.splitSourceDirs ?: emptyArray()) } diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/manage/AppManageViewModel.kt b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/manage/AppManageViewModel.kt index 7645791..51da66e 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/manage/AppManageViewModel.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/manage/AppManageViewModel.kt @@ -117,7 +117,7 @@ class AppManageViewModel : ViewModel() { } } } - Patcher.patch(logger, Patcher.Options(config, patchPaths, embeddedModulePaths)) + Patcher.patch(logger, Patcher.Options(false, config, patchPaths, embeddedModulePaths)) val (status, message) = LSPPackageManager.install() if (status != PackageInstaller.STATUS_SUCCESS) throw RuntimeException(message) } diff --git a/manager/src/main/res/values-zh-rCN/strings.xml b/manager/src/main/res/values-zh-rCN/strings.xml index 429971f..fa115e0 100644 --- a/manager/src/main/res/values-zh-rCN/strings.xml +++ b/manager/src/main/res/values-zh-rCN/strings.xml @@ -86,4 +86,6 @@ 别名错误 别名密码错误 详细修补日志 + 注入加载器 Dex + 对那些需要孤立服务进程的应用程序,譬如说浏览器的渲染引擎,请勾选此选项以确保他们正常运行 diff --git a/manager/src/main/res/values-zh-rTW/strings.xml b/manager/src/main/res/values-zh-rTW/strings.xml index 36f9782..0ad886b 100644 --- a/manager/src/main/res/values-zh-rTW/strings.xml +++ b/manager/src/main/res/values-zh-rTW/strings.xml @@ -86,4 +86,6 @@ 別名錯誤 別名密碼錯誤 詳細打包日誌 + 注入加載器 Dex + 對那些需要孤立服務進程的應用程序,譬如說瀏覽器的渲染引擎,請勾選此選項以確保他們正常運行 diff --git a/manager/src/main/res/values/strings.xml b/manager/src/main/res/values/strings.xml index 40e0f35..2739355 100644 --- a/manager/src/main/res/values/strings.xml +++ b/manager/src/main/res/values/strings.xml @@ -90,4 +90,6 @@ Wrong alias name Wrong alias password Detail patch logs + Inject loader dex + For applications with isolated services, such as the render engines of browsers, please turn on this option to ensure that they work properly. diff --git a/patch/src/main/java/org/lsposed/patch/LSPatch.java b/patch/src/main/java/org/lsposed/patch/LSPatch.java index 37e51ab..c7907a8 100644 --- a/patch/src/main/java/org/lsposed/patch/LSPatch.java +++ b/patch/src/main/java/org/lsposed/patch/LSPatch.java @@ -46,7 +46,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; public class LSPatch { @@ -79,6 +78,9 @@ public class LSPatch { @Parameter(names = {"-l", "--sigbypasslv"}, description = "Signature bypass level. 0 (disable), 1 (pm), 2 (pm+openat). default 0") private int sigbypassLevel = 0; + @Parameter(names = {"--injectdex"}, description = "Inject directly the loder dex file into the original application package") + private boolean injectDex = false; + @Parameter(names = {"-k", "--keystore"}, arity = 4, description = "Set custom signature keystore. Followed by 4 arguments: keystore path, keystore password, keystore alias, keystore alias password") private List keystoreArgs = Arrays.asList(null, "123456", "key0", "123456"); @@ -208,7 +210,7 @@ public class LSPatch { String originalSignature = null; if (sigbypassLevel > 0) { - originalSignature = ApkSignatureHelper.getApkSignInfo(srcApkFile.getAbsolutePath()); + originalSignature = ApkSignatureHelper.getApkSignInfo(srcApkFile.getAbsolutePath()); if (originalSignature == null || originalSignature.isEmpty()) { throw new PatchError("get original signature failed"); } @@ -239,7 +241,8 @@ public class LSPatch { for (StoredEntry entry : srcZFile.entries()) { String name = entry.getCentralDirectoryHeader().getName(); if (dstZFile.get(name) != null) continue; - if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) continue; + if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) + continue; srcZFile.addFileLink(name, name); } return; @@ -266,11 +269,15 @@ public class LSPatch { logger.i("Adding metaloader dex..."); try (var is = getClass().getClassLoader().getResourceAsStream(Constants.META_LOADER_DEX_ASSET_PATH)) { - var dexCount = srcZFile.entries().stream().filter(entry -> { - var name = entry.getCentralDirectoryHeader().getName(); - return name.startsWith("classes") && name.endsWith(".dex"); - }).collect(Collectors.toList()).size() + 1; - dstZFile.add("classes" + dexCount + ".dex", is); + if (!injectDex) { + dstZFile.add("classes.dex", is); + } else { + var dexCount = srcZFile.entries().stream().filter(entry -> { + var name = entry.getCentralDirectoryHeader().getName(); + return name.startsWith("classes") && name.endsWith(".dex"); + }).collect(Collectors.toList()).size() + 1; + dstZFile.add("classes" + dexCount + ".dex", is); + } } catch (Throwable e) { throw new PatchError("Error when adding dex", e); } @@ -307,6 +314,7 @@ public class LSPatch { for (StoredEntry entry : srcZFile.entries()) { String name = entry.getCentralDirectoryHeader().getName(); if (dstZFile.get(name) != null) continue; + if (!injectDex && name.startsWith("classes") && name.endsWith(".dex")) continue; if (name.equals("AndroidManifest.xml")) continue; if (name.startsWith("META-INF") && (name.endsWith(".SF") || name.endsWith(".MF") || name.endsWith(".RSA"))) continue; srcZFile.addFileLink(name, name);