From 0e2783f8e512d1249122dfbfc5eaf4da4bd5a40b Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 27 Jan 2021 19:03:05 +0800 Subject: [PATCH] Hook UpdateMethodCode --- .../main/cpp/external/yahfa/src/HookMain.cpp | 73 +++++++++++-------- .../cpp/main/include/art/runtime/art_method.h | 71 +++++++++--------- .../include/art/runtime/instrumentation.h | 30 ++++++++ .../src/main/cpp/main/src/config_manager.cpp | 1 + .../src/main/cpp/main/src/native_hook.cpp | 4 +- 5 files changed, 111 insertions(+), 68 deletions(-) create mode 100644 edxp-core/src/main/cpp/main/include/art/runtime/instrumentation.h diff --git a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp index 0cf941e9..9f9f21e0 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp +++ b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp @@ -5,34 +5,40 @@ #include "common.h" #include "HookMain.h" + extern "C" { #include "trampoline.h" } int SDKVersion; -static uint32_t OFFSET_entry_point_from_interpreter_in_ArtMethod; -static uint32_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; -static uint32_t OFFSET_ArtMehod_in_Object; -static uint32_t OFFSET_access_flags_in_ArtMethod; -static uint32_t kAccCompileDontBother = 0x01000000; +namespace { + uint32_t OFFSET_entry_point_from_interpreter_in_ArtMethod; + uint32_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; + uint32_t OFFSET_ArtMehod_in_Object; + uint32_t OFFSET_access_flags_in_ArtMethod; + uint32_t kAccCompileDontBother = 0x01000000; + uint32_t kAccNative = 0x0100; + uint32_t kAccFastInterpreterToInterpreterInvoke = 0x40000000; -static jfieldID fieldArtMethod = nullptr; -static std::unordered_map replaced_entrypoint; + jfieldID fieldArtMethod = nullptr; -static inline uint32_t read32(void *addr) { - return *((uint32_t *) addr); -} + std::unordered_map replaced_entrypoint; -static inline void write32(void *addr, uint32_t value) { - *((uint32_t *) addr) = value; -} + inline uint32_t read32(void *addr) { + return *((uint32_t *) addr); + } -static inline void *readAddr(void *addr) { - return *((void **) addr); -} + inline void write32(void *addr, uint32_t value) { + *((uint32_t *) addr) = value; + } -static inline void writeAddr(void *addr, void *value) { - *((void **)addr) = value; + inline void *readAddr(void *addr) { + return *((void **) addr); + } + + inline void writeAddr(void *addr, void *value) { + *((void **) addr) = value; + } } extern "C" void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion) { @@ -97,13 +103,13 @@ extern "C" void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, j } static uint32_t getFlags(void *method_) { - char* method = (char*)method_; + char *method = (char *) method_; uint32_t access_flags = read32(method + OFFSET_access_flags_in_ArtMethod); return access_flags; } static void setFlags(void *method_, uint32_t access_flags) { - char* method = (char*)method_; + char *method = (char *) method_; write32(method + OFFSET_access_flags_in_ArtMethod, access_flags); } @@ -118,20 +124,21 @@ void setNonCompilable(void *method) { LOGI("setNonCompilable: change access flags from 0x%x to 0x%x", old_flags, access_flags); } -void *getEntryPoint(void* method) { +void *getEntryPoint(void *method) { return readAddr((char *) method + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod); } static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) { // replace entry point void *newEntrypoint = nullptr; - void* fromEntrypoint = (char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; + void *fromEntrypoint = + (char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; if (isBackup) { - void *originEntrypoint = readAddr((char *) toMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod); + void *originEntrypoint = readAddr( + (char *) toMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod); // entry point hardcoded newEntrypoint = genTrampoline(toMethod, originEntrypoint); - } - else { + } else { // entry point from ArtMethod struct newEntrypoint = genTrampoline(toMethod, nullptr); } @@ -147,7 +154,8 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) { // 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); + void *interpEntrypoint = readAddr( + (char *) toMethod + OFFSET_entry_point_from_interpreter_in_ArtMethod); writeAddr(fromEntrypoint, interpEntrypoint); } @@ -165,7 +173,7 @@ static int doBackupAndHook(void *targetMethod, void *hookMethod, void *backupMet if (SDKVersion >= __ANDROID_API_N__) { setNonCompilable(targetMethod); // setNonCompilable(hookMethod); - if(backupMethod) setNonCompilable(backupMethod); + if (backupMethod) setNonCompilable(backupMethod); } if (backupMethod) {// do method backup @@ -201,8 +209,9 @@ void *getArtMethod(JNIEnv *env, jobject jmethod) { } extern "C" jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz, - jclass targetClass, jstring methodName, - jstring methodSig) { + jclass targetClass, + jstring methodName, + jstring methodSig) { const char *c_methodName = env->GetStringUTFChars(methodName, nullptr); const char *c_methodSig = env->GetStringUTFChars(methodSig, nullptr); jobject ret = nullptr; @@ -228,8 +237,8 @@ extern "C" jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, } extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz, - jobject target, jobject hook, - jobject backup) { + jobject target, jobject hook, + jobject backup) { if (!doBackupAndHook(getArtMethod(env, target), getArtMethod(env, hook), @@ -243,6 +252,6 @@ extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *e } } -void *getOriginalEntryPointFromTargetMethod(void* method) { +void *getOriginalEntryPointFromTargetMethod(void *method) { return replaced_entrypoint[method]; } \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/art_method.h b/edxp-core/src/main/cpp/main/include/art/runtime/art_method.h index 75cdbd23..3c3da32e 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/art_method.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/art_method.h @@ -26,40 +26,40 @@ namespace art { return PrettyMethod(thiz, true); } - CREATE_MEM_HOOK_STUB_ENTRIES( - LP_SELECT("_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj", "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"), - void *, GetOatQuickMethodHeader, - (void * thiz, uintptr_t pc), { - // This is a partial copy from AOSP. We only touch them if they are hooked. - if (UNLIKELY(edxp::isHooked(thiz))) { - uintptr_t original_ep = - reinterpret_cast(getOriginalEntryPointFromTargetMethod( - thiz)) & ~0x1; - if (original_ep) { - char *code_length_loc = - reinterpret_cast(original_ep) + - oat_header_code_length_offset; - uint32_t code_length = - *reinterpret_cast(code_length_loc) & - ~0x80000000u; - LOGD("art_method::GetOatQuickMethodHeader: ArtMethod=%p (%s), isHooked=true, original_ep=0x%zux, code_length=0x%x, pc=0x%zux", - thiz, PrettyMethod(thiz).c_str(), - original_ep, code_length, pc); - if (original_ep <= pc && - pc <= original_ep + code_length) - return reinterpret_cast( - original_ep - - oat_header_length); - // If PC is not in range, we mark it as not found. - LOGD("art_method::GetOatQuickMethodHeader: PC not found in current method."); - return nullptr; - } else { - LOGD("art_method::GetOatQuickMethodHeader: ArtMethod=%p (%s) isHooked but not backup, fallback to system", - thiz, PrettyMethod(thiz).c_str()); - } - } - return backup(thiz, pc); - }); +// CREATE_MEM_HOOK_STUB_ENTRIES( +// LP_SELECT("_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj", "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"), +// void *, GetOatQuickMethodHeader, +// (void * thiz, uintptr_t pc), { +// // This is a partial copy from AOSP. We only touch them if they are hooked. +// if (UNLIKELY(edxp::isHooked(thiz))) { +// uintptr_t original_ep = +// reinterpret_cast(getOriginalEntryPointFromTargetMethod( +// thiz)) & ~0x1; +// if (original_ep) { +// char *code_length_loc = +// reinterpret_cast(original_ep) + +// oat_header_code_length_offset; +// uint32_t code_length = +// *reinterpret_cast(code_length_loc) & +// ~0x80000000u; +// LOGD("art_method::GetOatQuickMethodHeader: ArtMethod=%p (%s), isHooked=true, original_ep=0x%zux, code_length=0x%x, pc=0x%zux", +// thiz, PrettyMethod(thiz).c_str(), +// original_ep, code_length, pc); +// if (original_ep <= pc && +// pc <= original_ep + code_length) +// return reinterpret_cast( +// original_ep - +// oat_header_length); +// // If PC is not in range, we mark it as not found. +// LOGD("art_method::GetOatQuickMethodHeader: PC not found in current method."); +// return nullptr; +// } else { +// LOGD("art_method::GetOatQuickMethodHeader: ArtMethod=%p (%s) isHooked but not backup, fallback to system", +// thiz, PrettyMethod(thiz).c_str()); +// } +// } +// return backup(thiz, pc); +// }); static void Setup(void *handle, HookFunType hook_func) { LOGD("art_method hook setup, handle=%p", handle); @@ -84,7 +84,8 @@ namespace art { oat_header_code_length_offset = -4; break; } - edxp::HookSyms(handle, hook_func, GetOatQuickMethodHeader); +// edxp::HookSyms(handle, hook_func, GetOatQuickMethodHeader); + RETRIEVE_MEM_FUNC_SYMBOL(PrettyMethod, "_ZN3art9ArtMethod12PrettyMethodEb"); } diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/instrumentation.h b/edxp-core/src/main/cpp/main/include/art/runtime/instrumentation.h new file mode 100644 index 00000000..4b7296de --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/art/runtime/instrumentation.h @@ -0,0 +1,30 @@ +// +// Created by loves on 1/27/2021. +// + +#ifndef EDXPOSED_INSTRUMENTATION_H +#define EDXPOSED_INSTRUMENTATION_H + +#include "base/object.h" + +namespace art { + namespace instrumentation { + + CREATE_MEM_HOOK_STUB_ENTRIES( + "_ZN3art15instrumentation15Instrumentation21UpdateMethodsCodeImplEPNS_9ArtMethodEPKv", + void, UpdateMethodsCode, (void * thiz, void * art_method, const void *quick_code), { + if (UNLIKELY(edxp::isHooked(art_method))) { + LOGD("Skip update method code for hooked method %s", + art_method::PrettyMethod(art_method).c_str()); + return; + } else { + backup(thiz, art_method, quick_code); + } + }); + + static void DisableUpdateHookedMethodsCode(void *handle, HookFunType hook_func) { + edxp::HookSym(handle, hook_func, UpdateMethodsCode); + } + } +} +#endif //EDXPOSED_INSTRUMENTATION_H diff --git a/edxp-core/src/main/cpp/main/src/config_manager.cpp b/edxp-core/src/main/cpp/main/src/config_manager.cpp index 9275f390..10119e98 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/config_manager.cpp @@ -123,6 +123,7 @@ namespace edxp { std::string ConfigManager::GetPackageNameFromBaseApkPath(const fs::path &path) { std::vector paths(path.begin(), path.end()); + if (paths.empty()) return {}; auto base_apk = paths.back(); // base.apk if (base_apk != "base.apk") return {}; paths.pop_back(); diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index 25020127..19cd0bc8 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -20,6 +20,7 @@ #include "art/runtime/oat_file_manager.h" #include "art/runtime/jit/jit_code_cache.h" #include "art/runtime/art_method.h" +#include "art/runtime/instrumentation.h" std::vector linker_get_solist(); // Dobby but not in .h @@ -83,7 +84,8 @@ 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::jit::HookJitCacheCode(art_handle, hook_func); +// art::jit::HookJitCacheCode(art_handle, hook_func); + art::instrumentation::DisableUpdateHookedMethodsCode(art_handle, hook_func); art_hooks_installed = true; LOGI("ART hooks installed");