未验证 提交 d89225dd 编写于 作者: J Jack Li 提交者: GitHub

Merge pull request #39 from ljc545w/socket_receivemsg

弃用旧接收消息接口
......@@ -2,39 +2,14 @@
BOOL ReceiveMessageHooked = FALSE;
struct GetRemoteMessageStruct {
DWORD type;
BOOL isSendMessage;
DWORD sender;
DWORD l_sender;
DWORD wxid;
DWORD l_wxid;
DWORD message;
DWORD l_message;
DWORD filepath;
DWORD l_filepath;
DWORD time;
DWORD l_time;
};
struct MessageStruct {
DWORD type;
BOOL isSendMessage;
wchar_t* time;
wchar_t* sender;
wchar_t* wxid;
wchar_t* message;
wchar_t* filepath;
};
BOOL StartReceiveMessage() {
BOOL StartReceiveMessage(int port) {
if (!hProcess || ReceiveMessageHooked)
return 1;
DWORD WeChatRobotBase = GetWeChatRobotBase();
DWORD dwId = 0;
DWORD HookReceiveMessageAddr = WeChatRobotBase + HookReceiveMessageRemoteOffset;
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)HookReceiveMessageAddr, NULL, 0, &dwId);
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)HookReceiveMessageAddr, (LPVOID)port, 0, &dwId);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
}
......@@ -65,113 +40,4 @@ BOOL StopReceiveMessage() {
CloseHandle(hThread);
ReceiveMessageHooked = FALSE;
return 0;
}
BOOL GetHeadMessage(GetRemoteMessageStruct* message) {
if (!hProcess || !ReceiveMessageHooked)
return 1;
DWORD WeChatRobotBase = GetWeChatRobotBase();
DWORD dwId = 0;
DWORD dwHandle = 0;
DWORD GetHeadMessageAddr = WeChatRobotBase + GetHeadMessageRemoteOffset;
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetHeadMessageAddr, NULL, 0, &dwId);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &dwHandle);
}
else {
return 1;
}
if (!dwHandle)
return 0;
ReadProcessMemory(hProcess,(LPCVOID)dwHandle, message,sizeof(GetRemoteMessageStruct),0);
CloseHandle(hThread);
return 0;
}
BOOL PopHeadMessage() {
if (!hProcess || !ReceiveMessageHooked)
return 1;
DWORD WeChatRobotBase = GetWeChatRobotBase();
DWORD dwId = 0;
DWORD PopHeadMessageAddr = WeChatRobotBase + PopHeadMessageRemoteOffset;
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)PopHeadMessageAddr, NULL, 0, &dwId);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
}
else {
return 1;
}
CloseHandle(hThread);
return 0;
}
SAFEARRAY* ReceiveMessage() {
if (!hProcess || !ReceiveMessageHooked)
return NULL;
GetRemoteMessageStruct remotemessage = { 0 };
MessageStruct message = { 0 };
HRESULT hr = S_OK;
GetHeadMessage(&remotemessage);
#ifdef _DEBUG
printf("0x%X,0x%08X,0x%08X,0x%08X\n", remotemessage.type, remotemessage.sender, remotemessage.wxid, remotemessage.message);
#endif
DWORD dwInfoAddr = 0;
if (remotemessage.type) {
message.type = remotemessage.type;
message.isSendMessage = remotemessage.isSendMessage;
message.time = new wchar_t[remotemessage.l_time + 1];
ReadProcessMemory(hProcess, (LPCVOID)remotemessage.time, message.time, (remotemessage.l_time + 1) * sizeof(wchar_t), 0);
message.sender = new wchar_t[remotemessage.l_sender + 1];
ReadProcessMemory(hProcess, (LPCVOID)remotemessage.sender, message.sender, (remotemessage.l_sender + 1) * sizeof(wchar_t), 0);
message.wxid = new wchar_t[remotemessage.l_wxid + 1];
ReadProcessMemory(hProcess, (LPCVOID)remotemessage.wxid, message.wxid, (remotemessage.l_wxid + 1) * sizeof(wchar_t), 0);
message.message = new wchar_t[remotemessage.l_message + 1];
ReadProcessMemory(hProcess, (LPCVOID)remotemessage.message, message.message, (remotemessage.l_message + 1) * sizeof(wchar_t), 0);
message.filepath = new wchar_t[remotemessage.l_filepath + 1];
ZeroMemory(message.filepath, (remotemessage.l_filepath + 1) * 2);
if(remotemessage.l_filepath)
ReadProcessMemory(hProcess, (LPCVOID)remotemessage.filepath, message.filepath, (remotemessage.l_filepath + 1) * sizeof(wchar_t), 0);
}
else {
return NULL;
}
PopHeadMessage();
SAFEARRAY* psaValue;
vector<wstring> MessageInfoKey = {
L"type",
L"isSendMessage",
L"time",
message.isSendMessage ? L"sendto" : L"from",
L"wxid",
L"message",
L"filepath",
};
SAFEARRAYBOUND rgsaBound[2] = { {MessageInfoKey.size(),0},{2,0} };
psaValue = SafeArrayCreate(VT_VARIANT, 2, rgsaBound);
long keyIndex[2] = { 0,0 };
keyIndex[0] = 0; keyIndex[1] = 0;
for (unsigned int i = 0; i < MessageInfoKey.size(); i++) {
keyIndex[0] = i; keyIndex[1] = 0;
hr = SafeArrayPutElement(psaValue, keyIndex, &(_variant_t)MessageInfoKey[i].c_str());
keyIndex[0] = i; keyIndex[1] = 1;
if(i < 2)
hr = SafeArrayPutElement(psaValue, keyIndex, &(_variant_t)((DWORD*)&message)[i]);
else {
hr = SafeArrayPutElement(psaValue, keyIndex, &(_variant_t)((wchar_t**)&message)[i]);
}
}
delete[] message.time;
message.time = NULL;
delete[] message.sender;
message.sender = NULL;
delete[] message.wxid;
message.wxid = NULL;
delete[] message.message;
message.message = NULL;
delete[] message.filepath;
message.filepath = NULL;
return psaValue;
}
\ No newline at end of file
#pragma once
#include<windows.h>
BOOL StartReceiveMessage();
SAFEARRAY* ReceiveMessage();
BOOL StartReceiveMessage(int port);
BOOL StopReceiveMessage();
BOOL HookImageMsg(wchar_t* savepath);
......
......@@ -155,19 +155,8 @@ STDMETHODIMP CWeChatRobot::CGetComWorkPath(BSTR* __result) {
/*
* 参数1:预返回的值,调用时无需提供
*/
STDMETHODIMP CWeChatRobot::CStartReceiveMessage(int* __result) {
*__result = StartReceiveMessage();
return S_OK;
}
/*
* 参数1:预返回的值,调用时无需提供
*/
STDMETHODIMP CWeChatRobot::CReceiveMessage(VARIANT* __result) {
VARIANT vsaValue;
vsaValue.vt = VT_ARRAY | VT_VARIANT;
V_ARRAY(&vsaValue) = ReceiveMessage();
*__result = vsaValue;
STDMETHODIMP CWeChatRobot::CStartReceiveMessage(int port,int* __result) {
*__result = StartReceiveMessage(port);
return S_OK;
}
......
......@@ -65,8 +65,7 @@ public:
STDMETHODIMP CGetSelfInfo(BSTR* __result);
STDMETHODIMP CCheckFriendStatus(BSTR wxid, int* __result);
STDMETHODIMP CGetComWorkPath(BSTR* __result);
STDMETHODIMP CStartReceiveMessage(int* __result);
STDMETHODIMP CReceiveMessage(VARIANT* __result);
STDMETHODIMP CStartReceiveMessage(int port, int* __result);
STDMETHODIMP CStopReceiveMessage(int* __result);
STDMETHODIMP CGetChatRoomMembers(BSTR chatroomid, VARIANT* __result);
STDMETHODIMP CGetDbHandles(VARIANT* __result);
......
......@@ -29,8 +29,7 @@ interface IWeChatRobot : IDispatch
[id(11), helpstring("获取个人信息")] HRESULT CGetSelfInfo([out, retval] BSTR* __result);
[id(13), helpstring("检查是否被好友删除")] HRESULT CCheckFriendStatus([in] BSTR wxid, [out, retval] int* __result);
[id(15), helpstring("获取COM的工作目录")] HRESULT CGetComWorkPath([out, retval] BSTR* __result);
[id(16), helpstring("启动接收消息Hook")] HRESULT CStartReceiveMessage([out, retval] int* __result);
[id(17), helpstring("从Hook缓存中获取一条消息")] HRESULT CReceiveMessage([out, retval] VARIANT* __result);
[id(16), helpstring("启动接收消息Hook")] HRESULT CStartReceiveMessage([in] int port, [out, retval] int* __result);
[id(18), helpstring("停止接收消息Hook")] HRESULT CStopReceiveMessage([out, retval] int* __result);
[id(19), helpstring("发送艾特消息")] HRESULT CSendAtText([in] BSTR chatroomid, [in] VARIANT* wxid, [in] BSTR wxmsg, [in] BOOL AutoNickName, [out, retval] int* __result);
[id(20), helpstring("获取群成员wxid")] HRESULT CGetChatRoomMembers([in] BSTR chatroomid, [out, retval] VARIANT* __result);
......
......@@ -170,11 +170,9 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [retval][out] */ BSTR *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CStartReceiveMessage(
/* [in] */ int port,
/* [retval][out] */ int *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CReceiveMessage(
/* [retval][out] */ VARIANT *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CStopReceiveMessage(
/* [retval][out] */ int *__result) = 0;
......@@ -387,12 +385,9 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CStartReceiveMessage )(
IWeChatRobot * This,
/* [in] */ int port,
/* [retval][out] */ int *__result);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CReceiveMessage )(
IWeChatRobot * This,
/* [retval][out] */ VARIANT *__result);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CStopReceiveMessage )(
IWeChatRobot * This,
/* [retval][out] */ int *__result);
......@@ -572,11 +567,8 @@ EXTERN_C const IID IID_IWeChatRobot;
#define IWeChatRobot_CGetComWorkPath(This,__result) \
( (This)->lpVtbl -> CGetComWorkPath(This,__result) )
#define IWeChatRobot_CStartReceiveMessage(This,__result) \
( (This)->lpVtbl -> CStartReceiveMessage(This,__result) )
#define IWeChatRobot_CReceiveMessage(This,__result) \
( (This)->lpVtbl -> CReceiveMessage(This,__result) )
#define IWeChatRobot_CStartReceiveMessage(This,port,__result) \
( (This)->lpVtbl -> CStartReceiveMessage(This,port,__result) )
#define IWeChatRobot_CStopReceiveMessage(This,__result) \
( (This)->lpVtbl -> CStopReceiveMessage(This,__result) )
......
此差异已折叠。
......@@ -28,8 +28,6 @@ DWORD CheckFriendStatusRemoteOffset = 0x0;
DWORD HookReceiveMessageRemoteOffset = 0x0;
DWORD UnHookReceiveMessageRemoteOffset = 0x0;
DWORD GetHeadMessageRemoteOffset = 0x0;
DWORD PopHeadMessageRemoteOffset = 0x0;
DWORD GetChatRoomMembersRemoteOffset = 0x0;
......@@ -154,10 +152,6 @@ BOOL GetProcOffset(wchar_t* workPath) {
HookReceiveMessageRemoteOffset = HookReceiveMessageRemoteAddr - WeChatBase;
DWORD UnHookReceiveMessageRemoteAddr = (DWORD)GetProcAddress(hd, UnHookReceiveMessageRemote);
UnHookReceiveMessageRemoteOffset = UnHookReceiveMessageRemoteAddr - WeChatBase;
DWORD GetHeadMessageRemoteAddr = (DWORD)GetProcAddress(hd, GetHeadMessageRemote);
GetHeadMessageRemoteOffset = GetHeadMessageRemoteAddr - WeChatBase;
DWORD PopHeadMessageRemoteAddr = (DWORD)GetProcAddress(hd, PopHeadMessageRemote);
PopHeadMessageRemoteOffset = PopHeadMessageRemoteAddr - WeChatBase;
DWORD GetChatRoomMembersRemoteAddr = (DWORD)GetProcAddress(hd, GetChatRoomMembersRemote);
GetChatRoomMembersRemoteOffset = GetChatRoomMembersRemoteAddr - WeChatBase;
......
......@@ -48,8 +48,6 @@ extern DWORD CheckFriendStatusRemoteOffset;
extern DWORD HookReceiveMessageRemoteOffset;
extern DWORD UnHookReceiveMessageRemoteOffset;
extern DWORD GetHeadMessageRemoteOffset;
extern DWORD PopHeadMessageRemoteOffset;
extern DWORD GetChatRoomMembersRemoteOffset;
......@@ -98,8 +96,6 @@ extern DWORD ChangeWeChatVerRemoteOffset;
#define HookReceiveMessageRemote "HookReceiveMessage"
#define UnHookReceiveMessageRemote "UnHookReceiveMessage"
#define GetHeadMessageRemote "GetHeadMessage"
#define PopHeadMessageRemote "PopHeadMessage"
#define GetChatRoomMembersRemote "GetChatRoomMembersRemote"
......
#include "pch.h"
#include <vector>
#include <iostream>
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define CLTIP "127.0.0.1"
// 接收消息的HOOK地址偏移
#define ReceiveMessageHookOffset 0x547C0F4C - 0x54270000
......@@ -12,8 +19,17 @@
// 发送消息HOOK的CALL偏移
#define SendMessageNextCallOffset 0x101E8170 - 0x0FDE0000
// 保存多条信息的动态数组
vector<ReceiveMsgStruct> messageVector;
static int SRVPORT = 0;
struct ScoketMsgStruct {
int messagetype;
BOOL isSendMessage;
wchar_t sender[80];
wchar_t wxid[80];
wchar_t message[0x1000B];
wchar_t filepath[MAX_PATH];
wchar_t time[20];
};
// 是否开启接收消息HOOK标志
BOOL ReceiveMessageHooked = false;
......@@ -33,6 +49,68 @@ DWORD SendMessageNextCall = GetWeChatWinBase() + SendMessageNextCallOffset;
// 发送HOOK的跳转地址
DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
// 通过socket将消息发送给服务端
BOOL SendSocketMessage(ReceiveMsgStruct* ms)
{
SOCKET clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientsocket < 0)
{
#ifdef _DEBUG
cout << "create socket error:" << strerror(errno) << " errno:" << errno << endl;
#endif
return false;
}
BOOL status = false;
sockaddr_in clientAddr;
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons((u_short)SRVPORT);
InetPtonA(AF_INET,CLTIP,&clientAddr.sin_addr.s_addr);
if (connect(clientsocket, reinterpret_cast<sockaddr*>(&clientAddr), sizeof(sockaddr)) < 0)
{
#ifdef _DEBUG
cout << "connect error:" << strerror(errno) << " errno:" << errno << endl;
#endif
delete ms;
return false;
}
char recvbuf[1024] = { 0 };
ScoketMsgStruct* sms = new ScoketMsgStruct;
ZeroMemory(sms, sizeof(ScoketMsgStruct));
sms->messagetype = ms->messagetype;
sms->isSendMessage = ms->isSendMessage;
memcpy(sms->wxid, ms->wxid, ms->l_wxid * 2);
memcpy(sms->sender, ms->sender, ms->l_sender * 2);
memcpy(sms->message, ms->message, ms->l_message * 2);
memcpy(sms->filepath, ms->filepath, ms->l_filepath * 2);
memcpy(sms->time, ms->time, ms->l_time * 2);
int ret = send(clientsocket, (char*)sms, sizeof(ScoketMsgStruct), 0);
if (ret == -1 || ret == 0)
{
#ifdef _DEBUG
printf("send fail %s\n", strerror(errno));
#endif
delete ms;
delete sms;
closesocket(clientsocket);
return false;
}
memset(recvbuf, 0, sizeof(recvbuf));
ret = recv(clientsocket, recvbuf, sizeof(recvbuf), 0);
delete ms;
delete sms;
closesocket(clientsocket);
if (ret == -1 || ret == 0)
{
#ifdef _DEBUG
cout << "the server close" << endl;
#endif
return false;
}
return true;
}
// 创建广播消息数组
#ifndef USE_SOCKET
static SAFEARRAY* CreateMessageArray(ReceiveMsgStruct* ms) {
......@@ -78,84 +156,58 @@ VOID ReceiveMessage(DWORD messageAddr) {
// 此处用于区别是发送的还是接收的消息
BOOL isSendMessage = *(BOOL*)(messageAddr + 0x3C);
ReceiveMsgStruct message = { 0 };
message.isSendMessage = isSendMessage;
message.time = GetTimeW();
message.l_time = wcslen(message.time);
message.messagetype = *(DWORD*)(messageAddr + 0x38);
ReceiveMsgStruct* message = new ReceiveMsgStruct;
ZeroMemory(message, sizeof(ReceiveMsgStruct));
message->isSendMessage = isSendMessage;
message->time = GetTimeW();
message->l_time = wcslen(message->time);
message->messagetype = *(DWORD*)(messageAddr + 0x38);
DWORD length = *(DWORD*)(messageAddr + 0x48 + 0x4);
message.sender = new wchar_t[length + 1];
ZeroMemory(message.sender, (length + 1) * 2);
memcpy(message.sender,(wchar_t*)(*(DWORD*)(messageAddr + 0x48)),length * 2);
message.l_sender = length;
message->sender = new wchar_t[length + 1];
ZeroMemory(message->sender, (length + 1) * 2);
memcpy(message->sender,(wchar_t*)(*(DWORD*)(messageAddr + 0x48)),length * 2);
message->l_sender = length;
length = *(DWORD*)(messageAddr + 0x170 + 0x4);
if (length == 0) {
message.wxid = new wchar_t[message.l_sender + 1];
ZeroMemory(message.wxid, (message.l_sender + 1) * 2);
memcpy(message.wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x48)), message.l_sender * 2);
message.l_wxid = message.l_sender;
message->wxid = new wchar_t[message->l_sender + 1];
ZeroMemory(message->wxid, (message->l_sender + 1) * 2);
memcpy(message->wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x48)), message->l_sender * 2);
message->l_wxid = message->l_sender;
}
else {
message.wxid = new wchar_t[length + 1];
ZeroMemory(message.wxid, (length + 1) * 2);
memcpy(message.wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x170)), length * 2);
message.l_wxid = length;
message->wxid = new wchar_t[length + 1];
ZeroMemory(message->wxid, (length + 1) * 2);
memcpy(message->wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x170)), length * 2);
message->l_wxid = length;
}
length = *(DWORD*)(messageAddr + 0x70 + 0x4);
message.message = new wchar_t[length + 1];
ZeroMemory(message.message, (length + 1) * 2);
memcpy(message.message, (wchar_t*)(*(DWORD*)(messageAddr + 0x70)), length * 2);
message.l_message = length;
message->message = new wchar_t[length + 1];
ZeroMemory(message->message, (length + 1) * 2);
memcpy(message->message, (wchar_t*)(*(DWORD*)(messageAddr + 0x70)), length * 2);
message->l_message = length;
length = *(DWORD*)(messageAddr + 0x1AC + 0x4);
message.filepath = new wchar_t[length + 1];
ZeroMemory(message.filepath, (length + 1) * 2);
memcpy(message.filepath, (wchar_t*)(*(DWORD*)(messageAddr + 0x1AC)), length * 2);
message.l_filepath = length;
message->filepath = new wchar_t[length + 1];
ZeroMemory(message->filepath, (length + 1) * 2);
memcpy(message->filepath, (wchar_t*)(*(DWORD*)(messageAddr + 0x1AC)), length * 2);
message->l_filepath = length;
#ifdef USE_COM
// 通过连接点,将消息广播给客户端
SAFEARRAY* psaValue = CreateMessageArray(&message);
SAFEARRAY* psaValue = CreateMessageArray(message);
VARIANT vsaValue;
vsaValue.vt = VT_ARRAY | VT_VARIANT;
V_ARRAY(&vsaValue) = psaValue;
PostComMessage(&vsaValue);
#endif
messageVector.push_back(message);
}
/*
* 供外部调用的获取消息接口,优先返回较早消息
* return:DWORD,messageVector第一个成员地址
*/
DWORD GetHeadMessage() {
if (messageVector.size() == 0)
return 0;
return (DWORD)&messageVector[0].messagetype;
HANDLE hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendSocketMessage,message,NULL,0);
if (hThread) {
CloseHandle(hThread);
}
}
/*
* 供外部调用的删除消息接口,用于删除messageVector第一个成员,每读一条需要执行一次
* return:void
*/
VOID PopHeadMessage() {
if (messageVector.size() == 0)
return;
delete[] messageVector[0].message;
messageVector[0].message = NULL;
delete[] messageVector[0].sender;
messageVector[0].sender = NULL;
delete[] messageVector[0].wxid;
messageVector[0].wxid = NULL;
delete[] messageVector[0].filepath;
messageVector[0].filepath = NULL;
delete[] messageVector[0].time;
messageVector[0].time = NULL;
vector<ReceiveMsgStruct>::iterator k = messageVector.begin();
messageVector.erase(k);
}
/*
* HOOK的具体实现,接收到消息后调用处理函数
......@@ -196,7 +248,8 @@ _declspec(naked) void dealSendMessage() {
* 开始接收消息HOOK
* return:void
*/
VOID HookReceiveMessage() {
VOID HookReceiveMessage(int port) {
SRVPORT = port;
if (ReceiveMessageHooked)
return;
HookAnyAddress(ReceiveMessageHookAddress,(LPVOID)dealReceiveMessage,OldReceiveMessageAsmCode);
......@@ -209,6 +262,7 @@ VOID HookReceiveMessage() {
* return:void
*/
VOID UnHookReceiveMessage() {
SRVPORT = 0;
if (!ReceiveMessageHooked)
return;
UnHookAnyAddress(ReceiveMessageHookAddress,OldReceiveMessageAsmCode);
......
#pragma once
#include<windows.h>
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) DWORD GetHeadMessage();
extern "C" __declspec(dllexport) VOID PopHeadMessage();
extern "C" __declspec(dllexport) VOID HookReceiveMessage();
extern "C" __declspec(dllexport) VOID HookReceiveMessage(int port);
extern "C" __declspec(dllexport) VOID UnHookReceiveMessage();
extern "C" __declspec(dllexport) void UnHookVoiceMsg();
extern "C" __declspec(dllexport) BOOL HookVoiceMsgRemote(LPVOID lpParameter);
extern "C" __declspec(dllexport) void UnHookImageMsg();
extern "C" __declspec(dllexport) BOOL HookImageMsgRemote(LPVOID lpParameter);
#else
VOID HookReceiveMessage();
VOID HookReceiveMessage(int port);
VOID UnHookReceiveMessage();
void UnHookImageMsg();
void UnHookVoiceMsg();
......
......@@ -61,6 +61,18 @@ struct ReceiveMsgStruct {
DWORD l_filepath;
wchar_t* time;
DWORD l_time;
~ReceiveMsgStruct() {
if (this->sender)
delete[] this->sender;
if (this->wxid)
delete[] this->wxid;
if (this->message)
delete[] this->message;
if (this->filepath)
delete[] this->filepath;
if (this->time)
delete[] this->time;
}
};
// vector在内存中的表现形式
......
......@@ -6,16 +6,6 @@ Created on Sat Apr 16 14:06:24 2022
"""
import time
from wxRobot import WeChatRobot
# 一个示例回调,将收到的文本消息转发给filehelper
def ReceiveMessageCallBack(robot,message):
chatwith = message.get('sendto') or message.get('from')
if message['type'] == 1 and not message['isSendMessage'] and chatwith != 'filehelper':
robot.robot.CSendText('filehelper',message['message'])
chatwith = message.get('sendto') or message.get('from')
wxSender = robot.GetWxUserInfo(chatwith)
sender = wxSender['wxNickName'] if wxSender['wxNickName'] != 'null' else chatwith
print("来自 {}\n".format(sender),message)
def test_SendText():
import os
......@@ -59,18 +49,6 @@ def test_FriendStatus():
f.close()
wx.StopService()
def test_ReceiveMessage():
wx = WeChatRobot()
wx.StartService()
wx.robot.CStartReceiveMessage()
wx.StartReceiveMessage(CallBackFunc = ReceiveMessageCallBack)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
wx.StopService()
def test_ExecuteSQL():
wx = WeChatRobot()
wx.StartService()
......@@ -104,6 +82,6 @@ if __name__ == '__main__':
wx = WeChatRobot()
print([i for i in dir(wx.robot) if '_' not in i and i[0] == 'C'])
print(wx.GetWeChatVer())
print(wx.StartService())
wx.StartReceiveMsgByEvent()
wx.StartService()
wx.StartReceiveMessage()
wx.StopService()
\ No newline at end of file
......@@ -8,12 +8,73 @@ Created on Thu Feb 24 16:19:48 2022
# Before use,execute `CWeChatRebot.exe /regserver` in cmd by admin user
# need `pip install comtypes`
import comtypes.client
from ctypes import wintypes
import ast
import os
import socketserver
import threading
import time
from comtypes.client import GetEvents
from comtypes.client import PumpEvents
class WeChatEventSink():
"""
接收消息的默认回调,可以自定义,并将实例化对象作为StartReceiveMsgByEvent参数
自定义的类需要包含以下所有成员
"""
def OnGetMessageEvent(self,msg,*args,**kwargs):
print(msg)
class ReceviveMsgBaseServer(socketserver.BaseRequestHandler):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
class ReceiveMsgStruct(comtypes.Structure):
_fields_ = [("type", wintypes.DWORD),
("isSendMsg", wintypes.DWORD),
("sender",comtypes.c_wchar * 80),
("wxid",comtypes.c_wchar * 80),
("message",comtypes.c_wchar * 0x1000B),
("filepath",comtypes.c_wchar * 260),
("time",comtypes.c_wchar * 20),
]
def handle(self):
conn = self.request
comtypes.CoInitialize()
while True:
try:
ptrdata = conn.recv(comtypes.sizeof(self.ReceiveMsgStruct))
if ptrdata == 'bye'.encode():
break
elif ptrdata:
pReceiveMsgStruct = comtypes.cast(ptrdata,comtypes.POINTER(self.ReceiveMsgStruct))
self.msgcallback(pReceiveMsgStruct.contents)
response = "200 OK"
conn.sendall(response.encode())
except OSError:
break
except:
conn.sendall("200 OK".encode())
conn.close()
comtypes.CoUninitialize()
def msgcallback(self,data):
# 主线程中已经注入,此处禁止调用StartService和StopService
robot = WeChatRobot()
msg = {'time':data.time,'type':data.type,'isSendMsg':data.isSendMsg,'wxid':data.wxid,
'sendto' if data.isSendMsg else 'from':data.sender,'message':data.message}
if '@chatroom' in data.sender:
chatroominfo = robot.GetWxUserInfo(data.sender)
userinfo = robot.GetWxUserInfo(data.wxid)
msg['chatroomname'] = chatroominfo['wxNickName']
else:
userinfo = robot.GetWxUserInfo(data.sender)
msg['nickname'] = userinfo['wxNickName']
msg['alias'] = userinfo['wxNumber']
print(msg)
# TODO: ...
class ChatSession():
def __init__(self,robot,wxid):
......@@ -45,16 +106,6 @@ class ChatSession():
def SendAppMsg(self,appid):
return self.robot.CSendAppMsg(self.chatwith,appid)
class WeChatEventSink():
"""
接收消息的默认回调,可以自定义,并将实例化对象作为StartReceiveMsgByEvent参数
自定义的类需要包含以下所有成员
"""
def OnGetMessageEvent(self,msg,*args,**kwargs):
# 为了兼容原有接口,需要在接收到广播后调用此接口,否则会导致严重的内存泄漏
WeChatRobot().robot.CReceiveMessage()
print(msg)
class WeChatRobot():
......@@ -63,7 +114,6 @@ class WeChatRobot():
self.event = comtypes.client.CreateObject("WeChatRobot.RobotEvent")
self.AddressBook = []
self.myinfo = {}
self.ReceiveMessageStarted = False
def StartService(self) -> int:
"""
......@@ -462,44 +512,22 @@ class WeChatRobot():
"""
return self.robot.CCheckFriendStatus(wxid)
def ReceiveMessage(self,CallBackFunc = None) -> None:
"""
消息监听函数
Parameters
----------
CallBackFunc : 'function' or None, optional
消息回调函数. 默认为空.
Returns
-------
None
.
"""
comtypes.CoInitialize()
# 线程中必须新建一个对象,但无需重复注入
ThreadRobot = WeChatRobot()
while self.ReceiveMessageStarted:
try:
message = dict(ThreadRobot.robot.CReceiveMessage())
if CallBackFunc and message:
CallBackFunc(ThreadRobot,message)
except IndexError:
message = None
time.sleep(0.5)
comtypes.CoUninitialize()
# 接收消息的函数,可以添加一个回调
def StartReceiveMessage(self,CallBackFunc = None) -> int:
# 接收消息的函数
def StartReceiveMessage(self,port:int = 10808,RequestHandler: 'ReceviveMsgBaseServer' = ReceviveMsgBaseServer,mainThread = True) -> int:
"""
启动接收消息Hook,并创建监听线程
Parameters
----------
CallBackFunc : 'function' or None, optional
指定的回调函数. 默认为空.
port : int
socket的监听端口号.
RequestHandler : ReceviveMsgBaseServer
用于处理消息的类,需要继承自socketserver.BaseRequestHandler或ReceviveMsgBaseServer
mainThread : bool
是否在主线程中启动server
Returns
-------
......@@ -507,13 +535,27 @@ class WeChatRobot():
启动成功返回0,失败返回非0值.
"""
self.ReceiveMessageStarted = True
status = self.robot.CStartReceiveMessage()
if status == 0:
self.ReceiveMessageThread = threading.Thread(target = self.ReceiveMessage,args= (CallBackFunc,))
self.ReceiveMessageThread.daemon = True
self.ReceiveMessageThread.start()
ip_port=("127.0.0.1",port)
status = self.robot.CStartReceiveMessage(port)
if status != 0:
print('warning: Hook not success')
return status
if mainThread:
try:
s = socketserver.ThreadingTCPServer(ip_port,RequestHandler)
s.serve_forever()
except:
pass
else:
try:
s = socketserver.ThreadingTCPServer(ip_port,RequestHandler)
self.socket_server = threading.Thread(target = s.serve_forever)
self.socket_server.setDaemon(True)
self.socket_server.start()
except:
pass
return status
def StartReceiveMsgByEvent(self,EventSink:object or None = None) -> None:
"""
......@@ -624,9 +666,18 @@ class WeChatRobot():
成功返回0,失败返回非0值.
"""
self.ReceiveMessageStarted = False
import inspect
try:
self.ReceiveMessageThread.join()
"""raises the exception, performs cleanup if needed"""
tid = comtypes.c_long(self.socket_server.ident)
if not inspect.isclass(SystemExit):
exctype = type(SystemExit)
res = comtypes.pythonapi.PyThreadState_SetAsyncExc(tid, comtypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
comtypes.ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
except:
pass
status = self.robot.CStopReceiveMessage()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册