Commit 5bc325a2 authored by swift_gan's avatar swift_gan

[reconsit]done

parent 5bd6ce01
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
#include "../includes/art_method.h" #include "../includes/art_method.h"
#include "../includes/cast_art_method.h" #include "../includes/cast_art_method.h"
#include "../includes/hide_api.h" #include "../includes/hide_api.h"
#include "../includes/utils.h"
using namespace art::mirror; using namespace art::mirror;
using namespace SandHook; using namespace SandHook;
void ArtMethod::tryDisableInline() { void ArtMethod::tryDisableInline() {
if (SDK_INT < ANDROID_O) if (SDK_INT < ANDROID_O)
return; return;
...@@ -47,7 +47,7 @@ bool ArtMethod::isNative() { ...@@ -47,7 +47,7 @@ bool ArtMethod::isNative() {
} }
bool ArtMethod::isCompiled() { bool ArtMethod::isCompiled() {
return getQuickCodeEntry() == SandHook::CastArtMethod::quickToInterpreterBridge; return getQuickCodeEntry() != SandHook::CastArtMethod::quickToInterpreterBridge;
} }
void ArtMethod::setAccessFlags(uint32_t flags) { void ArtMethod::setAccessFlags(uint32_t flags) {
...@@ -94,23 +94,31 @@ void ArtMethod::setInterpreterCodeEntry(void *entry) { ...@@ -94,23 +94,31 @@ void ArtMethod::setInterpreterCodeEntry(void *entry) {
CastArtMethod::entryPointFormInterpreter->set(this, entry); CastArtMethod::entryPointFormInterpreter->set(this, entry);
} }
void ArtMethod::setDexCacheResolveList(void *list) {
CastArtMethod::dexCacheResolvedMethods->set(this, list);
}
void ArtMethod::setDexCacheResolveItem(uint32_t index, void* item) { void ArtMethod::setDexCacheResolveItem(uint32_t index, void* item) {
CastArtMethod::dexCacheResolvedMethods->setElement(this, index, item); CastArtMethod::dexCacheResolvedMethods->setElement(this, index, item);
} }
bool ArtMethod::compile() { bool ArtMethod::compile(JNIEnv* env) {
// if (isCompiled()) if (isCompiled())
// return true; return true;
// Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId");
// if (threadId == 0) if (threadId == 0)
// return false; return false;
// return compileMethod(this, ) && isCompiled(); return compileMethod(this, reinterpret_cast<void *>(threadId)) && isCompiled();
} }
void ArtMethod::flushCache() { void ArtMethod::flushCache() {
flushCacheExt(reinterpret_cast<Size>(this), size());
} }
void ArtMethod::backup(ArtMethod *backup) { void ArtMethod::backup(ArtMethod *backup) {
memcpy(backup, this, size());
}
Size ArtMethod::size() {
return CastArtMethod::size;
} }
\ No newline at end of file
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#ifndef ART_H #ifndef ART_H
#define ART_H #define ART_H
#include <jni.h>
#include "arch.h"
namespace art { namespace art {
namespace mirror { namespace mirror {
class Object { class Object {
...@@ -41,7 +44,6 @@ public: ...@@ -41,7 +44,6 @@ public:
class ArtMethod { class ArtMethod {
public: public:
void* codeEntry;
bool isAbstract(); bool isAbstract();
bool isNative(); bool isNative();
...@@ -57,6 +59,7 @@ public: ...@@ -57,6 +59,7 @@ public:
void setQuickCodeEntry(void* entry); void setQuickCodeEntry(void* entry);
void setJniCodeEntry(void* entry); void setJniCodeEntry(void* entry);
void setInterpreterCodeEntry(void* entry); void setInterpreterCodeEntry(void* entry);
void setDexCacheResolveList(void* list);
void setDexCacheResolveItem(uint32_t index, void* item); void setDexCacheResolveItem(uint32_t index, void* item);
void* getQuickCodeEntry(); void* getQuickCodeEntry();
...@@ -64,10 +67,12 @@ public: ...@@ -64,10 +67,12 @@ public:
uint32_t getAccessFlags(); uint32_t getAccessFlags();
uint32_t getDexMethodIndex(); uint32_t getDexMethodIndex();
bool compile(); bool compile(JNIEnv* env);
void flushCache(); void flushCache();
void backup(ArtMethod* backup); void backup(ArtMethod* backup);
static Size size();
}; };
} }
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
extern "C" { extern "C" {
void initHideApi(JNIEnv *env, int SDK_VERSION); void initHideApi(JNIEnv *env, int SDK_VERSION);
bool compileMethod(void *artMethod, void *thread); bool compileMethod(void *artMethod, void *thread);
} }
......
...@@ -10,16 +10,19 @@ ...@@ -10,16 +10,19 @@
#include "jni.h" #include "jni.h"
#include "../includes/arch.h" #include "../includes/arch.h"
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
extern "C" { extern "C" {
Size getAddressFromJava(JNIEnv *env, const char *className, const char *fieldName); Size getAddressFromJava(JNIEnv *env, const char *className, const char *fieldName);
Size getAddressFromJavaByCallMethod(JNIEnv *env, const char *className, const char *methodName);
Size getAddressFromJavaByCallMethod(JNIEnv *env, const char *className, const char *methodName); jint getIntFromJava(JNIEnv *env, const char *className, const char *fieldName);
jint getIntFromJava(JNIEnv *env, const char *className, const char *fieldName); bool munprotect(size_t addr, size_t len);
bool munprotect(size_t addr, size_t len); bool flushCacheExt(Size addr, Size len);
} }
......
...@@ -26,62 +26,12 @@ Java_com_swift_sandhook_SandHook_initNative(JNIEnv *env, jclass type, jint sdk) ...@@ -26,62 +26,12 @@ Java_com_swift_sandhook_SandHook_initNative(JNIEnv *env, jclass type, jint sdk)
} }
void disableCompilable(art::mirror::ArtMethod* method) {
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
if (SDK_INT >= ANDROID_O2) {
accessFlag |= 0x02000000;
accessFlag |= 0x00800000;
} else {
accessFlag |= 0x01000000;
}
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
void tryDisableInline(art::mirror::ArtMethod* method) {
if (method == nullptr)
return;
if (SDK_INT < ANDROID_O)
return;
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag &= ~ 0x08000000;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
void disableInterpreterForO(art::mirror::ArtMethod* method) {
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag |= 0x0100;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
void setPrivate(art::mirror::ArtMethod* method) {
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag &= ~ 0x1;
accessFlag |= 0x2;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
void setStatic(art::mirror::ArtMethod* method) {
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag |= 0x0008;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
bool isAbsMethod(art::mirror::ArtMethod* method) {
uint32_t accessFlags = SandHook::CastArtMethod::accessFlag->get(method);
return ((accessFlags & 0x0400) != 0);
}
bool isNative(art::mirror::ArtMethod* method) {
uint32_t accessFlags = SandHook::CastArtMethod::accessFlag->get(method);
return ((accessFlags & 0x0100) != 0);
}
void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMethod *backupMethod) { void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMethod *backupMethod) {
if (SDK_INT >= ANDROID_P) if (SDK_INT >= ANDROID_P)
return; return;
uint32_t index = SandHook::CastArtMethod::dexMethodIndex->get(backupMethod); uint32_t index = backupMethod->getDexMethodIndex();
if (SDK_INT < ANDROID_O2) { if (SDK_INT < ANDROID_O2) {
SandHook::CastArtMethod::dexCacheResolvedMethods->setElement(hookMethod, index, backupMethod); hookMethod->setDexCacheResolveItem(index, backupMethod);
} else { } else {
int cacheSize = 1024; int cacheSize = 1024;
Size slotIndex = index % cacheSize; Size slotIndex = index % cacheSize;
...@@ -96,41 +46,46 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth ...@@ -96,41 +46,46 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth
&index, &index,
4 4
); );
SandHook::CastArtMethod::dexCacheResolvedMethods->set(hookMethod, &newCachedMethodsArray); hookMethod->setDexCacheResolveList(&newCachedMethodsArray);
} }
} }
bool doHookWithReplacement(art::mirror::ArtMethod *originMethod, bool doHookWithReplacement(JNIEnv* env,
art::mirror::ArtMethod *originMethod,
art::mirror::ArtMethod *hookMethod, art::mirror::ArtMethod *hookMethod,
art::mirror::ArtMethod *backupMethod) { art::mirror::ArtMethod *backupMethod) {
if (!hookMethod->isCompiled()) {
hookMethod->compile(env);
}
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
disableCompilable(originMethod); originMethod->disableCompilable();
disableCompilable(hookMethod); hookMethod->disableCompilable();
} }
tryDisableInline(originMethod); originMethod->tryDisableInline();
if (backupMethod != nullptr) { if (backupMethod != nullptr) {
memcpy(backupMethod, originMethod, SandHook::CastArtMethod::size); originMethod->backup(backupMethod);
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
disableCompilable(backupMethod); backupMethod->disableCompilable();
} }
if (SDK_INT >= ANDROID_O) { if (SDK_INT >= ANDROID_O) {
disableInterpreterForO(backupMethod); backupMethod->disableInterpreterForO();
} }
tryDisableInline(backupMethod); backupMethod->tryDisableInline();
setPrivate(backupMethod); backupMethod->setPrivate();
SandHook::Trampoline::flushCache(reinterpret_cast<Size>(originMethod), SandHook::CastArtMethod::size); backupMethod->flushCache();
} }
if (SDK_INT >= ANDROID_O) { if (SDK_INT >= ANDROID_O) {
disableInterpreterForO(originMethod); originMethod->disableInterpreterForO();
} }
SandHook::HookTrampoline* hookTrampoline = trampolineManager.installReplacementTrampoline(originMethod, hookMethod, backupMethod); SandHook::HookTrampoline* hookTrampoline = trampolineManager.installReplacementTrampoline(originMethod, hookMethod, backupMethod);
if (hookTrampoline != nullptr) { if (hookTrampoline != nullptr) {
SandHook::CastArtMethod::entryPointQuickCompiled->set(originMethod, hookTrampoline->replacement->getCode()); originMethod->setQuickCodeEntry(hookTrampoline->replacement->getCode());
void* entryPointFormInterpreter = SandHook::CastArtMethod::entryPointFormInterpreter->get(hookMethod); void* entryPointFormInterpreter = hookMethod->getInterpreterCodeEntry();
if (entryPointFormInterpreter != NULL) { if (entryPointFormInterpreter != NULL) {
SandHook::CastArtMethod::entryPointFormInterpreter->set(originMethod, entryPointFormInterpreter); originMethod->setInterpreterCodeEntry(entryPointFormInterpreter);
} }
hookTrampoline->replacement->flushCache(reinterpret_cast<Size>(originMethod), SandHook::CastArtMethod::size); originMethod->flushCache();
return true; return true;
} else { } else {
return false; return false;
...@@ -142,41 +97,36 @@ bool doHookWithInline(JNIEnv* env, ...@@ -142,41 +97,36 @@ bool doHookWithInline(JNIEnv* env,
art::mirror::ArtMethod *hookMethod, art::mirror::ArtMethod *hookMethod,
art::mirror::ArtMethod *backupMethod) { art::mirror::ArtMethod *backupMethod) {
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(hookMethod) == SandHook::CastArtMethod::quickToInterpreterBridge;
//fix >= 8.1 //fix >= 8.1
if (isInterpreter) { if (!hookMethod->isCompiled()) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); hookMethod->compile(env);
compileMethod(hookMethod, reinterpret_cast<void*>(threadId));
} }
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
disableCompilable(originMethod); originMethod->disableCompilable();
SandHook::Trampoline::flushCache(reinterpret_cast<Size>(originMethod), SandHook::CastArtMethod::size); originMethod->flushCache();
} }
originMethod->tryDisableInline();
tryDisableInline(originMethod);
SandHook::HookTrampoline* hookTrampoline = trampolineManager.installInlineTrampoline(originMethod, hookMethod, backupMethod); SandHook::HookTrampoline* hookTrampoline = trampolineManager.installInlineTrampoline(originMethod, hookMethod, backupMethod);
if (hookTrampoline == nullptr) if (hookTrampoline == nullptr)
return false; return false;
hookTrampoline->inlineSecondory->flushCache(reinterpret_cast<Size>(hookMethod), SandHook::CastArtMethod::size); hookMethod->flushCache();
if (hookTrampoline->callOrigin != nullptr) { if (hookTrampoline->callOrigin != nullptr) {
//backup //backup
memcpy(backupMethod, originMethod, SandHook::CastArtMethod::size); originMethod->backup(backupMethod);
backupMethod->setQuickCodeEntry(hookTrampoline->callOrigin->getCode());
SandHook::CastArtMethod::entryPointQuickCompiled->set(backupMethod, hookTrampoline->callOrigin->getCode());
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
disableCompilable(backupMethod); backupMethod->disableCompilable();
} }
if (SDK_INT >= ANDROID_O) { if (SDK_INT >= ANDROID_O) {
disableInterpreterForO(backupMethod); backupMethod->disableInterpreterForO();
} }
tryDisableInline(backupMethod); backupMethod->tryDisableInline();
setPrivate(backupMethod); backupMethod->setPrivate();
hookTrampoline->callOrigin->flushCache(reinterpret_cast<Size>(backupMethod), SandHook::CastArtMethod::size); backupMethod->flushCache();
} }
return true; return true;
} }
...@@ -191,50 +141,45 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or ...@@ -191,50 +141,45 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or
art::mirror::ArtMethod* hook = reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(hookMethod)); art::mirror::ArtMethod* hook = reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(hookMethod));
art::mirror::ArtMethod* backup = backupMethod == NULL ? nullptr : reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(backupMethod)); art::mirror::ArtMethod* backup = backupMethod == NULL ? nullptr : reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(backupMethod));
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(origin) == SandHook::CastArtMethod::quickToInterpreterBridge; bool isInlineHook = false;
int mode = reinterpret_cast<int>(hookMode); int mode = reinterpret_cast<int>(hookMode);
if (mode == INLINE) { if (mode == INLINE) {
if (isInterpreter) { if (!origin->isCompiled()) {
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId");
if (compileMethod(origin, reinterpret_cast<void *>(threadId)) && isInlineHook = compileMethod(origin, reinterpret_cast<void *>(threadId));
SandHook::CastArtMethod::entryPointQuickCompiled->get(origin) !=
SandHook::CastArtMethod::quickToInterpreterBridge) {
return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup));
} else {
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup));
}
} }
} else { } else {
return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup)); isInlineHook = true;
} }
} else if (mode == REPLACE) { } else if (mode == REPLACE) {
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup)); isInlineHook = false;
} }
if (SDK_INT >= ANDROID_P && BYTE_POINT == 4) { if (SDK_INT >= ANDROID_P && BYTE_POINT == 4) {
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(hook) == SandHook::CastArtMethod::quickToInterpreterBridge; isInlineHook = false;
if (isInterpreter) { } else if (origin->isAbstract()) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); isInlineHook = false;
compileMethod(hook, reinterpret_cast<void*>(threadId)); } else if (!origin->isCompiled()) {
}
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup));
} else if (isAbsMethod(origin)) {
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup));
} else if (isInterpreter) {
if (SDK_INT >= ANDROID_N) { if (SDK_INT >= ANDROID_N) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId"); if (SDK_INT >= ANDROID_N) {
if (compileMethod(origin, reinterpret_cast<void *>(threadId)) && SandHook::CastArtMethod::entryPointQuickCompiled->get(origin) != SandHook::CastArtMethod::quickToInterpreterBridge) { isInlineHook = origin->compile(env);
return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup));
} else {
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup));
} }
} else { } else {
return static_cast<jboolean>(doHookWithReplacement(origin, hook, backup)); isInlineHook = false;
} }
} else { } else {
isInlineHook = true;
}
char *msg;
if (isInlineHook && trampolineManager.canSafeInline(origin, msg)) {
return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup)); return static_cast<jboolean>(doHookWithInline(env, origin, hook, backup));
} else {
return static_cast<jboolean>(doHookWithReplacement(env, origin, hook, backup));
} }
} }
......
...@@ -59,5 +59,19 @@ extern "C" { ...@@ -59,5 +59,19 @@ extern "C" {
return true; return true;
} }
bool flushCacheExt(Size addr, Size len) {
#if defined(__arm__)
int i = cacheflush(addr, addr + len, 0);
if (i == -1) {
return false;
}
return true;
#elif defined(__aarch64__)
char *begin = reinterpret_cast<char *>(addr);
__builtin___clear_cache(begin, begin + len);
#endif
return true;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment