Indicate plt hook explicitly
The file magisk_loader.cpp is reformatted using clangd
This commit is contained in:
parent
c2c4e5207f
commit
e28e194682
|
|
@ -80,7 +80,7 @@ static dev_t dev = 0;
|
||||||
static ino_t inode = 0;
|
static ino_t inode = 0;
|
||||||
static std::vector<std::pair<const char *, void **>> plt_hook_saved = {};
|
static std::vector<std::pair<const char *, void **>> plt_hook_saved = {};
|
||||||
|
|
||||||
inline int HookArtFunction(void *art_symbol, void *callback, void **backup, bool save = true) {
|
inline int HookPLT(void *art_symbol, void *callback, void **backup, bool save = true) {
|
||||||
auto symbol = reinterpret_cast<const char *>(art_symbol);
|
auto symbol = reinterpret_cast<const char *>(art_symbol);
|
||||||
|
|
||||||
if (GetArt()->isStripped()) {
|
if (GetArt()->isStripped()) {
|
||||||
|
|
@ -106,25 +106,25 @@ inline int HookArtFunction(void *art_symbol, void *callback, void **backup, bool
|
||||||
if (auto addr = GetArt()->getSymbAddress(symbol); addr) {
|
if (auto addr = GetArt()->getSymbAddress(symbol); addr) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
if (dladdr(addr, &info) && info.dli_sname != nullptr && strcmp(info.dli_sname, symbol) == 0)
|
if (dladdr(addr, &info) && info.dli_sname != nullptr && strcmp(info.dli_sname, symbol) == 0)
|
||||||
HookFunction(addr, callback, backup);
|
HookInline(addr, callback, backup);
|
||||||
} else if (*backup == nullptr && isDebug) {
|
} else if (*backup == nullptr && isDebug) {
|
||||||
LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol);
|
LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol);
|
||||||
}
|
}
|
||||||
return *backup == nullptr;
|
return *backup == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int UnhookArtFunction(void *original) {
|
inline int UnhookPLT(void *original) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
|
|
||||||
if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1;
|
if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1;
|
||||||
if (!GetArt()->isStripped()) return UnhookFunction(original);
|
if (!GetArt()->isStripped()) return UnhookInline(original);
|
||||||
|
|
||||||
auto hook_iter =
|
auto hook_iter =
|
||||||
std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(),
|
std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(),
|
||||||
[info](auto record) { return strcmp(record.first, info.dli_sname) == 0; });
|
[info](auto record) { return strcmp(record.first, info.dli_sname) == 0; });
|
||||||
void *stub = nullptr;
|
void *stub = nullptr;
|
||||||
if (hook_iter != plt_hook_saved.end() &&
|
if (hook_iter != plt_hook_saved.end() &&
|
||||||
HookArtFunction(original, *(hook_iter->second), &stub, false)) {
|
HookPLT(original, *(hook_iter->second), &stub, false)) {
|
||||||
plt_hook_saved.erase(hook_iter);
|
plt_hook_saved.erase(hook_iter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,8 @@ namespace lspd {
|
||||||
const auto[entries] = []() {
|
const auto[entries] = []() {
|
||||||
auto *entries = new(protected_page.get()) NativeAPIEntries{
|
auto *entries = new(protected_page.get()) NativeAPIEntries{
|
||||||
.version = 2,
|
.version = 2,
|
||||||
.hookFunc = &HookFunction,
|
.hookFunc = &HookInline,
|
||||||
.unhookFunc = &UnhookFunction,
|
.unhookFunc = &UnhookInline,
|
||||||
};
|
};
|
||||||
|
|
||||||
mprotect(protected_page.get(), 4096, PROT_READ);
|
mprotect(protected_page.get(), 4096, PROT_READ);
|
||||||
|
|
@ -71,7 +71,7 @@ namespace lspd {
|
||||||
return InstallNativeAPI(lsplant::InitInfo {
|
return InstallNativeAPI(lsplant::InitInfo {
|
||||||
.inline_hooker = [](auto t, auto r) {
|
.inline_hooker = [](auto t, auto r) {
|
||||||
void* bk = nullptr;
|
void* bk = nullptr;
|
||||||
return HookFunction(t, r, &bk) == 0 ? bk : nullptr;
|
return HookInline(t, r, &bk) == 0 ? bk : nullptr;
|
||||||
},
|
},
|
||||||
.art_symbol_resolver = [](auto symbol){
|
.art_symbol_resolver = [](auto symbol){
|
||||||
return GetLinker()->getSymbAddress(symbol);
|
return GetLinker()->getSymbAddress(symbol);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace lspd {
|
||||||
|
|
||||||
void RegisterNativeLib(const std::string &library_name);
|
void RegisterNativeLib(const std::string &library_name);
|
||||||
|
|
||||||
inline int HookFunction(void *original, void *replace, void **backup) {
|
inline int HookInline(void *original, void *replace, void **backup) {
|
||||||
if constexpr (isDebug) {
|
if constexpr (isDebug) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
if (dladdr(original, &info))
|
if (dladdr(original, &info))
|
||||||
|
|
@ -64,7 +64,7 @@ namespace lspd {
|
||||||
return DobbyHook(original, reinterpret_cast<dobby_dummy_func_t>(replace), reinterpret_cast<dobby_dummy_func_t *>(backup));
|
return DobbyHook(original, reinterpret_cast<dobby_dummy_func_t>(replace), reinterpret_cast<dobby_dummy_func_t *>(backup));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int UnhookFunction(void *original) {
|
inline int UnhookInline(void *original) {
|
||||||
if constexpr (isDebug) {
|
if constexpr (isDebug) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
if (dladdr(original, &info))
|
if (dladdr(original, &info))
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2a18d73b4d2150ca02b30938c0e82eb9aab1619e
|
Subproject commit d73aa7f9742b3c13084bb719962cfcd9358dd0f3
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
* Copyright (C) 2021 - 2022 LSPosed Contributors
|
* Copyright (C) 2021 - 2022 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "magisk_loader.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -25,7 +27,6 @@
|
||||||
#include "config_impl.h"
|
#include "config_impl.h"
|
||||||
#include "elf_util.h"
|
#include "elf_util.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "magisk_loader.h"
|
|
||||||
#include "native_util.h"
|
#include "native_util.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
|
|
@ -36,207 +37,194 @@ using namespace lsplant;
|
||||||
static_assert(FS_IOC_SETFLAGS == LP_SELECT(0x40046602, 0x40086602));
|
static_assert(FS_IOC_SETFLAGS == LP_SELECT(0x40046602, 0x40086602));
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
extern int *allowUnload;
|
extern int *allowUnload;
|
||||||
jboolean is_parasitic_manager = JNI_FALSE;
|
jboolean is_parasitic_manager = JNI_FALSE;
|
||||||
|
|
||||||
constexpr int FIRST_ISOLATED_UID = 99000;
|
constexpr int FIRST_ISOLATED_UID = 99000;
|
||||||
constexpr int LAST_ISOLATED_UID = 99999;
|
constexpr int LAST_ISOLATED_UID = 99999;
|
||||||
constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
||||||
constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
|
constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
|
||||||
constexpr int SHARED_RELRO_UID = 1037;
|
constexpr int SHARED_RELRO_UID = 1037;
|
||||||
constexpr int PER_USER_RANGE = 100000;
|
constexpr int PER_USER_RANGE = 100000;
|
||||||
|
|
||||||
static constexpr uid_t kAidInjected = INJECTED_AID;
|
static constexpr uid_t kAidInjected = INJECTED_AID;
|
||||||
static constexpr uid_t kAidInet = 3003;
|
static constexpr uid_t kAidInet = 3003;
|
||||||
|
|
||||||
void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) {
|
void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) {
|
||||||
auto classloader = JNI_FindClass(env, "java/lang/ClassLoader");
|
auto classloader = JNI_FindClass(env, "java/lang/ClassLoader");
|
||||||
auto getsyscl_mid = JNI_GetStaticMethodID(
|
auto getsyscl_mid = JNI_GetStaticMethodID(env, classloader, "getSystemClassLoader",
|
||||||
env, classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
|
"()Ljava/lang/ClassLoader;");
|
||||||
auto sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid);
|
auto sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid);
|
||||||
if (!sys_classloader) [[unlikely]] {
|
if (!sys_classloader) [[unlikely]] {
|
||||||
LOGE("getSystemClassLoader failed!!!");
|
LOGE("getSystemClassLoader failed!!!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
|
auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
|
||||||
auto initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
auto initMid = 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 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, initMid,
|
if (auto my_cl =
|
||||||
dex_buffer, sys_classloader)) {
|
JNI_NewObject(env, in_memory_classloader, initMid, dex_buffer, sys_classloader)) {
|
||||||
inject_class_loader_ = JNI_NewGlobalRef(env, my_cl);
|
inject_class_loader_ = JNI_NewGlobalRef(env, my_cl);
|
||||||
} else {
|
} else {
|
||||||
LOGE("InMemoryDexClassLoader creation failed!!!");
|
LOGE("InMemoryDexClassLoader creation failed!!!");
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
env->DeleteLocalRef(dex_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetEntryClassName() {
|
env->DeleteLocalRef(dex_buffer);
|
||||||
const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map();
|
}
|
||||||
static auto signature = obfs_map.at("org.lsposed.lspd.core.") + "Main";
|
|
||||||
return signature;
|
std::string GetEntryClassName() {
|
||||||
|
const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map();
|
||||||
|
static auto signature = obfs_map.at("org.lsposed.lspd.core.") + "Main";
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskLoader::SetupEntryClass(JNIEnv *env) {
|
||||||
|
if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(), GetEntryClassName())) {
|
||||||
|
entry_class_ = JNI_NewGlobalRef(env, entry_class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MagiskLoader::SetupEntryClass(JNIEnv *env) {
|
void MagiskLoader::OnNativeForkSystemServerPre(JNIEnv *env) {
|
||||||
if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(),
|
Service::instance()->InitService(env);
|
||||||
GetEntryClassName())) {
|
setAllowUnload(skip_);
|
||||||
entry_class_ = JNI_NewGlobalRef(env, entry_class);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void MagiskLoader::OnNativeForkSystemServerPost(JNIEnv *env) {
|
||||||
MagiskLoader::OnNativeForkSystemServerPre(JNIEnv *env) {
|
if (!skip_) {
|
||||||
Service::instance()->InitService(env);
|
|
||||||
setAllowUnload(skip_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MagiskLoader::OnNativeForkSystemServerPost(JNIEnv *env) {
|
|
||||||
if (!skip_) {
|
|
||||||
auto *instance = Service::instance();
|
|
||||||
auto system_server_binder = instance->RequestSystemServerBinder(env);
|
|
||||||
if (!system_server_binder) {
|
|
||||||
LOGF("Failed to get system server binder, system server initialization failed.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto application_binder = instance->RequestApplicationBinderFromSystemServer(env, system_server_binder);
|
|
||||||
|
|
||||||
// Call application_binder directly if application binder is available,
|
|
||||||
// or we proxy the request from system server binder
|
|
||||||
auto &&next_binder = application_binder ? application_binder : system_server_binder;
|
|
||||||
const auto [dex_fd, size] = instance->RequestLSPDex(env, next_binder);
|
|
||||||
auto obfs_map = instance->RequestObfuscationMap(env, next_binder);
|
|
||||||
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
|
||||||
LoadDex(env, PreloadedDex(dex_fd, size));
|
|
||||||
close(dex_fd);
|
|
||||||
instance->HookBridge(*this, env);
|
|
||||||
|
|
||||||
// always inject into system server
|
|
||||||
lsplant::InitInfo initInfo{
|
|
||||||
.inline_hooker = [](auto t, auto r) {
|
|
||||||
void* bk = nullptr;
|
|
||||||
return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr;
|
|
||||||
},
|
|
||||||
.inline_unhooker = [](auto t) {
|
|
||||||
return UnhookArtFunction(t) == 0 ;
|
|
||||||
},
|
|
||||||
.art_symbol_resolver = [](auto symbol) {
|
|
||||||
return GetArt()->getSymbAddress(symbol);
|
|
||||||
},
|
|
||||||
.art_symbol_prefix_resolver = [](auto symbol) {
|
|
||||||
return GetArt()->getSymbPrefixFirstAddress(symbol);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
InitArtHooker(env, initInfo);
|
|
||||||
InitHooks(env);
|
|
||||||
SetupEntryClass(env);
|
|
||||||
FindAndCall(env, "forkCommon",
|
|
||||||
"(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V",
|
|
||||||
JNI_TRUE, JNI_NewStringUTF(env, "system"), nullptr, application_binder, is_parasitic_manager);
|
|
||||||
GetArt(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MagiskLoader::OnNativeForkAndSpecializePre(JNIEnv *env,
|
|
||||||
jint uid,
|
|
||||||
jintArray &gids,
|
|
||||||
jstring &nice_name,
|
|
||||||
jboolean is_child_zygote,
|
|
||||||
jstring app_data_dir) {
|
|
||||||
jboolean is_manager = JNI_FALSE;
|
|
||||||
if (uid == kAidInjected) {
|
|
||||||
const JUTFString name(env, nice_name);
|
|
||||||
if (name.get() == "org.lsposed.manager"sv) {
|
|
||||||
int array_size = gids ? env->GetArrayLength(gids) : 0;
|
|
||||||
auto region = std::make_unique<jint[]>(array_size + 1);
|
|
||||||
auto *new_gids = env->NewIntArray(array_size + 1);
|
|
||||||
if (gids) env->GetIntArrayRegion(gids, 0, array_size, region.get());
|
|
||||||
region.get()[array_size] = kAidInet;
|
|
||||||
env->SetIntArrayRegion(new_gids, 0, array_size + 1, region.get());
|
|
||||||
if (gids) env->SetIntArrayRegion(gids, 0, 1, region.get() + array_size);
|
|
||||||
gids = new_gids;
|
|
||||||
nice_name = JNI_NewStringUTF(env, "com.android.shell").release();
|
|
||||||
is_manager = JNI_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is_parasitic_manager = is_manager;
|
|
||||||
Service::instance()->InitService(env);
|
|
||||||
const auto app_id = uid % PER_USER_RANGE;
|
|
||||||
JUTFString process_name(env, nice_name);
|
|
||||||
skip_ = false;
|
|
||||||
if (!skip_ && !app_data_dir) {
|
|
||||||
LOGD("skip injecting into {} because it has no data dir", process_name.get());
|
|
||||||
skip_ = true;
|
|
||||||
}
|
|
||||||
if (!skip_ && is_child_zygote) {
|
|
||||||
skip_ = true;
|
|
||||||
LOGD("skip injecting into {} because it's a child zygote", process_name.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skip_ && ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) ||
|
|
||||||
(app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID &&
|
|
||||||
app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) ||
|
|
||||||
app_id == SHARED_RELRO_UID)) {
|
|
||||||
skip_ = true;
|
|
||||||
LOGI("skip injecting into {} because it's isolated", process_name.get());
|
|
||||||
}
|
|
||||||
setAllowUnload(skip_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MagiskLoader::OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir) {
|
|
||||||
const JUTFString process_name(env, nice_name);
|
|
||||||
auto *instance = Service::instance();
|
auto *instance = Service::instance();
|
||||||
if (is_parasitic_manager) nice_name = JNI_NewStringUTF(env, "org.lsposed.manager").release();
|
auto system_server_binder = instance->RequestSystemServerBinder(env);
|
||||||
auto binder = skip_ ? ScopedLocalRef<jobject>{env, nullptr}
|
if (!system_server_binder) {
|
||||||
: instance->RequestBinder(env, nice_name);
|
LOGF("Failed to get system server binder, system server initialization failed.");
|
||||||
if (binder) {
|
return;
|
||||||
lsplant::InitInfo initInfo{
|
|
||||||
.inline_hooker = [](auto t, auto r) {
|
|
||||||
void* bk = nullptr;
|
|
||||||
return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr;
|
|
||||||
},
|
|
||||||
.inline_unhooker = [](auto t) {
|
|
||||||
return UnhookArtFunction(t) == 0;
|
|
||||||
},
|
|
||||||
.art_symbol_resolver = [](auto symbol){
|
|
||||||
return GetArt()->getSymbAddress(symbol);
|
|
||||||
},
|
|
||||||
.art_symbol_prefix_resolver = [](auto symbol) {
|
|
||||||
return GetArt()->getSymbPrefixFirstAddress(symbol);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
auto [dex_fd, size] = instance->RequestLSPDex(env, binder);
|
|
||||||
auto obfs_map = instance->RequestObfuscationMap(env, binder);
|
|
||||||
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
|
||||||
LoadDex(env, PreloadedDex(dex_fd, size));
|
|
||||||
close(dex_fd);
|
|
||||||
InitArtHooker(env, initInfo);
|
|
||||||
InitHooks(env);
|
|
||||||
SetupEntryClass(env);
|
|
||||||
LOGD("Done prepare");
|
|
||||||
FindAndCall(env, "forkCommon",
|
|
||||||
"(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V",
|
|
||||||
JNI_FALSE, nice_name, app_dir, binder);
|
|
||||||
LOGD("injected xposed into {}", process_name.get());
|
|
||||||
setAllowUnload(false);
|
|
||||||
GetArt(true);
|
|
||||||
} else {
|
|
||||||
auto context = Context::ReleaseInstance();
|
|
||||||
auto service = Service::ReleaseInstance();
|
|
||||||
GetArt(true);
|
|
||||||
LOGD("skipped {}", process_name.get());
|
|
||||||
setAllowUnload(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto application_binder =
|
||||||
|
instance->RequestApplicationBinderFromSystemServer(env, system_server_binder);
|
||||||
|
|
||||||
|
// Call application_binder directly if application binder is available,
|
||||||
|
// or we proxy the request from system server binder
|
||||||
|
auto &&next_binder = application_binder ? application_binder : system_server_binder;
|
||||||
|
const auto [dex_fd, size] = instance->RequestLSPDex(env, next_binder);
|
||||||
|
auto obfs_map = instance->RequestObfuscationMap(env, next_binder);
|
||||||
|
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
||||||
|
LoadDex(env, PreloadedDex(dex_fd, size));
|
||||||
|
close(dex_fd);
|
||||||
|
instance->HookBridge(*this, env);
|
||||||
|
|
||||||
|
// always inject into system server
|
||||||
|
lsplant::InitInfo initInfo{
|
||||||
|
.inline_hooker =
|
||||||
|
[](auto t, auto r) {
|
||||||
|
void *bk = nullptr;
|
||||||
|
return HookPLT(t, r, &bk) == 0 ? bk : nullptr;
|
||||||
|
},
|
||||||
|
.inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; },
|
||||||
|
.art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); },
|
||||||
|
.art_symbol_prefix_resolver =
|
||||||
|
[](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); },
|
||||||
|
.is_plt_hook = true};
|
||||||
|
InitArtHooker(env, initInfo);
|
||||||
|
InitHooks(env);
|
||||||
|
SetupEntryClass(env);
|
||||||
|
FindAndCall(env, "forkCommon",
|
||||||
|
"(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", JNI_TRUE,
|
||||||
|
JNI_NewStringUTF(env, "system"), nullptr, application_binder,
|
||||||
|
is_parasitic_manager);
|
||||||
|
GetArt(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskLoader::OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jintArray &gids,
|
||||||
|
jstring &nice_name, jboolean is_child_zygote,
|
||||||
|
jstring app_data_dir) {
|
||||||
|
jboolean is_manager = JNI_FALSE;
|
||||||
|
if (uid == kAidInjected) {
|
||||||
|
const JUTFString name(env, nice_name);
|
||||||
|
if (name.get() == "org.lsposed.manager"sv) {
|
||||||
|
int array_size = gids ? env->GetArrayLength(gids) : 0;
|
||||||
|
auto region = std::make_unique<jint[]>(array_size + 1);
|
||||||
|
auto *new_gids = env->NewIntArray(array_size + 1);
|
||||||
|
if (gids) env->GetIntArrayRegion(gids, 0, array_size, region.get());
|
||||||
|
region.get()[array_size] = kAidInet;
|
||||||
|
env->SetIntArrayRegion(new_gids, 0, array_size + 1, region.get());
|
||||||
|
if (gids) env->SetIntArrayRegion(gids, 0, 1, region.get() + array_size);
|
||||||
|
gids = new_gids;
|
||||||
|
nice_name = JNI_NewStringUTF(env, "com.android.shell").release();
|
||||||
|
is_manager = JNI_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_parasitic_manager = is_manager;
|
||||||
|
Service::instance()->InitService(env);
|
||||||
|
const auto app_id = uid % PER_USER_RANGE;
|
||||||
|
JUTFString process_name(env, nice_name);
|
||||||
|
skip_ = false;
|
||||||
|
if (!skip_ && !app_data_dir) {
|
||||||
|
LOGD("skip injecting into {} because it has no data dir", process_name.get());
|
||||||
|
skip_ = true;
|
||||||
|
}
|
||||||
|
if (!skip_ && is_child_zygote) {
|
||||||
|
skip_ = true;
|
||||||
|
LOGD("skip injecting into {} because it's a child zygote", process_name.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskLoader::setAllowUnload(bool unload) {
|
if (!skip_ &&
|
||||||
if (allowUnload) {
|
((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) ||
|
||||||
*allowUnload = unload ? 1 : 0;
|
(app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) ||
|
||||||
}
|
app_id == SHARED_RELRO_UID)) {
|
||||||
|
skip_ = true;
|
||||||
|
LOGI("skip injecting into {} because it's isolated", process_name.get());
|
||||||
}
|
}
|
||||||
|
setAllowUnload(skip_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskLoader::OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir) {
|
||||||
|
const JUTFString process_name(env, nice_name);
|
||||||
|
auto *instance = Service::instance();
|
||||||
|
if (is_parasitic_manager) nice_name = JNI_NewStringUTF(env, "org.lsposed.manager").release();
|
||||||
|
auto binder =
|
||||||
|
skip_ ? ScopedLocalRef<jobject>{env, nullptr} : instance->RequestBinder(env, nice_name);
|
||||||
|
if (binder) {
|
||||||
|
lsplant::InitInfo initInfo{
|
||||||
|
.inline_hooker =
|
||||||
|
[](auto t, auto r) {
|
||||||
|
void *bk = nullptr;
|
||||||
|
return HookPLT(t, r, &bk) == 0 ? bk : nullptr;
|
||||||
|
},
|
||||||
|
.inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; },
|
||||||
|
.art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); },
|
||||||
|
.art_symbol_prefix_resolver =
|
||||||
|
[](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); },
|
||||||
|
.is_plt_hook = true};
|
||||||
|
auto [dex_fd, size] = instance->RequestLSPDex(env, binder);
|
||||||
|
auto obfs_map = instance->RequestObfuscationMap(env, binder);
|
||||||
|
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
||||||
|
LoadDex(env, PreloadedDex(dex_fd, size));
|
||||||
|
close(dex_fd);
|
||||||
|
InitArtHooker(env, initInfo);
|
||||||
|
InitHooks(env);
|
||||||
|
SetupEntryClass(env);
|
||||||
|
LOGD("Done prepare");
|
||||||
|
FindAndCall(env, "forkCommon",
|
||||||
|
"(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", JNI_FALSE,
|
||||||
|
nice_name, app_dir, binder);
|
||||||
|
LOGD("injected xposed into {}", process_name.get());
|
||||||
|
setAllowUnload(false);
|
||||||
|
GetArt(true);
|
||||||
|
} else {
|
||||||
|
auto context = Context::ReleaseInstance();
|
||||||
|
auto service = Service::ReleaseInstance();
|
||||||
|
GetArt(true);
|
||||||
|
LOGD("skipped {}", process_name.get());
|
||||||
|
setAllowUnload(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskLoader::setAllowUnload(bool unload) {
|
||||||
|
if (allowUnload) {
|
||||||
|
*allowUnload = unload ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace lspd
|
} // namespace lspd
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue