Opt mem fun & fix hook mem fun

This commit is contained in:
LoveSy 2021-01-08 17:20:07 +08:00 committed by 双草酸酯
parent f78355a189
commit 981094e06f
9 changed files with 93 additions and 78 deletions

View File

@ -14,11 +14,11 @@ namespace art {
inline static size_t oat_header_length; inline static size_t oat_header_length;
inline static int32_t oat_header_code_length_offset; inline static int32_t oat_header_code_length_offset;
CREATE_FUNC_SYMBOL_ENTRY(std::string, PrettyMethod, void *thiz, bool with_signature) { CREATE_MEM_FUNC_SYMBOL_ENTRY(std::string, PrettyMethod, void *thiz, bool with_signature) {
if (UNLIKELY(thiz == nullptr)) if (UNLIKELY(thiz == nullptr))
return "null"; return "null";
if (LIKELY(PrettyMethodSym)) if (LIKELY(PrettyMethodSym))
return edxp::call_as_member_func(PrettyMethodSym, thiz, with_signature); return PrettyMethodSym(thiz, with_signature);
else return "null sym"; else return "null sym";
} }
@ -26,7 +26,7 @@ namespace art {
return PrettyMethod(thiz, true); return PrettyMethod(thiz, true);
} }
CREATE_HOOK_STUB_ENTRIES(void *, GetOatQuickMethodHeader, void *thiz, uintptr_t pc) { CREATE_MEM_HOOK_STUB_ENTRIES(void *, GetOatQuickMethodHeader, void *thiz, uintptr_t pc) {
// This is a partial copy from AOSP. We only touch them if they are hooked. // This is a partial copy from AOSP. We only touch them if they are hooked.
if (UNLIKELY(edxp::isHooked(thiz))) { if (UNLIKELY(edxp::isHooked(thiz))) {
uintptr_t original_ep = reinterpret_cast<uintptr_t>(getOriginalEntryPointFromTargetMethod( uintptr_t original_ep = reinterpret_cast<uintptr_t>(getOriginalEntryPointFromTargetMethod(
@ -75,12 +75,12 @@ namespace art {
break; break;
} }
if constexpr (edxp::is64) { if constexpr (edxp::is64) {
HOOK_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"); HOOK_MEM_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm");
} else { } else {
HOOK_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj"); HOOK_MEM_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj");
} }
RETRIEVE_FUNC_SYMBOL(PrettyMethod, "_ZN3art9ArtMethod12PrettyMethodEb"); RETRIEVE_MEM_FUNC_SYMBOL(PrettyMethod, "_ZN3art9ArtMethod12PrettyMethodEb");
} }
} }
} }

View File

