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(
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)

View File

@ -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<const SandHook::ElfImg> &GetC(bool release = false) {
static std::unique_ptr<const SandHook::ElfImg> kImg = nullptr;
// 修改回傳型別以匹配 kImg 的實際型別
std::unique_ptr<SandHook::ElfImg> &GetC(bool release = false) {
static auto kImg = std::make_unique<SandHook::ElfImg>(kLibCName);
if (release) {
kImg.reset();
} else if (!kImg) {
kImg = std::make_unique<SandHook::ElfImg>(kLibCName);
kImg = nullptr;
}
return kImg;
}
@ -34,17 +35,21 @@ std::unique_ptr<const SandHook::ElfImg> &GetC(bool release = false) {
inline static auto __openat_ =
"__openat"_sym.hook->*[]<lsplant::Backup auto backup>(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();
auto r = HookOpenat(lsplant::InitInfo{
.inline_hooker =
[](auto t, auto r) {
@ -55,14 +60,8 @@ LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath,
});
if (!r) {
LOGE("Hook __openat fail");
return;
}
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());
// 无论 Hook 成功与否,都确保清除 libc.so 的 ElfImg
GetC(true);
}

View File

@ -37,44 +37,35 @@ 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_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 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]] {
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, "<init>",
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer");
auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
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 {
ScopedLocalRef<jobject> my_cl(JNI_NewObject(env, in_memory_classloader, mid_init, dex_buffer, stub_classloader));
if (!my_cl) {
LOGE("InMemoryDexClassLoader creation failed!!!");
return;
}
env->DeleteLocalRef(dex_buffer);
inject_class_loader_ = JNI_NewGlobalRef(env, my_cl.get());
}
void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) {
@ -90,14 +81,15 @@ void PatchLoader::InitHooks(JNIEnv* 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);
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) {
/* InitSymbolCache(nullptr); */
lsplant::InitInfo initInfo{
.inline_hooker =
[](auto t, auto r) {
@ -112,10 +104,14 @@ void PatchLoader::Load(JNIEnv* env) {
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub");
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
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);
LoadDex(env, std::move(dex));