Xposed功能:

Xposed理论上能够hook到系统任意一个Java进程,由于是从底层hook,所以需要root权限,并且每次更新都要重新启动。

[1] 对普通函数或者构造函数有作用(针对具体实现类,不包括接口,抽象类的实现函数也可以hook)。

[2] 对目标函数进行 before、after 代码插桩,多用于操作(查看或修改)api的入参以及返回值。

[3] 目标函数替换,多用于功能变更、版本升级。

主要API:

1、IXposedHookLoadPackage 接口,App被加载的时候调用,用于App应用的hook回调方法是handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam)

lpparam包含正在加载的应用程序的有关信息。

2、XposedHelps 类,hook函数/构造函数,获取变量的辅助类

findMehtod/findConstructor/findField方法

上述三种方法可以不适用反射技术来检索methods,constructors和fields。当然,你可以使用“best match”通过确切的参数类型来查找methods和constructors。例如:调用findMethodBestMatch(Class<?> clazz,String methodName,Object… args)

callMethod/callStaticMethod/newInstance方法

通过利用上述的findxxx 方法,可以很容易地调用方法或创建一个类的实例。调用者无需对此使用反射。在这之前不许检索方法,仅仅使用上述三个方法就可以做到即时调用。参数类型会自动地从实际参数值和被调用的best-matching方法中拷贝过来。假使你想要精确地为一个参数指定类型,那么需要创建一个 Class<?>数组并传递给callMethod/callStaticMethod/newInstance方法。你可以丢弃数组中一些null值仅仅使用类的实际参数,但是数组的长度不得不与参数的数量想匹配。

getxxxField/setxxxField/getStaticxxxField/setStaticxxxField方法

上述四种方法常被使用来获取或设置实例的内容和类的变量。只需要获得对对象的引用,就可以获得对象的field的名称和类型。如果你想要 get/set 一个静态的字段,并且没有对象的引用,那么这时就可以使用getStaticxxx和setStaticxxx方法。当你获得一个对象的引用时,就可以使用getxxx和setxxx方法,因为没必要再区分静态和实例字段。

getAdditionalxxxField/setAdditionalxxxField方法

上面的两个方法可以让你要么与一个对象的实例关联任何值,要么与整个类关联任何值。这些值都是以键值对的形式存储在map中,所以你可以为每个对象保存许多值。键名key可以是string类型的,包括对象真实的字段名。请注意你不能通过调用getAdditionalInstanceField方法来检索一个以setAdditionalStaticField方法存储的值。使用getAdditionalStaticField方法可以。

getProcessPid方法

这个方法可以通过它的/proc/[pid]/cmdline的第一部分找到一个进程并且以字符串的形式返回PID。

getMD5Sum方法

这个方法可以返回文件系统中的一个文件的md5值。这需要app有对文件读取的权限。

#####assetAsByteArray方法

这个方法可以将一个asset资源以字节数组的形式返回。如果想要加载module的资源,可以通过以下的方法实现:

public class XposedTweakbox implements IXposedHookZygoteInit {
  @Override
  public void initZygote(StartupParam startupParam) throws Throwable {
      Resources tweakboxRes = XModuleResources.createInstance(startupParam.modulePath, null);
      byte[] crtPatch = assetAsByteArray(tweakboxRes, "crtfix_samsung_d506192d5049a4042fb84c0265edfe42.bsdiff");
...

MethodHookParam param 包含与调用方法有关的信息。可以通过调用param.setResult()设置方法返回值。

param.thisObject,代表调用该方法的对象实例,如果是静态方法的话,返回一个NULL。

hook重载函数时候,只需要忽略参数的具体类型即可。这种方式其实可以达到两种效果:1. 高效的处理函数重载问题 2.目标函数参数类型太复杂,自定义的类型太多

3、XposedBridge 类,打印日志log(),有长度限制(1024),否则会被截断

hookAllMethods和hookAllConstructors方法

如果想通过明确的函数名或者一个类的构造函数 来hook所有的方法,我们可以使用这两个方法。如果要hook的类有不同的变体,这将是很有用的,但你想执行的代码(before/after)已经被调用了。注意其他不同的ROM可能也会有不同的变体,那么他们也会被hook。特别要留意你得到的回调函数的参数。

实例解析:

1.不需要获取类对象,即可直接修改类中的私有静态变量staticInt

XposedHelpers.setStaticIntField(clazz, "staticInt", 99);

2.Hook无参构造函数,啥也不干。。。。

XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("Haha, HookDemo constructed was hooked" );
                    //大坑,此时对象还没有建立,即不能获取对象,也不能修改非静态变量的值
                    //XposedHelpers.setIntField(param.thisObject, "publicInt", 199);
                    //XposedHelpers.setIntField(param.thisObject, "privateInt", 299);
                }
            });

3.Hook有参构造函数,修改参数

    XposedHelpers.findAndHookConstructor(clazz, String.class,  new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, HookDemo(str) are hooked";
                }
            });

4.Hook有参构造函数,修改参数------不能使用XC_MethodReplacement()替换构造函数内容

  //XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodReplacement() {
            //    @Override
            //    protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
            //        Log.d("HookDemo" , "HookDemo(str) was replace");
            //    }
            //});

