MingKing 发表于 2018-1-18 03:41

【Xposed模块开发入门】真·第一课

本帖最后由 MingKing 于 2018-1-18 14:59 编辑

【Xposed模块开发入门】真·第一课

之前按网上的教程来,遇到各种问题,所幸问题一一得到解决,下面整理一篇详细的入门教程,细节地方皆详细说明(如有不懂的地方,评论区问我,以便我稍加修改)


本次在android studio上进行讲解,因为感觉现在用这个的人比较多,问题也多

【开始前的准备】

1.掌握基本的android开发知识,搭建好android开发环境(环境怎么搭啥的也有一堆蛋疼问题,这里就不说了,改天我仔细探索整理一下)
2.有xposed框架作为环境(真机或者模拟器,我下面直接真机调试)
3.Xposed框架API(网上各种坑爹教程附各种不知啥时候会挂掉,资源老,老子可能要账号才能下载的坑爹链接,也不给个官网地址,所以)
   由于它是不断更新的,请大家直接到官网页面进行下载:https://jcenter.bintray.com/de/robv/android/xposed/api/


下载如下两个文件:api-82-sources.jar   
                              api-82.jar

下方括号中是使用eclipse要注意的,android studio不用管
(在Eclipse中,你必须从这里手动下载jar:https : //jcenter.bintray.com/de/robv/android/xposed/api/我建议将这些文件放到一个名为的子目录中lib。不要把它们放到libs子目录中!Jar文件libs将自动使Eclipse将API类编译到您的APK中,但它们只能被引用(参见上文)。现在右键单击该api-XX.jar文件并选择Build Path -> Add to Build Path。您还可以添加一个源api-XX-sources.jar文件(在文件中),以便在Eclipse中直接查看文档。)(懒得打了,直接官网copy)


【环境的搭建】
就是将Xposed框架API引用到项目中,这样就能进行Xposed模块的开发了

1.使用android studio构建一个项目


(小提示,注意设置为project查看,这样项目结构看得更加清楚)




下方修改处皆在上图中用箭头指出(build.gradle是app文件夹中的,注意不要搞错)


1.将下载下来的两个文件复制到文件夹libs中


2.在build.gradle中将添加图中两句


provided 'de.robv.android.xposed:api:82'
provided 'de.robv.android.xposed:api:82:sources'

有人说
provided 'de.robv.android.xposed:api:82:sources'
这句不是必要的,确实,它里面存放了javadoc,方便Ctrl+Q快速查阅,反正也是一堆英文看着晕,不写这句也行

作用:将libs中的Xposed框架API引用到项目中(构建依赖)

可能会遇到的问题:

1.这两句报错!?
provided 'de.robv.android.xposed:api:82'
provided 'de.robv.android.xposed:api:82:sources'

异常:
Error:A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApkCopy'.
   > Could not resolve com.squareup.okhttp3:okhttp:3.5.0.
   Required by:
         retrofit-rxjava-okhttp:app:unspecified > com.squareup.retrofit2:retrofit:2.1.0
      > No cached version of com.squareup.okhttp3:okhttp:3.5.0 available for offline mode.

这个问题是因为之前我android环境没有搭建好,改动了一些配置导致,大家通常应该不会遇到这个问题

解决方法:
Settings-Build.Execution,Deployment-Gradle–取消勾选的Offline Work,重新编译即可



2.使用compile fileTree(dir: 'libs', include: ['*.jar'])导致出错


一定要使用 provided ,不要使用 compile! compile 会将整个 API 类 编译进你的apk中而导致出问题。provided 则只是提供了API 类的引用,
API 类真正的实现则在 Xposed FramWork中。 在大多数情况下,repositories已经存在,并且已经有一些依赖,所以只需要将provided 这一
行添加到存在的dependcies模块中即可。


(之前我使用provided失败,就转而使用compile,结果还是失败,真的无语了,大家要注意)


3.在AndroidManifest.xml将自己标识为一个Xposed模块,语句添加在如下位置


      <meta-data
            android:name="xposedmodule"
            android:value="true" />
      <meta-data
            android:name="xposeddescription"
            android:value="我是一个Xposed例程" />
      <meta-data
            android:name="xposedminversion"
            android:value="53" />

作用:
xposedmodule:value为true,表示自己是一个xposed模块
xposeddescription:value中的文字就是对模块的描述,这些能够在手机上的Xposed框架中看到,举个栗子

情迁抢包是项目名,后面一堆文字描述就是在xposeddescription的value中标注的(这个抢红包贼稳)

xposedminversion:xposed最低版本,这些应该都是向下兼容的吧?所以直接填最低版本好了

4.下面就可以开车啦


【第一个Xposed模块的编写】
直接输出日志什么的太low了,找其他软件hook我怕被举报(放屁,其实是我特么也还不会),所以就自己写个类来hook练练手吧!


我们先写一个MainActivity类输出一个Toast提示,然后再写一个HookToast类作为Xposed模块来hook它,实现修改


0.在界面中添加一个可爱的小button


1.代码逻辑如下:

public class MainActivity extends AppCompatActivity {
    private Button button;

    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      button = (Button) findViewById(R.id.button);

      button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, toastMessage(), Toast.LENGTH_SHORT).show();
            }
      });
    }

    public String toastMessage() {
      return "我未被劫持";
    }

}

