xposed微信长视频转发_利用 Xposed 快速实现一个简易微信机器人
目标
当前微信网页版限制越来越多,考虑尝试在手机上实现类似机器人的功能。本文目的是利用 Xposed 快速实现简易机器人功能,包括获取好友发来的消息,以及回复消息。后续可以增加智能回复,比如接入图灵机器人,或者自己自定义实现一些功能。
快速实现
项目框架的搭建
WechatSpellbook - 站在"巨人"的肩膀上
WechatSpellbook 是微信巫师作者在微信巫师的基础提取出来的通用微信 Xposed 插件框架。它提供了友好的的 API,提供自动分析微信内部结构特征的API(忽略微信版本差异),对 hook 微信出现的常见问题都做了优化,总之就是使用它会更容易对微信 hook,感谢作者的贡献,项目的集成和详细介绍参见wiki,以下步骤的实现都是基于这个框架的。
以下源码均基于微信 6.6.6 版本,由于使用了 WechatSpellbook 框架动态匹配的原理,大部分微信版本均可自动适配。
获得好友发来的消息
实现机器人功能的首要步骤就是获得好友发来的消息,获得消息之后才能回复吧,才能叫“机器人”吧。
使用了 WechatSpellbook,获取消息是很容易的,参见api,当新消息存入数据库后回调,具体代码:
object WechatMessageHook : IMessageStorageHook {
override fun onMessageStorageInserted(msgId: Long, msgObject: Any) {
XposedBridge.log("onMessageStorageInserted msgId=$msgId,msgObject=$msgObject")
// 这些都是消息的属性,内容,发送人,类型等
val field_content = XposedHelpers.getObjectField(msgObject, "field_content") as String?
val field_talker = XposedHelpers.getObjectField(msgObject, "field_talker") as String?
val field_type = (XposedHelpers.getObjectField(msgObject, "field_type") as Int).toInt()
val field_isSend = (XposedHelpers.getObjectField(msgObject, "field_isSend") as Int).toInt()
XposedBridge.log("field_content=$field_content,field_talker=$field_talker," +
"field_type=$field_type,field_isSend=$field_isSend")
if (field_isSend == 1) {// 代表自己发出的,不处理
return
}
// 做其他事情
}
}
其中字段名含义如下:
field_content: 消息内容
field_talker: 发送者
field_type: 消息类型
field_isSend: 是谁发出的,我自己发出为1
这步到此就完成了,下一步是机器人怎么将消息回复给好友。
机器人回复消息
机器人回复消息需要找到发送消息出去这个 API,然后 hook 它,在我们的代码里调用就行了。
利用 Monitor 的 Method Profiling 功能分析
首先在模拟器中打开微信聊天窗口,打开 Monitor,选中微信进程,点击Start Method Profiling,然后在聊天窗口随便发送一条消息,然后回来点击Stop Method Profiling,会生成分析文件。分析步骤如下:
先搜索 click,点击发送按钮,肯定是触发了点击事件的嘛,先找找看
image.png
发现调用了 ChatFooter$3.onClick() 方法,单从名字上来看,应该就是这里了,点进去,看这个函数调用了哪里
image.png
它调用了 chatting.o.FZ 方法,注意参数是 String,返回值是 Boolean,大胆猜测一下,这个字符串就是消息文本,返回值应该是发送是否成功。验证一下,直接 Hook 这个函数,运行发现猜测是真的,这里比较简单就不贴代码了。
分析到这里,已经知道了chatting.o.FZ 方法就是发送消息的,参数就是消息文本,但是有个很重要的地方忽略了,为什么没有接收者参数?,微信内部联系人 ID 一般是以 wx_idxxx 开头的,接收者 id 设置在哪,怎么设置 hook,现在就差这个问题了。
到这里已经知道了发送消息的 API,hook 掉就可以搞事情了,但是缺少接收者这个重要参数的设置,分析下源码吧。
反编译查看源码分析
反编译之后分析 chatting.o.FZ 方法源码:
public final boolean FZ(String str) {
mS(false);
ctQ();
return this.yOg.yRO.dt(str, 0);
}
然后分析yOg.yRO.dt方法,它是com.tencent.mm.ui.chatting.b类的方法,看下源码:
public final boolean dt(String str, int i) {
int i2 = 0;
String Xf = bh.Xf(str);
if (Xf == null || Xf.length() == 0) {
w.e("MicroMsg.ChattingUI.TextImp", "doSendMessage null");
return false;
}
x xVar = this.yXC;
if (!ah.oB(Xf)) {
az azVar = new az();
azVar.setContent(Xf);
azVar.eW(1);
xVar.aB(azVar);
}
bt btVar = new bt();
// 省略
}
可以看到在azVar.setContent(Xf);这里将发送的消息文本放在放在了az这个类中,setContent() 是 az 的父类com.tencent.mm.g.c.cg的方法,看下这个类的源码:
// 截取了几个方法
public final void av(long j) {
this.field_createTime = j;
this.eRw = true;
}
public final long wQ() {
return this.field_createTime;
}
public final void ed(String str) {
this.field_talker = str;
this.feh = true;
}
public final String wR() {
return this.field_talker;
}
public final void setContent(String str) {
this.field_content = str;
this.eRE = true;
}
只截取了几个方法,可以看到这个类不仅仅包含消息文本,还包含了接受者field_talker,发送时间field_createTime等,大胆猜想,这个类就是消息的包装类,包含消息所有的属性,这里关注的字段是接收者 field_talker,只要知道在哪里调用了ed方法 hook 掉就可以为所欲为了。
但是,通过 AS 查找调用这个的地方有很多,根本无法判断具体发消息是哪里调用了,怎么办。
借助 Xposed 分析com.tencent.mm.g.c.cg.ed()方法,也就是设置接收者 field_talker 的方法,只要 hook 这个方法,然后打印出调用堆栈看看到底是哪里回调了。
val clz = XposedHelpers.findClass("com.tencent.mm.g.c.cg", WechatGlobal.wxLoader)
XposedHelpers.findAndHookMethod(clz, "ed", String::class.java, object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam?) {
log("set field_talker start")
LogUtil.logStackTraces() // 打印调用堆栈
log("set field_talker end")
}
})
打印结果:
image.png
可以看到函数调用链,关键点在com.tencent.mm.modelmulti.i.,看下这个方法的源码:
public i(String str, String str2, int i, int i2, Object obj) {
w.d("MicroMsg.NetSceneSendMsg", "dktext :%s", new Object[]{bh.cjG()});
if (!bh.oB(str)) {
cg azVar = new az();
azVar.eV(1);
azVar.ed(str);
azVar.av(bd.in(str));
azVar.eW(1);
azVar.setContent(str2);
azVar.setType(i);
String a = a(((o) g.l(o.class)).s(azVar), obj, i2);
if (!bh.oB(a)) {
azVar.ej(a);
w.d("MicroMsg.NetSceneSendMsg", "NetSceneSendMsg:MsgSource:%s", new Object[]{azVar.fnF});
// 省略很多代码
}
可以看到这个类的构造方法实例化了cg azVar = new az();,并调用了ed()方法。分析下这个构造函数,很有意思的是:参数 str 就是微信 id,str2是文本内容,后几个不知道,大胆猜测下这个类就是去发送消息的,从源码很难分析,hook 掉看看。
hook com.tencent.mm.modelmulti.i的构造方法打印参数,看下是否和发送消息有关。这里就不贴代码和截图了,结论是有关。那可以 hook 这个类的构造方法发送消息啊。
找到的 hook 关键点
com.tencent.mm.ui.chatting.o.FZ(String) 方法,参数是消息文本,调用该方法可以发消息,但是无法设置接收者
com.tencent.mm.modelmulti.i()构造方法,第0个参数是接收者 id,第1个参数是消息文本
机器人回复消息思路:调用第一个 API 发送消息文本,hook 第二个 API 修改接收者 id,然后就可以愉快的发消息了
关键点存在的问题
上述 hook 思路存在的问题:当 hook 第二个API 时,不知道该条消息的接收者是谁,不太好设置。
问题解决方法
既然我能 hook 这两个 API,那么我可不可以直接在调用第一个 API 的时候,将接收者 id 放在文本消息前面,然后在 hook 第二个 API 时将文本消息中的接收者 id 解析出来赋值给第0个参数。
新消息文本 = 接收者ID + 分隔符号 + 真实消息文本
分割符号可以采用特殊字符,用户不会输入的字符,比如 \t 等
代码实现
源码在这里,关键地方都有注释,有兴趣可以 star
效果图
image.png
xposed微信长视频转发_利用 Xposed 快速实现一个简易微信机器人相关推荐
- xposed微信长视频转发_实现可以跨版本使用的微信 Xposed 模块
众所周知的,微信每个版本升级后,变量名都会有一些变化,引起过去的 xposed 模块失效,所以针对微信的 xposed 模块都有版本判断,以便告知用户该模块适应哪个版本.而一旦用户不小心把版本升级了, ...
- xposed微信长视频转发_Xposed微信之发送文件
本帖最后由 randompath 于 2019-8-27 16:34 编辑 本文主要介绍通过静态分析微信发送文件的逻辑,并通过xposed实现文件自动发送.分析的微信版本为当前最新版(v7.0.6), ...
- 利用 Xposed 快速实现一个简易微信机器人
目标 当前微信网页版限制越来越多,考虑尝试在手机上实现类似机器人的功能.本文目的是利用 Xposed 快速实现简易机器人功能,包括获取好友发来的消息,以及回复消息.后续可以增加智能回复,比如接入图灵机 ...
- 2020.2idea怎么创建html模块_利用idea快速搭建一个项目
一.前提准备:电脑安装好jdk1.8,安装好IDEA 二.步骤 1.点击创建一个新项目 2.选择 Spring initializr选项,这是一个非常方便的生成Springboot的工具,确认信息无误 ...
- 钉钉一行代码_利用Python快速搭建钉钉和邮件数据推送系统
前面的文章我们写到了利用Python实现钉钉和邮件的数据推送,在数据处理这一块实现了对mysql和odps的数据获取和处理,可以满足常规业务大部分数据场景需求,在一家初创公司数据基础建设还不完善的时候 ...
- 微信小程序是什么?如何快速搭建一个微信小程序?
目录 一.微信小程序是什么 二.安全管理 三.微信小程序的功能 四.快速开发一个微信小程序APP 1.集成即构实时音视频SDK 2.初始化SDK引擎 3.创建房间与登录房间 4.房主创建房间 5.推流 ...
- windows和Linux利用Python快速搭建一个网站
windows和Linux利用Python快速搭建一个网站 一.windows 步骤1:安装Python3(自行百度) 步骤2:在cmd窗口输入ipconfig查看本机ip地址,IPV4那一行.如:1 ...
- Android studio设计一个简易微信界面
一.设计要求及实现构想 1.设计一个简易微信界面框架,包含至少4个tab页面(我设计的4个分别为message.contact.find.config),要求能实现四个页面之间的点击切换. 2.首先分 ...
- 利用java swing编写一个简易的计算器,实现了括号,优先级,三角函数,阶乘等功能
利用java swing编写一个简易的计算器 背景 效果图 一.默认图 二.计算三角函数 三.阶乘运算 四.常见的四则运算(实现了优先级) 代码 本文借鉴了"初识Java,实现简易计算器(带 ...
最新文章
- 对于正交频分复用的异构网络的理解
- 解决MySQL报错... right syntax to use near ‘password ‘XXX‘ at line 1...ERROR 1064 42000: You have an erro
- 多线程三种同步方式(模拟银行取款)
- Python机器学习:评价分类结果005precisoion-Recall的平衡
- 从用户空间直接访问系统调用
- js引用类型和基本类型、隐式类型转换以及强制类型转换面试题
- Quart2D文字图像绘制
- 什么是超级浏览器?目前超级浏览器有哪些分类?
- iot软件测试,IoT研发测试工程师
- 亚马逊服务器443端口开放配置aws
- 2023全新纯净版本知识付费微信小程序源码_附搭建教程_亲测可用
- 计算机 管理 mmc 注册表,我的注册表没有MMC文件
- Mysql时间函数的坑
- 软件定义和硬件重构知多少(二)
- 汽车动力性仿真matlab程序,汽车理论课程设计:基于Matlab的汽车动力性的仿真
- 上海工程技术大学计算机专硕,上海工程技术大学2019年硕士研究生调剂公告
- Codeforces Round #143 (Div. 2)-D. Magic Box
- 智慧园区BIM智能化系统平台建设方案
- 在WIN7中找回你熟悉的记事本字体Fixedsys
- 人工智能-逻辑回归、分类评估方法、ROC曲线、类别不平衡
热门文章
- 崔炜:全面分析学生行为数据,AI正在改变中国基础教育
- PIXHAWK:LED灯意义
- 【明解C语言】之do... while循环
- 反思:你的装饰公司为什么签单能力差?
- 完整解释 Monad -- 程序员范畴论入门
- php强行横屏,android强制横屏apk下载
- 如何使用winscp工具连接windows(windows to windows)
- 【搭建NextCloud私有云盘服务】采用docker在linux上进行部署,内含nextCloud移植(迁移服务器)方法
- DIOR HOMME_百度百科
- java如何枚举定义一个数组_java 枚举(Enum)笔记