动手编写Xposed模块

写在前面:今天自己动手实现了Xposed模块的编写,又费了很大劲,之前一直在搞crypto(对于我这个没学过数论的菜鸡,确实好难),这次把很多丢了的东西又捡回来了,所以在这里做个记录,下次再丢可以来这里看看。其实关于Xposed模块编写,网上有很多文章,都可以拿来借鉴,但自己写的才是最好的!

一、准备

  1. 一只安装Xposed框架的Android手机
  2. 基本的Android的开发环境(-.-)
  3. XposedBridgeApi-54.jar (这里我不提供链接了,自己网上找找)

    准备差不多这么多

二、编写被Hook的app

注意:XposedBridgeApi-54.jar 这个包必须是要使用provided 进行编译的,否则会重复包含,导致错误。这里提供两种方案:
方案一:将jar包导入到libs目录下(当然这里也可以直接复制粘贴进来),修改build.gradle文件。修改前后如下:

修改前:compile fileTree(include: ['*.jar'], dir: 'libs')
修改后:provided fileTree(include: ['*.jar'], dir: 'libs')

注意:在添加jar包后在同步gradle,否则会加载不出来-2018/3/7注
也可以这么做provided files(‘libs/XposedBridgeApi-54.jar’) 总之是要将jar包利用provided方式进行加载-2018/3/8注
方案二:在app目录下新建lib目录和libs目录同一级,将jar包导入到lib目录中,同样修改build.gradle文件。如下:

在原有的dependences块中增加一行:provided files('lib/XposedBridgeApi-54.jar')

这样修改后就不有编译错误了。

具体案例的代码如下,写得比较简单,就不解释了。
private ImageView imageView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
        imageView=(ImageView) findViewById(R.id.picture);
        Resources resources=this.getResources();
        Bitmap bitmap = BitmapFactory.decodeResource(resources,R.drawable.image1);//给你个眼神自行体会
        imageView.setImageBitmap(bitmap);
        Button buttonHook = (Button) findViewById(R.id.buttonHook);
        Button buttonRecover = (Button) findViewById(R.id.buttonRecover);
        buttonHook.setOnClickListener(this);
        buttonRecover.setOnClickListener(this);
    }
    public void onClick(View v){
        switch (v.getId()){
            case R.id.buttonHook:
                if(check()){
                    //Toast.makeText(MainActivity.this, "Congratulation!", Toast.LENGTH_SHORT).show();
                    imageView.setImageResource(R.drawable.image2);
                }
                break;
            case R.id.buttonRecover:
                imageView.setImageResource(R.drawable.image1);
                break;
        }
    }
    private boolean check() {
        Toast.makeText(MainActivity.this, "This is test!", Toast.LENGTH_SHORT).show();
        return false;
    }

其实我最开始是想Hook Toast的,但是尝试失败,无奈之下写了check。那接下来我们就来Xposed模块咯。

三、编写Xposed模块:

Xposed模块通常是没有界面的,当然你也可以提供一个界面,在文末我会贴上有界面的图和代码。

新建一个项目,修改build.gradle,在app->src->main下新建assets目录,在assets目录下新建xposed_init文件,并添加com.code.jsk.xposedhook.MainCtf 包名+类名 用于xposed的初始化,它会执行该目录下的代码。接着只要编写Hook类,并重写handleLoadPackage即可。

public class MainCtf implements IXposedHookLoadPackage {
    //包加载时回调
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if (!loadPackageParam.packageName.equals("com.code.jsk.xposedexampleapp")) return;
        XposedBridge.log("Load app" + loadPackageParam.packageName); //在日志中记录我hook了哪个包
        //findAndHookMethod("android.widget.Toast", loadPackageParam.classLoader, "makeText", new XC_MethodReplacement() {
        findAndHookMethod("com.code.jsk.xposedexampleapp.MainActivity",loadPackageParam.classLoader, "check", new XC_MethodReplacement() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("This is beforeHookedMethod!");
            }

            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                //Toast.makeText(, "Hacked!", Toast.LENGTH_SHORT).show();
                XposedBridge.log("Hacked check");
                return true;
            }
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("This is the afterHookedMethod!");
            }
        });

    }
}

代码中我都加了关键注释,主要就是处理beforeHookedMethodreplaceHookedMethodafterHookedMethod 这三个函数
基本的过程就是先找到相应的包,之后再匹配需要hook的方法,之后就是replace方法。
我个人比较喜欢用adb进行操作:

adb install -r hook.apk 进行安装 -r是强制覆盖安装
adb reboot 重启

之前有一段代码写错了。这里记录这个错误就不做修改了。
findAndHookMethod(“com.code.jsk.xposedexampleapp.MainActivity”,loadPackageParam.classLoader, “check”, new XC_MethodReplacement() {})
他有两种写法,一种是

findAndHookMethod(String className,

ClassLoader classLoader,

String methodName, 

Object... parameter TypesAndCallback)

还有一种:

findAndHookMethod(Class<?> clazz, 

String methodName,

Object... parameter TypesAndCallback)

最后一个参数new的对象也有不同如果仅仅是replaceMethoed,那么使用new XC_MethodReplacement() { 即可,如果需要使用beforeHookedMethodafterHookedMethod 这两个函数那么就需要 new XC_MethodHook() {
修改后的代码如下:

findAndHookMethod("com.code.jsk.xposedexampleapp.MainActivity",loadPackageParam.classLoader, "check", new XC_MethodReplacement() {
            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                //Toast.makeText(, "Hacked!", Toast.LENGTH_SHORT).show();
                XposedBridge.log("Hacked check");
                return true;
            }
        });
        findAndHookMethod("com.code.jsk.xposedexampleapp.MainActivity", loadPackageParam.classLoader, "check", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("This is the beforeHookedMethod!");
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("This is the afterHookedMethod!");
            }
        });

这里写图片描述

最后并没有执行afterHookedMethod 这部分代码,我也不带清楚为什么。
最后在贴上带界面的Xposed模块的图
这里写图片描述
简单的增加一个主活动,并添加界面即可。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
        ImageView imageView = (ImageView) findViewById(R.id.imageview);
        imageView.setImageResource(R.drawable.image3);
    }
}

到此文章也差不多结束了,Xposed框架的原理有兴趣的也可以自行去了解,它是重写了部分zygote代码,总之,搞机有风险,测试需谨慎。别一不小心把手机变成了板砖。

猜你喜欢

转载自blog.csdn.net/qq_33438733/article/details/79254908