微信机器人技术实现深度解析:从消息Hook到自动化处理

51 阅读3分钟

一、项目概述

本文基于 Wechaty 生态系统的 wechaty-puppet-xp 项目进行分析。这是一个基于 Windows 平台的微信机器人实现,通过模拟微信 PC 客户端的操作来实现自动化功能。

二、核心技术栈

2.1 底层技术

  1. 内存注入技术

    • 使用 Frida 框架进行动态二进制插桩
    • 通过内存偏移定位关键函数和数据结构
    • 实现对微信进程的实时监控和操作
  2. 消息拦截技术

    • Hook 系统API调用
    • 内存数据结构解析
    • 消息数据包解密和重组

2.2 架构设计

项目采用了分层架构设计:

  1. Puppet 层:负责与微信客户端的直接交互
  2. Sidecar 层:处理底层消息拦截和注入
  3. API 层:提供友好的编程接口

三、技术实现细节

3.1 关键偏移地址

const wxOffsets = {
  chatMgr: {
    WX_CHAT_MGR_OFFSET: 0x792700,
  },
  sendMessageMgr: {
    WX_SEND_MESSAGE_MGR_OFFSET: 0x768140,
  },
  setChatMsgValue: {
    WX_INIT_CHAT_MSG_OFFSET: 0xf59e40,
  }
}

3.2 消息处理系统

class PuppetXp extends PUPPET.Puppet {
  private messageStore: { [k: string]: PUPPET.payloads.Message }
  private roomStore: { [k: string]: PUPPET.payloads.Room }
  private contactStore: { [k: string]: PUPPET.payloads.Contact }
}

3.3 版本适配机制

class XpSidecar {
  private supportedVersions = {
    v330115:'3.3.0.115',
    v360000:'3.6.0.18',
    v39223:'3.9.2.23',
  }
  
  constructor (options?:WeChatVersion) {
    if (options?.wechatVersion) {
      XpSidecar.currentVersion = options.wechatVersion
    }
    // 根据版本加载对应的注入脚本
  }
}

四、核心功能实现

4.1 消息发送实现

const sendMsgNativeFunction = (talkerId: any, content: any) => {
  // 1. 分配内存
  const msgStruct = initmsgStruct(content)
  
  // 2. 设置消息内容
  const contentPtr = Memory.allocUtf16String(content)
  msgStruct.buffer.writePointer(contentPtr)
  
  // 3. 调用发送函数
  const sendFunc = new NativeFunction(
    ptr(baseAddress.add(wxOffsets.sendMessageMgr.WX_SEND_MESSAGE_MGR_OFFSET)),
    'void',
    ['pointer', 'pointer']
  )
  sendFunc(talkerId, msgStruct)
}

4.2 消息接收实现

const recvMsgHook = () => {
  Interceptor.attach(ptr(baseAddress.add(wxOffsets.chatMgr.WX_CHAT_MGR_OFFSET)), {
    onEnter(args) {
      const msgType = args[0].toInt32()
      const sender = readWStringPtr(args[1])
      const content = readWStringPtr(args[2])
      
      // 消息分发
      emitMessage({
        type: msgType,
        sender,
        content,
        timestamp: Date.now()
      })
    }
  })
}

4.3 群聊消息处理

const handleChatRoomMsg = () => {
  const chatroomRecurse = (node: NativePointer, memberList: any[]) => {
    if (node.isNull()) {
      return
    }
    
    // 解析群成员信息
    const wxid = readWStringPtr(node.add(0x10))
    const nickname = readWStringPtr(node.add(0x78))
    memberList.push({ wxid, nickname })
    
    // 递归遍历
    chatroomRecurse(node.add(0x8), memberList)
  }
}

五、Hook机制原理

5.1 为什么能够Hook成功?

  1. 内存布局分析
  • 微信客户端是一个Win32应用程序
  • 关键函数和数据结构在内存中有固定偏移
  • 通过逆向分析获得这些偏移地址
  1. 注入时机选择
  • 在进程初始化完成后注入
  • 确保所有关键模块都已加载
  • 避免与微信自身的反注入机制冲突
  1. 稳定性保证
const checkSupportedFunction = () => {
  const version = getWechatVersionString()
  // 检查版本兼容性
  if (!supportedVersions.includes(version)) {
    throw new Error(`Unsupported WeChat version: ${version}`)
  }
}

5.2 数据安全性

  1. 内存安全
// 安全的内存分配和释放
const allocateString = (str: string) => {
  const buffer = Memory.alloc(str.length * 2 + 2)
  buffer.writeUtf16String(str)
  return buffer
}

// 使用完后释放
const freeString = (buffer: NativePointer) => {
  Memory.free(buffer)
}
  1. 异常处理
const safeHook = (address: NativePointer, callback: Function) => {
  try {
    Interceptor.attach(address, {
      onEnter: callback
    })
  } catch (e) {
    console.error('Hook failed:', e)
    // 进行错误恢复
    recover()
  }
}

六、实战应用示例

6.1 自动回复机器人

class AutoReplyBot {
  constructor() {
    // 安装消息Hook
    this.installHook()
    // 初始化回复规则
    this.initRules()
  }

  private installHook() {
    recvMsgHook()
    // 注册消息处理器
    on('message', this.handleMessage.bind(this))
  }

  private async handleMessage(msg: Message) {
    if (this.shouldReply(msg)) {
      const reply = await this.generateReply(msg)
      sendMsgNativeFunction(msg.sender, reply)
    }
  }
}

6.2 群管理助手

class GroupManager {
  constructor() {
    this.initChatRoomHook()
  }

  private initChatRoomHook() {
    // Hook群成员变动
    Interceptor.attach(ptr(baseAddress.add(wxOffsets.chatRoom.WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET)), {
      onEnter: this.handleMemberChange.bind(this)
    })
  }

  public async addMember(roomId: string, wxid: string) {
    return addMemberToChatRoom(roomId, [wxid])
  }
}

七、总结

微信机器人的实现涉及多项关键技术的协同工作:

  1. Frida提供的动态二进制插桩能力
  2. 精确的内存定位和操作
  3. 稳定的Hook机制
  4. 安全的数据处理
  5. 完善的异常处理

这些技术的结合使得我们能够实现稳定、高效的微信机器人功能。理解这些技术的工作原理和协作方式,对于开发更强大的自动化工具具有重要意义。

想了解更多技术实现细节和源码解析,欢迎关注我的微信公众号**【松哥ai自动化】**。每周我都会带来一篇深度技术文章,从源码角度剖析各种实用工具的实现原理。