From d22a4efe72d67ebf2a4853b588442dc253df6b7b Mon Sep 17 00:00:00 2001 From: LoveSy Date: Thu, 6 May 2021 14:09:02 +0800 Subject: [PATCH] [core] Only allow hidden api for recognized classloaders (#537) --- .../cpp/main/include/art/runtime/hidden_api.h | 92 ++++++++++++------- .../cpp/main/include/art/runtime/runtime.h | 12 ++- core/src/main/cpp/main/src/context.cpp | 2 +- core/src/main/cpp/main/src/context.h | 2 +- core/src/main/cpp/main/src/native_hook.cpp | 2 +- core/src/main/cpp/main/src/service.cpp | 1 - core/src/main/cpp/main/src/symbol_cache.cpp | 16 +++- core/src/main/cpp/main/src/symbol_cache.h | 3 + 8 files changed, 89 insertions(+), 41 deletions(-) diff --git a/core/src/main/cpp/main/include/art/runtime/hidden_api.h b/core/src/main/cpp/main/include/art/runtime/hidden_api.h index 696cc3b4..ab9a7007 100644 --- a/core/src/main/cpp/main/include/art/runtime/hidden_api.h +++ b/core/src/main/cpp/main/include/art/runtime/hidden_api.h @@ -20,56 +20,84 @@ #pragma once +#include "symbol_cache.h" #include "base/object.h" +#include "context.h" +#include "runtime.h" namespace art { namespace hidden_api { - enum Action { - kAllow, - kAllowButWarn, - kAllowButWarnAndToast, - kDeny + CREATE_FUNC_SYMBOL_ENTRY(void, DexFile_setTrusted, JNIEnv *env, jclass clazz, + jobject j_cookie) { + if (LIKELY(DexFile_setTrustedSym != nullptr)) { + Runtime::Current()->SetJavaDebuggable(true); + DexFile_setTrustedSym(env, clazz, j_cookie); + Runtime::Current()->SetJavaDebuggable(false); + } }; - CREATE_HOOK_STUB_ENTRIES( - "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_9ArtMethodEEENS0_6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE", - Action, GetMethodActionImpl, (), { - return Action::kAllow; - }); + inline void + maybeSetTrusted(JNIEnv *env, jclass clazz, jobject class_loader, jobject j_cookie) { + static auto get_parent = env->GetMethodID(env->FindClass("java/lang/ClassLoader"), + "getParent", "()Ljava/lang/ClassLoader;"); + for (auto current = lspd::Context::GetInstance()->GetCurrentClassLoader(); + class_loader != nullptr; + class_loader = env->CallObjectMethod(class_loader, get_parent)) { + if (!current || env->IsSameObject(class_loader, current)) { + DexFile_setTrusted(env, clazz, j_cookie); + LOGD("Set classloader as trusted"); + return; + } + } + } CREATE_HOOK_STUB_ENTRIES( - "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_8ArtFieldEEENS0_6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE", - Action, GetFieldActionImpl, (), { - return Action::kAllow; - }); + "_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray", + jobject, DexFile_openDexFileNative, (JNIEnv * env, + jclass clazz, + jstring javaSourceName, + jstring javaOutputName, + jint flags, + jobject class_loader, + jobjectArray dex_elements), { + auto j_cookie = backup(env, clazz, javaSourceName, javaOutputName, flags, + class_loader, + dex_elements); + maybeSetTrusted(env, clazz, class_loader, j_cookie); + return j_cookie; + } + ); CREATE_HOOK_STUB_ENTRIES( - "_ZN3art9hiddenapi6detail28ShouldDenyAccessToMemberImplINS_9ArtMethodEEEbPT_NS0_7ApiListENS0_12AccessMethodE", - bool, ShouldDenyAccessToMethodImpl, (), { - return false; - }); + "_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_", + jobject, DexFile_openInMemoryDexFilesNative, (JNIEnv * env, + jclass clazz, + jobjectArray buffers, + jobjectArray arrays, + jintArray jstarts, + jintArray jends, + jobject class_loader, + jobjectArray dex_elements), { + auto j_cookie = backup(env, clazz, buffers, arrays, jstarts, jends, + class_loader, + dex_elements); + maybeSetTrusted(env, clazz, class_loader, j_cookie); + return j_cookie; + } + ); - CREATE_HOOK_STUB_ENTRIES( - "_ZN3art9hiddenapi6detail28ShouldDenyAccessToMemberImplINS_8ArtFieldEEEbPT_NS0_7ApiListENS0_12AccessMethodE", - bool, ShouldDenyAccessToFieldImpl, (), { - return false; - }); - - // @ApiSensitive(Level.HIGH) static void DisableHiddenApi(void *handle) { + const int api_level = lspd::GetAndroidApiLevel(); if (api_level < __ANDROID_API_P__) { return; } - if (api_level == __ANDROID_API_P__) { - lspd::HookSyms(handle, GetMethodActionImpl); - lspd::HookSyms(handle, GetFieldActionImpl); - } else { - lspd::HookSyms(handle, ShouldDenyAccessToMethodImpl); - lspd::HookSyms(handle, ShouldDenyAccessToFieldImpl); - } + DexFile_setTrustedSym = reinterpret_cast(lspd::sym_setTrusted); + lspd::HookSymNoHandle(lspd::sym_openDexFileNative, DexFile_openDexFileNative); + lspd::HookSymNoHandle(lspd::sym_openInMemoryDexFilesNative, + DexFile_openInMemoryDexFilesNative); }; } diff --git a/core/src/main/cpp/main/include/art/runtime/runtime.h b/core/src/main/cpp/main/include/art/runtime/runtime.h index a9c34b0f..56596c8b 100644 --- a/core/src/main/cpp/main/include/art/runtime/runtime.h +++ b/core/src/main/cpp/main/include/art/runtime/runtime.h @@ -27,6 +27,11 @@ namespace art { class Runtime : public lspd::HookedObject { private: inline static Runtime *instance_; + CREATE_MEM_FUNC_SYMBOL_ENTRY(void, SetJavaDebuggable, void *thiz, bool value) { + if (LIKELY(SetJavaDebuggableSym)) { + SetJavaDebuggableSym(thiz, value); + } + } public: Runtime(void *thiz) : HookedObject(thiz) {} @@ -35,10 +40,15 @@ namespace art { return instance_; } + void SetJavaDebuggable(bool value) { + SetJavaDebuggable(thiz_, value); + } + // @ApiSensitive(Level.LOW) static void Setup(void *handle) { RETRIEVE_FIELD_SYMBOL(instance, "_ZN3art7Runtime9instance_E"); - void * thiz = *reinterpret_cast(instance); + RETRIEVE_MEM_FUNC_SYMBOL(SetJavaDebuggable, "_ZN3art7Runtime17SetJavaDebuggableEb"); + void *thiz = *reinterpret_cast(instance); LOGD("_ZN3art7Runtime9instance_E = %p", thiz); instance_ = new Runtime(thiz); } diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index fac3b428..11f3ae0a 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -220,8 +220,8 @@ namespace lspd { auto binder = skip_ ? ScopedLocalRef{env, nullptr} : Service::instance()->RequestBinder(env, nice_name_); if (binder) { - LoadDex(env); InstallInlineHooks(); + LoadDex(env); Init(env); LOGD("Done prepare"); FindAndCall(env, "forkAndSpecializePost", diff --git a/core/src/main/cpp/main/src/context.h b/core/src/main/cpp/main/src/context.h index 500fd8e1..d1de8f65 100644 --- a/core/src/main/cpp/main/src/context.h +++ b/core/src/main/cpp/main/src/context.h @@ -41,7 +41,7 @@ namespace lspd { return std::move(instance_); } - inline auto GetCurrentClassLoader() const { return inject_class_loader_; } + inline jobject GetCurrentClassLoader() const { return inject_class_loader_; } void CallOnPostFixupStaticTrampolines(void *class_ptr); diff --git a/core/src/main/cpp/main/src/native_hook.cpp b/core/src/main/cpp/main/src/native_hook.cpp index 74cbf88e..25ec1724 100644 --- a/core/src/main/cpp/main/src/native_hook.cpp +++ b/core/src/main/cpp/main/src/native_hook.cpp @@ -70,8 +70,8 @@ namespace lspd { if (art_hooks_installed) { return; } - art::hidden_api::DisableHiddenApi(art_handle); art::Runtime::Setup(art_handle); + art::hidden_api::DisableHiddenApi(art_handle); art::art_method::Setup(art_handle); art::Thread::Setup(art_handle); art::ClassLinker::Setup(art_handle); diff --git a/core/src/main/cpp/main/src/service.cpp b/core/src/main/cpp/main/src/service.cpp index d4c57355..dff63e0e 100644 --- a/core/src/main/cpp/main/src/service.cpp +++ b/core/src/main/cpp/main/src/service.cpp @@ -34,7 +34,6 @@ namespace lspd { Service::exec_transact_replace(jboolean *res, JNIEnv *env, [[maybe_unused]] jobject obj, va_list args) { jint code; - va_list copy; va_copy(copy, args); code = va_arg(copy, jint); diff --git a/core/src/main/cpp/main/src/symbol_cache.cpp b/core/src/main/cpp/main/src/symbol_cache.cpp index e940228a..e19df115 100644 --- a/core/src/main/cpp/main/src/symbol_cache.cpp +++ b/core/src/main/cpp/main/src/symbol_cache.cpp @@ -36,6 +36,9 @@ namespace lspd { void *sym_system_property_get = nullptr; void *sym_get_property = nullptr; void *handle_libart = nullptr; + void *sym_openInMemoryDexFilesNative = nullptr; + void *sym_openDexFileNative = nullptr; + void *sym_setTrusted = nullptr; struct soinfo; @@ -117,10 +120,15 @@ namespace lspd { for (const auto &soinfo : linker_get_solist()) { if (const auto &real_path = soinfo->get_realpath(), &soname = soinfo->get_soname(); (real_path && - std::string_view(real_path).find(kLibArtName) != std::string_view::npos) || - (soname && - std::string_view(soname).find(kLibArtName) != std::string_view::npos)) { - return soinfo->to_handle(); + std::string_view(real_path).find(kLibArtName) != std::string_view::npos)) { + auto art = SandHook::ElfImg(real_path); + if ((sym_openDexFileNative = reinterpret_cast(art.getSymbAddress( + "_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray"))) && + (sym_openInMemoryDexFilesNative = reinterpret_cast(art.getSymbAddress( + "_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_"))) && + (sym_setTrusted = reinterpret_cast(art.getSymbAddress( + "_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject")))) + return soinfo->to_handle(); } } return nullptr; diff --git a/core/src/main/cpp/main/src/symbol_cache.h b/core/src/main/cpp/main/src/symbol_cache.h index 8e70cbd2..0ad5c0e7 100644 --- a/core/src/main/cpp/main/src/symbol_cache.h +++ b/core/src/main/cpp/main/src/symbol_cache.h @@ -31,6 +31,9 @@ namespace lspd { extern void *sym_system_property_get; extern void *sym_get_property; extern void *handle_libart; + extern void *sym_openInMemoryDexFilesNative; + extern void *sym_openDexFileNative; + extern void *sym_setTrusted; void InitSymbolCache(); }