diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/page/manage/AppManagePage.kt b/manager/src/main/java/org/lsposed/lspatch/ui/page/manage/AppManagePage.kt index 62a91f1..7064b02 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/page/manage/AppManagePage.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/page/manage/AppManagePage.kt @@ -195,7 +195,7 @@ fun AppManageBody( } ) { DropdownMenuItem( - text = { Text(text = it.first.label, color = MaterialTheme.colorScheme.primary) }, + text = { Text(text = appInfo.label, color = MaterialTheme.colorScheme.primary) }, onClick = {}, enabled = false ) val shizukuUnavailable = stringResource(R.string.shizuku_unavailable) @@ -205,18 +205,18 @@ fun AppManageBody( onClick = { expanded = false scope.launch { - viewModel.dispatch(AppManageViewModel.ViewAction.UpdateLoader(it.first, it.second)) + viewModel.dispatch(AppManageViewModel.ViewAction.UpdateLoader(appInfo, patchConfig)) } } ) } - if (it.second.useManager) { + if (patchConfig.useManager) { DropdownMenuItem( text = { Text(stringResource(R.string.manage_module_scope)) }, onClick = { expanded = false scope.launch { - scopeApp = it.first.app.packageName + scopeApp = appInfo.app.packageName val activated = ConfigManager.getModulesForApp(scopeApp).map { it.pkgName }.toSet() val initialSelected = LSPPackageManager.appList.mapNotNullTo(ArrayList()) { if (activated.contains(it.app.packageName)) it.app.packageName else null @@ -234,7 +234,7 @@ fun AppManageBody( if (!ShizukuApi.isPermissionGranted) { snackbarHost.showSnackbar(shizukuUnavailable) } else { - viewModel.dispatch(AppManageViewModel.ViewAction.PerformOptimize(it.first)) + viewModel.dispatch(AppManageViewModel.ViewAction.PerformOptimize(appInfo)) } } } @@ -252,7 +252,7 @@ fun AppManageBody( onClick = { expanded = false val intent = Intent(Intent.ACTION_DELETE).apply { - data = Uri.parse("package:${it.first.app.packageName}") + data = Uri.parse("package:${appInfo.app.packageName}") putExtra(Intent.EXTRA_RETURN_RESULT, true) } launcher.launch(intent) diff --git a/patch-loader/src/main/jni/src/jni/bypass_sig.cpp b/patch-loader/src/main/jni/src/jni/bypass_sig.cpp index f08e60f..dd3419d 100644 --- a/patch-loader/src/main/jni/src/jni/bypass_sig.cpp +++ b/patch-loader/src/main/jni/src/jni/bypass_sig.cpp @@ -1,5 +1,6 @@ // // Created by VIP on 2021/4/25. +// Update by HSSkyBoy on 2025/9/7 // #include "bypass_sig.h" @@ -19,14 +20,14 @@ namespace lspd { std::string apkPath; std::string redirectPath; -inline static constexpr auto kLibCName = "libc.so"; +inline static constexpr const char* kLibCName = "libc.so"; -std::unique_ptr &GetC(bool release = false) { - static std::unique_ptr kImg = nullptr; +// 修改回傳型別以匹配 kImg 的實際型別 +std::unique_ptr &GetC(bool release = false) { + static auto kImg = std::make_unique(kLibCName); if (release) { kImg.reset(); - } else if (!kImg) { - kImg = std::make_unique(kLibCName); + kImg = nullptr; } return kImg; } @@ -34,17 +35,21 @@ std::unique_ptr &GetC(bool release = false) { inline static auto __openat_ = "__openat"_sym.hook->*[](int fd, const char *pathname, int flag, int mode) static -> int { - if (pathname == apkPath) { - LOGD("Redirect openat from {} to {}", pathname, redirectPath); + if (pathname && strcmp(pathname, apkPath.c_str()) == 0) { return backup(fd, redirectPath.c_str(), flag, mode); } return backup(fd, pathname, flag, mode); }; -bool HookOpenat(const lsplant::HookHandler &handler) { return handler(__openat_); } + static bool HookOpenat(const lsplant::HookHandler &handler) { return handler(__openat_); } + + LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, + jstring cacheApkPath) { + lsplant::JUTFString str1(env, origApkPath); + lsplant::JUTFString str2(env, cacheApkPath); + apkPath = str1.get(); + redirectPath = str2.get(); -LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, - jstring cacheApkPath) { auto r = HookOpenat(lsplant::InitInfo{ .inline_hooker = [](auto t, auto r) { @@ -55,16 +60,10 @@ LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, }); if (!r) { LOGE("Hook __openat fail"); - return; + } + // 无论 Hook 成功与否,都确保清除 libc.so 的 ElfImg + GetC(true); } - lsplant::JUTFString str1(env, origApkPath); - lsplant::JUTFString str2(env, cacheApkPath); - apkPath = str1.get(); - redirectPath = str2.get(); - LOGD("apkPath {}", apkPath.c_str()); - LOGD("redirectPath {}", redirectPath.c_str()); - GetC(true); -} static JNINativeMethod gMethods[] = { LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")}; diff --git a/patch-loader/src/main/jni/src/patch_loader.cpp b/patch-loader/src/main/jni/src/patch_loader.cpp index 97a3053..5ffd307 100644 --- a/patch-loader/src/main/jni/src/patch_loader.cpp +++ b/patch-loader/src/main/jni/src/patch_loader.cpp @@ -35,95 +35,91 @@ using namespace lsplant; namespace lspd { -void PatchLoader::LoadDex(JNIEnv* env, Context::PreloadedDex&& dex) { - auto class_activity_thread = JNI_FindClass(env, "android/app/ActivityThread"); - auto class_activity_thread_app_bind_data = - JNI_FindClass(env, "android/app/ActivityThread$AppBindData"); - auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk"); + void PatchLoader::LoadDex(JNIEnv* env, Context::PreloadedDex&& dex) { + auto class_activity_thread = JNI_FindClass(env, "android/app/ActivityThread"); + auto class_activity_thread_app_bind_data = JNI_FindClass(env, "android/app/ActivityThread$AppBindData"); + auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk"); - auto mid_current_activity_thread = JNI_GetStaticMethodID( - env, class_activity_thread, "currentActivityThread", "()Landroid/app/ActivityThread;"); - auto mid_get_classloader = - JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;"); - auto fid_m_bound_application = JNI_GetFieldID(env, class_activity_thread, "mBoundApplication", - "Landroid/app/ActivityThread$AppBindData;"); - auto fid_info = - JNI_GetFieldID(env, class_activity_thread_app_bind_data, "info", "Landroid/app/LoadedApk;"); + auto mid_current_activity_thread = JNI_GetStaticMethodID(env, class_activity_thread, "currentActivityThread", "()Landroid/app/ActivityThread;"); + auto mid_get_classloader = JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;"); + auto fid_m_bound_application = JNI_GetFieldID(env, class_activity_thread, "mBoundApplication", "Landroid/app/ActivityThread$AppBindData;"); + auto fid_info = JNI_GetFieldID(env, class_activity_thread_app_bind_data, "info", "Landroid/app/LoadedApk;"); - auto activity_thread = - JNI_CallStaticObjectMethod(env, class_activity_thread, mid_current_activity_thread); - auto m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application); - auto info = JNI_GetObjectField(env, m_bound_application, fid_info); - auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader); + auto activity_thread = JNI_CallStaticObjectMethod(env, class_activity_thread, mid_current_activity_thread); + auto m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application); + auto info = JNI_GetObjectField(env, m_bound_application, fid_info); + auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader); - if (!stub_classloader) [[unlikely]] { - LOGE("getStubClassLoader failed!!!"); - return; + if (!stub_classloader) { + LOGE("getStubClassLoader failed!!!"); + return; + } + + auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); + auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); + auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size()); + + ScopedLocalRef my_cl(JNI_NewObject(env, in_memory_classloader, mid_init, dex_buffer, stub_classloader)); + if (!my_cl) { + LOGE("InMemoryDexClassLoader creation failed!!!"); + return; + } + + inject_class_loader_ = JNI_NewGlobalRef(env, my_cl.get()); } - auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); - auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "", - "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); - auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer"); - auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size()); - if (auto my_cl = - JNI_NewObject(env, in_memory_classloader, mid_init, dex_buffer, stub_classloader)) { - inject_class_loader_ = JNI_NewGlobalRef(env, my_cl); - } else { - LOGE("InMemoryDexClassLoader creation failed!!!"); - return; + void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) { + Context::InitArtHooker(env, initInfo); + handler = initInfo; + art::ProfileSaver::DisableInline(initInfo); + art::FileManager::DisableBackgroundVerification(initInfo); } - env->DeleteLocalRef(dex_buffer); -} - -void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) { - Context::InitArtHooker(env, initInfo); - handler = initInfo; - art::ProfileSaver::DisableInline(initInfo); - art::FileManager::DisableBackgroundVerification(initInfo); -} - -void PatchLoader::InitHooks(JNIEnv* env) { - Context::InitHooks(env); - RegisterBypass(env); -} - -void PatchLoader::SetupEntryClass(JNIEnv* env) { - if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(), - "org.lsposed.lspatch.loader.LSPApplication")) { - entry_class_ = JNI_NewGlobalRef(env, entry_class); + void PatchLoader::InitHooks(JNIEnv* env) { + Context::InitHooks(env); + RegisterBypass(env); } -} -void PatchLoader::Load(JNIEnv* env) { - /* InitSymbolCache(nullptr); */ - lsplant::InitInfo initInfo{ - .inline_hooker = - [](auto t, auto r) { - void* bk = nullptr; - return HookInline(t, r, &bk) == 0 ? bk : nullptr; - }, - .inline_unhooker = [](auto t) { return UnhookInline(t) == 0; }, - .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); }, - .art_symbol_prefix_resolver = - [](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); }, - }; + void PatchLoader::SetupEntryClass(JNIEnv* env) { + ScopedLocalRef entry_class(FindClassFromLoader(env, GetCurrentClassLoader(), "org.lsposed.lspatch.loader.LSPApplication")); + if (entry_class) { + entry_class_ = JNI_NewGlobalRef(env, entry_class.get()); + } else { + LOGE("Failed to find entry class."); + } + } - auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub"); - auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B"); + void PatchLoader::Load(JNIEnv* env) { + lsplant::InitInfo initInfo{ + .inline_hooker = + [](auto t, auto r) { + void* bk = nullptr; + return HookInline(t, r, &bk) == 0 ? bk : nullptr; + }, + .inline_unhooker = [](auto t) { return UnhookInline(t) == 0; }, + .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); }, + .art_symbol_prefix_resolver = + [](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); }, + }; - ScopedLocalRef array = JNI_GetStaticObjectField(env, stub, dex_field); - auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr), - static_cast(JNI_GetArrayLength(env, array))}; + auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub"); + auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B"); + ScopedLocalRef array = JNI_GetStaticObjectField(env, stub, dex_field); - InitArtHooker(env, initInfo); - LoadDex(env, std::move(dex)); - InitHooks(env); + if (!array) { + LOGE("Failed to get dex byte array from stub."); + return; + } - GetArt(true); + auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr), static_cast(JNI_GetArrayLength(env, array.get()))}; - SetupEntryClass(env); - FindAndCall(env, "onLoad", "()V"); -} + InitArtHooker(env, initInfo); + LoadDex(env, std::move(dex)); + InitHooks(env); + + GetArt(true); + + SetupEntryClass(env); + FindAndCall(env, "onLoad", "()V"); + } } // namespace lspd