@ -20,21 +20,12 @@ namespace art {
private: private:
inline static ClassLinker *instance_; inline static ClassLinker *instance_;
CREATE_FUNC_SYMBOL_ENTRY(void, SetEntryPointsToInterpreter, void *thiz, void *art_method) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, SetEntryPointsToInterpreter, void *thiz, void *art_method) {
if (LIKELY(SetEntryPointsToInterpreterSym)) if (LIKELY(SetEntryPointsToInterpreterSym))
edxp::call_as_member_func(SetEntryPointsToInterpreterSym, thiz, art_method); SetEntryPointsToInterpreterSym(thiz, art_method);
} }
CREATE_HOOK_STUB_ENTRIES(void *, Constructor, void *thiz, void *intern_table) { CREATE_MEM_HOOK_STUB_ENTRIES(void, FixupStaticTrampolines, void *thiz, void *clazz_ptr) {
LOGI("ConstructorReplace called");
if (LIKELY(instance_))
instance_->Reset(thiz);
else
instance_ = new ClassLinker(thiz);
return ConstructorBackup(thiz, intern_table);
}
CREATE_HOOK_STUB_ENTRIES(void, FixupStaticTrampolines, void *thiz, void *clazz_ptr) {
FixupStaticTrampolinesBackup(thiz, clazz_ptr); FixupStaticTrampolinesBackup(thiz, clazz_ptr);
art::mirror::Class mirror_class(clazz_ptr); art::mirror::Class mirror_class(clazz_ptr);
auto class_def = mirror_class.GetClassDef(); auto class_def = mirror_class.GetClassDef();
@ -46,10 +37,10 @@ namespace art {
} }
} }
CREATE_FUNC_SYMBOL_ENTRY(void, MakeInitializedClassesVisiblyInitialized, void *thiz, CREATE_MEM_FUNC_SYMBOL_ENTRY(void, MakeInitializedClassesVisiblyInitialized, void *thiz,
void *self, bool wait) { void *self, bool wait) {
if (LIKELY(MakeInitializedClassesVisiblyInitializedSym)) if (LIKELY(MakeInitializedClassesVisiblyInitializedSym))
edxp::call_as_member_func(MakeInitializedClassesVisiblyInitializedSym, thiz, self, wait); MakeInitializedClassesVisiblyInitializedSym(thiz, self, wait);
} }
@ -115,12 +106,10 @@ namespace art {
LOGD("Classlinker object: %p", thiz); LOGD("Classlinker object: %p", thiz);
instance_ = new ClassLinker(thiz); instance_ = new ClassLinker(thiz);
HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE", RETRIEVE_MEM_FUNC_SYMBOL(SetEntryPointsToInterpreter,
"_ZN3art11ClassLinkerC2EPNS_11InternTableEb"); // 10.0
RETRIEVE_FUNC_SYMBOL(SetEntryPointsToInterpreter,
"_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"); "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE");
HOOK_FUNC(FixupStaticTrampolines, HOOK_MEM_FUNC(FixupStaticTrampolines,
"_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"); "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE");
HOOK_FUNC(ShouldUseInterpreterEntrypoint, HOOK_FUNC(ShouldUseInterpreterEntrypoint,

View File

@ -16,10 +16,10 @@ namespace art {
private: private:
inline static Heap *instance_; inline static Heap *instance_;
CREATE_FUNC_SYMBOL_ENTRY(collector::GcType, WaitForGcToComplete, CREATE_MEM_FUNC_SYMBOL_ENTRY(collector::GcType, WaitForGcToComplete,
void *thiz, GcCause cause, void *threadSelf) { void *thiz, GcCause cause, void *threadSelf) {
if (LIKELY(WaitForGcToCompleteSym)) if (LIKELY(WaitForGcToCompleteSym))
return edxp::call_as_member_func(WaitForGcToCompleteSym, thiz, cause, threadSelf); return WaitForGcToCompleteSym(thiz, cause, threadSelf);
return art::gc::collector::GcType::kGcTypeNone; return art::gc::collector::GcType::kGcTypeNone;
} }
@ -83,7 +83,7 @@ namespace art {
reinterpret_cast<size_t>(Runtime::Current()->Get()) + OFFSET_heap); reinterpret_cast<size_t>(Runtime::Current()->Get()) + OFFSET_heap);
LOGD("art::runtime::Heap object: %p", thiz); LOGD("art::runtime::Heap object: %p", thiz);
instance_ = new Heap(thiz); instance_ = new Heap(thiz);
RETRIEVE_FUNC_SYMBOL(WaitForGcToComplete, RETRIEVE_MEM_FUNC_SYMBOL(WaitForGcToComplete,
"_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE"); "_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE");
} }

View File

