[core] Refactor Yahfa
This commit is contained in:
parent
26a4decfeb
commit
a6b4ed548e
|
|
@ -3,26 +3,18 @@
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
namespace yahfa {
|
||||||
extern "C" {
|
void init(JNIEnv *env, jclass clazz, jint sdkVersion);
|
||||||
#endif
|
|
||||||
|
|
||||||
void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion);
|
jobject findMethodNative(JNIEnv *env, jclass clazz,
|
||||||
|
|
||||||
jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz,
|
|
||||||
jclass targetClass, jstring methodName,
|
jclass targetClass, jstring methodName,
|
||||||
jstring methodSig);
|
jstring methodSig);
|
||||||
|
|
||||||
jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz,
|
jboolean backupAndHookNative(JNIEnv *env, jclass clazz,
|
||||||
jobject target, jobject hook,
|
jobject target, jobject hook,
|
||||||
jobject backup);
|
jobject backup);
|
||||||
|
|
||||||
void setNonCompilable(void *method);
|
void *getArtMethod(JNIEnv *env, jobject jmethod);
|
||||||
|
|
||||||
void *getArtMethodYahfa(JNIEnv *env, jobject jmethod);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // HOOK_MAIN_H
|
#endif // HOOK_MAIN_H
|
||||||
|
|
|
||||||
|
|
@ -8,113 +8,36 @@
|
||||||
#include "HookMain.h"
|
#include "HookMain.h"
|
||||||
|
|
||||||
int SDKVersion;
|
int SDKVersion;
|
||||||
static size_t OFFSET_entry_point_from_interpreter_in_ArtMethod;
|
|
||||||
size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
static size_t OFFSET_ArtMehod_in_Object;
|
namespace {
|
||||||
static size_t OFFSET_access_flags_in_ArtMethod;
|
size_t ArtMethodSize;
|
||||||
static size_t ArtMethodSize;
|
constexpr size_t OFFSET_access_flags_in_ArtMethod = 4;
|
||||||
static uint32_t kAccCompileDontBother = 0x01000000;
|
constexpr uint32_t kAccCompileDontBother = 0x02000000;
|
||||||
static uint32_t kAccPublic = 0x0001; // class, field, method, ic
|
constexpr uint32_t kAccPreCompiled = 0x00100000 | 0x00200000;
|
||||||
static uint32_t kAccPrivate = 0x0002; // field, method, ic
|
constexpr uint32_t kAccPublic = 0x0001; // class, field, method, ic
|
||||||
static uint32_t kAccProtected = 0x0004; // field, method, ic
|
constexpr uint32_t kAccPrivate = 0x0002; // field, method, ic
|
||||||
static uint32_t kAccStatic = 0x0008; // field, method, ic
|
constexpr uint32_t kAccProtected = 0x0004; // field, method, ic
|
||||||
static uint32_t kAccFastInterpreterToInterpreterInvoke = 0x40000000;
|
constexpr uint32_t kAccStatic = 0x0008; // field, method, ic
|
||||||
|
constexpr uint32_t kAccFastInterpreterToInterpreterInvoke = 0x40000000;
|
||||||
|
|
||||||
|
jfieldID fieldArtMethod = nullptr;
|
||||||
|
|
||||||
static jfieldID fieldArtMethod = nullptr;
|
constexpr inline uint32_t read32(void *addr) {
|
||||||
|
|
||||||
static inline uint32_t read32(void *addr) {
|
|
||||||
return *((uint32_t *) addr);
|
return *((uint32_t *) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void write32(void *addr, uint32_t value) {
|
constexpr inline void write32(void *addr, uint32_t value) {
|
||||||
*((uint32_t *) addr) = value;
|
*((uint32_t *) addr) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *readAddr(void *addr) {
|
constexpr inline void *readAddr(void *addr) {
|
||||||
return *((void **) addr);
|
return *((void **) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void writeAddr(void *addr, void *value) {
|
constexpr inline void writeAddr(void *addr, void *value) {
|
||||||
*((void **) addr) = value;
|
*((void **) addr) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion) {
|
|
||||||
SDKVersion = sdkVersion;
|
|
||||||
jclass classExecutable;
|
|
||||||
LOGI("init to SDK %d", sdkVersion);
|
|
||||||
switch (sdkVersion) {
|
|
||||||
case __ANDROID_API_S__:
|
|
||||||
classExecutable = env->FindClass("java/lang/reflect/Executable");
|
|
||||||
fieldArtMethod = env->GetFieldID(classExecutable, "artMethod", "J");
|
|
||||||
kAccCompileDontBother = 0x02000000;
|
|
||||||
OFFSET_ArtMehod_in_Object = 0;
|
|
||||||
OFFSET_access_flags_in_ArtMethod = 4;
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
roundUpToPtrSize(4 * 3 + 2 * 2) + pointer_size;
|
|
||||||
ArtMethodSize = roundUpToPtrSize(4 * 3 + 2 * 2) + pointer_size * 2;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_R__:
|
|
||||||
classExecutable = env->FindClass("java/lang/reflect/Executable");
|
|
||||||
fieldArtMethod = env->GetFieldID(classExecutable, "artMethod", "J");
|
|
||||||
case __ANDROID_API_Q__:
|
|
||||||
case __ANDROID_API_P__:
|
|
||||||
kAccCompileDontBother = 0x02000000;
|
|
||||||
OFFSET_ArtMehod_in_Object = 0;
|
|
||||||
OFFSET_access_flags_in_ArtMethod = 4;
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size;
|
|
||||||
ArtMethodSize = roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 2;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_O_MR1__:
|
|
||||||
kAccCompileDontBother = 0x02000000;
|
|
||||||
case __ANDROID_API_O__:
|
|
||||||
OFFSET_ArtMehod_in_Object = 0;
|
|
||||||
OFFSET_access_flags_in_ArtMethod = 4;
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 2;
|
|
||||||
ArtMethodSize = roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 3;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_N_MR1__:
|
|
||||||
case __ANDROID_API_N__:
|
|
||||||
OFFSET_ArtMehod_in_Object = 0;
|
|
||||||
OFFSET_access_flags_in_ArtMethod = 4; // sizeof(GcRoot<mirror::Class>) = 4
|
|
||||||
// ptr_sized_fields_ is rounded up to pointer_size in ArtMethod
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 3;
|
|
||||||
|
|
||||||
ArtMethodSize = roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 4;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_M__:
|
|
||||||
OFFSET_ArtMehod_in_Object = 0;
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod = roundUpToPtrSize(4 * 7);
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod + pointer_size * 2;
|
|
||||||
ArtMethodSize = roundUpToPtrSize(4 * 7) + pointer_size * 3;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_L_MR1__:
|
|
||||||
OFFSET_ArtMehod_in_Object = 4 * 2;
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod = roundUpToPtrSize(
|
|
||||||
OFFSET_ArtMehod_in_Object + 4 * 7);
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod + pointer_size * 2;
|
|
||||||
ArtMethodSize = OFFSET_entry_point_from_interpreter_in_ArtMethod + pointer_size * 3;
|
|
||||||
break;
|
|
||||||
case __ANDROID_API_L__:
|
|
||||||
OFFSET_ArtMehod_in_Object = 4 * 2;
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod = OFFSET_ArtMehod_in_Object + 4 * 4;
|
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
|
||||||
OFFSET_entry_point_from_interpreter_in_ArtMethod + 8 * 2;
|
|
||||||
ArtMethodSize = OFFSET_ArtMehod_in_Object + 4 * 4 + 8 * 4 + 4 * 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOGE("not compatible with SDK %d", sdkVersion);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
setupTrampoline();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNonCompilable(void *method) {
|
void setNonCompilable(void *method) {
|
||||||
if (SDKVersion < __ANDROID_API_N__) {
|
if (SDKVersion < __ANDROID_API_N__) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -122,6 +45,7 @@ void setNonCompilable(void *method) {
|
||||||
uint32_t access_flags = read32((char *) method + OFFSET_access_flags_in_ArtMethod);
|
uint32_t access_flags = read32((char *) method + OFFSET_access_flags_in_ArtMethod);
|
||||||
LOGI("setNonCompilable: access flags is 0x%x", access_flags);
|
LOGI("setNonCompilable: access flags is 0x%x", access_flags);
|
||||||
access_flags |= kAccCompileDontBother;
|
access_flags |= kAccCompileDontBother;
|
||||||
|
access_flags &= ~kAccPreCompiled;
|
||||||
write32((char *) method + OFFSET_access_flags_in_ArtMethod, access_flags);
|
write32((char *) method + OFFSET_access_flags_in_ArtMethod, access_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +60,7 @@ void setPrivate(void *method) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int doBackupAndHook(JNIEnv *env, void *targetMethod, void *hookMethod, void *backupMethod) {
|
int doBackupAndHook(void *targetMethod, void *hookMethod, void *backupMethod) {
|
||||||
if (hookCount >= hookCap) {
|
if (hookCount >= hookCap) {
|
||||||
LOGI("not enough capacity. Allocating...");
|
LOGI("not enough capacity. Allocating...");
|
||||||
if (doInitHookCap(DEFAULT_CAP)) {
|
if (doInitHookCap(DEFAULT_CAP)) {
|
||||||
|
|
@ -182,12 +106,6 @@ static int doBackupAndHook(JNIEnv *env, void *targetMethod, void *hookMethod, vo
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OFFSET_entry_point_from_interpreter_in_ArtMethod != 0) {
|
|
||||||
writeAddr((char *) targetMethod + OFFSET_entry_point_from_interpreter_in_ArtMethod,
|
|
||||||
readAddr((char *) hookMethod + OFFSET_entry_point_from_interpreter_in_ArtMethod));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDKVersion >= __ANDROID_API_Q__) {
|
if (SDKVersion >= __ANDROID_API_Q__) {
|
||||||
uint32_t access_flags = read32((char *) targetMethod + OFFSET_access_flags_in_ArtMethod);
|
uint32_t access_flags = read32((char *) targetMethod + OFFSET_access_flags_in_ArtMethod);
|
||||||
// On API 29 whether to use the fast path or not is cached in the ART method structure
|
// On API 29 whether to use the fast path or not is cached in the ART method structure
|
||||||
|
|
@ -200,25 +118,53 @@ static int doBackupAndHook(JNIEnv *env, void *targetMethod, void *hookMethod, vo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getArtMethodYahfa(JNIEnv *env, jobject jmethod) {
|
}
|
||||||
void *artMethod = nullptr;
|
|
||||||
|
|
||||||
|
namespace yahfa {
|
||||||
|
|
||||||
|
void init(JNIEnv *env, [[maybe_unused]] jclass clazz, jint sdkVersion) {
|
||||||
|
SDKVersion = sdkVersion;
|
||||||
|
jclass classExecutable = env->FindClass("java/lang/reflect/Executable");
|
||||||
|
fieldArtMethod = env->GetFieldID(classExecutable, "artMethod", "J");
|
||||||
|
LOGI("init to SDK %d", sdkVersion);
|
||||||
|
switch (sdkVersion) {
|
||||||
|
case __ANDROID_API_S__:
|
||||||
|
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
||||||
|
roundUpToPtrSize(4 * 3 + 2 * 2) + pointer_size;
|
||||||
|
ArtMethodSize = roundUpToPtrSize(4 * 3 + 2 * 2) + pointer_size * 2;
|
||||||
|
break;
|
||||||
|
case __ANDROID_API_R__:
|
||||||
|
case __ANDROID_API_Q__:
|
||||||
|
case __ANDROID_API_P__:
|
||||||
|
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
||||||
|
roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size;
|
||||||
|
ArtMethodSize = roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 2;
|
||||||
|
break;
|
||||||
|
case __ANDROID_API_O_MR1__:
|
||||||
|
case __ANDROID_API_O__:
|
||||||
|
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod =
|
||||||
|
roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 2;
|
||||||
|
ArtMethodSize = roundUpToPtrSize(4 * 4 + 2 * 2) + pointer_size * 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGE("not compatible with SDK %d", sdkVersion);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupTrampoline();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
||||||
if (jmethod == nullptr) {
|
if (jmethod == nullptr) {
|
||||||
return artMethod;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (SDKVersion >= __ANDROID_API_R__) {
|
|
||||||
artMethod = (void *) env->GetLongField(jmethod, fieldArtMethod);
|
|
||||||
} else {
|
} else {
|
||||||
artMethod = (void *) env->FromReflectedMethod(jmethod);
|
return (void *) env->GetLongField(jmethod, fieldArtMethod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI("ArtMethod: %p", artMethod);
|
jobject findMethodNative(JNIEnv *env, [[maybe_unused]] jclass clazz,
|
||||||
return artMethod;
|
jclass targetClass,
|
||||||
}
|
jstring methodName,
|
||||||
|
|
||||||
extern "C" jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz,
|
|
||||||
jclass targetClass, jstring methodName,
|
|
||||||
jstring methodSig) {
|
jstring methodSig) {
|
||||||
const char *c_methodName = env->GetStringUTFChars(methodName, nullptr);
|
const char *c_methodName = env->GetStringUTFChars(methodName, nullptr);
|
||||||
const char *c_methodSig = env->GetStringUTFChars(methodSig, nullptr);
|
const char *c_methodSig = env->GetStringUTFChars(methodSig, nullptr);
|
||||||
|
|
@ -244,14 +190,13 @@ extern "C" jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz,
|
jboolean backupAndHookNative(JNIEnv *env, [[maybe_unused]] jclass clazz,
|
||||||
jobject target, jobject hook,
|
jobject target, jobject hook,
|
||||||
jobject backup) {
|
jobject backup) {
|
||||||
|
|
||||||
if (!doBackupAndHook(env,
|
if (!doBackupAndHook(getArtMethod(env, target),
|
||||||
getArtMethodYahfa(env, target),
|
getArtMethod(env, hook),
|
||||||
getArtMethodYahfa(env, hook),
|
getArtMethod(env, backup)
|
||||||
getArtMethodYahfa(env, backup)
|
|
||||||
)) {
|
)) {
|
||||||
env->NewGlobalRef(hook); // keep a global ref so that the hook method would not be GCed
|
env->NewGlobalRef(hook); // keep a global ref so that the hook method would not be GCed
|
||||||
if (backup) env->NewGlobalRef(backup);
|
if (backup) env->NewGlobalRef(backup);
|
||||||
|
|
@ -260,3 +205,4 @@ extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *e
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace lspd {
|
||||||
static std::unordered_set<void *> deopted_methods;
|
static std::unordered_set<void *> deopted_methods;
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(void, ClassLinker, setEntryPointsToInterpreter, jobject method) {
|
LSP_DEF_NATIVE_METHOD(void, ClassLinker, setEntryPointsToInterpreter, jobject method) {
|
||||||
void *reflected_method = getArtMethodYahfa(env, method);
|
void *reflected_method = yahfa::getArtMethod(env, method);
|
||||||
if (deopted_methods.contains(reflected_method)) {
|
if (deopted_methods.contains(reflected_method)) {
|
||||||
LOGD("method %p has been deopted before, skip...", reflected_method);
|
LOGD("method %p has been deopted before, skip...", reflected_method);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ namespace lspd {
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(void, PendingHooks, recordPendingMethodNative, jobject method_ref, jclass class_ref){
|
LSP_DEF_NATIVE_METHOD(void, PendingHooks, recordPendingMethodNative, jobject method_ref, jclass class_ref){
|
||||||
auto *class_ptr = art::Thread::Current().DecodeJObject(class_ref);
|
auto *class_ptr = art::Thread::Current().DecodeJObject(class_ref);
|
||||||
auto *method = getArtMethodYahfa(env, method_ref);
|
auto *method = yahfa::getArtMethod(env, method_ref);
|
||||||
art::mirror::Class mirror_class(class_ptr);
|
art::mirror::Class mirror_class(class_ptr);
|
||||||
if (auto def = mirror_class.GetClassDef(); LIKELY(def)) {
|
if (auto def = mirror_class.GetClassDef(); LIKELY(def)) {
|
||||||
LOGD("record pending: %p (%s) with %p", class_ptr, mirror_class.GetDescriptor().c_str(),
|
LOGD("record pending: %p (%s) with %p", class_ptr, mirror_class.GetDescriptor().c_str(),
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,12 @@
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
using namespace startop::dex;
|
using namespace startop::dex;
|
||||||
LSP_DEF_NATIVE_METHOD(void, Yahfa, init, jint sdkVersion) {
|
LSP_DEF_NATIVE_METHOD(void, Yahfa, init, jint sdkVersion) {
|
||||||
Java_lab_galaxy_yahfa_HookMain_init(env, clazz, sdkVersion);
|
yahfa::init(env, clazz, sdkVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jobject, Yahfa, findMethodNative, jclass targetClass,
|
LSP_DEF_NATIVE_METHOD(jobject, Yahfa, findMethodNative, jclass targetClass,
|
||||||
jstring methodName, jstring methodSig) {
|
jstring methodName, jstring methodSig) {
|
||||||
return Java_lab_galaxy_yahfa_HookMain_findMethodNative(env, clazz, targetClass, methodName,
|
return yahfa::findMethodNative(env, clazz, targetClass, methodName,
|
||||||
methodSig);
|
methodSig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,19 +47,21 @@ namespace lspd {
|
||||||
art::gc::kGcCauseDebugger,
|
art::gc::kGcCauseDebugger,
|
||||||
art::gc::kCollectorTypeDebugger);
|
art::gc::kCollectorTypeDebugger);
|
||||||
art::thread_list::ScopedSuspendAll suspend("Yahfa Hook", false);
|
art::thread_list::ScopedSuspendAll suspend("Yahfa Hook", false);
|
||||||
return Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(env, clazz, target, hook, backup);
|
return yahfa::backupAndHookNative(env, clazz, target, hook, backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(void, Yahfa, recordHooked, jobject member) {
|
LSP_DEF_NATIVE_METHOD(void, Yahfa, recordHooked, jobject member) {
|
||||||
lspd::recordHooked(getArtMethodYahfa(env, member));
|
lspd::recordHooked(yahfa::getArtMethod(env, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jboolean, Yahfa, isHooked, jobject member) {
|
LSP_DEF_NATIVE_METHOD(jboolean, Yahfa, isHooked, jobject member) {
|
||||||
return lspd::isHooked(getArtMethodYahfa(env, member));
|
return lspd::isHooked(yahfa::getArtMethod(env, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jclass, Yahfa, buildHooker, jobject app_class_loader, jclass return_class, jobjectArray classes, jstring method_name) {
|
LSP_DEF_NATIVE_METHOD(jclass, Yahfa, buildHooker, jobject app_class_loader, jclass return_class,
|
||||||
static auto in_memory_classloader = (jclass)env->NewGlobalRef(env->FindClass( "dalvik/system/InMemoryDexClassLoader"));
|
jobjectArray classes, jstring method_name) {
|
||||||
|
static auto in_memory_classloader = (jclass) env->NewGlobalRef(
|
||||||
|
env->FindClass("dalvik/system/InMemoryDexClassLoader"));
|
||||||
static jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
static jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
|
||||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||||
DexBuilder dex_file;
|
DexBuilder dex_file;
|
||||||
|
|
@ -69,7 +71,9 @@ namespace lspd {
|
||||||
parameter_types.reserve(parameter_length);
|
parameter_types.reserve(parameter_length);
|
||||||
std::string storage;
|
std::string storage;
|
||||||
auto current_thread = art::Thread::Current();
|
auto current_thread = art::Thread::Current();
|
||||||
auto return_type = TypeDescriptor::FromDescriptor(art::mirror::Class(current_thread.DecodeJObject(return_class)).GetDescriptor(&storage));
|
auto return_type = TypeDescriptor::FromDescriptor(
|
||||||
|
art::mirror::Class(current_thread.DecodeJObject(return_class)).GetDescriptor(
|
||||||
|
&storage));
|
||||||
for (int i = 0; i < parameter_length; ++i) {
|
for (int i = 0; i < parameter_length; ++i) {
|
||||||
auto param = (jclass) env->GetObjectArrayElement(classes, i);
|
auto param = (jclass) env->GetObjectArrayElement(classes, i);
|
||||||
auto *param_ref = current_thread.DecodeJObject(param);
|
auto *param_ref = current_thread.DecodeJObject(param);
|
||||||
|
|
@ -160,7 +164,8 @@ namespace lspd {
|
||||||
static jmethodID mid = JNI_GetMethodID(env, in_memory_classloader, "loadClass",
|
static jmethodID mid = JNI_GetMethodID(env, in_memory_classloader, "loadClass",
|
||||||
"(Ljava/lang/String;)Ljava/lang/Class;");
|
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||||
if (!mid) {
|
if (!mid) {
|
||||||
mid = JNI_GetMethodID(env, in_memory_classloader, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
mid = JNI_GetMethodID(env, in_memory_classloader, "findClass",
|
||||||
|
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||||
}
|
}
|
||||||
jobject target = env->CallObjectMethod(my_cl, mid, env->NewStringUTF("LspHooker_"));
|
jobject target = env->CallObjectMethod(my_cl, mid, env->NewStringUTF("LspHooker_"));
|
||||||
// LOGD("Created %zd", image.size());
|
// LOGD("Created %zd", image.size());
|
||||||
|
|
@ -178,7 +183,8 @@ namespace lspd {
|
||||||
"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)Z"),
|
"(Ljava/lang/reflect/Executable;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)Z"),
|
||||||
LSP_NATIVE_METHOD(Yahfa, recordHooked, "(Ljava/lang/reflect/Executable;)V"),
|
LSP_NATIVE_METHOD(Yahfa, recordHooked, "(Ljava/lang/reflect/Executable;)V"),
|
||||||
LSP_NATIVE_METHOD(Yahfa, isHooked, "(Ljava/lang/reflect/Executable;)Z"),
|
LSP_NATIVE_METHOD(Yahfa, isHooked, "(Ljava/lang/reflect/Executable;)Z"),
|
||||||
LSP_NATIVE_METHOD(Yahfa, buildHooker, "(Ljava/lang/ClassLoader;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Class;"),
|
LSP_NATIVE_METHOD(Yahfa, buildHooker,
|
||||||
|
"(Ljava/lang/ClassLoader;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Class;"),
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterYahfa(JNIEnv *env) {
|
void RegisterYahfa(JNIEnv *env) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue