diff --git a/appveyor.yml b/appveyor.yml index 4650fc73..9046bba7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '0.5.1.1_{build}-{branch}' +version: '0.5.1.2_{build}-{branch}' environment: ANDROID_HOME: C:\android-sdk-windows diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index c0139995..2cf7dc64 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -14,7 +14,7 @@ static def calcSha256(file) { } // Values set here will be overriden by AppVeyor, feel free to modify during development. -def buildVersionName = 'v0.5.1.1' +def buildVersionName = 'v0.5.1.2' def buildVersionCode = 233 if (System.env.APPVEYOR_BUILD_VERSION != null) { diff --git a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h index 178449fe..f61ced19 100644 --- a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h +++ b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h @@ -30,5 +30,8 @@ void *getArtMethod(JNIEnv *env, jobject jmethod); // TODO: move to common utils instead of in YAHFA's code void *getEntryPoint(void* method); +// get original entrypoint from target ArtMethod +void *getOriginalEntryPointFromTargetMethod(void* method); + #endif // HOOK_MAIN_H \ No newline at end of file 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 2d2c5f0c..0a1c270f 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp +++ b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.cpp @@ -17,7 +17,7 @@ static uint32_t OFFSET_access_flags_in_ArtMethod; static uint32_t kAccCompileDontBother = 0x01000000; static jfieldID fieldArtMethod = nullptr; -//static std::unordered_map replaced_entrypoint; +static std::unordered_map replaced_entrypoint; static inline uint32_t read32(void *addr) { return *((uint32_t *) addr); @@ -136,7 +136,7 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) { } void* fromEntrypoint = (char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod; - //replaced_entrypoint[fromEntrypoint] = newEntrypoint; + replaced_entrypoint[fromMethod] = newEntrypoint; LOGI("replace entry point from %p to %p", readAddr(fromEntrypoint), @@ -248,3 +248,7 @@ extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *e return JNI_FALSE; } } + +void *getOriginalEntryPointFromTargetMethod(void* method) { + return replaced_entrypoint[method]; +} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/yahfa/src/trampoline.c b/edxp-core/src/main/cpp/external/yahfa/src/trampoline.c index 1892d672..9648c788 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/trampoline.c +++ b/edxp-core/src/main/cpp/external/yahfa/src/trampoline.c @@ -131,25 +131,7 @@ void *genTrampoline(void *toMethod, void *entrypoint) { size_t size = entrypoint == NULL ? sizeof(trampoline) : sizeof(trampolineForBackup); // TODO: make use of thread_local to avoid frequent memory allocate - size_t oatHeaderLen; - switch (SDKVersion) { - case __ANDROID_API_O__: - case __ANDROID_API_O_MR1__: - case __ANDROID_API_P__: - oatHeaderLen = 12 + 12; // 3*u32 + QuickMethodFrameInfo(3*u32) - break; - default: - LOGW("No valid offset in SDK %d for oatHeaderLen, using Android R", SDKVersion); - case __ANDROID_API_Q__: - case __ANDROID_API_R__: - oatHeaderLen = 8; // 2*u32 - break; - } - char *targetAddr = doInitHookCap(size + oatHeaderLen); - // 4 bytes for AOT header, then copy code_size_. - memcpy(targetAddr, toMethod - oatHeaderLen, oatHeaderLen); - targetAddr += oatHeaderLen; - + char *targetAddr = doInitHookCap(size); if (targetAddr == NULL) return NULL; if (entrypoint != NULL) { 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 new file mode 100644 index 00000000..da39bb60 --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/art/runtime/art_method.h @@ -0,0 +1,60 @@ +// +// Created by εŒθ‰ι…Έι…― on 12/19/20. +// + +#ifndef EDXPOSED_ART_METHOD_H +#define EDXPOSED_ART_METHOD_H + +#include "jni/edxp_pending_hooks.h" +#include + +namespace art { + + class ArtMethod : public edxp::HookedObject { + + private: + inline static size_t oat_header_length; + inline static int32_t oat_header_code_length_offset; + CREATE_HOOK_STUB_ENTRIES(void *, GetOatQuickMethodHeader, void *thiz, uintptr_t pc) { + LOGD("GetOatQuickMethodHeader called"); + // This is a partial copy from AOSP. We only touch them if they are hooked. + if (LIKELY(edxp::isHooked(thiz))) { + LOGD("GetOatQuickMethodHeader: isHooked=true, thiz=%p", thiz); + char* thiz_ = static_cast(thiz); + char* code_length_loc = thiz_ + oat_header_code_length_offset; + uint32_t code_length = *reinterpret_cast(code_length_loc); + uintptr_t original_ep = reinterpret_cast( + getOriginalEntryPointFromTargetMethod(thiz)); + if (original_ep <= pc <= original_ep + code_length) return thiz_ - oat_header_length; + // If PC is not in range, we mark it as not found. + LOGD("GetOatQuickMethodHeader: PC not found in current method."); + return nullptr; + } + return GetOatQuickMethodHeaderBackup(thiz, pc); + } + + public: + // @ApiSensitive(Level.MIDDLE) + static void Setup(void *handle, HookFunType hook_func) { + LOGD("Classlinker hook setup, handle=%p", handle); + int api_level = edxp::GetAndroidApiLevel(); + switch (api_level) { + case __ANDROID_API_O__: + case __ANDROID_API_O_MR1__: + case __ANDROID_API_P__: + oat_header_length = 24; + oat_header_code_length_offset = -4; + break; + default: + LOGW("No valid offset in SDK %d for oatHeaderLen, using offset from Android R", api_level); + case __ANDROID_API_Q__: + case __ANDROID_API_R__: + oat_header_length = 8; + oat_header_code_length_offset = -4; + break; + } + HOOK_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj"); + } + }; +} +#endif //EDXPOSED_ART_METHOD_H diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h index 915d5ea2..39ea2a96 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h @@ -71,7 +71,6 @@ namespace art { // @ApiSensitive(Level.MIDDLE) static void Setup(void *handle, HookFunType hook_func) { LOGD("Classlinker hook setup, handle=%p", handle); - // TODO: Maybe not compatible with Android 10- int api_level = edxp::GetAndroidApiLevel(); size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA switch (api_level) { 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 f73e3144..9c42a3cb 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -13,6 +13,7 @@ #include "native_hook.h" #include "riru_hook.h" #include "art/runtime/mirror/class.h" +#include "art/runtime/art_method.h" #include "art/runtime/class_linker.h" #include "art/runtime/gc/heap.h" #include "art/runtime/hidden_api.h" @@ -75,6 +76,7 @@ namespace edxp { art::hidden_api::DisableHiddenApi(art_handle, hook_func); art::Runtime::Setup(art_handle, hook_func); art::gc::Heap::Setup(art_handle, hook_func); + art::ArtMethod::Setup(art_handle, hook_func); art::ClassLinker::Setup(art_handle, hook_func); art::mirror::Class::Setup(art_handle, hook_func); art::JNIEnvExt::Setup(art_handle, hook_func);