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 {
virtual InstArch instArch() const = 0;
virtual bool pcRelated() = 0;
virtual Size bin() = 0;
};
class InstVisitor {
......
......@@ -85,7 +85,7 @@ namespace SandHook {
return reinterpret_cast<Code>(addr);
}
bool inlineSecurityCheck = true;
private:
Size quickCompileOffset;
......
......@@ -34,6 +34,10 @@ namespace SandHook {
return instType < InstType_Thumb32::PC_NO_RELATED;
}
Size bin() override {
return code.code;
}
InstType_Thumb32 initType() {
CASE(code.code, 0xF800D000, 0xF000C000, InstType_Thumb32::BLX_THUMB32)
CASE(code.code, 0xF800D000, 0xF000D000, InstType_Thumb32::BL_THUMB32)
......@@ -75,6 +79,10 @@ namespace SandHook {
return instType < InstType_Thumb16 ::PC_NO_RELATED;
}
Size bin() override {
return code.code;
}
InstType_Thumb16 initType() {
CASE(code.code, 0xF000, 0xD000, InstType_Thumb16::B1_THUMB16)
CASE(code.code, 0xF800, 0xE000, InstType_Thumb16::B2_THUMB16)
......
......@@ -35,6 +35,12 @@ namespace SandHook {
return instType < InstType_Arm64::PC_NO_RELATED;
}
Size bin() override {
return code.code;
}
private:
InstType_Arm64 initType() {
CASE(code.code, 0x7e000000, 0x34000000, InstType_Arm64::CBZ_CBNZ);
CASE(code.code, 0xff000010, 0x54000000, InstType_Arm64::B_COND);
......
......@@ -56,7 +56,38 @@ void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMeth
void ensureMethodDeclaringClass(art::mirror::ArtMethod *origin, art::mirror::ArtMethod *backup) {
if (origin->getDeclaringClassPtr() != backup->getDeclaringClassPtr()) {
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();
}
}
......@@ -70,11 +101,7 @@ bool doHookWithReplacement(JNIEnv* env,
backupMethod->compile(env);
}
if (SDK_INT >= ANDROID_N) {
originMethod->disableCompilable();
hookMethod->disableCompilable();
}
originMethod->tryDisableInline();
hookMethod->compile(env);
if (backupMethod != nullptr) {
originMethod->backup(backupMethod);
......@@ -88,7 +115,14 @@ bool doHookWithReplacement(JNIEnv* env,
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();
}
......@@ -232,10 +266,13 @@ Java_com_swift_sandhook_SandHook_ensureMethodDeclaringClass(JNIEnv *env, jclass
extern "C"
JNIEXPORT void JNICALL
Java_com_swift_sandhook_SandHook_setHookMode(JNIEnv *env, jclass type, jint mode) {
// TODO
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"
......
......@@ -7,7 +7,7 @@
#include "../includes/log.h"
extern int SDK_INT;
#define SWITCH_SETX0 false
#define SWITCH_SETX0 true
namespace SandHook {
......@@ -31,13 +31,22 @@ namespace SandHook {
int instSize = 0;
TrampolineManager* trampolineManager;
PCRelatedCheckVisitor(TrampolineManager* t) {
trampolineManager = t;
}
bool visit(Inst *inst, Size offset, Size length) override {
instSize += inst->instLen();
if (inst->pcRelated()) {
pcRelated = true;
return false;
LOGW("found pc related inst: %x !", inst->bin());
if (trampolineManager->inlineSecurityCheck) {
pcRelated = true;
return false;
}
}
if (instSize > SIZE_ORIGIN_PLACE_HOLDER) {
......@@ -69,7 +78,7 @@ namespace SandHook {
}
//check pc relate inst & backup inst len
PCRelatedCheckVisitor visitor;
PCRelatedCheckVisitor visitor(this);
InstDecode::decode(method->getQuickCodeEntry(), SIZE_DIRECT_JUMP_TRAMPOLINE, &visitor);
......@@ -129,8 +138,9 @@ namespace SandHook {
replacementHookTrampoline->setEntryCodeOffset(quickCompileOffset);
replacementHookTrampoline->setHookMethod(reinterpret_cast<Code>(hookMethod));
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();
checkThumbCode(callOriginTrampoline, getEntryCode(originMethod));
callOriginTrampoline->init();
......
......@@ -19,6 +19,11 @@ public class SandHook {
static Map<Member,HookWrapper.HookEntity> globalHookEntityMap = 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 Field nativePeerField;
......@@ -87,15 +92,27 @@ public class SandHook {
if (target instanceof Method) {
((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) {
backup.setAccessible(true);
}
return res;
}
public static void ensureBackupDelaringClass(Method backupMethod) {
public static void ensureBackupDeclaringClass(Method backupMethod) {
if (backupMethod == null)
return;
HookWrapper.HookEntity hookEntity = globalBackupMap.get(backupMethod);
......@@ -206,10 +223,18 @@ public class SandHook {
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);
public static native void ensureMethodCached(Method hook, Method backup);
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