比较容易理解,这个类的功能是,点击按钮,弹出一个toast提示,内容由toastMessage()方法提供,而toastMessage()的返回值为“我未被劫持”


下面我们正式开始写我们的xposed模块,来hook我们的MainActivity,修改toastMessage()方法的返回值为“你已被劫持”


2.我们新建一个HookToast类

public class HookToast implements IXposedHookLoadPackage {

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

      if (loadPackageParam.packageName.equals("com.example.mingking.xposedtest")) {
            
            Class clazz = loadPackageParam.classLoader.loadClass("com.example.mingking.xposedtest.MainActivity");
            
            XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  super.beforeHookedMethod(param);
                }
               
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                  param.setResult("你已被劫持");
                }
            });
      }
    }
}

这个类实现IXposedHookLoadPackage接口,并实现IXposedHookLoadPackage接口中的handleLoadPackage方法


代码中,hook的包名记得改成自己的

在handleLoadPackage方法中先筛选到我们本程序的包名,然后用XposedHelpers里的findAndHookMethod方法对
MainActivity中的toastMessage方法进行劫持,在其Hook的回调中的beforeHookedMethod或afterHookedMethod
方法里进行劫持操作


afterHookedMethod方法中,我们修改了toastMessage()方法的返回值为“你已被劫持”


beforeHookedMethod方法中,我们什么也不用做,当然,我们也可以在xposed日志中输出一点调试信息玩耍一下,
方法中添加语句:


XposedBridge.log("别看了,老子已经成功Hook");


到此,所有代码已经写完,之前在AndroidManifest.xml中标识了我们的项目是一个Xposed模块,可是我们可能会有许多Activity,
它怎么才能知道模块的入口在哪呢?


所以,下面要告诉Xposed框架,我们的应用中,Xposed模块的入口到底在哪。

3.标注Xposed模块入口

右键点击 main , 选择new --> Folder -->Assets Folder,然后确认即可。



在assets中new一个file,文件名为xposed_init(文件类型选text),并在其中写上入口类的完整路径(下面是我的类路径,你们填自己的,就是activity中packege后面的包名)





这样,xposed框架就能够读取xposed_init中的信息来找到模块的入口

4.Run

请确保禁用Instant Run(File -> Settings -> Build, Execution, Deployment -> Instant Run),否则您的类不会直接包含在APK中,导致HOOK失败!!!



以上是来自官方的警告,一定要注意,之前我死活hook不了,日志也输出不了,就是因为这个!!!

如果你不这样做,你会惊喜地发现发现xposed日志反复给你抛出类似这样一个错误:
xposed didn't find class on dexpathlist:……(省略一长串)
而这个错误是你百度到死(google也没用)也不一定查的到解决方案的(这个故事提醒我们要仔细阅读官方文档)

