zoukankan      html  css  js  c++  java
  • 【转】编写微信聊天机器人4《聊天精灵WeChatGenius》:实时获取到微信聊天消息,hook数据库插入操作。

    接上篇,使用Xposed来hook微信,找到微信进程:https://blog.csdn.net/weixin_42127613/article/details/81839537

    既然已经找到了微信进程,那么就可以对微信的数据进行拦截获取了。

    hook到微信的聊天消息,比较简单,只需要hook住数据库的插入方法即可。

    因为一旦来了新消息,微信就会往本地数据库插入聊天消息,将聊天消息保存到本地。所以我们只要hook住消息的插入动作,就能实时的获取到聊天消息。

    微信的数据库操作有很多类和实例,但最终都是调用了com.tencent.wcdb.database.SQLiteDatabase这个类。

    插入方法用的是insert,insert内部又调用了insertWithOnConflict方法。我们可以hook住insert方法,也可以hook住insertWithOnConflict方法。

    我们采用hook最终方法吧。hook这个insertWithOnConflict方法。

    反编译微信,去查看com.tencent.wcdb.database.SQLiteDatabase这个类的insertWithOnConflict方法,看看都有什么参数,才能编写hook代码。如下图所示,有4个参数。

    现在编写hook代码。在MainXposed中新建一个方法hookDatabaseInsert,进行hook。

    //hook数据库插入操作
    private void hookDatabaseInsert(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
    Class<?> classDb = XposedHelpers.findClassIfExists(WECHAT_DATABASE_PACKAGE_NAME, loadPackageParam.classLoader);
    if (classDb == null) {
    XposedBridge.log("hook数据库insert操作:未找到类" + WECHAT_DATABASE_PACKAGE_NAME);
    return;
    }
    XposedHelpers.findAndHookMethod(classDb,
    "insertWithOnConflict",
    String.class, String.class, ContentValues.class, int.class,
    new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    XposedBridge.log("HOOK住微信数据库插入操作。");
    }
    });
    }
    在主函数handleLoadPackage方法中加入调用,如下代码。

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
    if (!lpparam.processName.equals(WECHAT_PROCESS_NAME)) {
    return;
    }
    XposedBridge.log("进入微信进程:" + lpparam.processName);
    //调用 hook数据库插入。
    hookDatabaseInsert(lpparam);
    }
    现在开始执行,测试,查看日志。如下图所示,发现了很多数据库操作。

    为了能清晰的查看消息。我们过滤掉非聊天消息的插入动作,同时将聊天消息的内容解析出来。

    微信的新聊天消息,会插入2个表:message和rconversation。

    message表:消息内容总表。所有的聊天消息,都会存入到这个表。
    rconversation表:当前的会话表。就是进入微信,在主界面看到的列表。这个表保存的是最后一条聊天记录,每次有新消息,都会更新这个表。
    我们hook这2个表中的任意一个都可以,但是rconversation表不仅有insert,还有update操作,所以我们还是只取message表即可。

    为了能输出数据库的插入数据,我们特意定义一个函数printInsertLog,用于输出数据库插入日志。

    //输出插入操作日志
    private void printInsertLog(String tableName, String nullColumnHack, ContentValues contentValues, int conflictValue) {
    String[] arrayConflicValues =
    {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
    if (conflictValue < 0 || conflictValue > 5) {
    return;
    }
    XposedBridge.log("Hook数据库insert。table:" + tableName
    + ";nullColumnHack:" + nullColumnHack
    + ";CONFLICT_VALUES:" + arrayConflicValues[conflictValue]
    + ";contentValues:" + contentValues);
    }
    改进代码,去掉之前的日志输出,过滤掉非聊天消息表,输出消息日志。现在hookDatabaseInsert的代码为:

    //hook数据库插入操作
    private void hookDatabaseInsert(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
    Class<?> classDb = XposedHelpers.findClassIfExists(WECHAT_DATABASE_PACKAGE_NAME, loadPackageParam.classLoader);
    if (classDb == null) {
    XposedBridge.log("hook数据库insert操作:未找到类" + WECHAT_DATABASE_PACKAGE_NAME);
    return;
    }
    XposedHelpers.findAndHookMethod(classDb,
    "insertWithOnConflict",
    String.class, String.class, ContentValues.class, int.class,
    new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    String tableName = (String) param.args[0];
    ContentValues contentValues = (ContentValues) param.args[2];
    if (tableName == null || tableName.length() == 0 || contentValues == null) {
    return;
    }
    //过滤掉非聊天消息
    if (!tableName.equals("message")){
    return;
    }
    //打印出日志
    printInsertLog(tableName, (String) param.args[1], contentValues, (Integer) param.args[3]);
    }
    });
    }
    编译、运行、重启,查看日志。没有日志输出,那么给当前的微信号,发送一条消息试试看。如下图所示,已经成功的获取到了聊天消息。

    查看日志详情,可以看到插入的contentValues数据内容。

    Hook数据库insert。table:message;nullColumnHack:msgId;CONFLICT_VALUES:;contentValues:bizClientMsgId= msgId=2622 msgSvrId=6403889649528004581 talker=wxid_e77yg22 content=在不在 flag=0 status=3 msgSeq=680182320 createTime=1534678573000 lvbuffer=[B@4428279 isSend=0 type=1 bizChatId=-1 talkerId=378

    我们想要什么数据,只需要从contentValues的相应字段中取即可。

    好了,现在我们已经成功的hook到微信的实时聊天消息,想怎么处理,就看你了。

    代码已提交:https://github.com/dalu2048/WeChatGenius.git

    接下来,下篇文章,测试文本消息自动回复功能:https://blog.csdn.net/weixin_42127613/article/details/81841099
    ---------------------

    from:https://blog.csdn.net/weixin_42127613/article/details/81840536

  • 相关阅读:
    WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构
    WCF后续之旅(13): 创建一个简单的WCF SOAP Message拦截、转发工具[上篇]
    Enterprise Library深入解析与灵活应用(6):自己动手创建迷你版AOP框架
    [原创]WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿
    WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成
    WCF技术剖析之四:基于IIS的WCF服务寄宿(Hosting)实现揭秘
    谈谈基于SQL Server 的Exception Handling
    Is this a MS EnterLib DAAB BUG or not?
    难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?
    WCF中的Binding模型之一: Binding模型简介
  • 原文地址:https://www.cnblogs.com/xuan52rock/p/9965364.html
Copyright © 2011-2022 走看看