Xposed安装与使用

框架安装与模块使用

Posted by JovenHe on July 10, 2018

手机安装Xposed

之前是在电脑模拟器上安装的,使用的是网易mumu模拟器,这个模拟器已经被root,安装XposedInstaller后点击框架-安装或更新-重启,就可用了,而且重启十分快速,用于开发前期的工作十分方便,但一些问题在真机上会 暴露出来,所以还是需要一个真机的。

华为手机

官网申请解锁,有了解锁码,下载华为手机助手和Google adb(包含fastboot),根据华为官网上的解锁步骤进行解锁

解锁后于花粉论坛上找的教程,刷入第三方rec,使用第三方rec安装第三方ROM包,需要专门找版本、手机型号都对应的包,不然会出不少问题,我就因为没刷补丁,死活打不开开发者模式,刷入补丁就好了。

安装Xposed

官方安装器下载地址

xposed安装器下载.png

第一个适用于android5及以上的,第二个是5以下的。

下载XposedInstaller.apk并安装到手机

打开app,点击安装框架,重启生效

工程

引入jar包

https://bintray.com/rovo89/de.robv.android.xposed/api

AndroidManifest

AndroidManifest中在application标签下写入

<!--是否是Xposed模块-->
<meta-data
	android:name="xposedmodule"
    android:value="true" />
<!--Xposed模块说明-->
<meta-data
    android:name="xposeddescription"
    android:value="wechat自动添加联系人" />
<!--Xposed模块的适用版本-->
<meta-data
	android:name="xposedminversion"
    android:value="82" />

assets

main文件夹下新建assets包,然后新建xposed_init文件,并写入执行类的路径

执行类

新建一个java类,并implements IXposedHookLoadPackage,然后就可以在实现方法中写入相关的Hook方法了。

XposedHelpers中的方法

findAndHookMethod

查找并拦截方法的执行,只需要找到类名,方法名,函数名,参数类型就可以使用 该方法使用最多,但大多局限于改参数与改结果,在真正Hook大型应用中需要追根溯源,结合其他方法使用

该方法有两种传值,我通过以下案例来说明 要拦截的方法在微信源码:

findAndHookMethod图片.png

-方法1:

XposedHelpers.findAndHookMethod("com.tencent.mm.plugin.qqmail.ui.MailAddrsViewControl$5",//完整类名
    lpparam.classLoader ,"onKey",//方法名
    View.class,int.class,KeyEvent.class,//参数class
    new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            param.args[1]=67;
            KeyEvent key= new KeyEvent(0,0);
            param.args[2]=key;
        }
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            param.setResult(true);
        }
    });

-方法2:

Class<?> cControl = null;
try {
    cControl = mlpparam.classLoader.loadClass("com.tencent.mm.plugin.qqmail.ui.MailAddrsViewControl$5");
    XposedHelpers.findAndHookMethod(cControl ,"onKey", View.class,int.class,KeyEvent.class,new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) {
            param.args[1]=67;
            KeyEvent key= new KeyEvent(0,0);
            param.args[2]=key;
        }
        @Override
        protected void afterHookedMethod(MethodHookParam param) {
            param.setResult(true);
        }
    });
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

其实两种方式大致相同,差异只有,第一种传入的完整类名与lpparam.classLoader,第二种传入Class< ?> ,其实第一种通过传入类名与lpparam.classLoader就是用来构建Class< ?>

如果我想执行源码中的if语句,就可以在方法未执行的beforeHookedMethod中修改了方法参数int与KeyEvent

如果我想让方法返回值为true,不继续传递keyEvent,就可以在方法执行后的afterHookedMethod中修改方法结果setResult(true);

findClass

查找类,因为HookMethod时,参数可能是应用内自定义的类,所以需要这个方法来找到,在未找到时抛出异常 参数(完整类名String,classLoader 应用的类加载器)

final Class<?> cf = XposedHelpers.findClass("com.tencent.mm.plugin.luckymoney.b.f",
    mlpparam.classLoader);

find出来后就可以作为findAndHookMethod中方法的参数来进行拦截了,拦截到后可以使用findField来查看类中的变量值。

findClassIfExists

和上一个方法功能一致,只是未找到时则返回null,不会有异常

findField

查找类中的变量

参数是(变量所在的Class,变量名String),再通过get方法就可以得到变量,get方法的参数就是变量所在的Class的实例Object 直接引用上一个帖子中的例子

try {
    final Class<?> SnsUploadUIClass = cl.loadClass("com.tencent.mm.plugin.sns.ui.SnsUploadUI");
    XposedHelpers.findAndHookMethod(SnsUploadUIClass, "onCreate", Bundle.class,
        new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                Object oSnsUploadUI = param.thisObject;
                XposedHelpers.findAndHookMethod("com.tencent.mm.plugin.sns.ui.SnsUploadUI$5$1",
                    mlpparam.classLoader, "pO", String.class,new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        super.beforeHookedMethod(param);
                        //获取SnsUploadUIClass中的nRk变量
                        Object nRk=XposedHelpers.findField(SnsUploadUIClass, "nRk").get(oSnsUploadUI);
                        //方法1
                        //强转为EditText
                        EditText editText = (EditText) nRk;
                        //得到发表朋友圈的文本
                        String text=editText.getText().toString();
                        //方法2
                        //执行getText().toString()得到发表朋友圈的文本
                        String text=  XposedHelpers.callMethod(nRk,"getText").toString();
                        //todo上传数据
                    }
                });
            }
        });
} catch (Exception e) {
    e.printStackTrace();
}

最外层的findAndHookMethod拦截到SnsUploadUI这个Activity类的实例对象,里层的findAndHookMethod拦截的是点击事件,点击时通过findField取出SnsUploadUI中的变量nRk

callMethod

执行某个类里的方法,如果有个方法是查询数据库的,你可以得到类的实例后再使用这个方法来执行自己写的语句

参数是(方法所在类的实例Object,执行方法名String,参数)

在上面的例子中我们可以看到

String text = XposedHelpers.callMethod(nRk,"getText").toString();

通过执行nRk实例的getText方法字符对象,再通过.toString()转化为字符串

callStaticMethod

执行静态方法,源码中有一个方法,我们可以直接调用它

callStaticMethod图片.png

Class<?> classMultiProcessSharedPreferences=
    XposedHelpers.findClass("com.tencent.mm.sdk.platformtools.MultiProcessSharedPreferences",mlpparam.classLoader);
SharedPreferences preferences=
    (SharedPreferences) XposedHelpers.callStaticMethod(classMultiProcessSharedPreferences,
    "getSharedPreferences",mwxContext,"notify_key_pref_no_account",4);
String username=preferences.getString("login_weixin_username","");

可以直接得到notify_key_pref_no_account.xml中存储的notify_key_pref_no_account字段的值。

大致用的最多的可能就是这几个方法了,当然还有其他方法在实际中会用到,最好的方法是阅读Xposed 的API文档,并在实际使用中多多使用