@ -7,7 +7,7 @@ namespace art {
namespace jit { namespace jit {
CREATE_HOOK_STUB_ENTRIES(const void*, GetSavedEntryPointOfPreCompiledMethod, void *thiz, CREATE_MEM_HOOK_STUB_ENTRIES(const void*, GetSavedEntryPointOfPreCompiledMethod, void *thiz,
void *art_method) { void *art_method) {
if (UNLIKELY(edxp::isHooked(art_method))) { if (UNLIKELY(edxp::isHooked(art_method))) {
LOGD("Found hooked method %p (%s), return entrypoint as jit entrypoint", art_method, LOGD("Found hooked method %p (%s), return entrypoint as jit entrypoint", art_method,
@ -24,7 +24,7 @@ namespace art {
// our hooked entry point won't be overwritten. // our hooked entry point won't be overwritten.
// This is for SandHook and YAHFA // This is for SandHook and YAHFA
if (api_level >= __ANDROID_API_R__) { if (api_level >= __ANDROID_API_R__) {
HOOK_FUNC(GetSavedEntryPointOfPreCompiledMethod, HOOK_MEM_FUNC(GetSavedEntryPointOfPreCompiledMethod,
"_ZN3art3jit12JitCodeCache37GetSavedEntryPointOfPreCompiledMethodEPNS_9ArtMethodE"); "_ZN3art3jit12JitCodeCache37GetSavedEntryPointOfPreCompiledMethodEPNS_9ArtMethodE");
} }
} }

View File

@ -9,12 +9,12 @@ namespace art {
class JNIEnvExt : edxp::HookedObject { class JNIEnvExt : edxp::HookedObject {
private: private:
CREATE_FUNC_SYMBOL_ENTRY(jobject, NewLocalRef, void *thiz, void *mirror_ptr) { CREATE_MEM_FUNC_SYMBOL_ENTRY(jobject, NewLocalRef, void *thiz, void *mirror_ptr) {
return edxp::call_as_member_func(NewLocalRefSym, thiz, mirror_ptr); return NewLocalRefSym(thiz, mirror_ptr);
} }
CREATE_FUNC_SYMBOL_ENTRY(void, DeleteLocalRef, void *thiz, jobject obj) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, DeleteLocalRef, void *thiz, jobject obj) {
return edxp::call_as_member_func(DeleteLocalRefSym, thiz, obj); return DeleteLocalRefSym(thiz, obj);
} }
public: public:
@ -22,8 +22,8 @@ namespace art {
// @ApiSensitive(Level.MIDDLE) // @ApiSensitive(Level.MIDDLE)
static void Setup(void *handle, HookFunType hook_func) { static void Setup(void *handle, HookFunType hook_func) {
RETRIEVE_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE"); RETRIEVE_MEM_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE");
RETRIEVE_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject"); RETRIEVE_MEM_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject");
} }
jobject NewLocalRefer(void *mirror_ptr) { jobject NewLocalRefer(void *mirror_ptr) {

View File

@ -14,15 +14,15 @@ namespace art {
private: private:
CREATE_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, void *thiz, CREATE_MEM_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, void *thiz,
std::string *storage) { std::string *storage) {
if (GetDescriptorSym) if (GetDescriptorSym)
return edxp::call_as_member_func(GetDescriptorSym, thiz, storage); return GetDescriptorSym(thiz, storage);
else else
return ""; return "";
} }
CREATE_HOOK_STUB_ENTRIES(bool, IsInSamePackage, void *thiz, void *that) { CREATE_MEM_HOOK_STUB_ENTRIES(bool, IsInSamePackage, void *thiz, void *that) {
std::string storage1, storage2; std::string storage1, storage2;
const char *thisDesc = GetDescriptor(thiz, &storage1); const char *thisDesc = GetDescriptor(thiz, &storage1);
const char *thatDesc = GetDescriptor(that, &storage2); const char *thatDesc = GetDescriptor(that, &storage2);
@ -43,9 +43,9 @@ namespace art {
return IsInSamePackageBackup(thiz, that); return IsInSamePackageBackup(thiz, that);
} }
CREATE_FUNC_SYMBOL_ENTRY(void*, GetClassDef, void* thiz) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void*, GetClassDef, void* thiz) {
if (LIKELY(GetClassDefSym)) if (LIKELY(GetClassDefSym))
return edxp::call_as_member_func(GetClassDefSym, thiz); return GetClassDefSym(thiz);
return nullptr; return nullptr;
} }
@ -54,15 +54,15 @@ namespace art {
// @ApiSensitive(Level.MIDDLE) // @ApiSensitive(Level.MIDDLE)
static void Setup(void *handle, HookFunType hook_func) { static void Setup(void *handle, HookFunType hook_func) {
RETRIEVE_FUNC_SYMBOL(GetDescriptor, "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112" RETRIEVE_MEM_FUNC_SYMBOL(GetDescriptor, "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112"
"basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE"); "basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE");
RETRIEVE_FUNC_SYMBOL(GetClassDef, "_ZN3art6mirror5Class11GetClassDefEv"); RETRIEVE_MEM_FUNC_SYMBOL(GetClassDef, "_ZN3art6mirror5Class11GetClassDefEv");
// RETRIEVE_FIELD_SYMBOL(mutator_lock_, "_ZN3art5Locks13mutator_lock_E"); // RETRIEVE_FIELD_SYMBOL(mutator_lock_, "_ZN3art5Locks13mutator_lock_E");
// LOGE("mutator_lock_: %p", mutator_lock_); // LOGE("mutator_lock_: %p", mutator_lock_);
HOOK_FUNC(IsInSamePackage, HOOK_MEM_FUNC(IsInSamePackage,
"_ZN3art6mirror5Class15IsInSamePackageENS_6ObjPtrIS1_EE", //8.0- "_ZN3art6mirror5Class15IsInSamePackageENS_6ObjPtrIS1_EE", //8.0-
"_ZN3art6mirror5Class15IsInSamePackageEPS1_"); //5.0-7.1 "_ZN3art6mirror5Class15IsInSamePackageEPS1_"); //5.0-7.1

View File

@ -11,9 +11,9 @@ namespace art {
private: private:
inline static Runtime *instance_; inline static Runtime *instance_;
CREATE_FUNC_SYMBOL_ENTRY(void, DeoptimizeBootImage, void *thiz) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, DeoptimizeBootImage, void *thiz) {
if (LIKELY(DeoptimizeBootImageSym)) if (LIKELY(DeoptimizeBootImageSym))
edxp::call_as_member_func(DeoptimizeBootImageSym, thiz); DeoptimizeBootImageSym(thiz);
} }
public: public:
@ -25,7 +25,7 @@ namespace art {
// @ApiSensitive(Level.LOW) // @ApiSensitive(Level.LOW)
static void Setup(void *handle, HookFunType hook_func) { static void Setup(void *handle, HookFunType hook_func) {
RETRIEVE_FUNC_SYMBOL(DeoptimizeBootImage, RETRIEVE_MEM_FUNC_SYMBOL(DeoptimizeBootImage,
"_ZN3art7Runtime19DeoptimizeBootImageEv"); "_ZN3art7Runtime19DeoptimizeBootImageEv");
RETRIEVE_FIELD_SYMBOL(instance, "_ZN3art7Runtime9instance_E"); RETRIEVE_FIELD_SYMBOL(instance, "_ZN3art7Runtime9instance_E");
void * thiz = *reinterpret_cast<void**>(instance); void * thiz = *reinterpret_cast<void**>(instance);

View File

@ -7,9 +7,9 @@ namespace art {
class Thread : public edxp::HookedObject { class Thread : public edxp::HookedObject {
CREATE_FUNC_SYMBOL_ENTRY(edxp::ObjPtr, DecodeJObject, void *thiz, jobject obj) { CREATE_MEM_FUNC_SYMBOL_ENTRY(edxp::ObjPtr, DecodeJObject, void *thiz, jobject obj) {
if (DecodeJObjectSym) if (DecodeJObjectSym)
return edxp::call_as_member_func(DecodeJObjectSym, thiz, obj); return DecodeJObjectSym(thiz, obj);
else else
return {.data=nullptr}; return {.data=nullptr};
} }
@ -27,7 +27,7 @@ namespace art {
} }
static void Setup(void *handle, [[maybe_unused]] HookFunType hook_func) { static void Setup(void *handle, [[maybe_unused]] HookFunType hook_func) {
RETRIEVE_FUNC_SYMBOL(DecodeJObject, RETRIEVE_MEM_FUNC_SYMBOL(DecodeJObject,
"_ZNK3art6Thread13DecodeJObjectEP8_jobject"); "_ZNK3art6Thread13DecodeJObjectEP8_jobject");
RETRIEVE_FUNC_SYMBOL(CurrentFromGdb, RETRIEVE_FUNC_SYMBOL(CurrentFromGdb,
"_ZN3art6Thread14CurrentFromGdbEv"); "_ZN3art6Thread14CurrentFromGdbEv");

View File

@ -28,6 +28,17 @@ typedef void (*HookFunType)(void *, void *, void **);
inline static ret (*func##Backup)(__VA_ARGS__); \ inline static ret (*func##Backup)(__VA_ARGS__); \
static ret func##Replace(__VA_ARGS__) static ret func##Replace(__VA_ARGS__)
#define HOOK_MEM_FUNC(func, ...) \
edxp::HookSyms(handle, hook_func, \
reinterpret_cast<void *>(func##Replace), \
reinterpret_cast<void **>(&func##BackupSym), \
__VA_ARGS__), func##Backup = func##BackupSym
#define CREATE_MEM_HOOK_STUB_ENTRIES(ret, func, thiz, ...) \
inline static edxp::MemberFunction<ret(__VA_ARGS__)> func##Backup; \
inline static ret (*func##BackupSym)(thiz, ## __VA_ARGS__); \
static ret func##Replace(thiz, ## __VA_ARGS__)
#define CREATE_ORIGINAL_ENTRY(ret, func, ...) \ #define CREATE_ORIGINAL_ENTRY(ret, func, ...) \
static ret func(__VA_ARGS__) static ret func(__VA_ARGS__)
@ -35,6 +46,10 @@ typedef void (*HookFunType)(void *, void *, void **);
name##Sym = reinterpret_cast<name##Type>( \ name##Sym = reinterpret_cast<name##Type>( \
edxp::Dlsym(handle, __VA_ARGS__)) edxp::Dlsym(handle, __VA_ARGS__))
#define RETRIEVE_MEM_FUNC_SYMBOL(name, ...) \
name##Sym = reinterpret_cast<name##Type::FunType>( \
edxp::Dlsym(handle, __VA_ARGS__))
#define RETRIEVE_FIELD_SYMBOL(name, ...) \ #define RETRIEVE_FIELD_SYMBOL(name, ...) \
void *name = edxp::Dlsym(handle, __VA_ARGS__) void *name = edxp::Dlsym(handle, __VA_ARGS__)
@ -43,6 +58,11 @@ typedef void (*HookFunType)(void *, void *, void **);
inline static ret (*func##Sym)(__VA_ARGS__); \ inline static ret (*func##Sym)(__VA_ARGS__); \
ALWAYS_INLINE static ret func(__VA_ARGS__) ALWAYS_INLINE static ret func(__VA_ARGS__)
#define CREATE_MEM_FUNC_SYMBOL_ENTRY(ret, func, thiz, ...) \
using func##Type = edxp::MemberFunction<ret(__VA_ARGS__)>; \
inline static func##Type func##Sym; \
ALWAYS_INLINE static ret func(thiz, ## __VA_ARGS__)
namespace edxp { namespace edxp {
class ShadowObject { class ShadowObject {
@ -83,7 +103,7 @@ namespace edxp {
}; };
struct ObjPtr { struct ObjPtr {
void* data; void *data;
}; };
ALWAYS_INLINE static void *Dlsym(void *handle, const char *name) { ALWAYS_INLINE static void *Dlsym(void *handle, const char *name) {
@ -130,7 +150,7 @@ namespace edxp {
} }
template<typename Class, typename Return, typename T, typename... Args> template<typename Class, typename Return, typename T, typename... Args>
inline auto memfun_cast(Return (*func)(T *, Args...)) { inline static auto memfun_cast(Return (*func)(T *, Args...)) {
static_assert(std::is_same_v<T, void> || std::is_same_v<Class, T>, static_assert(std::is_same_v<T, void> || std::is_same_v<Class, T>,
"Not viable cast"); "Not viable cast");
union { union {
@ -145,39 +165,45 @@ namespace edxp {
return u.f; return u.f;
} }
template<typename Return, typename... Args, typename T, template<typename T, typename Return, typename... Args,
typename = std::enable_if_t<!std::is_same_v<T, void>>> typename = std::enable_if_t<!std::is_same_v<T, void>>>
inline auto memfun_cast(Return (*func)(T *, Args...)) { inline auto memfun_cast(Return (*func)(T *, Args...)) {
return memfun_cast<T>(func); return memfun_cast<T>(func);
} }
template<typename Return, typename... Args, typename T, typename U, template<typename, typename=void>
typename = std::enable_if_t<!std::is_same_v<T, void> || !std::is_same_v<U, void>>> class MemberFunction;
inline Return
call_as_member_func(Return (*func)(U *, std::remove_reference_t<Args>...), T *thiz, template<typename This, typename Return, typename ... Args>
Args &&... args) { class MemberFunction<Return(Args...), This> {
using Class = std::conditional_t<std::is_same_v<T, void>, U, T>; using SelfType = MemberFunction<Return(This *, Args...), This>;
return (reinterpret_cast<Class *>(thiz)->*memfun_cast<Class> using ThisType = std::conditional_t<std::is_same_v<This, void>, SelfType, This>;
(func))( using MemFunType = Return(ThisType::*)(Args...);
std::forward<Args>(args)...); public:
using FunType = Return (*)(This *, Args...);
private:
MemFunType f_ = nullptr;
public:
MemberFunction() = default;
MemberFunction(FunType f) : f_(memfun_cast<ThisType>(f)) {}
MemberFunction(MemFunType f) : f_(f) {}
Return operator()(This *thiz, Args... args) {
return (reinterpret_cast<ThisType *>(thiz)->*f_)(std::forward<Args>(args)...);
} }
template<typename Class, typename Return, typename... Args> inline operator bool() {
inline Return return f_ != nullptr;
call_as_member_func(Return (*func)(void *, std::remove_reference_t<Args>...), void *thiz,
Args &&... args) {
return (reinterpret_cast<Class *>(thiz)->*memfun_cast<Class>(func))(
std::forward<Args>(args)...);
} }
template<typename Return, typename... Args>
inline Return
call_as_member_func(Return (*func)(void *, std::remove_reference_t<Args>...), void *thiz,
Args &&... args) {
struct DummyClass {
}; };
return (reinterpret_cast<DummyClass *>(thiz)->*memfun_cast<DummyClass>(func))(
std::forward<Args>(args)...); // deduction guide
} template<typename This, typename Return, typename...Args>
MemberFunction(Return(*f)(This *, Args...)) -> MemberFunction<Return(Args...), This>;
template<typename This, typename Return, typename...Args>
MemberFunction(Return(This::*f)(Args...)) -> MemberFunction<Return(Args...), This>;
} // namespace edxp } // namespace edxp