Commit 6bce5cfd authored by swift_gan's avatar swift_gan Committed by swift_gan

add hook mode choice

parent fc125fb0
...@@ -101,6 +101,8 @@ namespace SandHook { ...@@ -101,6 +101,8 @@ namespace SandHook {
virtual InstArch instArch() const = 0; virtual InstArch instArch() const = 0;
virtual bool pcRelated() = 0; virtual bool pcRelated() = 0;
virtual Size bin() = 0;
}; };
class InstVisitor { class InstVisitor {
......
...@@ -85,7 +85,7 @@ namespace SandHook { ...@@ -85,7 +85,7 @@ namespace SandHook {
return reinterpret_cast<Code>(addr); return reinterpret_cast<Code>(addr);
} }
bool inlineSecurityCheck = true;
private: private:
Size quickCompileOffset; Size quickCompileOffset;
......
...@@ -34,6 +34,10 @@ namespace SandHook { ...@@ -34,6 +34,10 @@ namespace SandHook {
return instType < InstType_Thumb32::PC_NO_RELATED; return instType < InstType_Thumb32::PC_NO_RELATED;
} }
Size bin() override {
return code.code;
}
InstType_Thumb32 initType() { InstType_Thumb32 initType() {
CASE(code.code, 0xF800D000, 0xF000C000, InstType_Thumb32::BLX_THUMB32) CASE(code.code, 0xF800D000, 0xF000C000, InstType_Thumb32::BLX_THUMB32)
CASE(code.code, 0xF800D000, 0xF000D000, InstType_Thumb32::BL_THUMB32) CASE(code.code, 0xF800D000, 0xF000D000, InstType_Thumb32::BL_THUMB32)
...@@ -75,6 +79,10 @@ namespace SandHook { ...@@ -75,6 +79,10 @@ namespace SandHook {
return instType < InstType_Thumb16 ::PC_NO_RELATED; return instType < InstType_Thumb16 ::PC_NO_RELATED;
} }
Size bin() override {
return code.code;
}
InstType_Thumb16 initType() { InstType_Thumb16 initType() {
CASE(code.code, 0xF000, 0xD000, InstType_Thumb16::B1_THUMB16) CASE(code.code, 0xF000, 0xD000, InstType_Thumb16::B1_THUMB16)
CASE(code.code, 0xF800, 0xE000, InstType_Thumb16::B2_THUMB16) CASE(code.code, 0xF800, 0xE000, InstType_Thumb16::B2_THUMB16)
......
...@@ -35,6 +35,12 @@ namespace SandHook { ...@@ -35,6 +35,12 @@ namespace SandHook {
return instType < InstType_Arm64::PC_NO_RELATED; return instType < InstType_Arm64::PC_NO_RELATED;
} }
Size bin() override {
return code.code;
}
private:
InstType_Arm64 initType() { InstType_Arm64 initType() {
CASE(code.code, 0x7e000000, 0x34000000, InstType_Arm64::CBZ_CBNZ); CASE(code.code, 0x7e000000, 0x34000000, InstType_Arm64::CBZ_CBNZ);
CASE(code.code, 0xff000010, 0x54000000, InstType_Arm64::B_COND); CASE(code.code, 0xff000010, 0x54000000, InstType_Arm64::B_COND);
......
...@@ -56,7 +56,38 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth ...@@ -56,7 +56,38 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth
void ensureMethodDeclaringClass(art::mirror::ArtMethod *origin, art::mirror::ArtMethod *backup) { void ensureMethodDeclaringClass(art::mirror::ArtMethod *origin, art::mirror::ArtMethod *backup) {
if (origin->getDeclaringClassPtr() != backup->getDeclaringClassPtr()) { if (origin->getDeclaringClassPtr() != backup->getDeclaringClassPtr()) {
LOGW("backup method declaringClass is out to date due to Moving GC!"); LOGW("backup method declaringClass is out to date due to Moving GC!");
backup->setDeclaringClassPtr(origin->getDeclaringClassPtr());
SandHook::HookTrampoline* trampoline = trampolineManager.getHookTrampoline(origin);
if (trampoline == nullptr)
return;
if (trampoline->inlineJump != nullptr) {
origin->backup(backup);
backup->setQuickCodeEntry(trampoline->callOrigin->getCode());
if (SDK_INT >= ANDROID_N) {
backup->disableCompilable();
}
if (SDK_INT >= ANDROID_O) {
backup->disableInterpreterForO();
}
backup->tryDisableInline();
} else if (trampoline->replacement != nullptr) {
origin->backup(backup);
if (trampoline->callOrigin != nullptr) {
backup->setQuickCodeEntry(trampoline->callOrigin->getCode());
} else {
backup->setQuickCodeEntry(trampoline->originCode);
}
if (SDK_INT >= ANDROID_N) {
backup->disableCompilable();
}
if (SDK_INT >= ANDROID_O) {
backup->disableInterpreterForO();
}
backup->tryDisableInline();
} else {
return;
}
backup->flushCache(); backup->flushCache();
} }
} }
...@@ -70,11 +101,7 @@ bool doHookWithReplacement(JNIEnv* env, ...@@ -70,11 +101,7 @@ bool doHookWithReplacement(JNIEnv* env,
backupMethod->compile(env); backupMethod->compile(env);
} }
if (SDK_INT >= ANDROID_N) { hookMethod->compile(env);
originMethod->disableCompilable();
hookMethod->disableCompilable();
}
originMethod->tryDisableInline();
if (backupMethod != nullptr) { if (backupMethod != nullptr) {
originMethod->backup(backupMethod); originMethod->backup(backupMethod);
...@@ -88,7 +115,14 @@ bool doHookWithReplacement(JNIEnv* env, ...@@ -88,7 +115,14 @@ bool doHookWithReplacement(JNIEnv* env,
backupMethod->flushCache(); backupMethod->flushCache();
} }
if (SDK_INT >= ANDROID_O && SDK_INT < ANDROID_P) { if (SDK_INT >= ANDROID_N) {
originMethod->disableCompilable();
hookMethod->disableCompilable();
hookMethod->flushCache();
}
originMethod->tryDisableInline();
if (SDK_INT >= ANDROID_O && !originMethod->isCompiled()) {
originMethod->disableInterpreterForO(); originMethod->disableInterpreterForO();
} }
...@@ -232,10 +266,13 @@ Java_com_swift_sandhook_SandHook_ensureMethodDeclaringClass(JNIEnv *env, jclass ...@@ -232,10 +266,13 @@ Java_com_swift_sandhook_SandHook_ensureMethodDeclaringClass(JNIEnv *env, jclass
extern "C" extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_swift_sandhook_SandHook_setHookMode(JNIEnv *env, jclass type, jint mode) { Java_com_swift_sandhook_SandHook_setHookMode(JNIEnv *env, jclass type, jint mode) {
// TODO
gHookMode = static_cast<HookMode>(mode); gHookMode = static_cast<HookMode>(mode);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_swift_sandhook_SandHook_setInlineSafeCheck(JNIEnv *env, jclass type, jboolean check) {
trampolineManager.inlineSecurityCheck = check;
} }
extern "C" extern "C"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "../includes/log.h" #include "../includes/log.h"
extern int SDK_INT; extern int SDK_INT;
#define SWITCH_SETX0 false #define SWITCH_SETX0 true
namespace SandHook { namespace SandHook {
...@@ -31,13 +31,22 @@ namespace SandHook { ...@@ -31,13 +31,22 @@ namespace SandHook {
int instSize = 0; int instSize = 0;
TrampolineManager* trampolineManager;
PCRelatedCheckVisitor(TrampolineManager* t) {
trampolineManager = t;
}
bool visit(Inst *inst, Size offset, Size length) override { bool visit(Inst *inst, Size offset, Size length) override {
instSize += inst->instLen(); instSize += inst->instLen();
if (inst->pcRelated()) { if (inst->pcRelated()) {
pcRelated = true; LOGW("found pc related inst: %x !", inst->bin());
return false; if (trampolineManager->inlineSecurityCheck) {
pcRelated = true;
return false;
}
} }
if (instSize > SIZE_ORIGIN_PLACE_HOLDER) { if (instSize > SIZE_ORIGIN_PLACE_HOLDER) {
...@@ -69,7 +78,7 @@ namespace SandHook { ...@@ -69,7 +78,7 @@ namespace SandHook {
} }
//check pc relate inst & backup inst len //check pc relate inst & backup inst len
PCRelatedCheckVisitor visitor; PCRelatedCheckVisitor visitor(this);
InstDecode::decode(method->getQuickCodeEntry(), SIZE_DIRECT_JUMP_TRAMPOLINE, &visitor); InstDecode::decode(method->getQuickCodeEntry(), SIZE_DIRECT_JUMP_TRAMPOLINE, &visitor);
...@@ -129,8 +138,9 @@ namespace SandHook { ...@@ -129,8 +138,9 @@ namespace SandHook {
replacementHookTrampoline->setEntryCodeOffset(quickCompileOffset); replacementHookTrampoline->setEntryCodeOffset(quickCompileOffset);
replacementHookTrampoline->setHookMethod(reinterpret_cast<Code>(hookMethod)); replacementHookTrampoline->setHookMethod(reinterpret_cast<Code>(hookMethod));
hookTrampoline->replacement = replacementHookTrampoline; hookTrampoline->replacement = replacementHookTrampoline;
hookTrampoline->originCode = static_cast<Code>(originMethod->getQuickCodeEntry());
if (SWITCH_SETX0 && backupMethod != nullptr) { if (SWITCH_SETX0 && SDK_INT >= ANDROID_O && backupMethod != nullptr) {
callOriginTrampoline = new CallOriginTrampoline(); callOriginTrampoline = new CallOriginTrampoline();
checkThumbCode(callOriginTrampoline, getEntryCode(originMethod)); checkThumbCode(callOriginTrampoline, getEntryCode(originMethod));
callOriginTrampoline->init(); callOriginTrampoline->init();
......
...@@ -19,6 +19,11 @@ public class SandHook { ...@@ -19,6 +19,11 @@ public class SandHook {
static Map<Member,HookWrapper.HookEntity> globalHookEntityMap = new ConcurrentHashMap<>(); static Map<Member,HookWrapper.HookEntity> globalHookEntityMap = new ConcurrentHashMap<>();
static Map<Method,HookWrapper.HookEntity> globalBackupMap = new ConcurrentHashMap<>(); static Map<Method,HookWrapper.HookEntity> globalBackupMap = new ConcurrentHashMap<>();
private static HookModeCallBack hookModeCallBack;
public static void setHookModeCallBack(HookModeCallBack hookModeCallBack) {
SandHook.hookModeCallBack = hookModeCallBack;
}
public static Class artMethodClass; public static Class artMethodClass;
public static Field nativePeerField; public static Field nativePeerField;
...@@ -87,15 +92,27 @@ public class SandHook { ...@@ -87,15 +92,27 @@ public class SandHook {
if (target instanceof Method) { if (target instanceof Method) {
((Method)target).setAccessible(true); ((Method)target).setAccessible(true);
} }
HookMode hookMode = hook.getAnnotation(HookMode.class);
boolean res = hookMethod(target, hook, backup, hookMode == null ? HookMode.AUTO : hookMode.value()); int mode = HookMode.AUTO;
if (hookModeCallBack != null) {
mode = hookModeCallBack.hookMode(target);
}
boolean res;
if (mode != HookMode.AUTO) {
res = hookMethod(target, hook, backup, mode);
} else {
HookMode hookMode = hook.getAnnotation(HookMode.class);
res = hookMethod(target, hook, backup, hookMode == null ? HookMode.AUTO : hookMode.value());
}
if (res && backup != null) { if (res && backup != null) {
backup.setAccessible(true); backup.setAccessible(true);
} }
return res; return res;
} }
public static void ensureBackupDelaringClass(Method backupMethod) { public static void ensureBackupDeclaringClass(Method backupMethod) {
if (backupMethod == null) if (backupMethod == null)
return; return;
HookWrapper.HookEntity hookEntity = globalBackupMap.get(backupMethod); HookWrapper.HookEntity hookEntity = globalBackupMap.get(backupMethod);
...@@ -206,10 +223,18 @@ public class SandHook { ...@@ -206,10 +223,18 @@ public class SandHook {
public static native void setHookMode(int hookMode); public static native void setHookMode(int hookMode);
//default on!
public static native void setInlineSafeCheck(boolean check);
private static native boolean hookMethod(Member originMethod, Method hookMethod, Method backupMethod, int hookMode); private static native boolean hookMethod(Member originMethod, Method hookMethod, Method backupMethod, int hookMode);
public static native void ensureMethodCached(Method hook, Method backup); public static native void ensureMethodCached(Method hook, Method backup);
public static native void ensureMethodDeclaringClass(Member originMethod, Method backupMethod); public static native void ensureMethodDeclaringClass(Member originMethod, Method backupMethod);
@FunctionalInterface
public interface HookModeCallBack {
int hookMode(Member originMethod);
}
} }
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