From 285ced4cf95f42e76d870a1bf123e02be72c762c Mon Sep 17 00:00:00 2001 From: solohsu Date: Sat, 9 Feb 2019 17:03:25 +0800 Subject: [PATCH] Fix IllegalAccessException via inline hooking method "IsInSamePackage" in libart.so, using Whale framework --- Core/jni/main/include/android_build.h | 30 ++++++++++ Core/jni/main/java_hook/java_hook.cpp | 2 + Core/jni/main/native_hook/native_hook.cpp | 72 ++++++++++++++++++----- Core/jni/main/native_hook/native_hook.h | 10 ++++ 4 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 Core/jni/main/include/android_build.h diff --git a/Core/jni/main/include/android_build.h b/Core/jni/main/include/android_build.h new file mode 100644 index 00000000..5d20d6ae --- /dev/null +++ b/Core/jni/main/include/android_build.h @@ -0,0 +1,30 @@ +#ifndef WHALE_ANDROID_ANDROID_BUILD_H_ +#define WHALE_ANDROID_ANDROID_BUILD_H_ + +#include +#include +#include + +#define ANDROID_ICE_CREAM_SANDWICH 14 +#define ANDROID_ICE_CREAM_SANDWICH_MR1 15 +#define ANDROID_JELLY_BEAN 16 +#define ANDROID_JELLY_BEAN_MR1 17 +#define ANDROID_JELLY_BEAN_MR2 18 +#define ANDROID_KITKAT 19 +#define ANDROID_KITKAT_WATCH 20 +#define ANDROID_LOLLIPOP 21 +#define ANDROID_LOLLIPOP_MR1 22 +#define ANDROID_M 23 +#define ANDROID_N 24 +#define ANDROID_N_MR1 25 +#define ANDROID_O 26 +#define ANDROID_O_MR1 27 +#define ANDROID_P 28 + +static inline int32_t GetAndroidApiLevel() { + char prop_value[PROP_VALUE_MAX]; + __system_property_get("ro.build.version.sdk", prop_value); + return atoi(prop_value); +} + +#endif // WHALE_ANDROID_ANDROID_BUILD_H_ diff --git a/Core/jni/main/java_hook/java_hook.cpp b/Core/jni/main/java_hook/java_hook.cpp index a5e231fa..15ba92bf 100644 --- a/Core/jni/main/java_hook/java_hook.cpp +++ b/Core/jni/main/java_hook/java_hook.cpp @@ -7,6 +7,7 @@ #include #include "java_hook/java_hook.h" #include "include/logging.h" +#include "native_hook/native_hook.h" extern "C" { @@ -44,6 +45,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) { if (isInited) { return; } + install_inline_hooks(); jclass clzClassLoader = env->FindClass("java/lang/ClassLoader"); LOGD("java/lang/ClassLoader: %p", clzClassLoader); jmethodID mdgetSystemClassLoader = env->GetStaticMethodID(clzClassLoader, diff --git a/Core/jni/main/native_hook/native_hook.cpp b/Core/jni/main/native_hook/native_hook.cpp index 6e1534aa..db621a3d 100644 --- a/Core/jni/main/native_hook/native_hook.cpp +++ b/Core/jni/main/native_hook/native_hook.cpp @@ -1,20 +1,62 @@ -#include -#include -#include -#include -#include -#include -#include -#include + #include -#include +#include #include -#include -#include - -#include "include/riru.h" #include "include/logging.h" #include "native_hook.h" -#include "java_hook/java_hook.h" -#include "inject/framework_hook.h" \ No newline at end of file + +static const char *(*getDesc)(void *, std::string *); + +static bool (*isInSamePackageBackup)(void *, void *) = nullptr; + +bool onIsInSamePackageCalled(void *thiz, void *that) { + std::string storage1, storage2; + const char *thisDesc = (*getDesc)(thiz, &storage1); + const char *thatDesc = (*getDesc)(that, &storage2); +// LOGE("onIsInSamePackageCalled, %s -> %s", thisDesc, thatDesc); + if (strstr(thisDesc, "EdHooker") != nullptr || strstr(thatDesc, "EdHooker") != nullptr) { + return true; + } + return (*isInSamePackageBackup)(thiz, that); +} + +void install_inline_hooks() { + int api_level = GetAndroidApiLevel(); + if (api_level < ANDROID_LOLLIPOP) { + return; + } + void *whaleHandle = dlopen(kLibWhalePath, RTLD_NOW); + if (!whaleHandle) { + LOGE("can't open libwhale"); + return; + } + void *hookFunSym = dlsym(whaleHandle, "WInlineHookFunction"); + if (!hookFunSym) { + LOGE("can't get WInlineHookFunction"); + return; + } + void (*hookFun)(void *, void *, void **) = reinterpret_cast(hookFunSym); + void *artHandle = dlopen(kLibArtPath, RTLD_NOW); + if (!artHandle) { + LOGE("can't open libart"); + return; + } + // 5.0 - 7.1 + const char *isInSamePackageSym = "_ZN3art6mirror5Class15IsInSamePackageEPS1_"; + const char *getDescriptorSym = "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE"; + if (api_level >= ANDROID_O) { + // 8.0 and later + isInSamePackageSym = "_ZN3art6mirror5Class15IsInSamePackageENS_6ObjPtrIS1_EE"; + } + void *original = dlsym(artHandle, isInSamePackageSym); + getDesc = reinterpret_cast(dlsym(artHandle, + getDescriptorSym)); + if (!original) { + LOGE("can't get isInSamePackageSym"); + return; + } + (*hookFun)(original, reinterpret_cast(onIsInSamePackageCalled), + reinterpret_cast(&isInSamePackageBackup)); +} \ No newline at end of file diff --git a/Core/jni/main/native_hook/native_hook.h b/Core/jni/main/native_hook/native_hook.h index ecb90cce..fab2f98b 100644 --- a/Core/jni/main/native_hook/native_hook.h +++ b/Core/jni/main/native_hook/native_hook.h @@ -3,6 +3,14 @@ #include +#if defined(__LP64__) +static constexpr const char *kLibArtPath = "/system/lib64/libart.so"; +static constexpr const char *kLibWhalePath = "/system/lib64/libwhale.so"; +#else +static constexpr const char *kLibArtPath = "/system/lib/libart.so"; +static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so"; +#endif + #define XHOOK_REGISTER(NAME) \ if (xhook_register(".*", #NAME, (void*) new_##NAME, (void **) &old_##NAME) != 0) \ LOGE("failed to register hook " #NAME "."); \ @@ -11,4 +19,6 @@ static ret (*old_##func)(__VA_ARGS__); \ static ret new_##func(__VA_ARGS__) +void install_inline_hooks(); + #endif // HOOK_H