xposed开发_xposed 开发文档 - CSDN
精华内容
参与话题
  • Xposed模块开发

    千次阅读 2019-07-16 15:42:06
      最近突然看到了Xposed这一项技术,觉得蛮有意思的,现在的蚂蚁森林自动收能量以及微信自动回复等都是通过这个来实现的,因此记录一下Xposed的基本实现。 Xposed模块介绍   Xposed框架是一款开源框架,其功能是...

      最近突然看到了Xposed这一项技术,觉得蛮有意思的,现在的蚂蚁森林自动收能量以及微信自动回复等都是通过这个来实现的,因此记录一下Xposed的基本实现。

    Xposed框架介绍

    概述

      Xposed框架是一款开源框架,其功能是可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。Xposed 就好比是 Google 模块化手机的主体,只是一个框架的存在,在添加其他功能模块(Modules)之前,发挥不了什么作用,但是没了它也不行。也正因为如此,Xposed 具有比较高的可定制化程度。

    工作原理

      Xposed框架主要通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。与采取传统的Inhook方式相比,Xposed在开机的时候完成对所有的Hook Function的劫持,在原Function执行的前后加上自定义代码。
      为什么需要这么做呢?
      Android基于Linux,第一个启动的进程自然是init进程,该进程会启动所有Android进程的父进程——Zygote(孵化)进程,该进程的启动配置在 /init.rc脚本中,而Zygote进程对应的执行文件是/system/bin/app_process, 该文件完成类库的加载以及一些函数的调用工作。在Zygote进程创建后, 再fork出SystemServer进程和其他进程。Xposed Framework,就是用自己实现的app_process替换掉了系统原本 提供的app_process,加载一个额外的jar包,然后入口从原来的: com.android.internal.osZygoteInit.main()被替换成了: de.robv.android.xposed.XposedBridge.main(),
    然后创建的Zygote进程就变成Hook的Zygote进程了,而后面Fork出来的进程 也是被Hook过的。
      这个Jar包在: /data/data/de.rbov.android.xposed.installer/bin/XposedBridge.jar 目录下。
      通过原理我们可以看出,要使用Xposed框架,那么手机必须要拥有最高权限(就是root权限),当然现在还出现了VirtualXposed,这个框架的话就相当于给你的手机开了一个平行空间,这个空间和你的手机系统一样,就相当于一个副本,所以当你在这个空间使用xposed的话,就不需要root,但是在这个空间你需要重新安装你想修改的程序,因为它刚创建出来的时候是什么都没有的,也因此你在这个空间修改并不会影响到你的手机本来的应用,就相当于双开应用。
      值得注意的是,既然给出了最高权限,那么别人就可以做很多坏事了,比如获取你的账号密码,还有一些私密的文件,因此对于别人写的Xposed模块可以看看他是不是开源的再决定用不用,如果不是开源的,建议不要使用。当然如果不想承担这么大的风险又不嫌麻烦的话,可以使用上面介绍的virtualXposed框架。

    环境要求

    Configuration RequireMent
    硬件 安卓手机或者模拟器
    软件 PC:Android studio  手机:xposed框架app
    Root Access 因为Xposed工作原理是在/system/bin目录下替换文件,在install的时候需要root权限,但是运行时不需要root权限。
    版本要求 需要在Android 4.0以上版本的机器中

    Xposed资源梳理

    • XposedBridge.jar:XposedBridge.jar是Xposed提供的jar文件,负责在Native层与FrameWork层进行交互。/system/bin/app_process进程启动过程中会加载该jar包,其它的Modules的开发与运行都是基于该jar包的。
      注意:XposedBridge.jar文件本质上是由XposedBridge生成的APK文件更名而来。
    • Xposed:Xposed的C++部分,主要是用来替换/system/bin/app_process,并为XposedBridge提供JNI方法。
    • XposedInstaller:Xposed的安装包,负责配置Xposed工作的环境并且提供对基于Xposed框架的Modules的管理。在安装XposedInstaller之后,app_process与XposedBridge.jar放置在了/data/data/de.robv.android.xposed.installer。
    • XposedMods:使用Xposed开发的一些Modules,其中AppSettings是一个可以进行权限动态管理的应用

    Xposed模块实现例子

      从本质上来讲,Xposed 模块也是一个 Android 程序。但与普通程序不同的是,想要让写出的Android程序成为一个Xposed 模块,要额外多完成以下四个硬性任务:

    1. 让手机上的xposed框架知道我们安装的这个程序是个xposed模块。

    2. 模块里要包含有xposed的API的jar包,以实现下一步的hook操作。

    3. 这个模块里面要有对目标程序进行hook操作的方法。

    4. 要让手机上的xposed框架知道,我们编写的xposed模块中,哪一个方法是实现hook操作的。

    &emsp: 对应上面的四个步骤我们需要做的修改有:

    1. AndroidManifest.xml

    2. XposedBridgeApi-xx.jar 与 build.gradle

    3. 实现hook操作的具体代码

    4. xposed_Init

      按照上述顺序一个一个实现,就能完成我们的第一个Xposed模块编写:

    修改AndroidManifest.xml

      首先我们新建了一个空项目,然后在布局文件中定义了一个按钮,点击效果为Toast出文字“我未被劫持”。将其先安装到手机或者模拟器上。
      基于以上的项目,首先想要我们写的app能够被识别成一个xposed模块的话,我们需要修改AndroidManifest.xml文件,如下:

    在这里插入图片描述
      插入之后,把手机连上AndroidStudio ,点击“编译”或者“运行”的话,手机就会启动刚刚编写的这个程序。而在手机里的Xposed框架中也会显示出这个模块:
    在这里插入图片描述
      这说明Xposed框架已经认出了我们写的程序,但是现在这个模块什么都没有做,因为我们还没有做出修改。

    配置XposedBridgeApi-xx.jar 与 build.gradle

      从上面的工作原理可以看出来,实现一个xposed模块,那必须需要XposedBridgeApi-xx.jar这个jar包来提供修改的文件,因此这一步的关键是下载XposedBridgeApi-xx.jar包并且将其放到libs工程目录中,当然这是一种方法,不过在Android studio不用这么麻烦,因为Android studio可以通过修改build.gradle来将其集成进来,插入以下代码:

    repositories {
    
    jcenter()
    
    }
    
    以及
    
    compileOnly 'de.robv.android.xposed:api:82'
    
    compileOnly 'de.robv.android.xposed:api:82:sources'
    

      如下:
    在这里插入图片描述
      这句代码是告诉AndroidStuido使用jcenter作为代码仓库,从这个仓库里远程寻找 de.robv.android.xposed:api:82 这个API,我们不用自己找XposedBridgeApi.jar了。
      注意!此处要用compileOnly这个修饰符!网上有些写的是provide ,现在已经停用了!)

    实现hook操作修改

      在MainActivity的同级路径下新建一个类“HookTest.java”,代码如下:

    package com.example.root.xposd_hook_new;
    import de.robv.android.xposed.IXposedHookLoadPackage;
    import de.robv.android.xposed.XC_MethodHook;
    import de.robv.android.xposed.XposedBridge;
    import de.robv.android.xposed.XposedHelpers;
    import de.robv.android.xposed.callbacks.XC_LoadPackage;
    
    public class HookTest implements IXposedHookLoadPackage {
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
          if (loadPackageParam.packageName.equals("com.example.root.xposd_hook_new")) {
              XposedBridge.log(" has Hooked!");
              Class clazz = loadPackageParam.classLoader.loadClass("com.example.root.xposd_hook_new.MainActivity");
              XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
                  protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  super.beforeHookedMethod(param);
               //XposedBridge.log(" has Hooked!");
              }
                  protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                  param.setResult("你已被劫持");
              }
         });
       }
      }
    }
    

      如图:
    在这里插入图片描述
      通过IXposedHookLoadPackage接口中的handleLoadPackage方法来实现Hook并篡改程序的输出结果的:

    • 代码中“com.example.root.xposd_hook_new ”是目标程序的包名;
    • ”com.example.root.xposd_hook_new.MainActivity” 是想要Hook的类;
    • “toastMessage”是想要Hook的方法。

      我们在afterHookedMethod方法(用来定义Hook了目标方法之后的操作)中,修改了toastMessage()方法的返回值为“你已被劫持”。

    xposed_init文件

      右键点击 “main ” 文件夹 , 选择new –> Folder –>Assets Folder,新建assets 文件夹:然后右键点击 assets文件夹, new–> file,文件名为xposed_init(文件类型选text),并在其中写上入口类的完整路径(就是自己编写的那一个Hook类),这样, Xposed框架就能够从这个 xposed_init 读取信息来找到模块的入口,然后进行Hook操作了,如图:
    在这里插入图片描述
      注意:最后选择禁用 Instant Run: 单击 File -> Settings -> Build, Execution, Deployment -> Instant Run,把勾全部去掉。因为如果勾选了Instant Run的话,
    在这里插入图片描述
      最后我们将程序运行到手机上,打开xposed框架,然后勾选我们创建的这个模块,重新打开应用,就会发现:
    在这里插入图片描述
      这说明我们的修改已经生效了,当然这只是最简单的对于Xposed模块的开发,举一反三,既然我们都可以修改一个应用的返回值,那么我们可以修改的东西可不止这么一些简单的东西,基于此,那么实现自动收能量、自动回复就都是可能的,当然还有一些数据的修改只需要将返回值修改不就实现了吗。
      在GitHub上这两个app源码可以向我们展示怎么hook类的变量、静态变量、公有方法、私有方法、静态方法、内部类、多复杂参数的方法、内部类的变量等。
      原始程序:https://github.com/Gordon0918/XposedHookTarget
      hook修改源程序地址:https://github.com/Gordon0918/XposedHook
      通过对比,就能发现上述这些是怎么被hook的。
      更深的了解以及实际应用的话可以看这篇帖子:https://www.jianshu.com/p/51dcc24900ba (技术文哦,当初看到这篇文章我才发现还有这么一个东西)。

    展开全文
  • xposed开发11 - 微信红包 private static Activity launcherUIActivity = null; // 微信红包 hookClass = "com.tencent.wcdb.database.SQLiteDatabase"; hookMethodName = "insertWithOnConflict"; XposedHelpers....

    xposed开发11 - 微信红包

    private static Activity launcherUIActivity = null;
    
    // 微信红包
    hookClass = "com.tencent.wcdb.database.SQLiteDatabase";
    hookMethodName = "insertWithOnConflict";
    XposedHelpers.findAndHookMethod(hookClass, lpparam.classLoader, hookMethodName, String.class, String.class, ContentValues.class, int.class, new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            ContentValues contentValues = (ContentValues) param.args[2];
            // 判断插入的数据是否是发送过来的消息
            String tableName = (String) param.args[0];
            if (TextUtils.isEmpty(tableName) || !tableName.equals("message")) {
                return;
            }
            // 判断是否是红包消息类型
            Integer type = contentValues.getAsInteger("type");
            if (type == null) {
                return;
            }
            if (type == 436207665) {
                // 处理红包消息
                String talker = contentValues.getAsString("talker");
                String content = contentValues.getAsString("content");
                if (!content.startsWith("<msg")) {
                    content = content.substring(content.indexOf("<msg"));
                }
    
                JSONObject wcpayinfo = new XmlToJson.Builder(content).build().toJson().getJSONObject("msg").getJSONObject("appmsg").getJSONObject("wcpayinfo");
                String nativeUrlString = wcpayinfo.getString("nativeurl");
    
                // 启动红包页面
                if (launcherUIActivity != null) {
                    Intent paramau = new Intent();
                    paramau.putExtra("key_way", 1);
                    paramau.putExtra("key_native_url", nativeUrlString);
                    paramau.putExtra("key_username", talker);
    
                    XposedHelpers.callStaticMethod(XposedHelpers.findClass("com.tencent.mm.bm.d", lpparam.classLoader), "b", launcherUIActivity, "luckymoney", ".ui.LuckyMoneyReceiveUI", paramau);
                } else {
                    XposedBridge.log("launcherUiActivity为空");
                }
            }
        }
    });
    
    // hook微信主界面的onCreate方法, 获取主界面对象
    hookClass = "com.tencent.mm.ui.LauncherUI";
    hookMethodName = "onCreate";
    XposedHelpers.findAndHookMethod(hookClass, lpparam.classLoader, hookMethodName, Bundle.class, new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            launcherUIActivity = (Activity) param.thisObject;
        }
    });
    
    // hook领取红包页面的onCreate方法,打印Intent中的参数(只起到调试作用)
    hookClass = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";
    hookMethodName = "onCreate";
    XposedHelpers.findAndHookMethod(hookClass, lpparam.classLoader, hookMethodName, Bundle.class, new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            Activity activity = (Activity) param.thisObject;
            String key_native_url = activity.getIntent().getStringExtra("key_native_url");
            String key_username = activity.getIntent().getStringExtra("key_username");
            int key_way = activity.getIntent().getIntExtra("key_way", 0);
            XposedBridge.log("微信主页: key_native_url: " + key_native_url);
            XposedBridge.log("微信主页: key_username: " + key_username);
            XposedBridge.log("微信主页: key_way: " + key_way);
        }
    });
    
    // hook红包界面初始化"开"按钮的方法, 在该方法完成后自动点击开按钮领取红包
    hookClass = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";
    hookMethodName = "d";
    XposedHelpers.findAndHookMethod(hookClass, lpparam.classLoader, hookMethodName, int.class, int.class, String.class,
            XposedHelpers.findClass("com.tencent.mm.ae.k", lpparam.classLoader), new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            Field buttonField = XposedHelpers.findField(param.thisObject.getClass(), "ogX");
            final Button openButton = (Button) buttonField.get(param.thisObject);
            openButton.performClick();
        }
    });
    

    最新版本微信里 com.tencent.mm.bm.d 失效了, 要重新看打开红包的逻辑.

    展开全文
  • 怎么为Xposed开发新的模块么?那么读读这篇教程(或者我们可以称他为”泛读短文”)学着怎么去做。这不仅包括“创建这个文件然后插入…”这类的技巧,也包括这些技巧背后的思想。这些思想正是创造价值的步...


    原文章地址:http://vbill.github.io/2015/02/10/xposed-1/

    文章讲述了Xposed的原理,以及怎么开发Xposed框架的模块。头一次翻译技术文档,有错误的话请多包涵。

    怎么为Xposed开发新的模块么?那么读读这篇教程(或者我们可以称他为”泛读短文”)学着怎么去做。这不仅包括“创建这个文件然后插入…”这类的技巧,也包括这些技巧背后的思想。这些思想正是创造价值的步骤以及你真正需要了解你做了什么和为什么这么做的原因。如果你觉得本文“太长,不想读”,那么你可以只看最后的源代码和阅读“使工程成为Xposed模块“部分。但是如果你读了整篇文章你就会有更好的理解。你之后会节省出来阅读这个的时间,因为你不必凭自己弄清楚每件事。

    修改主题


    你将重新创建在github上可以找到的红色钟表的的例子。它包括将状态栏的钟表变为红色并且加入一个笑脸的功能。我选择这个例子是因为它非常小,而且容易看见所做的修改。并且,它也使用了框架所提供的一些基本方法。

    Xposed如何工作


    在你开始做出自己的修改之前,你应当大致了解Xposed如何工作(如果觉得这部分无聊可以跳过)。以下就是原理:

    有一个叫做”Zygote”的进程,它是android运行环境的核心。每个应用都从一份它的拷贝(“fork”)产生。这个进程在手机启动时由一个叫 /init.rc 的脚本启动。这个进程的启动在 /system/bin/app_process 加载所需要的类和调用初始化方法后完成。

    这里就是Xposed发挥用处的地方了。当你安装完框架后,一个扩展过的app_process就会被复制到 /system/bin 下这个扩展过的启动进程会将一个额外的jar包添加到环境变量,并在特定场合调用里面的方法。比如:当虚拟机创建完成后和Zygote的main方法被调用前。并且在那个方法当中,我们已经是Zygote的一部分,而且能够在它的上下文context中活动。

    jar包的位置是 /data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar 它的源代码可以在这里找到。查看XposedBridge的类,你能找到main方法。这就是我上文中所写过的,它在每个进程的最开始部分被调用。一些初始化的工作在那里完成,并且我们的模块在那里加载(之后我再讲模块的加载)。

    方法的hook/替换


    真正使Xpoesed有威力的就是hook方法调用。当你反编译并修改APK时,你能够在任何你想的地方直接修改/替换指令。然而,你事后需要重新编译/给APK签名,并且只能发布整个安装包。使用Xposed能让你放置的hook,你并不能修改程序内部的方法代码(清楚地定义你想要在何处做什么样的修改是不可能的)。然而,你可以在方法调用的前后注入你的代码。这也是java中能够被清楚寻址的最小单位。

    XposedBridge 有一个私有的 native 方法叫做 hookMethodNative这个方法也在扩展后的 app_process 中被实现了它会将方法类型转为“native”,并把方法的实现与本地的通用方法相连。这意味着,每当被hook的方法调用后,调用者不知道实际调用的是通用的方法在这个方法中,位于 XposedBridge 的 handleHookedMethod 方法会被调用,并向方法调用传递参数、this指针以及其他东西。之后这个方法负责唤起之前方法调用注册过的回调。上述这些行为能够改变调用的参数、实例/静态变量、唤起其他方法、处理调用结果。。。或者跳过这些东西。它的弹性非常大。

    现在创建一个模块吧!

    创建工程


    一个模块就是一个普通的app,只不过多了一些特殊的文件和元数据。所以在我们创建新的android工程以前,我假设你已经做过这个了。如果没有,官方文档讲的很详细。对于SDK,我选择了4.0.3(API15)。我建议你也使用这个,并且不要立刻开始。你不需要创建Activity,因为我们的修改不需要任何用户界面。回答过了这个问题后,你应该有一个空白的工程项目。

    使工程成为Xposed模块


    现在我们把工程变成Xposed能加载的东西。我们需要以下几个步骤。

    AndroidManifest.xml

    Xposed Installer的模块列表搜寻所有有一种特殊元数据标记的应用程序。你可以到 AndroidManifest.xml => Application => Application Nodes (在底部) => Add => Meta Data 下面去创建这个标记。标记名称应该是 xposedmodule ,值应该是 true。给resource留空。重复以上过程创建 xposedminversion (见下文) 和 xposeddescription (你创建的模块的简单描述)。XML文件现在就是这个样子:

    <?xml version="1.0" encoding="utf-8"?>
     <manifest  xmlns:android="http://schemas.android.com/apk/res/android"
        package="de.robv.android.xposed.mods.tutorial"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk android:minSdkVersion="15" />
    
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <meta-data
                android:name="xposedmodule"
                android:value="true" />
            <meta-data
                android:name="xposeddescription"
                android:value="Easy example which makes the status bar clock red and adds a smiley" />
            <meta-data
                android:name="xposedminversion"
                android:value="30" />
        </application>
    </manifest>
    

    XposedBridgeApi.jar

    接下来,让程序能够找到 XposedBridge 的API。你可以从
    这里下载 XposedBridgeApi-<version>.jar 的最新版。把它复制到叫做lib的子文件夹下。右键单击选择Build Path => Add to Build Path。文件名当中的<version>是你在manifest文件的xposedminversion标签所插入的版本。

    保证API类没有被包含(但仅仅是参考)在你编译过的APK里,否则你会得到一个IllegalAccessError错误。libs(含有s)文件夹是eclipse自动生成的,不要把API文件放在那里。

    模块的实现

    现在你可以给你的模块创建一个类了。我的类叫做”Tutorial”,位于de.robv.android.xposed.mods.tutorial这个包中。

    package de.robv.android.xposed.mods.tutorial;
    
    public class Tutorial {
    
    }
    

    第一步,我们仅仅生成一些日志表明模块已经加载。一个模块可以有多个入口点。你选择哪个取决于你想修改什么。你可以在安卓系统启动时、在一个app将要启动时、在一个app的资源文件初始化时或其他时候,调用一个函数。

    在这个教程靠后面的一部分,你将了解到在一个特定的app中需要做出的修改。那么先让我们了解一下 “让我知道什么时候加载一个新app” 这个入口点。所有入口点都被标记为IXposedMod的子接口。这种情况下,你需要实现 IXposedHookLoadPackage 这个接口。其实它只有一个仅有一个参数的方法。这个方法向被实现的模块提供更多关于运行环境上下文的信息。在我们的例子中,我们用log输出加载的app的名称。

    package de.robv.android.xposed.mods.tutorial;
    
    import de.robv.android.xposed.IXposedHookLoadPackage;
    import de.robv.android.xposed.XposedBridge;
    import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
    
    public class Tutorial implements IXposedHookLoadPackage {
        public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
            XposedBridge.log("Loaded app: " + lpparam.packageName);
        }
    }
    

    这个log方法向标准logcat以及 /data/data/de.robv.android.xposed.installer/log/debug.log(通过Xposed Installer可以轻易访问到)输出信息(tag Xposed)。

    assets/xposed_init

    现在唯一遗漏的就是提示XposedBridge哪些类包含了入口点。这项工作通过一个叫 xposed_init 的文件完成。在assets文件夹下创建一个新的名叫xposed_init的text文件。在该文件中每行包含一个类的全名。在这个例子中,它是 de.robv.android.xposed.mods.tutorial.Tutorial。

    试试看


    保存你的文件。以Android Application的方式运行你的程序。因为这是你第一次安装它,在使用前你需要先启用。打开Xposed Installer这个app并确保你安装了xposed框架。之后切换到Modules标签。你应该能在那里找到你的app。在选择框内打钩使得它可用。然后重启。你当然什么变化也看不到,但如果检查log记录,以应该会看见以下的东西:

    Loading Xposed (for Zygote)...
    Loading modules from   /data/app/de.robv.android.xposed.mods.tutorial-1.apk
    Loading class de.robv.android.xposed.mods.tutorial.Tutorial
    Loaded app: com.android.systemui
    Loaded app: com.android.settings
    ... (many more apps follow)
    

    瞧!它起作用了。现在你拥有了一个Xposed模块。它能够变得比写一些log更加有用…

    探索你的目标并寻找修改它的方式


    好了,下面要开始讲的部分也许会非常不同,这取决于你想做什么。如果你之前修改过apk,也许你会知道在这里应当如何思考。总的来说,你需要了解目标的一些实现细节。在本教程中,目标选定为状态栏的时钟。这有助于了解到状态栏以及其他一些东西都是系统UI的一部分。现在让我们在那里开始我们的探索。

    可能性1:反汇编。这会告诉你它实际的实现,但是会很难阅读和理解,因为你得到的都是smali格式的东西。可能性2:获得AOSP源代码。比如这里这里。ROM不同代码也很不一样,但在本例中他们的实现是相似的甚至是相同的。我会先看AOSP,然后看看这么做够不够。如果我需要细节,我会看看实际的反汇编的代码。

    你可以找找名称中有“clock”的类。其他需要找的是用到的资源和布局。如果你下载官方的AOSP代码,你可以从 frameworks/base/packages/SystemUI 开始找。你会找到好几处“clock”出现的地方。找到有好几种方式实现修改是正常而且真实的。时刻记住你“只能” hook方法。所以你必须另找其他能够插入代码实现功能的地方,要么在方法的前面或是后面,或者是替换掉方法。你应当hook一个尽可能明确的方法,而不是一个被调用成千上万次的用于解决性能问题和非计划中的副作用的方法。

    在本例当中,你或许会发现布局 res/layout/status_bar.xml 包含一个指向带有类com.android.systemui.statusbar.policy.Clock的自定义view。现在你脑子里也许会有好多点子。文字的颜色是通过textAppearance属性定义的,所以最干净的更改它的方法就是修改外观的定义。然而,用Xposed框架改变外观属性几乎是不可能的(这需要深入本地代码)。替换状态栏的布局也许是可能的,但对于你试图做出的小小修改来说是杀鸡用牛刀。取而代之的是,看看这个类。有一个叫updateLock的方法,似乎每分钟都调用一次用于更新时间。

    final void updateClock() {
        mCalendar.setTimeInMillis(System.currentTimeMillis());
        setText(getSmallTime());
    }
    

    这个方法用于修改来说是很好的,因为这是一个足够具体的看似唯一能够修改时钟文字的方法。如果我们在这个方法的每次调用之后都加些修改时钟文字和颜色的东西,应该就能起作用。那么,我们开始做吧。

    对于单独修改字体颜色部分,有一种更好的办法。参见“替换资源”中“修改布局”的例子。

    使用反射寻找并hook方法


    现在我们已经知道了哪些东西?我们在com.android.systemui.statusbar.policy.Clock有一个叫做updateClock的希望干涉的方法。我们在系统UI资源中找到了这个类,所以它仅仅在系统UI进程当中有效。其它一些类属于框架,而且在任何地方都有效。如果我们在 handleLoadPackage 中试图直接获取任何这个类的信息和引用,就会失败。因为处于错误的进程中。所以让我们实现一种仅在某个特定包即将加载时执行特定代码的情况:

    public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
        if (!lpparam.packageName.equals("com.android.systemui"))
            return;
    
        XposedBridge.log("we are in SystemUI!");
    }
    

    使用参数,我们能轻松检查是否在正确的包中。一旦我们核实了这一点,我们就通过ClassLoader取得那个包中的也被这个变量引用的类。现在我们可以寻找com.android.systemui.statusbar.policy.Clock这个类以及它的updateClock方法,然后告诉XposedBridge去hook这个方法:

    package de.robv.android.xposed.mods.tutorial;
    
    import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
    import de.robv.android.xposed.IXposedHookLoadPackage;
    import de.robv.android.xposed.XC_MethodHook;
    import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
    
    public class Tutorial implements IXposedHookLoadPackage {
        public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
            if (!lpparam.packageName.equals("com.android.systemui"))
                return;
    
            findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    // this will be called before the clock was updated by the original method
                }
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    // this will be called after the clock was updated by the original method
                }
        });
        }
    }
    

    findAndHookMethod是一个Helper函数。注意静态导入,如果你像连接中说的一样做了,那就会被自动加入。这个方法使用系统UI包的ClassLoader寻找 Clock 这个类,然后寻找其中的updateClock方法。如果这个方法中有任何参数,你必须事后列出这些参数的类型。有许多方法做这件事,但因为我们的方法没有参数,所以就先跳过这个步骤。至于最后一点,你需要提供一个 XC_MethodHook 类的实现。对于更小的更改,你可以使用匿名类。如果你的代码很多,最好创建普通的类并且只在这里创建实例。helper之后会如之前所说的,做出所有hook这个方法的必要工作。

    XC_MethodHook中有两个你可以重写的方法。你可以两个都重写,或者都不重写。但后者的做法显然是没有道理的。这些方法就是beforeHookedMethod 和 afterHookedMethod。不难猜出他们在原有方法之前/后执行。你可以使用“before”方法在方法调用前估计/操纵参数(通过param.args)。甚至阻止调用原来的方法(发送你自己的结果)。“after”方法可以用来做一些基于原来方法的结果的事。你也可以在这个地方操纵结果。当然,你可以在方法调用的前/后添加你自己要执行的代码。

    如果你要彻底替换一个方法,去看看子类XC_MethodReplacement。在那里,你只需要重写replaceHookedMethod。

    XposedBridge为每个hook过的方法维护一个注册过的回调的表。拥有最高优先级(在hookMethod中被定义)的将被优先调用。原有的方法总是具有最低的优先级。所以如果你hook了一个拥有回调A(高优先级)和回调B(默认优先级)的方法,那么不管被hook的方法是如何被调用的,执行顺序总是这样的:A.before -> B.before -> original method -> B.after -> A.after。所以A可以影响B看到的参数,即把它们传递下去以前大幅度地修改它们。原有的方法的结果会先被B处理,但是A拥有原先调用者最终将得到什么样结果的决定权。

    最终步骤:在方法调用之前/后执行你自己的代码

    好了,你已经在正确的上下文运行环境中(比如:系统UI进程)有了一个在updateClock方法每次被调用时都会被调用的方法。现在让我们修改一些东西吧。

    第一个要检查的:我们有具体的Clock类型的引用么?是的,我们有。这就是param.thisObject参数。所以如果方法通过myClock.updateClock()被调用,那么param.thisObject 就是 myClock。

    接下来:我们对clock做什么?Clock类型并不可用,你不能将param.thisObject转换为类(也不要试着这样做)。然而它是从TextView继承而来。所以一旦你把Clock的引用转换为TextView,你可以使用像setText, getText 和 setTextColor之类的方法。我们的改动应该在原有的方法设置了新的时间以后进行。因为在方法被调用前什么都没有做,我们可以空着beforeHookedMethod。没有必要调用(空的)“super”方法。

    所以以下是完整的源代码:

    package de.robv.android.xposed.mods.tutorial;
    
    import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
    import android.graphics.Color;
    import android.widget.TextView;
    import de.robv.android.xposed.IXposedHookLoadPackage;
    import de.robv.android.xposed.XC_MethodHook;
    import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
    
    public class Tutorial implements IXposedHookLoadPackage {
        public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
            if (!lpparam.packageName.equals("com.android.systemui"))
                return;
    
            findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    TextView tv = (TextView) param.thisObject;
                    String text = tv.getText().toString();
                    tv.setText(text + " :)");
                    tv.setTextColor(Color.RED);
                }
            });
        }
    }
    

    对结果感到满意


    现在启动/安装你的app。因为你第一次启动它时已经在Xposed Installer中把它设置为了可用,你就不需要在做这一步了。重启即可。然而,如果你正在使用这个红色钟表的例子,你也许想禁用它。两者都对它们的updateClock 处理程序使用了默认的优先级。所以你不清楚哪个会胜出(实际上这依赖于处理方法的字符串表示形式,但不要依赖这个方式)。



    https://www.csdn.net/article/2015-08-14/2825462

    展开全文
  • Xposed框架开发入门(一)

    千次阅读 2017-04-01 23:43:58
    最近在学习Android逆向的时候涉及到了Hook方面的...关于这篇Xposed开发入门,准备分三章来写。第一章主要是关于Xposed框架的介绍和原理,第二章是Xposed框架的基础应用,第三章准备结合最近在做的一个某狗输入法的用户

    最近在学习Android逆向的时候涉及到了Hook方面的知识,所以研究了下Xposed和Cydiasubstrate框架,虽然最后还是成功搞起了,但是一路下来感觉还是有很多不顺的,所以在学习的时候就把学习笔记顺手写下来了。

    关于这篇Xposed开发入门,准备分三章来写。第一章主要是关于Xposed框架的介绍和原理,第二章是Xposed框架的基础应用,第三章准备结合最近在做的一个某狗输入法的用户词库的提取来介绍下Xposed框架在具体应用时的用法(关于某狗输入法用户个人词库的提取会在以后的章节中介绍)。

    OK,话不多说,搞起!

    一、什么是Hook技术

    Hook英文翻译是“钩子”的意思,“钩子”顾名思义就是可以勾起东西的工具,那么程序中这个“钩子”又是怎么用的呢?在Android操作系统中系统维护着自己的一套事件分发机制。应用程序,包括应用触发事件和后台逻辑处理,也是根据事件流程一步步地向下执行。而“钩子”的意思,就是在事件传送到终点前截获并监控事件的传输,像个钩子钩上事件一样,并且能够在钩上事件时,处理一些自己特定的事件。较为形象的流程如图所示。

    Hook的这个本领,使它能够将自身的代码“融入”被勾住(Hook)的程序的进程中,成为目标进程的一个部分。我们也知道,在Android系统中使用了沙箱机制,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是Hook的出现给我们开拓了解决此类问题的道路。当然,根据Hook对象与Hook后处理的事件方式不同,Hook还分为不同的种类,如消息Hook、API Hook等。
    (引用自动态注入技术 ,关于Hook更详细的介绍也可以参考这篇文章,写的非常详细)

    这里写图片描述

    二、Xposed框架介绍

    在日常工作学习中,我们希望使用Hook技术来完成某功能其实是相当烦琐的,我们很难手动地自己编写一个Hook工具,大多数情况下都是使用第三方提供的框架来做演示。常用的Hook框架有Xposed、CydiaSubstrate和ADBI/DDI,它们各自都有自己的特点,这里我们专门选择Xposed框架来进行介绍。

    1、Xposed框架原理

    Xposed框架是由rovo89开发的一款针对Android平台的动态劫持项目,是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,通过替换/system/bin/app_process 程序控制 zygote 进程,从而使 app_process 在启动过程中加载XposedBridge.jar 这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。

    Zygote进程在启动过程中,除了创建一个Dalvik虚拟机实例之外,还会将Java运行时库加载到进程中来,同时还会注册一些Android核心类的JNI方法到前面创建的Dalvik虚拟机实例中去。

    一个应用程序被孵化出来的时候,其不仅会获得Zygote进程中的Dalvik虚拟机实例,还会与Zygote一起共享Java运行时库,这也是可以将XposedBridge.jar这个jar包加载到每一个Android应用中的原因。
    XposedBridge有一个私有的Native方法:hookMethodNative,这个方法也在app_process中使用。该函数提供一个方法对象利用Java的反射机制来对内置的方法覆写。

    2、Xposed框架的使用步骤

    Xposed框架是基于一个Android的本地服务应用XposedInstaller与一个提供API的jar文件来完成的。所以,安装使用Xposed框架我们需要完成以下几个步骤。

    1)安装Xposed的本地服务

    在这里要安装Xposed的XposedInstall.apk本地应用,这个apk文件在各大应用市场都可以找到,推荐使用豌豆荚来安装,因为在豌豆荚中可以下到他的历史版本,许多手机由于适配或Android版本等一系列问题导致最新的apk安装后无法使用,会出现一堆蛋疼的问题,所以要么换手机要么可以试试虚拟机。

    这里我使用的是红米1s+Android4.4.2+XposedInstall.apk(v2.7)+XposedBridge.jar-54来测试。

    安装成功后画面如下:
    这里写图片描述

    点击框架,进入后点击“安装/更新”来安装Xposed框架(如图所示) ,重启后Xposed本地服务便安装完成了。

    这里写图片描述
    由于我这里已经安装好了,所以激活那里显示的是我当前XposedBridge.jar的版本54

    这里写图片描述

    2)从下载现有的Xposed模块使用或者自己编写Xposed模块

    下载Xposed模块可以自己在网上找也可以在aok的下载界面里面下载。
    在网上下载Xposed模块推荐在Xposed中文站 中下载
    在apk的下载界面中下载如图所示:
    这里写图片描述
    寻找自己想要的模块,下载下来,安装后重启手机便可以愉快的使用了。

    自己编写Xposed框架在下一篇文章中会具体介绍

    展开全文
  • Xposed模块开发教程

    千次阅读 2017-02-06 11:51:19
    原文地址。这是开发者所写的,可以说是官方开发指南。文章讲述了Xposed的...好了,你想学习怎么为Xposed开发新的模块么?那么读读这篇教程(或者我们可以称他为”泛读短文”)学着怎么去做。这不仅包括“创
  • [Android开发] Xposed 插件开发之一: Xposed入门

    万次阅读 多人点赞 2016-09-18 17:04:30
    一、什么是XposedXposed Framework 为来自国外XDA论坛(forum.xda-developers.com)的rovo89自行开发的一个开源的安卓系统框架。它是一款特殊的安卓App,其主要功能是提供一个新的应用平台,玩家们安装Xposed框架后...
  • Xposed入门教程

    万次阅读 2019-08-27 18:27:30
    2019年8月27日16时51分47秒 以前一直没机会接触Android Hook方式的逆向 今天有空试了下,以前也很少写这种东西, 今天第一次,认真写下,记录一下
  • Xposed模块开发入门教程

    万次阅读 热门讨论 2016-05-10 16:25:22
    前言:在高手如云的XDA论坛上Xposed框架都被许多开发者誉为“安卓第一神器”。究竟是什么神奇的能力让它在众多APP中脱引而出呢?本文将指引大家完成一个Xposed上最简单的Demo,让大家领略一下Xposed的威力。 一、...
  • xposed开发4 - 水了一篇

    2019-04-22 20:17:36
    VirtualXposed开发5 本来想写个微信防撤回练下手的, VirtaulXposed竟然登录不了微信, 头大, 只能试支付宝了
  • 前言: 本文章参考了以下文章: https://www.freebuf.com/articles/terminal/189021.html https://www.jianshu.com/p/002d9cf33653 https://www.52pojie.cn/thread-850885-1-1.html ...
  • xposed开发1 -环境搭建

    2019-04-22 20:16:50
    VirtualXposed开发1 1.安装 git clone https://github.com/android-hacker/VirtualXposed.git cd VirtualXposed git submodule update --init --recursive 使用android studio打开运行, 就安装成功了. 默认安装了...
  • Xposed开发初体验

    2017-12-01 08:56:53
    本篇文章具体是Xposed开发,如何安装Xposed需自行上网查找,本文同步更新于旺仔的个人博客,访问可能有点慢,多刷新几次。Xposed什么是Xposed呢? “Xposed是一个适用于Android的框架。基于这个框架开发的模块可以...
  • VirtualXposed开发2 1.测试目标apk用kotlin写能不能hook fun click(view: View) { Toast.makeText(this, toastMessage(), Toast.LENGTH_SHORT).show() } fun toastMessage(): String { return "I am not hooked" ...
  • xposed开发13 - 微信消息防撤回

    千次阅读 2019-04-23 18:41:25
    xposed开发13 - 微信消息防撤回 try { val clazz = XposedHelpers.findClass("com.tencent.wcdb.database.SQLiteDatabase", lpparam.classLoader) XposedHelpers.findAndHookMethod(clazz, "updateWithOnConflict...
  • xposed开发8- hook微信聊天消息数据库插入操作 // hook微信聊天消息数据库插入操作 hookClass = "com.tencent.wcdb.database.SQLiteDatabase"; hookMethodName = "insertWithOnConflict"; XposedHelpers....
  • xposed开发5-修改微信我的零钱的金额

    千次阅读 2019-04-22 20:17:56
    VirtualXposed开发5-修改微信我的零钱的金额 终于在virtualxposed上安装好微信了. 1.找到零钱的界面. 进入adb adb shell 开发android微信零钱界面 dumpsys activity | grep mResumedActivity 找到对应的类 2....
  • 安卓Hook系列教程(一):xposed模块开发环境搭建

    万次阅读 多人点赞 2016-11-30 08:32:34
    但是针对xposed开发技巧类的却不多,很难找。 经常有人问我xposed静态方法,静态变量如何hook,插件更新后能不能不重启调试,我决定针对这些写一系列教程,如果有不正确的地方希望大家指出来改正。 xposed是什么...
  • Xposed开发教程(Development tutorial)
  • Xposed开发例子修改IMEI(含源码)

    千次阅读 2018-10-21 18:12:15
    最近在研究xposed的框架,提供个简单的例子一共参考。 至于原理方面的东西 请自行查找了。 开发环境: windows7、android studio 3.2 源码路径: https://github.com/panuniverse/Xposed_Example...
  • Xposed开发入门笔记

    2016-07-07 11:27:22
    主要参考:Xposed Module开发教程。这个教程清晰易懂,而且是用AS开发的,很实用。但是这个链接里面有关键的一步没有指出,后面再讨论。开发环境是Android Studio 1.5,运行环境是模拟器Android 4.1.1 - API 16。0. ...
1 2 3 4 5 ... 20
收藏数 2,571
精华内容 1,028
关键字:

xposed开发