Commit cc279210 authored by swift_gan's avatar swift_gan Committed by swift_gan

done stub 32

parent 3b15f9e6
...@@ -66,9 +66,55 @@ public class ParamWrapper { ...@@ -66,9 +66,55 @@ public class ParamWrapper {
} }
} }
public static long objectToAddress(Object object) { public static long objectToAddress(Class objectType, Object object) {
if (object == null) { if (SandHook.is64Bit()) {
return objectToAddress64(objectType, object);
} else {
return objectToAddress32(objectType, object);
}
}
public static int objectToAddress32(Class objectType, Object object) {
if (object == null)
return 0; return 0;
if (objectType.isPrimitive()) {
if (objectType == int.class) {
return (int) object;
} else if (objectType == short.class) {
return (short)object;
} else if (objectType == byte.class) {
return (byte)object;
} else if (objectType == char.class) {
return (char)object;
} else if (objectType == boolean.class) {
return object == Boolean.TRUE ? 0 : 1;
} else {
throw new RuntimeException("unknown type: " + objectType.toString());
}
} else {
return (int) SandHook.getObjectAddress(object);
}
}
public static long objectToAddress64(Class objectType, Object object) {
if (object == null)
return 0;
if (objectType.isPrimitive()) {
if (objectType == int.class) {
return (int)object;
} else if (objectType == long.class) {
return (long) object;
} else if (objectType == short.class) {
return (short)object;
} else if (objectType == byte.class) {
return (byte)object;
} else if (objectType == char.class) {
return (char)object;
} else if (objectType == boolean.class) {
return object == Boolean.TRUE ? 0 : 1;
} else {
throw new RuntimeException("unknown type: " + objectType.toString());
}
} else { } else {
return SandHook.getObjectAddress(object); return SandHook.getObjectAddress(object);
} }
......
package com.swift.sandhook.xposedcompat.hookstub; package com.swift.sandhook.xposedcompat.hookstub;
public interface CallOriginCallBack { public interface CallOriginCallBack {
Object call(long... args) throws Throwable; int call(long... args) throws Throwable;
} }
package com.swift.sandhook.xposedcompat.hookstub; package com.swift.sandhook.xposedcompat.hookstub;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.utils.ParamWrapper; import com.swift.sandhook.utils.ParamWrapper;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
...@@ -11,14 +12,14 @@ public class HookMethodEntity { ...@@ -11,14 +12,14 @@ public class HookMethodEntity {
public Member origin; public Member origin;
public Method hook; public Method hook;
public Member bacup; public Method backup;
public Class[] parType; public Class[] parType;
public Class retType; public Class retType;
public HookMethodEntity(Member origin, Method hook, Member bacup) { public HookMethodEntity(Member origin, Method hook, Method backup) {
this.origin = origin; this.origin = origin;
this.hook = hook; this.hook = hook;
this.bacup = bacup; this.backup = backup;
} }
public Object[] getArgs(long... addresses) { public Object[] getArgs(long... addresses) {
...@@ -31,7 +32,7 @@ public class HookMethodEntity { ...@@ -31,7 +32,7 @@ public class HookMethodEntity {
argStart = 1; argStart = 1;
} }
Object[] args = new Object[parType.length]; Object[] args = new Object[parType.length];
for (int i = argStart;i < addresses.length;i++) { for (int i = argStart;i < parType.length + argStart;i++) {
args[i - argStart] = getArg(i - argStart, addresses[i]); args[i - argStart] = getArg(i - argStart, addresses[i]);
} }
return args; return args;
...@@ -46,8 +47,8 @@ public class HookMethodEntity { ...@@ -46,8 +47,8 @@ public class HookMethodEntity {
argStart = 1; argStart = 1;
addresses[0] = oldAddress[0]; addresses[0] = oldAddress[0];
} }
for (int i = 0;i < args.length;i++) { for (int i = argStart;i < parType.length + argStart;i++) {
addresses[i + argStart] = ParamWrapper.objectToAddress(args[i]); addresses[i + argStart] = ParamWrapper.objectToAddress(parType[i], args[i]);
} }
return addresses; return addresses;
} }
...@@ -55,13 +56,25 @@ public class HookMethodEntity { ...@@ -55,13 +56,25 @@ public class HookMethodEntity {
public Object getThis(long address) { public Object getThis(long address) {
if (isStatic()) if (isStatic())
return null; return null;
return getArg(0, address); return SandHook.getObject(address);
} }
public Object getArg(int index, long address) { public Object getArg(int index, long address) {
return ParamWrapper.addressToObject(parType[index], address); return ParamWrapper.addressToObject(parType[index], address);
} }
public Object getResult(long address) {
if (isVoid())
return null;
return ParamWrapper.addressToObject(retType, address);
}
public long getResultAddress(Object result) {
if (isVoid())
return 0;
return ParamWrapper.objectToAddress(retType, result);
}
public boolean isVoid() { public boolean isVoid() {
return retType == null || Void.TYPE.equals(retType); return retType == null || Void.TYPE.equals(retType);
} }
......
...@@ -16,26 +16,34 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -16,26 +16,34 @@ import java.util.concurrent.atomic.AtomicInteger;
import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedBridge;
import static de.robv.android.xposed.XposedBridge.sHookedMethodCallbacks;
public class HookStubManager { public class HookStubManager {
public final static int MAX_STUB_ARGS = 4; public final static int MAX_STUB_ARGS = 5;
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 int[] stubSizes = new int[] {
0,0,0,0,0,10
};
public final static AtomicInteger[] curUseStubIndexes = new AtomicInteger[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 int ALL_STUB = 0;
public static HookMethodEntity[] hookMethodEntities = new HookMethodEntity[MAX_STUB_COUNT];
public static Member[] originMethods;
public static HookMethodEntity[] hookMethodEntities;
private static final Map<Member, XposedBridge.CopyOnWriteSortedSet<XC_MethodHook>> hookCallbacks private static final Map<Member, XposedBridge.CopyOnWriteSortedSet<XC_MethodHook>> hookCallbacks
= new HashMap<>(); = sHookedMethodCallbacks;
static { static {
for (int i = 0;i < curUseStubIndexes.length;i++) { for (int i = 0;i < MAX_STUB_ARGS + 1;i++) {
curUseStubIndexes[i] = new AtomicInteger(0); curUseStubIndexes[i] = new AtomicInteger(0);
ALL_STUB += stubSizes[i];
} }
originMethods = new Member[ALL_STUB];
hookMethodEntities = new HookMethodEntity[ALL_STUB];
} }
...@@ -70,21 +78,31 @@ public class HookStubManager { ...@@ -70,21 +78,31 @@ public class HookStubManager {
if (!ParamWrapper.support(par)) if (!ParamWrapper.support(par))
return null; return null;
} }
} else {
parType = new Class[0];
} }
synchronized (HookStubManager.class) { synchronized (HookStubManager.class) {
Pair<Method,Method> methodPair = getStubMethodPair(SandHook.is64Bit(), needStubArgCount); StubMethodsInfo stubMethodInfo = getStubMethodPair(SandHook.is64Bit(), needStubArgCount);
if (methodPair == null) if (stubMethodInfo == null)
return null; return null;
HookMethodEntity entity = new HookMethodEntity(origin, methodPair.first, methodPair.second); HookMethodEntity entity = new HookMethodEntity(origin, stubMethodInfo.hook, stubMethodInfo.backup);
entity.retType = retType; entity.retType = retType;
entity.parType = parType; entity.parType = parType;
int id = getMethodId(stubMethodInfo.args, stubMethodInfo.index);
originMethods[id] = origin;
hookMethodEntities[id] = entity;
tryCompileCallOriginMethod(stubMethodInfo.args, stubMethodInfo.index);
return entity; return entity;
} }
} }
public static int getMethodId(int args, int index) { public static int getMethodId(int args, int index) {
return args * MAX_PER_STUB + index; int id = index;
for (int i = 0;i < args;i++) {
id += stubSizes[i];
}
return id;
} }
public static String getHookMethodName(int index) { public static String getHookMethodName(int index) {
...@@ -95,10 +113,33 @@ public class HookStubManager { ...@@ -95,10 +113,33 @@ public class HookStubManager {
return "stub_backup_" + index; return "stub_backup_" + index;
} }
private static synchronized Pair<Method,Method> getStubMethodPair(boolean is64Bit, int stubArgs) { public static String getCallOriginClassName(int args, int index) {
int curUseStubIndex = curUseStubIndexes[stubArgs].getAndIncrement(); return "call_origin_" + args + "_" + index;
if (curUseStubIndex >= MAX_PER_STUB) }
static class StubMethodsInfo {
int args = 0;
int index = 0;
Method hook;
Method backup;
public StubMethodsInfo(int args, int index, Method hook, Method backup) {
this.args = args;
this.index = index;
this.hook = hook;
this.backup = backup;
}
}
private static synchronized StubMethodsInfo getStubMethodPair(boolean is64Bit, int stubArgs) {
stubArgs = getMatchStubArgsCount(stubArgs);
if (stubArgs < 0)
return null; return null;
int curUseStubIndex = curUseStubIndexes[stubArgs].getAndIncrement();
Class[] pars = getFindMethodParTypes(is64Bit, stubArgs); Class[] pars = getFindMethodParTypes(is64Bit, stubArgs);
try { try {
if (is64Bit) { if (is64Bit) {
...@@ -106,19 +147,47 @@ public class HookStubManager { ...@@ -106,19 +147,47 @@ public class HookStubManager {
Method backup = MethodHookerStubs64.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars); Method backup = MethodHookerStubs64.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars);
if (hook == null || backup == null) if (hook == null || backup == null)
return null; return null;
return new Pair<>(hook, backup); return new StubMethodsInfo(stubArgs, curUseStubIndex, hook, backup);
} else { } else {
Method hook = MethodHookerStubs32.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars); Method hook = MethodHookerStubs32.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars);
Method backup = MethodHookerStubs32.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars); Method backup = MethodHookerStubs32.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars);
if (hook == null || backup == null) if (hook == null || backup == null)
return null; return null;
return new Pair<>(hook, backup); return new StubMethodsInfo(stubArgs, curUseStubIndex, hook, backup);
} }
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }
} }
public static Method getCallOriginMethod(int args, int index) {
String className = SandHook.is64Bit() ? MethodHookerStubs64.class.getName() : MethodHookerStubs32.class.getName();
className += "$";
className += getCallOriginClassName(args, index);
try {
Class callOriginClass = Class.forName(className);
return callOriginClass.getDeclaredMethod("call", long[].class);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void tryCompileCallOriginMethod(int args, int index) {
Method method = getCallOriginMethod(args, index);
if (method != null) {
SandHook.compileMethod(method);
}
}
public static int getMatchStubArgsCount(int stubArgs) {
for (int i = stubArgs;i <= MAX_STUB_ARGS;i++) {
if (curUseStubIndexes[i].get() < stubSizes[i])
return i;
}
return -1;
}
public static Class[] getFindMethodParTypes(boolean is64Bit, int stubArgs) { public static Class[] getFindMethodParTypes(boolean is64Bit, int stubArgs) {
if (stubArgs == 0) if (stubArgs == 0)
return null; return null;
...@@ -135,7 +204,7 @@ public class HookStubManager { ...@@ -135,7 +204,7 @@ public class HookStubManager {
return args; return args;
} }
public static Object hookBridge(int id, CallOriginCallBack callOrigin, long... stubArgs) throws Throwable { public static long hookBridge(int id, CallOriginCallBack callOrigin, long... stubArgs) throws Throwable {
if (XposedBridge.disableHooks) if (XposedBridge.disableHooks)
return callOrigin.call(stubArgs); return callOrigin.call(stubArgs);
...@@ -179,7 +248,7 @@ public class HookStubManager { ...@@ -179,7 +248,7 @@ public class HookStubManager {
try { try {
//prepare new args //prepare new args
long[] newArgs = entity.getArgsAddress(stubArgs, param.args); long[] newArgs = entity.getArgsAddress(stubArgs, param.args);
param.setResult(callOrigin.call(newArgs)); param.setResult(entity.getResult(callOrigin.call(newArgs)));
} catch (Exception e) { } catch (Exception e) {
XposedBridge.log(e); XposedBridge.log(e);
param.setThrowable(e); param.setThrowable(e);
...@@ -204,10 +273,10 @@ public class HookStubManager { ...@@ -204,10 +273,10 @@ public class HookStubManager {
} while (--afterIdx >= 0); } while (--afterIdx >= 0);
if (param.hasThrowable()) { if (param.hasThrowable()) {
return param.getResult(); return entity.getResultAddress(param.getResult());
} else { } else {
final Object result = param.getResult(); final Object result = param.getResult();
return result; return entity.getResultAddress(result);
} }
} }
......
package com.swift.sandhook.xposedcompat.hookstub; package com.swift.sandhook.xposedcompat.hookstub;
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge;
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.getMethodId;
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.originMethods;
import static com.swift.sandhook.xposedcompat.utils.DexLog.printCallOriginError;
public class MethodHookerStubs32 { public class MethodHookerStubs32 {
static class call_origin_5_0 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_0((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_0(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 0), new call_origin_5_0(), a, b, c, d, e);
}
public static int stub_backup_0(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 0)]);
} catch (Throwable throwable) {}
return 0;
}
static class call_origin_5_1 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_1((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_1(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 1), new call_origin_5_1(), a, b, c, d, e);
}
public static int stub_backup_1(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 1)]);
} catch (Throwable throwable) {}
return 0;
}
static class call_origin_5_2 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_2((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_2(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 2), new call_origin_5_2(), a, b, c, d, e);
}
public static int stub_backup_2(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 2)]);
} catch (Throwable throwable) {}
return 0;
}
static class call_origin_5_3 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_3((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_3(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 3), new call_origin_5_3(), a, b, c, d, e);
}
public static int stub_backup_3(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 3)]);
} catch (Throwable throwable) {}
return 0;
}
static class call_origin_5_4 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_4((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_4(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 4), new call_origin_5_4(), a, b, c, d, e);
}
public static int stub_backup_4(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 4)]);
} catch (Throwable throwable) {}
return 0;
}
static class call_origin_5_5 implements CallOriginCallBack {
@Override
public int call(long... args) throws Throwable {
return stub_backup_5((int)args[0], (int)args[1],(int) args[2], (int)args[3], (int)args[4]);
}
}
public static int stub_hook_5(int a, int b, int c, int d, int e) throws Throwable {
return (int) hookBridge(getMethodId(5, 5), new call_origin_5_5(), a, b, c, d, e);
}
public static int stub_backup_5(int a, int b, int c, int d, int e) throws Throwable {
try {
printCallOriginError(originMethods[getMethodId(5, 5)]);
} catch (Throwable throwable) {}
return 0;
}
} }
...@@ -2,7 +2,11 @@ package com.swift.sandhook.xposedcompat.methodgen; ...@@ -2,7 +2,11 @@ package com.swift.sandhook.xposedcompat.methodgen;
import android.os.Trace; import android.os.Trace;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.wrapper.HookWrapper;
import com.swift.sandhook.xposedcompat.XposedCompat; import com.swift.sandhook.xposedcompat.XposedCompat;
import com.swift.sandhook.xposedcompat.hookstub.HookMethodEntity;
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
import com.swift.sandhook.xposedcompat.utils.DexLog; import com.swift.sandhook.xposedcompat.utils.DexLog;
import com.swift.sandhook.xposedcompat.utils.FileUtils; import com.swift.sandhook.xposedcompat.utils.FileUtils;
...@@ -56,11 +60,16 @@ public final class DynamicBridge { ...@@ -56,11 +60,16 @@ public final class DynamicBridge {
} }
Trace.beginSection("SandHook-Xposed"); Trace.beginSection("SandHook-Xposed");
long timeStart = System.currentTimeMillis(); long timeStart = System.currentTimeMillis();
dexMaker.start(hookMethod, additionalHookInfo, HookMethodEntity stub = HookStubManager.getHookMethodEntity(hookMethod);
XposedCompat.classLoader, dexDir == null ? null : dexDir.getAbsolutePath()); if (stub != null) {
SandHook.hook(new HookWrapper.HookEntity(hookMethod, stub.hook, stub.backup));
} else {
dexMaker.start(hookMethod, additionalHookInfo,
XposedCompat.classLoader, dexDir == null ? null : dexDir.getAbsolutePath());
hookedInfo.put(hookMethod, dexMaker.getCallBackupMethod());
}
DexLog.d("hook method <" + hookMethod.toString() + "> use " + (System.currentTimeMillis() - timeStart) + " ms."); DexLog.d("hook method <" + hookMethod.toString() + "> use " + (System.currentTimeMillis() - timeStart) + " ms.");
Trace.endSection(); Trace.endSection();
hookedInfo.put(hookMethod, dexMaker.getCallBackupMethod());
} catch (Exception e) { } catch (Exception e) {
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e); DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
} }
......
...@@ -61,7 +61,7 @@ public final class XposedBridge { ...@@ -61,7 +61,7 @@ public final class XposedBridge {
private static final Object[] EMPTY_ARRAY = new Object[0]; private static final Object[] EMPTY_ARRAY = new Object[0];
// built-in handlers // built-in handlers
private static final Map<Member, CopyOnWriteSortedSet<XC_MethodHook>> sHookedMethodCallbacks = new HashMap<>(); public static final Map<Member, CopyOnWriteSortedSet<XC_MethodHook>> sHookedMethodCallbacks = new HashMap<>();
public static final CopyOnWriteSortedSet<XC_LoadPackage> sLoadedPackageCallbacks = new CopyOnWriteSortedSet<>(); public static final CopyOnWriteSortedSet<XC_LoadPackage> sLoadedPackageCallbacks = new CopyOnWriteSortedSet<>();
/*package*/ static final CopyOnWriteSortedSet<XC_InitPackageResources> sInitPackageResourcesCallbacks = new CopyOnWriteSortedSet<>(); /*package*/ static final CopyOnWriteSortedSet<XC_InitPackageResources> sInitPackageResourcesCallbacks = new CopyOnWriteSortedSet<>();
......
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