通过 hook Xposed Framework API 实现

1. 前言

       前段时间在分析一款 Xposed 模块时,发现其加固了。使用 FDex2 成功脱出 dex 后,发现它的混淆做得极好,甚至字符串也做了加密,加之它的功能比较强大,钩子数量很多,静态分析基本行不通。

       后来想起以前在吾爱破解看过一篇文章,作者也遇到了类似的问题,后面通过 hook Xposed 框架的 API 打印出了全部的钩子。因为时间比较久远,无法找到那篇文章,而且作者只提了思路,并没有给出具体实现,所以就自己实现了一下。

2. 常规方法

       先复习一下查看 Xposed 模块钩子的常规方法:

3. 新方法

3.1 思路

       在编写 Xposed 模块的钩子时,都是通过以下接口实现:

       XposedHelpers

* static XC_MethodHook.Unhook	findAndHookConstructor(Class<?> clazz, Object... parameterTypesAndCallback)
	* Look up a constructor and hook it.
* static XC_MethodHook.Unhook	findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback)
	* Look up a constructor and hook it.
* static XC_MethodHook.Unhook	findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)
	* Look up a method and hook it.
* static XC_MethodHook.Unhook	findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)
	* Look up a method and hook it.

       XposedBridge

* static Set<XC_MethodHook.Unhook>	hookAllConstructors(Class<?> hookClass, XC_MethodHook callback)
	* Hook all constructors of the specified class.
* static Set<XC_MethodHook.Unhook>	hookAllMethods(Class<?> hookClass, String methodName, XC_MethodHook callback)
	* Hooks all methods with a certain name that were declared in the specified class.

       因此,我们只需 hook Xposed Framework API 中的这些方法,将传入参数打印出来,就可以知道模块使用了哪些钩子。

3.2 实现

       移除存在间接调用的接口后,最终实现如下:

    @Override
    public void initZygote(StartupParam startupParam) throws Throwable {
        hookXposedFrameworkApi(startupParam);
    }

    /**
     * 用于分析第三方 XP 模块采用了哪些钩子,主要用于模块包体比较大,
     * 做了加固或者混淆做得比较彻底的场景
     * <p>
     * 钩子的目标类和方法名,可在 Xposed Installer 的日志中查看
     */
    private void hookXposedFrameworkApi(StartupParam param) {
        hookXpFindAndHookMethod();
        hookXpFindAndHookConstructor();
        hookXpHookAllMethods();
        hookXpHookAllConstructors();
    }

    private void hookXpFindAndHookMethod() {
        try {
            Class cls = XposedHelpers.findClass(
                    "de.robv.android.xposed.XposedHelpers",
                    HookUtils.class.getClassLoader());
            XposedHelpers.findAndHookMethod(cls, "findAndHookMethod",
                    Class.class, String.class, Object[].class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            XposedBridge.log("findAndHookMethod: cls = " + param.args[0]
                                    + ", method = " + param.args[1]);
                        }
                    });
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    private void hookXpFindAndHookConstructor() {
        try {
            Class cls = XposedHelpers.findClass(
                    "de.robv.android.xposed.XposedHelpers",
                    HookUtils.class.getClassLoader());
            XposedHelpers.findAndHookMethod(cls, "findAndHookConstructor",
                    Class.class, Object[].class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            XposedBridge.log("findAndHookConstructor: cls = " + param.args[0]);
                        }
                    });
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    private void hookXpHookAllMethods() {
        try {
            Class cls = XposedHelpers.findClass(
                    "de.robv.android.xposed.XposedBridge",
                    HookUtils.class.getClassLoader());
            Class clsXC_MethodHook = XposedHelpers.findClass(
                    "de.robv.android.xposed.XC_MethodHook", HookUtils.class.getClassLoader()
            );
            XposedHelpers.findAndHookMethod(cls, "hookAllMethods",
                    Class.class, String.class, clsXC_MethodHook, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            XposedBridge.log("hookAllMethods: cls = " + param.args[0]
                                    + ", method = " + param.args[1]);
                        }
                    });
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

    private void hookXpHookAllConstructors() {
        try {
            Class cls = XposedHelpers.findClass(
                    "de.robv.android.xposed.XposedBridge",
                    HookUtils.class.getClassLoader());
            Class clsXC_MethodHook = XposedHelpers.findClass(
                    "de.robv.android.xposed.XC_MethodHook", HookUtils.class.getClassLoader()
            );
            XposedHelpers.findAndHookMethod(cls, "hookAllConstructors",
                    Class.class, clsXC_MethodHook, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            XposedBridge.log("hookAllConstructors: cls = " + param.args[0]);
                        }
                    });
        } catch (Exception e) {
            XposedBridge.log(e);
        }
    }

3.3 说明

3.4 优缺点

优点

缺点

4. 总结

       你无法确定现在学到的知识是否会在将来的某一天派上用场,所以努力扩充你的知识,善待周边的人吧!