5.Hook公有方法publicFunc

            // 1、修改参数
            // 2、修改下publicInt和privateInt的值
            // 3、再顺便调用一下隐藏函数hideFunc
            //XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "publicFunc", String.class, new XC_MethodHook()
            XposedHelpers.findAndHookMethod(clazz, "publicFunc", String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, publicFunc are hooked";
                    XposedHelpers.setIntField(param.thisObject, "publicInt", 199);
                    XposedHelpers.setIntField(param.thisObject, "privateInt", 299);
                    // 让hook的对象本身去执行流程
                    Method md = clazz.getDeclaredMethod("hideFunc", String.class);
                    md.setAccessible(true);
                    //md.invoke(param.thisObject, "Haha, hideFunc was hooked");
                    XposedHelpers.callMethod(param.thisObject, "hideFunc", "Haha, hideFunc was hooked");

                    //实例化对象,然后再调用HideFunc方法
                    //Constructor constructor = clazz.getConstructor();
                    //XposedHelpers.callMethod(constructor.newInstance(), "hideFunc", "Haha, hideFunc was hooked");
                }
            });

6.Hook私有方法privateFunc,修改参数

        //XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "privateFunc", String.class, new XC_MethodHook()
            XposedHelpers.findAndHookMethod(clazz, "privateFunc", String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, privateFunc are hooked";
                }
            });

7.Hook私有静态方法staticPrivateFunc, 修改参数

     XposedHelpers.findAndHookMethod(clazz, "staticPrivateFunc", String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, staticPrivateFunc are hooked";
                }
            });

8.Hook复杂参数函数complexParameterFunc

    Class fclass1 = XposedHelpers.findClass("java.util.Map", loadPackageParam.classLoader);
            Class fclass2 = XposedHelpers.findClass("java.util.ArrayList", loadPackageParam.classLoader);
            XposedHelpers.findAndHookMethod(clazz, "complexParameterFunc", String.class,
                    "[[Ljava.lang.String;", fclass1, fclass2, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            param.args[0] = "Haha, complexParameterFunc are hooked";
                        }
                    });

9.Hook私有方法repleaceFunc, 替换打印内容

     XposedHelpers.findAndHookMethod(clazz, "repleaceFunc", new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                    Log.d("HookDemo", "Haha, repleaceFunc are replaced");
                    return null;
                }
            });

10.Hook方法, anonymousInner, 参数是抽象类,先加载所需要的类即可

            Class animalClazz  = loadPackageParam.classLoader.loadClass("com.example.xposedhooktarget.Animal");
            XposedHelpers.findAndHookMethod(clazz, "anonymousInner", animalClazz, String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("HookDemo This is test");
                    param.args[1] = "Haha, anonymousInner are hooked";
                }
            });

11.Hook匿名类的eatFunc方法,修改参数,顺便修改类中的anonymoutInt变量

            XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo$1", clazz.getClassLoader(),
                    "eatFunc", String.class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            param.args[0] = "Haha, eatFunc are hooked";
                            XposedHelpers.setIntField(param.thisObject, "anonymoutInt", 499);
                        }
                    });

12.hook内部类的构造方法失败,且会导致hook内部类的InnerFunc方法也失败,原因不明

//            XposedHelpers.findAndHookConstructor(clazz1, new XC_MethodHook() {
//                        @Override
//                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//                            XposedBridge.log("Haha, InnerClass constructed was hooked" );
//                        }
//                    });

13.Hook内部类InnerClass的InnerFunc方法,修改参数,顺便修改类中的innerPublicInt和innerPrivateInt变量

            final Class<?> clazz1 = XposedHelpers.findClass("com.example.xposedhooktarget.HookDemo$InnerClass", loadPackageParam.classLoader);
            XposedHelpers.findAndHookMethod(clazz1, "InnerFunc", String.class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            param.args[0] = "Haha, InnerFunc was hooked";
                            XposedHelpers.setIntField(param.thisObject, "innerPublicInt", 9);
                            XposedHelpers.setIntField(param.thisObject, "innerPrivateInt", 19);
                        }
                    });
//getFields()与getDeclaredFields()区别:
//getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有变量.
//getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的变量
//getMethods()与getDeclaredMethods()区别:
//getMethods()只能访问类中声明为公有的方法,私有的方法它无法访问,能访问从其它类继承来的公有方法.
//getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法
//getConstructors()与getDeclaredConstructors()区别:
//getConstructors()只能访问类中声明为public的构造函数
//getDeclaredConstructors()能访问类中所有的构造函数,与public,private,protect无关

简单使用:

1、新建Android project,将jar包api-xx.jar api-xx-sources.jar拷贝到新建lib文件夹,不能使用Android自带的libs文件夹

2、在app/main下新建assets文件夹,新建文件xposed-init ,只包含hook类全路径(例如:com.ex.yu.xposed_demo.Main)

3、配置app下build.gradle文件,dependencies中添加jar包依赖

provided 'de.robv.android.xposed:api:xx'

4、编辑AndroidManifest.xml,添加:

<meta-data
       android:name="xposedmodule"
       android:value="true"/>
   <meta-data
       android:name="xposeddescription"
       android:value="hello xposed"/>
   <meta-data
       android:name="xposedminversion"
       android:value="82"/>

5、编写Main文件

results matching ""

    No results matching ""