Commit cfa2690d authored by swift_gan's avatar swift_gan

invoke backup to resolve static method

parent 8ffd5536
......@@ -10,15 +10,15 @@
namespace SandHook {
class CastDexCacheResolvedMethods : public ArrayMember<art::mirror::ArtMethod> {
class CastDexCacheResolvedMethods : public ArrayMember<art::mirror::ArtMethod, void*> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
if (SDK_INT >= ANDROID_P)
return getParentSize() + 1;
int offset = 0;
Size addr = getAddressFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", "resolvedMethodsAddress");
if (addr != 0) {
offset = findOffset(&p, getParentSize(), 2, addr);
offset = findOffset(p, getParentSize(), 2, addr);
if (offset >= 0) {
return static_cast<Size>(offset);
}
......@@ -26,14 +26,11 @@ namespace SandHook {
return getParentSize() + 1;
}
Size calElementSize(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
return BYTE_POINT;
}
};
class CastEntryPointFormInterpreter : public IMember<art::mirror::ArtMethod, void*> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
if (SDK_INT >= ANDROID_L2 && SDK_INT <= ANDROID_M)
return getParentSize() - 3 * BYTE_POINT;
else if (SDK_INT <= ANDROID_L)
......@@ -45,7 +42,7 @@ namespace SandHook {
class CastEntryPointQuickCompiled : public IMember<art::mirror::ArtMethod, void*> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
if (SDK_INT >= ANDROID_L2) {
return getParentSize() - BYTE_POINT;
} else {
......@@ -56,7 +53,7 @@ namespace SandHook {
class CastEntryPointFromJni : public IMember<art::mirror::ArtMethod, void*> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
if (SDK_INT >= ANDROID_L2 && SDK_INT <= ANDROID_N) {
return getParentSize() - 2 * BYTE_POINT;
} else {
......@@ -68,12 +65,12 @@ namespace SandHook {
class CastAccessFlag : public IMember<art::mirror::ArtMethod, uint32_t> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
uint32_t accessFlag = getIntFromJava(jniEnv, "com/swift/sandhook/SandHook", "testAccessFlag");
if (accessFlag == 0) {
accessFlag = 524313;
}
int offset = findOffset(&p, getParentSize(), 2, accessFlag);
int offset = findOffset(p, getParentSize(), 2, accessFlag);
if (offset < 0)
return getParentSize() + 1;
else
......@@ -84,13 +81,13 @@ namespace SandHook {
class CastDexMethodIndex : public IMember<art::mirror::ArtMethod, uint32_t> {
protected:
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod p) override {
Size calOffset(JNIEnv *jniEnv, art::mirror::ArtMethod* p) override {
if (SDK_INT >= ANDROID_P)
return getParentSize() + 1;
int offset = 0;
jint index = getIntFromJava(jniEnv, "com/swift/sandhook/SandHookMethodResolver", "dexMethodIndex");
if (index != 0) {
offset = findOffset(&p, getParentSize(), 2, static_cast<uint32_t>(index));
offset = findOffset(p, getParentSize(), 2, static_cast<uint32_t>(index));
if (offset >= 0) {
return static_cast<Size>(offset);
}
......@@ -107,7 +104,7 @@ namespace SandHook {
static Size size;
static IMember<art::mirror::ArtMethod, void*>* entryPointQuickCompiled;
static IMember<art::mirror::ArtMethod, void*>* entryPointFormInterpreter;
static ArrayMember<art::mirror::ArtMethod>* dexCacheResolvedMethods;
static ArrayMember<art::mirror::ArtMethod,void*>* dexCacheResolvedMethods;
static IMember<art::mirror::ArtMethod, uint32_t>* dexMethodIndex;
static IMember<art::mirror::ArtMethod, uint32_t>* accessFlag;
static void* quickToInterpreterBridge;
......@@ -121,8 +118,8 @@ namespace SandHook {
Size artMethod2 = (Size) env->GetStaticMethodID(sizeTestClass, "method2", "()V");
size = artMethod2 - artMethod1;
art::mirror::ArtMethod m1 = *reinterpret_cast<art::mirror::ArtMethod *>(artMethod1);
art::mirror::ArtMethod m2 = *reinterpret_cast<art::mirror::ArtMethod *>(artMethod2);
art::mirror::ArtMethod* m1 = reinterpret_cast<art::mirror::ArtMethod *>(artMethod1);
art::mirror::ArtMethod* m2 = reinterpret_cast<art::mirror::ArtMethod *>(artMethod2);
//init Members
entryPointQuickCompiled = new CastEntryPointQuickCompiled();
......@@ -142,7 +139,7 @@ namespace SandHook {
jclass neverCallTestClass = env->FindClass("com/swift/sandhook/ClassNeverCall");
art::mirror::ArtMethod* neverCall = reinterpret_cast<art::mirror::ArtMethod *>(env->GetMethodID(neverCallTestClass, "neverCall", "()V"));
quickToInterpreterBridge = entryPointQuickCompiled->get(*neverCall);
quickToInterpreterBridge = entryPointQuickCompiled->get(neverCall);
}
......@@ -155,7 +152,7 @@ namespace SandHook {
Size CastArtMethod::size = 0;
IMember<art::mirror::ArtMethod, void*>* CastArtMethod::entryPointQuickCompiled = nullptr;
IMember<art::mirror::ArtMethod, void*>* CastArtMethod::entryPointFormInterpreter = nullptr;
ArrayMember<art::mirror::ArtMethod>* CastArtMethod::dexCacheResolvedMethods = nullptr;
ArrayMember<art::mirror::ArtMethod, void*>* CastArtMethod::dexCacheResolvedMethods = nullptr;
IMember<art::mirror::ArtMethod, uint32_t>* CastArtMethod::dexMethodIndex = nullptr;
IMember<art::mirror::ArtMethod, uint32_t>* CastArtMethod::accessFlag = nullptr;
void* CastArtMethod::quickToInterpreterBridge = nullptr;
......
......@@ -43,7 +43,7 @@ namespace SandHook {
class IMember {
public:
virtual void init(JNIEnv *jniEnv, PType p, Size size) {
virtual void init(JNIEnv *jniEnv, PType* p, Size size) {
this->parentSize = size;
offset = calOffset(jniEnv, p);
}
......@@ -56,10 +56,10 @@ namespace SandHook {
return parentSize;
}
virtual MType get(PType p) {
virtual MType get(PType* p) {
if (offset > parentSize)
return NULL;
return *reinterpret_cast<MType*>((Size)&p + getOffset());
return *reinterpret_cast<MType*>((Size)p + getOffset());
};
virtual void set(PType* p, MType t) {
......@@ -72,15 +72,15 @@ namespace SandHook {
Size offset = 0;
protected:
Size parentSize = 0;
virtual Size calOffset(JNIEnv *jniEnv, PType p) = 0;
virtual Size calOffset(JNIEnv *jniEnv, PType* p) = 0;
};
template<typename PType>
template<typename PType, typename ElementType>
class ArrayMember : public IMember<PType, void*> {
public:
virtual void init(JNIEnv *jniEnv, PType p, Size parentSize) override {
virtual void init(JNIEnv *jniEnv, PType* p, Size parentSize) override {
IMember<PType,void*>::init(jniEnv, p, parentSize);
elementSize = calElementSize(jniEnv, p);
}
......@@ -89,21 +89,24 @@ namespace SandHook {
return elementSize;
}
virtual Size arrayStart(PType parent) {
return reinterpret_cast<Size>(IMember<PType,void*>::get(parent));
virtual Size arrayStart(PType* parent) {
void* p = IMember<PType,void*>::get(parent);
return reinterpret_cast<Size>(p);
}
using IMember<PType,void*>::getParentSize;
virtual void setElement(PType parent, int position, void* elementPoint) {
virtual void setElement(PType* parent, int position, ElementType elementPoint) {
Size array = arrayStart(parent);
memcpy(reinterpret_cast<void*>(array + position * getElementSize()), elementPoint, getElementSize());
memcpy(reinterpret_cast<void*>(array + position * getElementSize()), &elementPoint, getElementSize());
}
private:
Size elementSize = 0;
protected:
virtual Size calElementSize(JNIEnv *jniEnv, PType p) = 0;
virtual Size calElementSize(JNIEnv *jniEnv, PType* p) {
return sizeof(ElementType);
};
};
}
......
......@@ -21,13 +21,13 @@ 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);
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag |= 0x01000000;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
void disableInterpreterForO(art::mirror::ArtMethod* method) {
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(*method);
uint32_t accessFlag = SandHook::CastArtMethod::accessFlag->get(method);
accessFlag |= 0x0100;
SandHook::CastArtMethod::accessFlag->set(method, accessFlag);
}
......@@ -35,9 +35,9 @@ void disableInterpreterForO(art::mirror::ArtMethod* method) {
void ensureMethodCached(art::mirror::ArtMethod *hookMethod, art::mirror::ArtMethod *backupMethod) {
if (SDK_INT >= ANDROID_P)
return;
uint32_t index = SandHook::CastArtMethod::dexMethodIndex->get(*backupMethod);
uint32_t index = SandHook::CastArtMethod::dexMethodIndex->get(backupMethod);
if (SDK_INT < ANDROID_O2) {
SandHook::CastArtMethod::dexCacheResolvedMethods->setElement(*hookMethod, index, backupMethod);
SandHook::CastArtMethod::dexCacheResolvedMethods->setElement(hookMethod, index, backupMethod);
} else {
int cacheSize = 1024;
Size slotIndex = index % cacheSize;
......@@ -72,6 +72,10 @@ bool doHookWithReplacement(art::mirror::ArtMethod *originMethod,
SandHook::HookTrampoline* hookTrampoline = trampolineManager.installReplacementTrampoline(originMethod, hookMethod, backupMethod);
if (hookTrampoline != nullptr) {
SandHook::CastArtMethod::entryPointQuickCompiled->set(originMethod, hookTrampoline->replacement->getCode());
void* entryPointFormInterpreter = SandHook::CastArtMethod::entryPointFormInterpreter->get(hookMethod);
if (entryPointFormInterpreter != NULL) {
SandHook::CastArtMethod::entryPointFormInterpreter->set(originMethod, entryPointFormInterpreter);
}
hookTrampoline->replacement->flushCache(reinterpret_cast<Size>(originMethod), SandHook::CastArtMethod::size);
}
}
......@@ -80,18 +84,13 @@ bool doHookWithInline(JNIEnv* env,
art::mirror::ArtMethod *originMethod,
art::mirror::ArtMethod *hookMethod,
art::mirror::ArtMethod *backupMethod) {
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(*hookMethod) == SandHook::CastArtMethod::quickToInterpreterBridge;
if (isInterpreter) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId");
compileMethod(hookMethod, reinterpret_cast<void*>(threadId));
}
isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(*backupMethod) == SandHook::CastArtMethod::quickToInterpreterBridge;
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(hookMethod) == SandHook::CastArtMethod::quickToInterpreterBridge;
//fix >= 8.1
if (isInterpreter) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId");
compileMethod(backupMethod, reinterpret_cast<void*>(threadId));
compileMethod(hookMethod, reinterpret_cast<void*>(threadId));
}
SandHook::HookTrampoline* hookTrampoline = trampolineManager.installInlineTrampoline(originMethod, hookMethod, backupMethod);
......@@ -124,12 +123,12 @@ Java_com_swift_sandhook_SandHook_hookMethod(JNIEnv *env, jclass type, jobject or
// memcpy(backup, origin, SandHook::CastArtMethod::size);
// }
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(*origin) == SandHook::CastArtMethod::quickToInterpreterBridge;
bool isInterpreter = SandHook::CastArtMethod::entryPointQuickCompiled->get(origin) == SandHook::CastArtMethod::quickToInterpreterBridge;
if (isInterpreter) {
if (SDK_INT >= ANDROID_N) {
Size threadId = getAddressFromJavaByCallMethod(env, "com/swift/sandhook/SandHook", "getThreadId");
if (compileMethod(origin, reinterpret_cast<void *>(threadId)) && SandHook::CastArtMethod::entryPointQuickCompiled->get(*origin) != SandHook::CastArtMethod::quickToInterpreterBridge) {
if (compileMethod(origin, reinterpret_cast<void *>(threadId)) && SandHook::CastArtMethod::entryPointQuickCompiled->get(origin) != SandHook::CastArtMethod::quickToInterpreterBridge) {
doHookWithInline(env, origin, hook, backup);
} else {
doHookWithReplacement(origin, hook, backup);
......@@ -151,5 +150,5 @@ Java_com_swift_sandhook_SandHook_ensureMethodCached(JNIEnv *env, jclass type, jo
jobject backup) {
art::mirror::ArtMethod* hookeMethod = reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(hook));
art::mirror::ArtMethod* backupMethod = backup == NULL ? nullptr : reinterpret_cast<art::mirror::ArtMethod *>(env->FromReflectedMethod(backup));
// ensureMethodCached(hookeMethod, backupMethod);
ensureMethodCached(hookeMethod, backupMethod);
}
\ No newline at end of file
......@@ -61,4 +61,16 @@ addr_hook_art_method:
.long 0
FUNCTION_END(INLINE_HOOK_TRAMPOLINE)
FUNCTION_START(CALL_ORIGIN_TRAMPOLINE)
ldr RegMethod, origin_art_method
ldr Reg0, addr_target
br Reg0
origin_art_method:
.long 0
.long 0
addr_origin:
.long 0
.long 0
FUNCTION_END(CALL_ORIGIN_TRAMPOLINE)
#endif
......@@ -16,5 +16,6 @@ x: \
#define REPLACEMENT_HOOK_TRAMPOLINE replacement_hook_trampoline
#define INLINE_HOOK_TRAMPOLINE inline_hook_trampoline
#define DIRECT_JUMP_TRAMPOLINE direct_jump_trampoline
#define CALL_ORIGIN_TRAMPOLINE call_origin_trampoline
#endif //SANDHOOK_BASE_H
......@@ -45,6 +45,7 @@ public class MainActivity extends AppCompatActivity {
@Override
public void run() {
methodBeHooked(savedInstanceState);
Log.w("gy", "dadadad");
}
}, 3000);
......
......@@ -3,15 +3,14 @@ package com.swift.sandhook;
import android.app.Application;
import com.swift.sandhook.wrapper.HookErrorException;
import com.swift.sandhook.wrapper.HookWrapper;
import com.swift.sandhook.wrapper.LogHooker;
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
ActivityHooker.onCreate(null, null);
try {
HookWrapper.addHookClass(ActivityHooker.class);
SandHook.addHookClass(LogHooker.class, ActivityHooker.class);
} catch (HookErrorException e) {
e.printStackTrace();
}
......
......@@ -48,13 +48,20 @@ public class SandHook {
}
public static void hook(@NonNull Member target, @NonNull Method hook, @Nullable Method backup) {
hook.setAccessible(true);
if (backup != null) {
resolveBackupMethod(backup);
SandHookMethodResolver.resolveMethod(hook, backup);
}
hookMethod(target, hook, backup);
}
private static void resolveBackupMethod(Method method) {
try {
method.invoke(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void initTestOffset() {
// make test methods sure resolved!
......
......@@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class HookWrapper {
Map<Member,HookEntity> hookEntityMap = new ConcurrentHashMap<>();
static Map<Member,HookEntity> globalHookEntityMap = new ConcurrentHashMap<>();
public static void addHookClass(Class<?>... classes) throws HookErrorException {
for (Class clazz:classes) {
......@@ -28,7 +28,7 @@ public class HookWrapper {
for (HookEntity entity:hookEntityMap.values()) {
if (entity.target != null && entity.hook != null) {
SandHook.hook(entity.target, entity.hook, entity.backup);
hookEntityMap.put(entity.target, entity);
globalHookEntityMap.put(entity.target, entity);
}
}
}
......
package com.swift.sandhook.wrapper;
import android.util.Log;
@HookClass(Log.class)
public class LogHooker {
@HookMethod("w")
@MethodParams({String.class, String.class})
public static int onCreate(String tag, String msg) {
Log.e("LogHooker", "hooked success " + tag);
return onCreateBackup(tag, msg);
}
@HookMethodBackup("w")
@MethodParams({String.class, String.class})
public static int onCreateBackup(String tag, String msg) {
return 0;
}
}
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