refactor: improve hook and dex loading logic

重構了 patch_loader.cpp 並修改了bypass_sig.cpp,優化了 openat hook 的實現方式,簡化了 HookOpenat 和 enableOpenatHook 的流程。PatchLoader 的 LoadDex、InitArtHooker、InitHooks、SetupEntryClass、Load 方法也進行了結構優化,提升了代碼可讀性和健壯性,減少了重複代碼,並加強了錯誤處理。
參考自 802d3fbe28 爲什麽這樣改我也有點忘了,commit用Copilot寫的
This commit is contained in:
NkBe 2025-09-07 22:17:31 +08:00
parent 4e63d61cd3
commit c2fdd4941d
No known key found for this signature in database
GPG Key ID: 75EF144ED8F4D7B8
3 changed files with 97 additions and 102 deletions

View File

@ -195,7 +195,7 @@ fun AppManageBody(
} }
) { ) {
DropdownMenuItem( DropdownMenuItem(
text = { Text(text = it.first.label, color = MaterialTheme.colorScheme.primary) }, text = { Text(text = appInfo.label, color = MaterialTheme.colorScheme.primary) },
onClick = {}, enabled = false onClick = {}, enabled = false
) )
val shizukuUnavailable = stringResource(R.string.shizuku_unavailable) val shizukuUnavailable = stringResource(R.string.shizuku_unavailable)
@ -205,18 +205,18 @@ fun AppManageBody(
onClick = { onClick = {
expanded = false expanded = false
scope.launch { 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( DropdownMenuItem(
text = { Text(stringResource(R.string.manage_module_scope)) }, text = { Text(stringResource(R.string.manage_module_scope)) },
onClick = { onClick = {
expanded = false expanded = false
scope.launch { scope.launch {
scopeApp = it.first.app.packageName scopeApp = appInfo.app.packageName
val activated = ConfigManager.getModulesForApp(scopeApp).map { it.pkgName }.toSet() val activated = ConfigManager.getModulesForApp(scopeApp).map { it.pkgName }.toSet()
val initialSelected = LSPPackageManager.appList.mapNotNullTo(ArrayList()) { val initialSelected = LSPPackageManager.appList.mapNotNullTo(ArrayList()) {
if (activated.contains(it.app.packageName)) it.app.packageName else null if (activated.contains(it.app.packageName)) it.app.packageName else null
@ -234,7 +234,7 @@ fun AppManageBody(
if (!ShizukuApi.isPermissionGranted) { if (!ShizukuApi.isPermissionGranted) {
snackbarHost.showSnackbar(shizukuUnavailable) snackbarHost.showSnackbar(shizukuUnavailable)
} else { } else {
viewModel.dispatch(AppManageViewModel.ViewAction.PerformOptimize(it.first)) viewModel.dispatch(AppManageViewModel.ViewAction.PerformOptimize(appInfo))
} }
} }
} }
@ -252,7 +252,7 @@ fun AppManageBody(
onClick = { onClick = {
expanded = false expanded = false
val intent = Intent(Intent.ACTION_DELETE).apply { 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) putExtra(Intent.EXTRA_RETURN_RESULT, true)
} }
launcher.launch(intent) launcher.launch(intent)

View File

@ -1,5 +1,6 @@
// //
// Created by VIP on 2021/4/25. // Created by VIP on 2021/4/25.
// Update by HSSkyBoy on 2025/9/7
// //
#include "bypass_sig.h" #include "bypass_sig.h"
@ -19,14 +20,14 @@ namespace lspd {
std::string apkPath; std::string apkPath;
std::string redirectPath; std::string redirectPath;
inline static constexpr auto kLibCName = "libc.so"; inline static constexpr const char* kLibCName = "libc.so";
std::unique_ptr<const SandHook::ElfImg> &GetC(bool release = false) { // 修改回傳型別以匹配 kImg 的實際型別
static std::unique_ptr<const SandHook::ElfImg> kImg = nullptr; std::unique_ptr<SandHook::ElfImg> &GetC(bool release = false) {
static auto kImg = std::make_unique<SandHook::ElfImg>(kLibCName);
if (release) { if (release) {
kImg.reset(); kImg.reset();
} else if (!kImg) { kImg = nullptr;
kImg = std::make_unique<SandHook::ElfImg>(kLibCName);
} }
return kImg; return kImg;
} }
@ -34,17 +35,21 @@ std::unique_ptr<const SandHook::ElfImg> &GetC(bool release = false) {
inline static auto __openat_ = inline static auto __openat_ =
"__openat"_sym.hook->*[]<lsplant::Backup auto backup>(int fd, const char *pathname, int flag, "__openat"_sym.hook->*[]<lsplant::Backup auto backup>(int fd, const char *pathname, int flag,
int mode) static -> int { int mode) static -> int {
if (pathname == apkPath) { if (pathname && strcmp(pathname, apkPath.c_str()) == 0) {
LOGD("Redirect openat from {} to {}", pathname, redirectPath);
return backup(fd, redirectPath.c_str(), flag, mode); return backup(fd, redirectPath.c_str(), flag, mode);
} }
return backup(fd, pathname, 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, LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath,
jstring cacheApkPath) { jstring cacheApkPath) {
lsplant::JUTFString str1(env, origApkPath);
lsplant::JUTFString str2(env, cacheApkPath);
apkPath = str1.get();
redirectPath = str2.get();
auto r = HookOpenat(lsplant::InitInfo{ auto r = HookOpenat(lsplant::InitInfo{
.inline_hooker = .inline_hooker =
[](auto t, auto r) { [](auto t, auto r) {
@ -55,16 +60,10 @@ LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath,
}); });
if (!r) { if (!r) {
LOGE("Hook __openat fail"); LOGE("Hook __openat fail");
return;
} }
lsplant::JUTFString str1(env, origApkPath); // 无论 Hook 成功与否,都确保清除 libc.so 的 ElfImg
lsplant::JUTFString str2(env, cacheApkPath);
apkPath = str1.get();
redirectPath = str2.get();
LOGD("apkPath {}", apkPath.c_str());
LOGD("redirectPath {}", redirectPath.c_str());
GetC(true); GetC(true);
} }
static JNINativeMethod gMethods[] = { static JNINativeMethod gMethods[] = {
LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")}; LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")};

View File

@ -35,69 +35,61 @@ using namespace lsplant;
namespace lspd { namespace lspd {
void PatchLoader::LoadDex(JNIEnv* env, Context::PreloadedDex&& dex) { void PatchLoader::LoadDex(JNIEnv* env, Context::PreloadedDex&& dex) {
auto class_activity_thread = JNI_FindClass(env, "android/app/ActivityThread"); auto class_activity_thread = JNI_FindClass(env, "android/app/ActivityThread");
auto class_activity_thread_app_bind_data = auto class_activity_thread_app_bind_data = JNI_FindClass(env, "android/app/ActivityThread$AppBindData");
JNI_FindClass(env, "android/app/ActivityThread$AppBindData");
auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk"); auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk");
auto mid_current_activity_thread = JNI_GetStaticMethodID( auto mid_current_activity_thread = JNI_GetStaticMethodID(env, class_activity_thread, "currentActivityThread", "()Landroid/app/ActivityThread;");
env, class_activity_thread, "currentActivityThread", "()Landroid/app/ActivityThread;"); auto mid_get_classloader = JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;");
auto mid_get_classloader = auto fid_m_bound_application = JNI_GetFieldID(env, class_activity_thread, "mBoundApplication", "Landroid/app/ActivityThread$AppBindData;");
JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;"); auto fid_info = JNI_GetFieldID(env, class_activity_thread_app_bind_data, "info", "Landroid/app/LoadedApk;");
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 = auto activity_thread = JNI_CallStaticObjectMethod(env, class_activity_thread, mid_current_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 m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application);
auto info = JNI_GetObjectField(env, m_bound_application, fid_info); auto info = JNI_GetObjectField(env, m_bound_application, fid_info);
auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader); auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader);
if (!stub_classloader) [[unlikely]] { if (!stub_classloader) {
LOGE("getStubClassLoader failed!!!"); LOGE("getStubClassLoader failed!!!");
return; return;
} }
auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "<init>", auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
"(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()); 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)) { ScopedLocalRef<jobject> my_cl(JNI_NewObject(env, in_memory_classloader, mid_init, dex_buffer, stub_classloader));
inject_class_loader_ = JNI_NewGlobalRef(env, my_cl); if (!my_cl) {
} else {
LOGE("InMemoryDexClassLoader creation failed!!!"); LOGE("InMemoryDexClassLoader creation failed!!!");
return; return;
} }
env->DeleteLocalRef(dex_buffer); inject_class_loader_ = JNI_NewGlobalRef(env, my_cl.get());
} }
void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) { void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) {
Context::InitArtHooker(env, initInfo); Context::InitArtHooker(env, initInfo);
handler = initInfo; handler = initInfo;
art::ProfileSaver::DisableInline(initInfo); art::ProfileSaver::DisableInline(initInfo);
art::FileManager::DisableBackgroundVerification(initInfo); art::FileManager::DisableBackgroundVerification(initInfo);
} }
void PatchLoader::InitHooks(JNIEnv* env) { void PatchLoader::InitHooks(JNIEnv* env) {
Context::InitHooks(env); Context::InitHooks(env);
RegisterBypass(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::Load(JNIEnv* env) { void PatchLoader::SetupEntryClass(JNIEnv* env) {
/* InitSymbolCache(nullptr); */ ScopedLocalRef<jclass> 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.");
}
}
void PatchLoader::Load(JNIEnv* env) {
lsplant::InitInfo initInfo{ lsplant::InitInfo initInfo{
.inline_hooker = .inline_hooker =
[](auto t, auto r) { [](auto t, auto r) {
@ -112,10 +104,14 @@ void PatchLoader::Load(JNIEnv* env) {
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub"); auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub");
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B"); auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field); ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);
auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr),
static_cast<size_t>(JNI_GetArrayLength(env, array))}; if (!array) {
LOGE("Failed to get dex byte array from stub.");
return;
}
auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr), static_cast<size_t>(JNI_GetArrayLength(env, array.get()))};
InitArtHooker(env, initInfo); InitArtHooker(env, initInfo);
LoadDex(env, std::move(dex)); LoadDex(env, std::move(dex));
@ -125,5 +121,5 @@ void PatchLoader::Load(JNIEnv* env) {
SetupEntryClass(env); SetupEntryClass(env);
FindAndCall(env, "onLoad", "()V"); FindAndCall(env, "onLoad", "()V");
} }
} // namespace lspd } // namespace lspd