-
-
[原创]企业微信(私有化部署版本)发送消息分析结果
-
-
[原创]企业微信(私有化部署版本)发送消息分析结果
段落引用 起因: 最近公司某个项目 需要根据用户在群里的聊天 做一些查数据的操作 所以需要获取聊天数据 但是上面又不给机器人权限 所以只能做一个可以拦截企业微信聊天内容的插件 核心功能主要是收发消息
由于是私有化部署的企微信,感觉网上的资料较少,根据得到的关键词PreSendNewMessage让AI分析了一波。
求各位大佬指点方向
WeWork 消息发送功能分析报告
概述
本报告分析了 WeWorkLib.dll 中的消息发送功能,重点关注 PreSendNewMessage 函数及其相关组件。
关键发现
1. 核心函数识别
PreSendNewMessage (0x118AFE50)
- 原函数名:
sub_118AFE50
- 功能: WeWork 发送新消息的核心函数
- 参数:
this: 任务对象指针
message_obj: 消息对象指针
conversation_obj: 会话对象指针
- 返回值: 成功返回1,失败返回0
SendNewMessage2 (0x112A8E60)
- 原函数名:
sub_112A8E60
- 功能: 消息发送管理器,调用 PreSendNewMessage
- 参数:
this: 管理器对象指针
a2: 返回结果对象
message_obj: 消息对象
a4: 未知参数
a5: 回调对象
a6: 未知参数
ConstructMessageProtobuf (0x118AF2F0)
- 原函数名:
sub_118AF2F0
- 功能: 构造消息的 protobuf 数据
- 参数:
this: 对象指针
a2: 参数1
a3: 参数2
a4: 参数3
ProcessForwardMessage (0x118AEAA0)
- 原函数名:
sub_118AEAA0
- 功能: 处理转发消息,涉及 protobuf 消息处理
2. 函数调用关系
1 2 3 4 5 6 7 | SendNewMessage2 (0x112A8E60)
↓
PreSendNewMessage (0x118AFE50)
↓
ConstructMessageProtobuf (0x118AF2F0)
↓
ProcessForwardMessage (0x118AEAA0)
|
3. 关键字符串
"PreSendNewMessage client_id: " (0x1274d02c)
"PreSendNewMessage" (0x1274d140)
"weworklocal::logic::PreSendMessageTask2::PreSendNewMessage" (0x12a5e250)
4. 重要的 protobuf 类型
从反编译代码中发现以下 protobuf 相关类型:
google::protobuf::MessageLite
wwlocal_richmessage::ForwardMessages
- 各种 P2P 文件传输消息类型
函数分析详情
PreSendNewMessage 函数分析
功能流程:
- 验证输入参数(消息对象和会话对象)
- 调用
sub_118AEB00 进行初始化
- 调用
sub_115838C0 处理消息对象
- 调用
sub_118AF0C0 获取会话信息
- 如果会话不存在,记录错误日志并返回
- 调用
sub_118AEAA0 处理消息
- 调用
sub_118AF2F0 构造 protobuf 消息
- 执行消息发送逻辑
关键验证:
1 2 | if ( !*message_obj || !*(_DWORD *)(v4 + 28) || !*(_DWORD *)(v4 + 16) || !*(_DWORD *)(conversation_obj + 16) )
return 0;
|
参数构造方法
基于分析,要主动调用 PreSendNewMessage 函数,需要构造以下参数:
任务对象 (this):
- 需要是一个有效的 PreSendMessageTask2 对象
- 包含必要的成员变量和状态
消息对象 (message_obj):
- 必须非空
- 偏移 +16 和 +28 处必须有有效数据
- 包含消息内容、类型等信息
会话对象 (conversation_obj):
- 必须非空
- 偏移 +16 处必须有有效数据
- 包含会话ID、参与者信息等
建议的调用方法
1. 通过现有接口调用
推荐通过 SendNewMessage2 函数调用,因为它提供了完整的消息发送流程:
1 2 3 4 5 6 7 | SendMessageManager* manager = GetSendMessageManager();
MessageObject* msg = CreateMessageObject();
ConversationObject* conv = GetConversationObject(conversationId);
CallbackObject* callback = CreateCallback();
SendNewMessage2(manager, result, msg, param4, callback, param6);
|
2. 直接调用 PreSendNewMessage
如果要直接调用核心函数:
1 2 3 4 5 6 | PreSendMessageTask2* task = CreatePreSendMessageTask2();
MessageObject* msg = CreateMessageObject();
ConversationObject* conv = GetConversationObject(conversationId);
int result = PreSendNewMessage(task, msg, conv);
|
进一步分析建议
- 分析消息对象结构: 需要进一步分析消息对象的内部结构,特别是偏移 +16 和 +28 处的数据
- 分析会话对象结构: 了解会话对象的完整结构和必需字段
- 分析 protobuf 消息格式: 研究
ConstructMessageProtobuf 函数中使用的 protobuf 消息格式
- Hook 测试: 可以通过 Hook 这些函数来观察实际的参数值和调用流程
总结
通过分析发现了 WeWork 消息发送的核心流程和关键函数。要成功调用这些函数发送消息,需要:
- 构造有效的任务对象、消息对象和会话对象
- 确保所有必需的字段都有正确的值
- 遵循正确的调用顺序和参数传递
建议通过动态分析和 Hook 技术来获取实际运行时的参数值,以便更准确地构造调用参数。
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!