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:
parent
4e63d61cd3
commit
c2fdd4941d
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
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")};
|
||||
|
|
|
|||
|
|
@ -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, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size());
|
||||
|
||||
ScopedLocalRef<jobject> 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, "<init>",
|
||||
"(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<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.");
|
||||
}
|
||||
}
|
||||
|
||||
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<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);
|
||||
auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr),
|
||||
static_cast<size_t>(JNI_GetArrayLength(env, array))};
|
||||
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);
|
||||
|
||||
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<size_t>(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
|
||||
|
|
|
|||
Loading…
Reference in New Issue