Run成功后……

可以发现,xposed模块里出现了我们的模块
XposedTest是应用名
后面的文字注释正是我们之前在AndroidManifest.xml中的xposeddescription里所标注的信息


xposed模块生效前


勾选并重启



啦啦啦,成功!!!


再让我们看看xposed框架里的日志




完全没毛病!!!(hook的是toastMessage()方法,它每次被调用都会在hook之前输出日志,hook之后修改返回值,我之前点击了三次,所以输出了三条)


到此,你就算是入坑xposed了,当然,上面的例程比较简单,实际的应用要复杂得多,大家可以到github找些开源项目学习一下,不懂的地方多多参照官方API文档:
http://api.xposed.info/reference/packages.html


【参考资料】
1.http://blog.csdn.net/mrglaucusss/article/details/50963542
2.https://www.52pojie.cn/thread-533120-1-1.html
3.https://www.cnblogs.com/dacainiao/p/6002609.html
4.https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
5.https://github.com/rovo89/Xposed ... posed-Framework-API
6.http://blog.csdn.net/w958796636/article/details/52919582
7.http://blog.csdn.net/aa464971/article/details/68948650

后续暂时没有时间深入学习,如果有,我再分享新的教程,当然,我可能在那之前你们可能已经更牛了,当然也欢迎你们分享学习成果

如果大家遇到什么新的问题,可以在评论区反馈,以便我及时更新整理完善,帮助后来之人

默默伤心 发表于 2019-8-22 11:49

本帖最后由 默默伤心 于 2019-8-22 11:50 编辑

我编写完成后 点击button 为什么显示未被劫持呢
package com.xposed.examcool.hook;

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 HookToast implements IXposedHookLoadPackage {

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
      XposedBridge.log("别看了,老子已经成功Hook");
      if (loadPackageParam.packageName.equals("com.xposed.examcool")) {

            Class clazz = loadPackageParam.classLoader.loadClass("com.xposed.examcool.activity.MainActivity");

            XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  super.beforeHookedMethod(param);
                }

                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                  param.setResult("你已被劫持");
                }
            });
      }
    }
}

xwzj20170829 发表于 2018-1-20 00:27

本帖最后由 xwzj20170829 于 2018-2-25 01:02 编辑

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class HookToast implements IXposedHookLoadPackage {

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

      if (loadPackageParam.packageName.equals("xp001.hook001")) {

            Class clazz = loadPackageParam.classLoader.loadClass("xp001.hook001.MainActivity");

            XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  super.beforeHookedMethod(param);
                }

                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                  param.setResult("你已被劫持");

public class HookToast implements IXposedHookLoadPackage 我的这句话的HookToast下面有红色波浪线丢失包的声明什么的不会是模拟器用不了吧

我成功了    之前只显示"我未被劫持"    看了这篇文章后修改成功了https://www.52pojie.cn/thread-682743-1-1.html

qianeymax6274 发表于 2018-1-18 04:28

谢谢太给力了

ljm115 发表于 2018-1-18 07:16

非常好的教程,给力

debug_cat 发表于 2018-1-18 07:24

如果一个actvity中有一个handler,如何hook这个handler的,handler message方法的返回值msg呢

psp7456 发表于 2018-1-18 07:31

不错,正需要这方面的资料,学习了!

凯林哥与你同在 发表于 2018-1-18 07:54

非常感谢分享    很有帮助   

挥洒灵魂 发表于 2018-1-18 08:31

楼主666啊,这么好的帖子竟然没人看。嘿嘿,心中窃喜,得到宝贝一样哭晕{:301_997:}

yxjoe 发表于 2018-1-18 08:35

教程挺不错的,感谢楼主分享

打卤楠楠 发表于 2018-1-18 08:37

谢谢楼主分享,学习学习

夏雨微凉 发表于 2018-1-18 08:41

好贴!跟着楼主来一遍
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 【Xposed模块开发入门】真·第一课