Commit 3b15f9e6 authored by swift_gan's avatar swift_gan

done stub manager

parent ff09c694
......@@ -199,7 +199,7 @@ public class SandHook {
public static Object getObject(long address) {
long threadSelf = getThreadId();
if (threadSelf == 0)
if (address == 0 || threadSelf == 0)
return null;
return getObjectNative(threadSelf, address);
}
......
package com.swift.sandhook.xposedcompat.hookstub;
import com.swift.sandhook.utils.ParamWrapper;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class HookMethodEntity {
public Member origin;
public Method hook;
public Member bacup;
public Class[] parType;
public Class retType;
public HookMethodEntity(Member origin, Method hook, Member bacup) {
this.origin = origin;
this.hook = hook;
this.bacup = bacup;
}
public Object[] getArgs(long... addresses) {
if (addresses == null || addresses.length == 0)
return new Object[0];
if (parType == null || parType.length == 0)
return new Object[0];
int argStart = 0;
if (!isStatic()) {
argStart = 1;
}
Object[] args = new Object[parType.length];
for (int i = argStart;i < addresses.length;i++) {
args[i - argStart] = getArg(i - argStart, addresses[i]);
}
return args;
}
public long[] getArgsAddress(long[] oldAddress, Object... args) {
if (oldAddress == null || oldAddress.length == 0)
return new long[0];
long[] addresses = new long[oldAddress.length];
int argStart = 0;
if (!isStatic()) {
argStart = 1;
addresses[0] = oldAddress[0];
}
for (int i = 0;i < args.length;i++) {
addresses[i + argStart] = ParamWrapper.objectToAddress(args[i]);
}
return addresses;
}
public Object getThis(long address) {
if (isStatic())
return null;
return getArg(0, address);
}
public Object getArg(int index, long address) {
return ParamWrapper.addressToObject(parType[index], address);
}
public boolean isVoid() {
return retType == null || Void.TYPE.equals(retType);
}
public boolean isConstructor() {
return origin instanceof Constructor;
}
public boolean isStatic() {
return Modifier.isStatic(origin.getModifiers());
}
}
package com.swift.sandhook.xposedcompat.hookstub;
import com.swift.sandhook.utils.ParamWrapper;
public class HookMethodInfo {
public Class[] parType;
public Class retType;
public Object getArg(int index, long address) {
return ParamWrapper.addressToObject(parType[index], address);
}
public boolean isVoid() {
return Void.TYPE.equals(retType);
}
}
package com.swift.sandhook.xposedcompat.hookstub;
import android.util.Pair;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.utils.ParamWrapper;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
public class HookStubManager {
public final static int MAX_STUB_COUNT = 100;
public final static int MAX_STUB_ARGS = 4;
public final static int MAX_PER_STUB = 5;
public final static int MAX_STUB_COUNT = MAX_PER_STUB * (MAX_STUB_ARGS + 1);
public final static AtomicInteger[] curUseStubIndexes = new AtomicInteger[MAX_STUB_ARGS + 1];
public static Member[] originMethods = new Member[MAX_STUB_COUNT];
public static HookMethodEntity[] hookMethodEntities = new HookMethodEntity[MAX_STUB_COUNT];
private static final Map<Member, XposedBridge.CopyOnWriteSortedSet<XC_MethodHook>> hookCallbacks
= new HashMap<>();
static {
for (int i = 0;i < curUseStubIndexes.length;i++) {
curUseStubIndexes[i] = new AtomicInteger(0);
}
}
public static HookMethodEntity getHookMethodEntity(Member origin) {
Class[] parType;
Class retType;
boolean isStatic = Modifier.isStatic(origin.getModifiers());
if (origin instanceof Method) {
Method method = (Method) origin;
retType = method.getReturnType();
parType = method.getParameterTypes();
} else if (origin instanceof Constructor) {
Constructor constructor = (Constructor) origin;
retType = Void.TYPE;
parType = constructor.getParameterTypes();
} else {
return null;
}
if (!ParamWrapper.support(retType))
return null;
int needStubArgCount = isStatic ? 0 : 1;
if (parType != null) {
needStubArgCount += parType.length;
if (needStubArgCount > MAX_STUB_ARGS)
return null;
for (Class par:parType) {
if (!ParamWrapper.support(par))
return null;
}
}
synchronized (HookStubManager.class) {
Pair<Method,Method> methodPair = getStubMethodPair(SandHook.is64Bit(), needStubArgCount);
if (methodPair == null)
return null;
HookMethodEntity entity = new HookMethodEntity(origin, methodPair.first, methodPair.second);
entity.retType = retType;
entity.parType = parType;
return entity;
}
}
public static int getMethodId(int args, int index) {
return args * MAX_PER_STUB + index;
}
public static String getHookMethodName(int index) {
return "stub_hook_" + index;
}
public static String getbackupMethodName(int index) {
public static String getBackupMethodName(int index) {
return "stub_backup_" + index;
}
public static Object hookBridge(int index, CallOriginCallBack callOrigin, long... stubArgs) throws Throwable {
Member originMethod = originMethods[index];
return null;
private static synchronized Pair<Method,Method> getStubMethodPair(boolean is64Bit, int stubArgs) {
int curUseStubIndex = curUseStubIndexes[stubArgs].getAndIncrement();
if (curUseStubIndex >= MAX_PER_STUB)
return null;
Class[] pars = getFindMethodParTypes(is64Bit, stubArgs);
try {
if (is64Bit) {
Method hook = MethodHookerStubs64.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars);
Method backup = MethodHookerStubs64.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars);
if (hook == null || backup == null)
return null;
return new Pair<>(hook, backup);
} else {
Method hook = MethodHookerStubs32.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars);
Method backup = MethodHookerStubs32.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars);
if (hook == null || backup == null)
return null;
return new Pair<>(hook, backup);
}
} catch (Exception e) {
return null;
}
}
public static Class[] getFindMethodParTypes(boolean is64Bit, int stubArgs) {
if (stubArgs == 0)
return null;
Class[] args = new Class[stubArgs];
if (is64Bit) {
for (int i = 0;i < stubArgs;i++) {
args[i] = long.class;
}
} else {
for (int i = 0;i < stubArgs;i++) {
args[i] = int.class;
}
}
return args;
}
public static Object hookBridge(int id, CallOriginCallBack callOrigin, long... stubArgs) throws Throwable {
if (XposedBridge.disableHooks)
return callOrigin.call(stubArgs);
Member originMethod = originMethods[id];
HookMethodEntity entity = hookMethodEntities[id];
Object[] snapshot = hookCallbacks.get(originMethod).getSnapshot();
if (snapshot == null || snapshot.length == 0)
return callOrigin.call(stubArgs);
XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.method = originMethod;
if (hasArgs(stubArgs)) {
param.thisObject = entity.getThis(stubArgs[0]);
param.args = entity.getArgs(stubArgs);
}
int beforeIdx = 0;
do {
try {
((XC_MethodHook) snapshot[beforeIdx]).callBeforeHookedMethod(param);
} catch (Throwable t) {
// reset result (ignoring what the unexpectedly exiting callback did)
param.setResult(null);
param.returnEarly = false;
continue;
}
if (param.returnEarly) {
// skip remaining "before" callbacks and corresponding "after" callbacks
beforeIdx++;
break;
}
} while (++beforeIdx < snapshot.length);
// call original method if not requested otherwise
if (!param.returnEarly) {
try {
//prepare new args
long[] newArgs = entity.getArgsAddress(stubArgs, param.args);
param.setResult(callOrigin.call(newArgs));
} catch (Exception e) {
XposedBridge.log(e);
param.setThrowable(e);
}
}
// call "after method" callbacks
int afterIdx = beforeIdx - 1;
do {
Object lastResult = param.getResult();
Throwable lastThrowable = param.getThrowable();
try {
((XC_MethodHook) snapshot[afterIdx]).callAfterHookedMethod(param);
} catch (Throwable t) {
XposedBridge.log(t);
if (lastThrowable == null)
param.setResult(lastResult);
else
param.setThrowable(lastThrowable);
}
} while (--afterIdx >= 0);
if (param.hasThrowable()) {
return param.getResult();
} else {
final Object result = param.getResult();
return result;
}
}
private static boolean hasArgs(long... args) {
return args != null && args.length > 0;
}
}
package com.swift.sandhook.xposedcompat.hookstub;
public class MethodHookerStubs64 {
}
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