From 58665b310595de7b8b3d5585d4689039dd6cc587 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 4 Jan 2023 10:56:34 +0800 Subject: [PATCH] Implement some xposed utils --- .../de/robv/android/xposed/XC_MethodHook.java | 25 ++++++++-- .../de/robv/android/xposed/XposedBridge.java | 4 +- .../org/lsposed/lspd/impl/LSPosedContext.java | 12 ++--- .../org/lsposed/lspd/impl/LSPosedUtils.java | 49 ++++++++++++++++--- .../io/github/libxposed/XposedInterface.java | 11 +++++ .../java/io/github/libxposed/XposedUtils.java | 16 ++++-- 6 files changed, 92 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/de/robv/android/xposed/XC_MethodHook.java b/core/src/main/java/de/robv/android/xposed/XC_MethodHook.java index 83bc6457..cdaca4b9 100644 --- a/core/src/main/java/de/robv/android/xposed/XC_MethodHook.java +++ b/core/src/main/java/de/robv/android/xposed/XC_MethodHook.java @@ -103,7 +103,7 @@ public abstract class XC_MethodHook extends XCallback { /** * Wraps information about the method call and allows to influence it. */ - public static final class MethodHookParam extends XCallback.Param implements XposedInterface.BeforeHookCallback, XposedInterface.AfterHookCallback { + public static final class MethodHookParam extends XCallback.Param implements XposedInterface.BeforeHookCallback, XposedInterface.AfterHookCallback { /** * @hide */ @@ -115,7 +115,7 @@ public abstract class XC_MethodHook extends XCallback { /** * The hooked method/constructor. */ - public Member method; + public T method; /** * The {@code this} reference for an instance method, or {@code null} for static methods. @@ -193,7 +193,7 @@ public abstract class XC_MethodHook extends XCallback { @NonNull @Override public T getOrigin() { - return (T) method; + return method; } @Nullable @@ -208,6 +208,17 @@ public abstract class XC_MethodHook extends XCallback { return args; } + @Nullable + @Override + public U getArg(int index) { + return (U) args[index]; + } + + @Override + public void setArg(int index, U value) { + args[index] = value; + } + @Override public void returnAndSkip(@Nullable Object returnValue) { setResult(returnValue); @@ -221,7 +232,13 @@ public abstract class XC_MethodHook extends XCallback { @Nullable @Override public Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException { - return HookBridge.invokeOriginalMethod((Executable) method, thisObject, args); + return HookBridge.invokeOriginalMethod(method, thisObject, args); + } + + @Nullable + @Override + public Object invokeOrigin() throws InvocationTargetException, IllegalAccessException { + return HookBridge.invokeOriginalMethod(method, thisObject, args); } @Nullable diff --git a/core/src/main/java/de/robv/android/xposed/XposedBridge.java b/core/src/main/java/de/robv/android/xposed/XposedBridge.java index ed722fb5..fee436bf 100644 --- a/core/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/core/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -396,7 +396,7 @@ public final class XposedBridge { } } - public static class AdditionalHookInfo { + public static class AdditionalHookInfo { private final Object params; private AdditionalHookInfo(Executable method) { @@ -421,7 +421,7 @@ public final class XposedBridge { var array = ((Object[]) params); - var method = (Executable) array[0]; + var method = (T) array[0]; var returnType = (Class) array[1]; var isStatic = (Boolean) array[2]; diff --git a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java index 8dbc61a4..d02991c9 100644 --- a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java +++ b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java @@ -51,7 +51,6 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; -import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; @@ -59,7 +58,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedInit; @@ -762,14 +760,14 @@ public class LSPosedContext extends XposedContext { private MethodUnhooker doHook(U hookMethod, int priority, T callback) { if (Modifier.isAbstract(hookMethod.getModifiers())) { throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod); - } else if (hookMethod.getDeclaringClass().getClassLoader() == XposedBridge.class.getClassLoader()) { + } else if (hookMethod.getDeclaringClass().getClassLoader() == LSPosedContext.class.getClassLoader()) { throw new IllegalArgumentException("Do not allow hooking inner methods"); } else if (hookMethod.getDeclaringClass() == Method.class && hookMethod.getName().equals("invoke")) { throw new IllegalArgumentException("Cannot hook Method.invoke"); } if (callback == null) { - throw new IllegalArgumentException("callback should not be null!"); + throw new IllegalArgumentException("hooker should not be null!"); } if (HookBridge.hookMethod(hookMethod, XposedBridge.AdditionalHookInfo.class, priority, callback)) { @@ -857,7 +855,7 @@ public class LSPosedContext extends XposedContext { return doHook(origin, priority, hooker); } - private static boolean deoptimize(@NonNull Executable method) { + private static boolean doDeoptimize(@NonNull Executable method) { if (Modifier.isAbstract(method.getModifiers())) { throw new IllegalArgumentException("Cannot deoptimize abstract methods: " + method); } else if (Proxy.isProxyClass(method.getDeclaringClass())) { @@ -868,12 +866,12 @@ public class LSPosedContext extends XposedContext { @Override public boolean deoptimize(@NonNull Method method) { - return deoptimize((Executable) method); + return doDeoptimize(method); } @Override public boolean deoptimize(@NonNull Constructor constructor) { - return deoptimize((Executable) constructor); + return doDeoptimize(constructor); } @Nullable diff --git a/core/src/main/java/org/lsposed/lspd/impl/LSPosedUtils.java b/core/src/main/java/org/lsposed/lspd/impl/LSPosedUtils.java index 797707f5..c85dc080 100644 --- a/core/src/main/java/org/lsposed/lspd/impl/LSPosedUtils.java +++ b/core/src/main/java/org/lsposed/lspd/impl/LSPosedUtils.java @@ -3,6 +3,11 @@ package org.lsposed.lspd.impl; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.apache.commons.lang3.ClassUtils; + +import java.lang.reflect.Field; + +import de.robv.android.xposed.XposedHelpers; import io.github.libxposed.XposedUtils; public class LSPosedUtils implements XposedUtils { @@ -14,25 +19,53 @@ public class LSPosedUtils implements XposedUtils { @NonNull @Override - public Class classByName(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { - throw new AbstractMethodError(); + public Class findClass(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { + return (Class) ClassUtils.getClass(classLoader, className.replace('/', '.'), false); } @Nullable @Override - public Class classOrNullByName(@NonNull String className, @Nullable ClassLoader classLoader) { - throw new AbstractMethodError(); + public Class findClassOrNull(@NonNull String className, @Nullable ClassLoader classLoader) { + try { + return findClass(className, classLoader); + } catch (ClassNotFoundException e) { + return null; + } } @NonNull @Override - public Class classByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) throws ClassNotFoundException { - throw new AbstractMethodError(); + public Field findField(@NonNull Class clazz, @NonNull String fieldName) throws NoSuchFieldException { + try { + return XposedHelpers.findField(clazz, fieldName); + } catch (NoSuchFieldError e) { + throw new NoSuchFieldException(e.getMessage()); + } + } + + @Override + public Field findFieldOrNull(@NonNull Class clazz, @NonNull String fieldName) { + try { + return findField(clazz, fieldName); + } catch (NoSuchFieldException e) { + return null; + } + } + + @NonNull + @Override + public Field findField(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) throws ClassNotFoundException, NoSuchFieldException { + var clazz = findClass(className, classLoader); + return findField(clazz, fieldName); } @Nullable @Override - public Class classOrNullByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) { - throw new AbstractMethodError(); + public Field findFieldOrNull(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) { + try { + return findField(className, fieldName, classLoader); + } catch (ClassNotFoundException | NoSuchFieldException e) { + return null; + } } } diff --git a/libxposed/api/src/main/java/io/github/libxposed/XposedInterface.java b/libxposed/api/src/main/java/io/github/libxposed/XposedInterface.java index d05559a8..f66f38cd 100644 --- a/libxposed/api/src/main/java/io/github/libxposed/XposedInterface.java +++ b/libxposed/api/src/main/java/io/github/libxposed/XposedInterface.java @@ -21,6 +21,11 @@ public interface XposedInterface { @NonNull Object[] getArgs(); + @Nullable + U getArg(int index); + + void setArg(int index, U value); + void returnAndSkip(@Nullable Object returnValue); void throwAndSkip(@Nullable Throwable throwable); @@ -28,6 +33,9 @@ public interface XposedInterface { @Nullable Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException; + @Nullable + Object invokeOrigin() throws InvocationTargetException, IllegalAccessException; + void setExtra(@NonNull String key, @Nullable U value) throws ConcurrentModificationException; } @@ -56,6 +64,9 @@ public interface XposedInterface { @Nullable Object invokeOrigin(@Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalAccessException; + @Nullable + Object invokeOrigin() throws InvocationTargetException, IllegalAccessException; + @Nullable U getExtra(@NonNull String key); } diff --git a/libxposed/api/src/main/java/io/github/libxposed/XposedUtils.java b/libxposed/api/src/main/java/io/github/libxposed/XposedUtils.java index b5e6a9ab..e4f01950 100644 --- a/libxposed/api/src/main/java/io/github/libxposed/XposedUtils.java +++ b/libxposed/api/src/main/java/io/github/libxposed/XposedUtils.java @@ -3,16 +3,24 @@ package io.github.libxposed; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.lang.reflect.Field; + public interface XposedUtils { @NonNull - Class classByName(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException; + Class findClass(@NonNull String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException; @Nullable - Class classOrNullByName(@NonNull String className, @Nullable ClassLoader classLoader); + Class findClassOrNull(@NonNull String className, @Nullable ClassLoader classLoader); @NonNull - Class classByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader) throws ClassNotFoundException; + Field findField(@NonNull Class clazz, @NonNull String fieldName) throws NoSuchFieldException; @Nullable - Class classOrNullByBinaryName(@NonNull String binaryClassName, @Nullable ClassLoader classLoader); + Field findFieldOrNull(@NonNull Class clazz, @NonNull String fieldName); + + @NonNull + Field findField(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader) throws ClassNotFoundException, NoSuchFieldException; + + @Nullable + Field findFieldOrNull(@NonNull String className, @NonNull String fieldName, @Nullable ClassLoader classLoader); }