影月 发表于 2018-8-25 09:50

Xposed快速入门例子(二)----- 调方法的合适时机

本帖最后由 影月 于 2018-8-25 11:30 编辑

一、前言
上篇文章已经介绍了如何用Xposed实现调一个小功能的方法(Xposed快速入门例子(一)----- 拉黑好友)
下面补充两点:
1.Android Studio3.0以上已经隐藏了DDMS的功能。DDMS在sdk目录下,/sdk/tools/monitor打开这个文件就可以了。
2.有些手机在DDMS中显示不了进程。需要安装一个apk 。Xposed打上勾,重启手机就可以了。

言归正传,这篇文章介绍Xposed代码的调用时机。我想到了以下两种模式。


二、两种调用方式
1.发送广播
这种方式主要用于测试。
具体思路就是往Xposed模块中注册广播,然后在其它app中发送广播过去。
那么在什么地方注册广播呢? 网上大佬们给的方法很多,但是很多都会出现重复接收的情况。
所以介绍一下我的思路。看以下代码

      //注意:这是kotlin代码,kotlin中"=="相当于java中的"equals"
      if (lpparam.processName=="com.tencent.mm"){
         
            //在此处注册广播!
            val intentFilter = IntentFilter().apply {
                addAction("action_pull_black")
            }

            context.registerReceiver(myReceiver, intentFilter)
      }

可以看到注册广播的时候,我是用进程过滤的。因为微信的进程很多,所以不要用包名过滤。这样保证不会收到重复的广播!
    /**
   * 广播接收器
   * */
    private val myReceiver = object :BroadcastReceiver(){
      override fun onReceive(context: Context?, intent: Intent) {
            if (intent.action=="action_pull_black"){
                val wxid = intent.getStringExtra("extra_wxid")

                Handle.setBlack(wxid)


            }
      }
    }

通过广播接收器,可以看到收到了一个wxid,直接调拉黑的方法就可以了。


我在app主页,写了一个EditText和一个Button。点拉黑就把广播发送了过去。看以下代码
      btn_pull_black.setOnClickListener {
            val wxid = et_wxid.text.toString()
            if (wxid==""){
                Toast.makeText(this, "wxid不能为空!", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            sendBroadcast(Intent().setAction("action_pull_black").apply {
                putExtra("extra_wxid", wxid)
            })


      }


这样这种模式就完成了!




2.hook到微信的方法之后,再调相应的Xposed代码
一般做Xposed模块的项目,主要用到的就是这种模式。
我们可以设想一个实际场景,如果好友说了一句骂人的话,我们就把他拉黑。
所以我们现在要做的就是hook到这个聊天内容和好友的wxid。
如何hook呢。我看大佬们的方法也是千奇百怪。
我觉得做实用的思路就是微信巫师所提供的------trace微信的数据库。
这种方式的好处就是简单明了,不用适配微信的版本。


以下是打开微信的db文件(db文件是加密的,网上有很多解密的方法,请自行百度),通过分析找到了聊天记录的表所在的地方。

我们只要hook插入数据库的方法就可以了。
    // Hook SQLiteDatabase to trace all the database operations.
    @JvmStatic
    fun traceDatabase() {

      XposedHelpers.findAndHookMethod(
                pkg.SQLiteDatabase, "insertWithOnConflict",
                String::class.java, String::class.java, ContentValues::class.java, Int::class.java, object : XC_MethodHook() {
            @Throws(Throwable::class)
            override fun beforeHookedMethod(param: MethodHookParam) {
                try {
                  val table = param.args as String?
                  val values = param.args as ContentValues?
                  val talker = values?.get("talker").toString()
                  if (table == "message") {
                        val content = values?.get("content").toString()
                        Log.e("Developer","hook到的---->content:$content\n" +
                              "talker--->$talker")

                        if (content == "滚") {
                            Handle.setBlack(talker)
                        }
                  }

                } catch (e: Exception) {
                }


            }

      })
    }


下面测试一下这个hook。我用我的微信给测试的微信号发一个“你好啊”
下图可以看到日志已经打印到logcat里了
所以这种方式也可以实时监控聊天记录。

如果我给测试的微信号发一个内容为“滚”的消息,那么测试的微信号肯定就拉黑我了!


三、Xposed更新免重启
修改Xposed代码的时候,每次都得重启设备,给测试工作带来了不少麻烦。
微信巫师中有一套免重启的方案,我拿来用了。文章最后会给出源码。
每次修改Xposed,只要重启微信就可以了,不用重启手机。
只要在源码的app主页,点击【重启微信】的按钮,就可以了。
以下是实现的代码:
   // handleLoadWechatOnFly uses reflection to load updated module without reboot.
    private fun handleLoadWechatOnFly(lpparam: XC_LoadPackage.LoadPackageParam, context: Context) {
      val path = findAPKPath(context, MAGICIAN_PACKAGE_NAME)
      if (!File(path).exists()) {
            XposedBridge.log("Cannot load module on fly: APK not found")
            return
      }
      val pathClassLoader = PathClassLoader(path, ClassLoader.getSystemClassLoader())
      val clazz = Class.forName("$MAGICIAN_PACKAGE_NAME.backend.WechatHook", true, pathClassLoader)
      val method = clazz.getDeclaredMethod("handleLoadWechat", lpparam.javaClass, Context::class.java)
      method.isAccessible = true
      method.invoke(clazz.newInstance(), lpparam, context)
    }



源码下载地址:https://github.com/syxxjujing/Occasion

下一篇文章计划分享利用群发助手,按照标签群发消息。

影月 发表于 2018-8-28 20:27

zhengyg 发表于 2018-8-28 16:28
为啥您那个能显示进程的apk是个zip包呀,我刚好显示不了进程,这个也不知道怎么安装,直接解压安装里面的ap ...

吾爱只能不能用apk作为附件。你下载完,然后重命名,改成.apk的文件就可以安装了。

zhengyg 发表于 2018-8-29 16:37

影月 发表于 2018-8-28 20:27
吾爱只能不能用apk作为附件。你下载完,然后重命名,改成.apk的文件就可以安装了。

别忽悠我了,刚又试了下,不行,你那个包直接重命名的话就不是一个apk包,里面一个文件重命名可以,但是没有界面,我昨天网上看了下,是不是需要安装expose之后,你那个是一个拓展插件用的呀,我是真小白,别喷我笨啊

雨之幽 发表于 2018-8-25 10:24

过了折腾得年龄了

WANGYU2010 发表于 2018-8-25 11:04

虽然不用,但还是支持楼主!

13169456869 发表于 2018-8-25 11:48

感谢分享,期待楼主下一篇技术文

muzb 发表于 2018-8-25 13:58

支持一下

rat0 发表于 2018-8-25 17:29

哎,真是不懂啊。

studio 发表于 2018-8-25 18:05

感谢楼主无私的分享,好好研究一下

Roxaman柒 发表于 2018-8-25 18:17


虽然不用,但还是支持楼主!

pkwfx 发表于 2018-8-25 21:05

不错,好文章,谢谢分享

xijie888 发表于 2018-8-25 23:32

不错的文章,谢谢
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: Xposed快速入门例子(二)----- 调方法的合适时机