[core] Only allow hidden api for recognized classloaders (#537)

This commit is contained in:
LoveSy 2021-05-06 14:09:02 +08:00 committed by GitHub
parent 94ef17f06d
commit d22a4efe72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 41 deletions

View File

@ -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<decltype(DexFile_setTrustedSym)>(lspd::sym_setTrusted);
lspd::HookSymNoHandle(lspd::sym_openDexFileNative, DexFile_openDexFileNative);
lspd::HookSymNoHandle(lspd::sym_openInMemoryDexFilesNative,
DexFile_openInMemoryDexFilesNative);
};
}

View File

@ -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<void**>(instance);
RETRIEVE_MEM_FUNC_SYMBOL(SetJavaDebuggable, "_ZN3art7Runtime17SetJavaDebuggableEb");
void *thiz = *reinterpret_cast<void **>(instance);
LOGD("_ZN3art7Runtime9instance_E = %p", thiz);
instance_ = new Runtime(thiz);
}

View File

@ -220,8 +220,8 @@ namespace lspd {
auto binder = skip_ ? ScopedLocalRef<jobject>{env, nullptr}
: Service::instance()->RequestBinder(env, nice_name_);
if (binder) {
LoadDex(env);
InstallInlineHooks();
LoadDex(env);
Init(env);
LOGD("Done prepare");
FindAndCall(env, "forkAndSpecializePost",

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,9 +120,14 @@ 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)) {
std::string_view(real_path).find(kLibArtName) != std::string_view::npos)) {
auto art = SandHook::ElfImg(real_path);
if ((sym_openDexFileNative = reinterpret_cast<void *>(art.getSymbAddress(
"_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray"))) &&
(sym_openInMemoryDexFilesNative = reinterpret_cast<void *>(art.getSymbAddress(
"_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_"))) &&
(sym_setTrusted = reinterpret_cast<void *>(art.getSymbAddress(
"_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject"))))
return soinfo->to_handle();
}
}

View File

@ -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();
}