Xposed從入門到棄坑:0x03、XposedHelpers類解析

WrBug發表於2019-03-04

感覺好久沒更新xposed教程了。應該有兩個月了,主要是工作太忙,沒有時間寫部落格。這節主要講解XposedHelpers類的一些用法,對前面內容有遺忘的可以再回過去預習下。
更多精彩內容可以關注我的部落格:www.wrbug.com

XposedHelpers類是幹嘛的?

在XposedHelpers類的頂部有一句註釋

/**
 * Helpers that simplify hooking and calling methods/constructors, getting and settings fields, ...
 */
public final class XposedHelpers {
}複製程式碼

大概意思是可以hook活著呼叫方法/建構函式。獲取該類的欄位等。這裡需要用到反射的姿勢。不瞭解的可以先看看反射相關的。XposedHelpers提供了非常方便的或者這些引數的方法。

XposedHelpers方法說明

//className  完整類名,classLoader 類載入器(app應用的類載入器)
public static Class<?> findClass(String className, ClassLoader classLoader)

public static Class<?> findClassIfExists(String className, ClassLoader classLoader)複製程式碼

獲取class的方法。其中findclass方法在未找到時丟擲異常,findClassIfExists則返回null


// clazz 通過findClass獲取,呼叫findFieldRecursiveImpl獲取
public static Field findField(Class<?> clazz, String fieldName)

public static Field findFieldIfExists(Class<?> clazz, String fieldName)

private static Field findFieldRecursiveImpl(Class<?> clazz, String fieldName) throws NoSuchFieldException {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            while (true) {
                clazz = clazz.getSuperclass();
                if (clazz == null || clazz.equals(Object.class))
                    break;

                try {
                    return clazz.getDeclaredField(fieldName);
                } catch (NoSuchFieldException ignored) {}
            }
            throw e;
        }
    }

public static Field findFirstFieldByExactType(Class<?> clazz, Class<?> type)

//獲取例項欄位的引用
public static Object getObjectField(Object obj, String fieldName)複製程式碼

獲取Field的方法,具體實現是在findFieldRecursiveImpl方法裡面獲取,外部不能訪問,Field是通過getDeclaredField獲取,所以只能獲取static型別的欄位。indFirstFieldByExactType()方法是匹配Field的classType,如果型別一樣,則返回該欄位,該方法的侷限性是隻能獲取到第一個匹配到的欄位,後面相同型別的無法獲取

public static Method findMethodExact(Class<?> clazz, String methodName, Object... parameterTypes) 

public static Method findMethodExactIfExists(Class<?> clazz, String methodName, Object... parameterTypes)複製程式碼

獲取Method方法,還有些其他的方法這裡省略,也只能獲取靜態方法

public static Constructor<?> findConstructorExact(Class<?> clazz, Object... parameterTypes)

public static Constructor<?> findConstructorExactIfExists(Class<?> clazz, Object... parameterTypes) 

public static Constructor<?> findConstructorBestMatch(Class<?> clazz, Class<?>... parameterTypes)複製程式碼

獲取Constructor方法,其中Object… parameterTypes 是一個Object的可變陣列,parameterTypes由Class<?>的可變陣列 ,完整類名字串和XC_MethodHook抽象類 組成。XC_MethodHook為可選引數,並且總在最後一個。XC_MethodHook在這裡並無實際意義,Class<?>[] 為相應的建構函式的型別,通過一個例子簡單說明,有一個T類,建構函式有三個引數,可以用以下幾種方式獲取:

public class T {
    String str;
    Context mContext;
    View mView;

    public T(String str, Context context, View view) {
        this.str = str;
        mContext = context;
        mView = view;

    }

}

//方式1:
Constructor constructor = XposedHelpers.findConstructorExact(clazz, String.class, Context.class, View.class);

//方式2:
Constructor constructor = XposedHelpers.findConstructorExact(T.class, String.class, "android.content.Context", View.class);

//方式3:(XC_MethodHook無實際意義)
Constructor constructor = XposedHelpers.findConstructorExact(T.class, String.class, "android.content.Context", View.class, new XC_MethodHook() {});複製程式碼

public static void setXXXField(Object obj, String fieldName, XXX value)
public static void setStaticXXXField(Class<?> clazz, String fieldName, XXX value)

public static Xxx getXxxField(Object obj, String fieldName)
public static Xxx getStaticXxxField(Class<?> clazzj, String fieldName)複製程式碼

設定或者獲取Field的值,obj為例項,則為設定或者獲取該成員變數的值

public static Object callMethod(Object obj, String methodName, Object... args)

public static Object callMethod(Object obj, String methodName, Class<?>[] parameterTypes, Object... args)

public static Object callStaticMethod(Class<?> clazz, String methodName, Object... args)

public static Object callStaticMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... args)複製程式碼

呼叫例項/靜態Method,返回值為方法返回值

public static XC_MethodHook.Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)

//通過className和classLoader獲取Class<?> ,再呼叫上面的方法
public static XC_MethodHook.Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)複製程式碼

Hook方法的一個方法,其中parameterTypesAndCallback和findConstructorExact方法的parameterTypes類似,不過這裡可變陣列最後一個物件必須為XC_MethodHook物件或者其子類,前面的物件為引數的ClassType或者類字串,在hook成功後,當呼叫hook的方法時,會在XC_MethodHook回撥

public abstract class XC_MethodHook extends XCallback {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                //方法呼叫前的回撥
                super.beforeHookedMethod(param);
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                //方法呼叫後的回撥
                super.afterHookedMethod(param);
            }
        }

public abstract class XC_MethodReplacement extends XC_MethodHook{
            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                //帶返回值的方法執行時呼叫
                return null;
            }
        }複製程式碼

可以通過這兩個class進行hook監聽。

本節示例

git提交:45c44ab4be96f012e7c4992bfdcc3bc2d3e458d7

git checkout 45c44ab複製程式碼

相關文章