Try to fix #740
This commit is contained in:
parent
01143501c7
commit
c23e3ff33d
|
|
@ -20,7 +20,9 @@ jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass
|
|||
void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz,
|
||||
jobject hook,
|
||||
jobject backup);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void setNonCompilable(void *method);
|
||||
|
||||
void *getArtMethod(JNIEnv *env, jobject jmethod);
|
||||
|
|
@ -28,8 +30,7 @@ void *getArtMethod(JNIEnv *env, jobject jmethod);
|
|||
// TODO: move to common utils instead of in YAHFA's code
|
||||
void *getEntryPoint(void* method);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void *getOriginalEntryPointFromHookedEntryPoint(void* method);
|
||||
|
||||
|
||||
#endif // HOOK_MAIN_H
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
extern int SDKVersion;
|
||||
|
||||
extern unsigned char trampoline[];
|
||||
extern unsigned char trampolineForBackup[];
|
||||
|
||||
void* doInitHookCap(size_t cap);
|
||||
void setupTrampoline(uint8_t offset);
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
#include "jni.h"
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <cstdlib>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common.h"
|
||||
#include "trampoline.h"
|
||||
#include "HookMain.h"
|
||||
extern "C" {
|
||||
#include "trampoline.h"
|
||||
}
|
||||
|
||||
int SDKVersion;
|
||||
static uint32_t OFFSET_entry_point_from_interpreter_in_ArtMethod;
|
||||
|
|
@ -14,7 +16,8 @@ static uint32_t OFFSET_ArtMehod_in_Object;
|
|||
static uint32_t OFFSET_access_flags_in_ArtMethod;
|
||||
static uint32_t kAccCompileDontBother = 0x01000000;
|
||||
|
||||
static jfieldID fieldArtMethod = NULL;
|
||||
static jfieldID fieldArtMethod = nullptr;
|
||||
static std::unordered_map<void*, void*> replaced_entrypoint;
|
||||
|
||||
static inline uint32_t read32(void *addr) {
|
||||
return *((uint32_t *) addr);
|
||||
|
|
@ -32,14 +35,14 @@ static inline void writeAddr(void *addr, void *value) {
|
|||
*((void **)addr) = value;
|
||||
}
|
||||
|
||||
void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion) {
|
||||
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_R__:
|
||||
classExecutable = (*env)->FindClass(env, "java/lang/reflect/Executable");
|
||||
fieldArtMethod = (*env)->GetFieldID(env, classExecutable, "artMethod", "J");
|
||||
classExecutable = env->FindClass("java/lang/reflect/Executable");
|
||||
fieldArtMethod = env->GetFieldID(classExecutable, "artMethod", "J");
|
||||
case __ANDROID_API_Q__:
|
||||
case __ANDROID_API_P__:
|
||||
kAccCompileDontBother = 0x02000000;
|
||||
|
|
@ -93,12 +96,14 @@ void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVers
|
|||
setupTrampoline(OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod);
|
||||
}
|
||||
|
||||
static uint32_t getFlags(char *method) {
|
||||
static uint32_t getFlags(void *method_) {
|
||||
char* method = (char*)method_;
|
||||
uint32_t access_flags = read32(method + OFFSET_access_flags_in_ArtMethod);
|
||||
return access_flags;
|
||||
}
|
||||
|
||||
static void setFlags(char *method, uint32_t access_flags) {
|
||||
static void setFlags(void *method_, uint32_t access_flags) {
|
||||
char* method = (char*)method_;
|
||||
write32(method + OFFSET_access_flags_in_ArtMethod, access_flags);
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +124,7 @@ void *getEntryPoint(void* method) {
|
|||
|
||||
static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
|
||||
// replace entry point
|
||||
void *newEntrypoint = NULL;
|
||||
void *newEntrypoint = nullptr;
|
||||
if(isBackup) {
|
||||
void *originEntrypoint = readAddr((char *) toMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod);
|
||||
// entry point hardcoded
|
||||
|
|
@ -127,24 +132,28 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
|
|||
}
|
||||
else {
|
||||
// entry point from ArtMethod struct
|
||||
newEntrypoint = genTrampoline(toMethod, NULL);
|
||||
newEntrypoint = genTrampoline(toMethod, nullptr);
|
||||
}
|
||||
|
||||
void* fromEntrypoint = (char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||
replaced_entrypoint[fromEntrypoint] = newEntrypoint;
|
||||
|
||||
LOGI("replace entry point from %p to %p",
|
||||
readAddr((char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod),
|
||||
readAddr(fromEntrypoint),
|
||||
newEntrypoint
|
||||
);
|
||||
if (newEntrypoint) {
|
||||
writeAddr((char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod,
|
||||
writeAddr(fromEntrypoint,
|
||||
newEntrypoint);
|
||||
} else {
|
||||
LOGE("failed to allocate space for trampoline of target method");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For pre Android M devices, should be not used by EdXposed.
|
||||
if (OFFSET_entry_point_from_interpreter_in_ArtMethod != 0) {
|
||||
void *interpEntrypoint = readAddr((char *) toMethod + OFFSET_entry_point_from_interpreter_in_ArtMethod);
|
||||
writeAddr((char *) fromMethod + OFFSET_entry_point_from_interpreter_in_ArtMethod,
|
||||
writeAddr(fromEntrypoint,
|
||||
interpEntrypoint);
|
||||
}
|
||||
|
||||
|
|
@ -180,16 +189,16 @@ static int doBackupAndHook(void *targetMethod, void *hookMethod, void *backupMet
|
|||
}
|
||||
|
||||
void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
||||
void *artMethod = NULL;
|
||||
void *artMethod = nullptr;
|
||||
|
||||
if (jmethod == NULL) {
|
||||
if (jmethod == nullptr) {
|
||||
return artMethod;
|
||||
}
|
||||
|
||||
if (SDKVersion == __ANDROID_API_R__) {
|
||||
artMethod = (void *) (*env)->GetLongField(env, jmethod, fieldArtMethod);
|
||||
artMethod = (void *) env->GetLongField(jmethod, fieldArtMethod);
|
||||
} else {
|
||||
artMethod = (void *) (*env)->FromReflectedMethod(env, jmethod);
|
||||
artMethod = (void *) env->FromReflectedMethod(jmethod);
|
||||
}
|
||||
|
||||
LOGI("HookMain: getArtMethod: %p", artMethod);
|
||||
|
|
@ -197,34 +206,34 @@ void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
|||
|
||||
}
|
||||
|
||||
jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz,
|
||||
extern "C" jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz,
|
||||
jclass targetClass, jstring methodName,
|
||||
jstring methodSig) {
|
||||
const char *c_methodName = (*env)->GetStringUTFChars(env, methodName, NULL);
|
||||
const char *c_methodSig = (*env)->GetStringUTFChars(env, methodSig, NULL);
|
||||
jobject ret = NULL;
|
||||
const char *c_methodName = env->GetStringUTFChars(methodName, nullptr);
|
||||
const char *c_methodSig = env->GetStringUTFChars(methodSig, nullptr);
|
||||
jobject ret = nullptr;
|
||||
|
||||
|
||||
//Try both GetMethodID and GetStaticMethodID -- Whatever works :)
|
||||
jmethodID method = (*env)->GetMethodID(env, targetClass, c_methodName, c_methodSig);
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
ret = (*env)->ToReflectedMethod(env, targetClass, method, JNI_FALSE);
|
||||
jmethodID method = env->GetMethodID(targetClass, c_methodName, c_methodSig);
|
||||
if (!env->ExceptionCheck()) {
|
||||
ret = env->ToReflectedMethod(targetClass, method, JNI_FALSE);
|
||||
} else {
|
||||
(*env)->ExceptionClear(env);
|
||||
method = (*env)->GetStaticMethodID(env, targetClass, c_methodName, c_methodSig);
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
ret = (*env)->ToReflectedMethod(env, targetClass, method, JNI_TRUE);
|
||||
env->ExceptionClear();
|
||||
method = env->GetStaticMethodID(targetClass, c_methodName, c_methodSig);
|
||||
if (!env->ExceptionCheck()) {
|
||||
ret = env->ToReflectedMethod(targetClass, method, JNI_TRUE);
|
||||
} else {
|
||||
(*env)->ExceptionClear(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, methodName, c_methodName);
|
||||
(*env)->ReleaseStringUTFChars(env, methodSig, c_methodSig);
|
||||
env->ReleaseStringUTFChars(methodName, c_methodName);
|
||||
env->ReleaseStringUTFChars(methodSig, c_methodSig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz,
|
||||
extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz,
|
||||
jobject target, jobject hook,
|
||||
jobject backup) {
|
||||
|
||||
|
|
@ -232,10 +241,14 @@ jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass
|
|||
getArtMethod(env, hook),
|
||||
getArtMethod(env, backup)
|
||||
)) {
|
||||
(*env)->NewGlobalRef(env, hook); // keep a global ref so that the hook method would not be GCed
|
||||
if (backup) (*env)->NewGlobalRef(env, backup);
|
||||
env->NewGlobalRef(hook); // keep a global ref so that the hook method would not be GCed
|
||||
if (backup) env->NewGlobalRef(backup);
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void *getOriginalEntryPointFromHookedEntryPoint(void* method) {
|
||||
return replaced_entrypoint[method];
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Created by 双草酸酯 on 12/18/20.
|
||||
//
|
||||
|
||||
#ifndef EDXPOSED_OAT_QUICK_METHOD_HEADER_H
|
||||
#define EDXPOSED_OAT_QUICK_METHOD_HEADER_H
|
||||
|
||||
#include <base/object.h>
|
||||
#include <config_manager.h>
|
||||
#include <HookMain.h>
|
||||
namespace art {
|
||||
// https://github.com/ElderDrivers/EdXposed/issues/740
|
||||
class OatQuickMethodHeader : public edxp::HookedObject {
|
||||
private:
|
||||
CREATE_HOOK_STUB_ENTRIES(uint32_t, GetCodeSize, void *thiz) {
|
||||
LOGD("OatQuickMethodHeader::GetCodeSize: %p", thiz);
|
||||
void* oep = getOriginalEntryPointFromHookedEntryPoint(thiz);
|
||||
if (oep) {
|
||||
LOGD("OatQuickMethodHeader: Original entry point: %p", oep);
|
||||
return GetCodeSizeBackup(oep);
|
||||
} else {
|
||||
LOGD("OatQuickMethodHeader: Original entry point not found");
|
||||
return GetCodeSizeBackup(thiz);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static void Setup(void *handle, HookFunType hook_func) {
|
||||
if (edxp::GetAndroidApiLevel() >= __ANDROID_API_R__) {
|
||||
HOOK_FUNC(GetCodeSize, "_ZNK3art20OatQuickMethodHeader11GetCodeSizeEv");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //EDXPOSED_OAT_QUICK_METHOD_HEADER_H
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "art/runtime/gc/heap.h"
|
||||
#include "art/runtime/hidden_api.h"
|
||||
#include "art/runtime/oat_file_manager.h"
|
||||
#include "art/runtime/oat_quick_method_header.h"
|
||||
#include "art/runtime/jit/jit_code_cache.h"
|
||||
|
||||
std::vector<soinfo_t> linker_get_solist(); // Dobby but not in .h
|
||||
|
|
@ -79,6 +80,7 @@ namespace edxp {
|
|||
art::mirror::Class::Setup(art_handle, hook_func);
|
||||
art::JNIEnvExt::Setup(art_handle, hook_func);
|
||||
art::oat_file_manager::DisableOnlyUseSystemOatFiles(art_handle, hook_func);
|
||||
art::OatQuickMethodHeader::Setup(art_handle, hook_func);
|
||||
art::jit::HookJitCacheCode(art_handle, hook_func);
|
||||
|
||||
art_hooks_installed = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue