Update JingMatrix/LSPosed
To avoid a crash in the fisrt launch (#7), we cannot use PLT .inline_hooker to DisableBackgroundVerification. Remove ccache to avoid difference between CI builds and local builds.
This commit is contained in:
parent
a85a0fa578
commit
557d56091d
|
|
@ -58,17 +58,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
gradle-home-cache-cleanup: true
|
gradle-home-cache-cleanup: true
|
||||||
|
|
||||||
- name: Setup ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1
|
|
||||||
with:
|
|
||||||
max-size: 2G
|
|
||||||
key: lsp
|
|
||||||
restore-keys: lsp
|
|
||||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
|
||||||
|
|
||||||
- name: Setup Android SDK
|
|
||||||
uses: android-actions/setup-android@v3
|
|
||||||
|
|
||||||
- name: Setup ninja
|
- name: Setup ninja
|
||||||
uses: seanmiddleditch/gha-setup-ninja@master
|
uses: seanmiddleditch/gha-setup-ninja@master
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
2
core
2
core
|
|
@ -1 +1 @@
|
||||||
Subproject commit bdba029fe9ebde961a4e7f9047226d4d7258c233
|
Subproject commit db9b97e53d39bb06d8ba706b74ccf01a80f2221c
|
||||||
|
|
@ -10,47 +10,49 @@
|
||||||
using namespace lsplant;
|
using namespace lsplant;
|
||||||
|
|
||||||
namespace art {
|
namespace art {
|
||||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
class ProfileSaver {
|
||||||
"_ZN3art12ProfileSaver20ProcessProfilingInfoEbPt",
|
private:
|
||||||
bool, ProcessProfilingInfo, (void * thiz, bool, uint16_t *), {
|
inline static MemberHooker<"_ZN3art12ProfileSaver20ProcessProfilingInfoEbPt", ProfileSaver,
|
||||||
LOGD("skipped profile saving");
|
bool(bool, uint16_t *)>
|
||||||
return true;
|
ProcessProfilingInfo_ = +[](ProfileSaver *thiz, bool a, uint16_t *b) {
|
||||||
});
|
LOGD("skipped profile saving");
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
inline static MemberHooker<"_ZN3art12ProfileSaver20ProcessProfilingInfoEbbPt", ProfileSaver,
|
||||||
"_ZN3art12ProfileSaver20ProcessProfilingInfoEbbPt",
|
bool(bool, bool, uint16_t *)>
|
||||||
bool, ProcessProfilingInfoWithBool, (void * thiz, bool, bool, uint16_t *), {
|
ProcessProfilingInfoWithBool_ = +[](ProfileSaver *thiz, bool, bool, uint16_t *) {
|
||||||
LOGD("skipped profile saving");
|
LOGD("skipped profile saving");
|
||||||
return true;
|
return true;
|
||||||
});
|
};
|
||||||
|
|
||||||
CREATE_HOOK_STUB_ENTRY(
|
inline static Hooker<"execve",
|
||||||
"execve",
|
int(const char *pathname, const char *argv[], char *const envp[])>
|
||||||
int, execve, (const char *pathname, const char *argv[], char *const envp[]), {
|
execve_ = +[](const char *pathname, const char *argv[], char *const envp[]) {
|
||||||
if (strstr(pathname, "dex2oat")) {
|
if (strstr(pathname, "dex2oat")) {
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
while (argv[count++] != nullptr);
|
while (argv[count++] != nullptr);
|
||||||
std::unique_ptr<const char *[]> new_args = std::make_unique<const char *[]>(
|
std::unique_ptr<const char *[]> new_args =
|
||||||
count + 1);
|
std::make_unique<const char *[]>(count + 1);
|
||||||
for (size_t i = 0; i < count - 1; ++i)
|
for (size_t i = 0; i < count - 1; ++i) new_args[i] = argv[i];
|
||||||
new_args[i] = argv[i];
|
new_args[count - 1] = "--inline-max-code-units=0";
|
||||||
new_args[count - 1] = "--inline-max-code-units=0";
|
new_args[count] = nullptr;
|
||||||
new_args[count] = nullptr;
|
|
||||||
|
|
||||||
LOGD("dex2oat by disable inline!");
|
LOGD("dex2oat by disable inline!");
|
||||||
int ret = backup(pathname, new_args.get(), envp);
|
int ret = execve_(pathname, new_args.get(), envp);
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
int ret = backup(pathname, argv, envp);
|
|
||||||
return ret;
|
return ret;
|
||||||
});
|
}
|
||||||
|
int ret = execve_(pathname, argv, envp);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
static void DisableInline(const HookHandler &handler) {
|
static void DisableInline(const HookHandler &handler) {
|
||||||
HookSyms(handler, ProcessProfilingInfo, ProcessProfilingInfoWithBool);
|
handler.hook(ProcessProfilingInfo_);
|
||||||
HookSymNoHandle(handler, reinterpret_cast<void*>(&::execve), execve);
|
handler.hook(ProcessProfilingInfoWithBool_);
|
||||||
|
handler.hook(execve_);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
} // namespace art
|
||||||
|
|
||||||
|
#endif // LSPATCH_PROFILE_SAVER_H
|
||||||
#endif //LSPATCH_PROFILE_SAVER_H
|
|
||||||
|
|
|
||||||
|
|
@ -26,39 +26,46 @@
|
||||||
using namespace lsplant;
|
using namespace lsplant;
|
||||||
|
|
||||||
namespace art {
|
namespace art {
|
||||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
class FileManager {
|
||||||
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobjectPKc",
|
public:
|
||||||
void, RunBackgroundVerificationWithContext,
|
inline static MemberHooker<
|
||||||
(void * thiz, const std::vector<const void *> &dex_files,
|
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__"
|
||||||
jobject class_loader,
|
"16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobjectPKc",
|
||||||
const char *class_loader_context), {
|
FileManager, void(const std::vector<const void *> &, jobject, const char *)>
|
||||||
|
RunBackgroundVerificationWithContext_ =
|
||||||
|
+[](FileManager *thiz, const std::vector<const void *> &dex_files, jobject class_loader,
|
||||||
|
const char *class_loader_context) {
|
||||||
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
||||||
LOGD("Disabled background verification");
|
LOGD("Disabled background verification");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backup(thiz, dex_files, class_loader, class_loader_context);
|
RunBackgroundVerificationWithContext_(thiz, dex_files, class_loader,
|
||||||
});
|
class_loader_context);
|
||||||
|
};
|
||||||
|
|
||||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
inline static MemberHooker<
|
||||||
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobject",
|
"_ZN3art14OatFileManager25RunBackgroundVerificationERKNSt3__"
|
||||||
void, RunBackgroundVerification,
|
"16vectorIPKNS_7DexFileENS1_9allocatorIS5_EEEEP8_jobject",
|
||||||
(void * thiz, const std::vector<const void *> &dex_files,
|
FileManager, void(const std::vector<const void *> &, jobject)>
|
||||||
jobject class_loader), {
|
RunBackgroundVerification_ =
|
||||||
|
+[](FileManager *thiz, const std::vector<const void *> &dex_files,
|
||||||
|
jobject class_loader) {
|
||||||
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
if (lspd::Context::GetInstance()->GetCurrentClassLoader() == nullptr) {
|
||||||
LOGD("Disabled background verification");
|
LOGD("Disabled background verification");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backup(thiz, dex_files, class_loader);
|
RunBackgroundVerification_(thiz, dex_files, class_loader);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
static void DisableBackgroundVerification(const lsplant::HookHandler &handler) {
|
static void DisableBackgroundVerification(const lsplant::HookHandler &handler) {
|
||||||
const int api_level = lspd::GetAndroidApiLevel();
|
const int api_level = lspd::GetAndroidApiLevel();
|
||||||
if (api_level >= __ANDROID_API_Q__) {
|
if (api_level >= __ANDROID_API_Q__) {
|
||||||
HookSyms(handler, RunBackgroundVerificationWithContext, RunBackgroundVerification);
|
handler.hook(RunBackgroundVerificationWithContext_);
|
||||||
|
handler.hook(RunBackgroundVerification_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
} // namespace art
|
||||||
|
|
||||||
|
#endif // LSPATCH_OAT_FILE_MANAGER_H
|
||||||
#endif //LSPATCH_OAT_FILE_MANAGER_H
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Created by VIP on 2021/4/25.
|
// Created by VIP on 2021/4/25.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "../src/native_api.h"
|
||||||
#include "bypass_sig.h"
|
#include "bypass_sig.h"
|
||||||
#include "elf_util.h"
|
#include "elf_util.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
@ -12,40 +13,46 @@
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
|
|
||||||
std::string apkPath;
|
std::string apkPath;
|
||||||
std::string redirectPath;
|
std::string redirectPath;
|
||||||
|
|
||||||
CREATE_HOOK_STUB_ENTRY(
|
inline static lsplant::Hooker<"__openat", int(int, const char*, int flag, int)> __openat_ =
|
||||||
"__openat",
|
+[](int fd, const char* pathname, int flag, int mode) {
|
||||||
int, __openat,
|
if (pathname == apkPath) {
|
||||||
(int fd, const char* pathname, int flag, int mode), {
|
LOGD("redirect openat");
|
||||||
if (pathname == apkPath) {
|
return __openat_(fd, redirectPath.c_str(), flag, mode);
|
||||||
LOGD("redirect openat");
|
|
||||||
return backup(fd, redirectPath.c_str(), flag, mode);
|
|
||||||
}
|
|
||||||
return backup(fd, pathname, flag, mode);
|
|
||||||
});
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, jstring cacheApkPath) {
|
|
||||||
auto sym_openat = SandHook::ElfImg("libc.so").getSymbAddress<void *>("__openat");
|
|
||||||
auto r = HookSymNoHandle(handler, sym_openat, __openat);
|
|
||||||
if (!r) {
|
|
||||||
LOGE("Hook __openat fail");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
lsplant::JUTFString str1(env, origApkPath);
|
return __openat_(fd, pathname, flag, mode);
|
||||||
lsplant::JUTFString str2(env, cacheApkPath);
|
|
||||||
apkPath = str1.get();
|
|
||||||
redirectPath = str2.get();
|
|
||||||
LOGD("apkPath %s", apkPath.c_str());
|
|
||||||
LOGD("redirectPath %s", redirectPath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
|
||||||
LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterBypass(JNIEnv* env) {
|
bool HookOpenat(const lsplant::HookHandler& handler) { return handler.hook(__openat_); }
|
||||||
REGISTER_LSP_NATIVE_METHODS(SigBypass);
|
|
||||||
|
LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath,
|
||||||
|
jstring cacheApkPath) {
|
||||||
|
auto r = HookOpenat(lsplant::InitInfo{
|
||||||
|
.inline_hooker =
|
||||||
|
[](auto t, auto r) {
|
||||||
|
void* bk = nullptr;
|
||||||
|
return HookInline(t, r, &bk) == 0 ? bk : nullptr;
|
||||||
|
},
|
||||||
|
.art_symbol_resolver =
|
||||||
|
[](auto symbol) { return SandHook::ElfImg("libc.so").getSymbAddress(symbol); },
|
||||||
|
});
|
||||||
|
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 %s", apkPath.c_str());
|
||||||
|
LOGD("redirectPath %s", redirectPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JNINativeMethod gMethods[] = {
|
||||||
|
LSP_NATIVE_METHOD(SigBypass, enableOpenatHook, "(Ljava/lang/String;Ljava/lang/String;)V")};
|
||||||
|
|
||||||
|
void RegisterBypass(JNIEnv* env) { REGISTER_LSP_NATIVE_METHODS(SigBypass); }
|
||||||
|
|
||||||
|
} // namespace lspd
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,13 @@
|
||||||
// Created by Nullptr on 2022/3/17.
|
// Created by Nullptr on 2022/3/17.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "art/runtime/oat_file_manager.h"
|
#include "patch_loader.h"
|
||||||
|
|
||||||
#include "art/runtime/jit/profile_saver.h"
|
#include "art/runtime/jit/profile_saver.h"
|
||||||
|
#include "art/runtime/oat_file_manager.h"
|
||||||
#include "elf_util.h"
|
#include "elf_util.h"
|
||||||
#include "jni/bypass_sig.h"
|
#include "jni/bypass_sig.h"
|
||||||
#include "native_util.h"
|
#include "native_util.h"
|
||||||
#include "patch_loader.h"
|
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
#include "utils/jni_helper.hpp"
|
#include "utils/jni_helper.hpp"
|
||||||
|
|
||||||
|
|
@ -34,93 +35,95 @@ 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 = JNI_FindClass(env, "android/app/ActivityThread$AppBindData");
|
auto class_activity_thread_app_bind_data =
|
||||||
auto class_loaded_apk = JNI_FindClass(env, "android/app/LoadedApk");
|
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",
|
auto mid_current_activity_thread = JNI_GetStaticMethodID(
|
||||||
"()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",
|
JNI_GetMethodID(env, class_loaded_apk, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||||
"Landroid/app/ActivityThread$AppBindData;");
|
auto fid_m_bound_application = JNI_GetFieldID(env, class_activity_thread, "mBoundApplication",
|
||||||
auto fid_info = JNI_GetFieldID(env, class_activity_thread_app_bind_data, "info", "Landroid/app/LoadedApk;");
|
"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 =
|
||||||
auto m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application);
|
JNI_CallStaticObjectMethod(env, class_activity_thread, mid_current_activity_thread);
|
||||||
auto info = JNI_GetObjectField(env, m_bound_application, fid_info);
|
auto m_bound_application = JNI_GetObjectField(env, activity_thread, fid_m_bound_application);
|
||||||
auto stub_classloader = JNI_CallObjectMethod(env, info, mid_get_classloader);
|
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) [[unlikely]] {
|
||||||
LOGE("getStubClassLoader failed!!!");
|
LOGE("getStubClassLoader failed!!!");
|
||||||
return;
|
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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->DeleteLocalRef(dex_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchLoader::InitArtHooker(JNIEnv* env, const InitInfo& initInfo) {
|
auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
|
||||||
Context::InitArtHooker(env, initInfo);
|
auto mid_init = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
||||||
handler = initInfo;
|
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||||
art::DisableInline(initInfo);
|
auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer");
|
||||||
art::DisableBackgroundVerification(initInfo);
|
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::InitHooks(JNIEnv* env) {
|
env->DeleteLocalRef(dex_buffer);
|
||||||
Context::InitHooks(env);
|
}
|
||||||
RegisterBypass(env);
|
|
||||||
|
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::SetupEntryClass(JNIEnv* env) {
|
void PatchLoader::Load(JNIEnv* env) {
|
||||||
if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(),
|
/* InitSymbolCache(nullptr); */
|
||||||
"org.lsposed.lspatch.loader.LSPApplication")) {
|
lsplant::InitInfo initInfo{
|
||||||
entry_class_ = JNI_NewGlobalRef(env, entry_class);
|
.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::Load(JNIEnv* env) {
|
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub");
|
||||||
/* InitSymbolCache(nullptr); */
|
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
|
||||||
lsplant::InitInfo initInfo {
|
|
||||||
.inline_hooker = [](auto t, auto r) {
|
|
||||||
void* bk = nullptr;
|
|
||||||
return HookFunction(t, r, &bk) == RS_SUCCESS ? bk : nullptr;
|
|
||||||
},
|
|
||||||
.inline_unhooker = [](auto t) {
|
|
||||||
return UnhookFunction(t) == RT_SUCCESS;
|
|
||||||
},
|
|
||||||
.art_symbol_resolver = [](auto symbol) {
|
|
||||||
return GetArt()->getSymbAddress<void*>(symbol);
|
|
||||||
},
|
|
||||||
.art_symbol_prefix_resolver = [](auto symbol) {
|
|
||||||
return GetArt()->getSymbPrefixFirstAddress(symbol);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
auto stub = JNI_FindClass(env, "org/lsposed/lspatch/metaloader/LSPAppComponentFactoryStub");
|
ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);
|
||||||
auto dex_field = JNI_GetStaticFieldID(env, stub, "dex", "[B");
|
auto dex = PreloadedDex{env->GetByteArrayElements(array.get(), nullptr),
|
||||||
|
static_cast<size_t>(JNI_GetArrayLength(env, array))};
|
||||||
|
|
||||||
ScopedLocalRef<jbyteArray> array = JNI_GetStaticObjectField(env, stub, dex_field);
|
InitArtHooker(env, initInfo);
|
||||||
auto dex = PreloadedDex {env->GetByteArrayElements(array.get(), nullptr), static_cast<size_t>(JNI_GetArrayLength(env, array))};
|
LoadDex(env, std::move(dex));
|
||||||
|
InitHooks(env);
|
||||||
|
|
||||||
InitArtHooker(env, initInfo);
|
GetArt(true);
|
||||||
LoadDex(env, std::move(dex));
|
|
||||||
InitHooks(env);
|
|
||||||
|
|
||||||
GetArt(true);
|
SetupEntryClass(env);
|
||||||
|
FindAndCall(env, "onLoad", "()V");
|
||||||
SetupEntryClass(env);
|
}
|
||||||
FindAndCall(env, "onLoad", "()V");
|
} // namespace lspd
|
||||||
}
|
|
||||||
} // namespace lspd
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ dependencyResolutionManagement {
|
||||||
|
|
||||||
rootProject.name = "LSPatch"
|
rootProject.name = "LSPatch"
|
||||||
include(
|
include(
|
||||||
|
":apache",
|
||||||
":apkzlib",
|
":apkzlib",
|
||||||
":core",
|
|
||||||
":axml",
|
":axml",
|
||||||
|
":core",
|
||||||
":hiddenapi:bridge",
|
":hiddenapi:bridge",
|
||||||
":hiddenapi:stubs",
|
":hiddenapi:stubs",
|
||||||
":jar",
|
":jar",
|
||||||
|
|
@ -48,8 +49,9 @@ include(
|
||||||
":share:java",
|
":share:java",
|
||||||
)
|
)
|
||||||
|
|
||||||
project(":core").projectDir = file("core/core")
|
project(":apache").projectDir = file("core/apache")
|
||||||
project(":axml").projectDir = file("core/axml")
|
project(":axml").projectDir = file("core/axml")
|
||||||
|
project(":core").projectDir = file("core/core")
|
||||||
project(":hiddenapi:bridge").projectDir = file("core/hiddenapi/bridge")
|
project(":hiddenapi:bridge").projectDir = file("core/hiddenapi/bridge")
|
||||||
project(":hiddenapi:stubs").projectDir = file("core/hiddenapi/stubs")
|
project(":hiddenapi:stubs").projectDir = file("core/hiddenapi/stubs")
|
||||||
project(":services:daemon-service").projectDir = file("core/services/daemon-service")
|
project(":services:daemon-service").projectDir = file("core/services/daemon-service")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue