美文网首页
关于XposedHook的实践

关于XposedHook的实践

作者: 戎码虫 | 来源:发表于2019-06-23 15:24 被阅读0次

    前言

    Xposed框架(Xposed Framework)是一套开源的、在Android高权限模式下运行的框架服务,可以在不修改APK文件的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。--百度百科

    准备

    1、 Xposed Installer apk包下载:https://repo.xposed.info/module/de.robv.android.xposed.installer
    这里唯一要注意的是Android 4.0.3 - Android 4.4.X和 Android 5.0以上,下载的版本不相同。
    2、编写测试APP
    3、编写Xposed插件APP
    4、一个Root的手机\color{red}{【重点】}

    步骤

    安装Xposed Installer

    安装好XposedInstaller后进入应用程序,会出现需要激活框架的界面,如下图所示,这里我们点击“安装/更新”就能完成框架的激活了。部分设备如果不支持直接写入的话,可以选择“安装方式”,修改为在Recovery模式下自动安装即可。

    Xposed 安装/更新

    安装成功之后重启手机,激活显示58、54框架的版本

    成功之后

    新建测试apk

    Android Studio新建一个工程,这里就写个TextView显示文字,将apk运行到手机上。

    public class MainActivity extends AppCompatActivity {
        TextView test;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //控件
            test = findViewById(R.id.test);
            test.setText("XposedHook");
        }
    }
    

    编写Xposed插件

    Android Studio新建一个没有Activity的项目

    新建NoActivity
    添加依赖

    在Module 中Gradle添加,这里特别【注意】\color{red}{compileOnly 千万不要改成implementation } 这里只是参与编译,不会将代码打入包中

        compileOnly 'de.robv.android.xposed:api:82'
        compileOnly 'de.robv.android.xposed:api:82:sources'
    
    配置插件

    在AndroidManifest.xml文件中application标签中配置插件名称和Api版本号

    <application
       ···         >
        <meta-data
            android:name="xposedmodule"
            android:value="true"/>
        <meta-data
            android:name="xposeddescription"
            android:value="Xposed插件测试"/>
        <meta-data
            android:name="xposedminversion"
            android:value="30"/>
    </application>
    
    新建一个入口类

    新建一个XposedHook类继承IXposedHookLoadPackage方法,这里我通过Hook改变测试APP TextView的值。

    //包名路径
    package com.zhj.xposedhooklib;
    
    public class XposedHook implements IXposedHookLoadPackage {
        @Override
        public void handleLoadPackage(final LoadPackageParam loadPackageParam) throws Throwable {
            // 判断是不是要Hook的包,不是直接返回   com.zhj.xposedhook为测试Demo的包名
            if (!"com.zhj.xposedhook".equals(loadPackageParam.packageName)) {
                //打印日志加载的包名
                XposedBridge.log("Loaded app: " + loadPackageParam.packageName);
                return;
            }
    
            // 需要Hook测试的   app的类绝对路径"com.zhj.xposedhook.MainActivity"  方法名 "onCreate"  方法参数 Bundle.class
            XposedHelpers.findAndHookMethod("com.zhj.xposedhook.MainActivity", loadPackageParam.classLoader,
                    "onCreate", Bundle.class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            XposedBridge.log("beforeHookedMethod");
                            super.beforeHookedMethod(param);
                        }
    
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            XposedBridge.log("afterHookedMethod");
    
                            //加载类
                            Class c = loadPackageParam.classLoader.loadClass("com.zhj.xposedhook.MainActivity");
                            //获取类中"test"成员变量
                            Field field = c.getDeclaredField("test");
                            //成员变量为private,故必须进行此操作
                            field.setAccessible(true);
                            //获取控件对象
                            TextView tv = (TextView) field.get(param.thisObject);
                            //改变TextView的值
                            tv.setText("我的值被hook改变了");
                            super.afterHookedMethod(param);
                        }
                    }
            );
        }
    }
    
    声明主入口路径

    新建Assets目录中添加xposed_init文件

    新建Asserts
    xposed_init

    xposed_init文件内容,XposedHook的类包名路径

    com.zhj.xposedhooklib.XposedHook
    
    将插件打包

    因为控件没有Activity,将build方式改成Nothing,将插件apk运行到手机上,再将插件添加到Xposed Installer模块中,如下图所示,重启手机

    打包设置 添加插件

    验证

    打开测试apk,可以发现里面的值发生改变

    打开测试apk

    打开Xposed Installer日志,可以发现我们打印的日志信息

    XposedHook日志

    原理

    Xposed框架是基于一个Android的本地服务应用XposedInstaller,与一个提供API 的jar文件来完成的。
    通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。
    基于Xposed框架可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。此外,Xposed框架中的每一个库还可以单独下载使用,如Per APP Setting(为每个应用设置单独的dpi或修改权限)、Cydia、XPrivacy(防止隐私泄露)、BootManager(开启自启动程序管理应用)对原生Launcher替换图标等应用或功能均基于此框架。

    参考文献

    Xposed hook:https://www.jianshu.com/p/f163c5eacf03

    相关文章

      网友评论

          本文标题:关于XposedHook的实践

          本文链接:https://www.haomeiwen.com/subject/uzwiqctx.html