Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
888H355
ComWeChatRobot
提交
07181059
C
ComWeChatRobot
项目概览
888H355
/
ComWeChatRobot
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ComWeChatRobot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
07181059
编写于
6月 21, 2022
作者:
L
ljc545w
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
弃用旧接收消息接口
上级
f40801c7
变更
17
展开全部
显示空白变更内容
内联
并排
Showing
17 changed file
with
711 addition
and
810 deletion
+711
-810
CWeChatRobot/ReceiveMessage.cpp
CWeChatRobot/ReceiveMessage.cpp
+2
-136
CWeChatRobot/ReceiveMessage.h
CWeChatRobot/ReceiveMessage.h
+1
-2
CWeChatRobot/WeChatRobot.cpp
CWeChatRobot/WeChatRobot.cpp
+2
-13
CWeChatRobot/WeChatRobot.h
CWeChatRobot/WeChatRobot.h
+1
-2
CWeChatRobot/WeChatRobotCOM.idl
CWeChatRobot/WeChatRobotCOM.idl
+1
-2
CWeChatRobot/WeChatRobotCOM_i.h
CWeChatRobot/WeChatRobotCOM_i.h
+4
-12
CWeChatRobot/WeChatRobotCOM_p.c
CWeChatRobot/WeChatRobotCOM_p.c
+466
-492
CWeChatRobot/pch.cpp
CWeChatRobot/pch.cpp
+0
-6
CWeChatRobot/robotdata.h
CWeChatRobot/robotdata.h
+0
-4
DWeChatRobot/ReceiveMessage.cpp
DWeChatRobot/ReceiveMessage.cpp
+115
-61
DWeChatRobot/ReceiveMessage.h
DWeChatRobot/ReceiveMessage.h
+2
-4
DWeChatRobot/wxdata.h
DWeChatRobot/wxdata.h
+12
-0
Python/test.py
Python/test.py
+2
-24
Python/wxRobot.py
Python/wxRobot.py
+103
-52
Release/CWeChatRobot.exe
Release/CWeChatRobot.exe
+0
-0
Release/DWeChatRobot.dll
Release/DWeChatRobot.dll
+0
-0
Release/socket/SWeChatRobot.dll
Release/socket/SWeChatRobot.dll
+0
-0
未找到文件。
CWeChatRobot/ReceiveMessage.cpp
浏览文件 @
07181059
...
...
@@ -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
);
}
...
...
@@ -66,112 +41,3 @@ BOOL StopReceiveMessage() {
ReceiveMessageHooked
=
FALSE
;
return
0
;
}
\ No newline at end of file
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
CWeChatRobot/ReceiveMessage.h
浏览文件 @
07181059
#pragma once
#include<windows.h>
BOOL
StartReceiveMessage
();
SAFEARRAY
*
ReceiveMessage
();
BOOL
StartReceiveMessage
(
int
port
);
BOOL
StopReceiveMessage
();
BOOL
HookImageMsg
(
wchar_t
*
savepath
);
...
...
CWeChatRobot/WeChatRobot.cpp
浏览文件 @
07181059
...
...
@@ -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
;
}
...
...
CWeChatRobot/WeChatRobot.h
浏览文件 @
07181059
...
...
@@ -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
);
...
...
CWeChatRobot/WeChatRobotCOM.idl
浏览文件 @
07181059
...
...
@@ -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
)
;
...
...
CWeChatRobot/WeChatRobotCOM_i.h
浏览文件 @
07181059
...
...
@@ -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
)
)
...
...
CWeChatRobot/WeChatRobotCOM_p.c
浏览文件 @
07181059
此差异已折叠。
点击以展开。
CWeChatRobot/pch.cpp
浏览文件 @
07181059
...
...
@@ -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
;
...
...
CWeChatRobot/robotdata.h
浏览文件 @
07181059
...
...
@@ -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"
...
...
DWeChatRobot/ReceiveMessage.cpp
浏览文件 @
07181059
#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
);
...
...
DWeChatRobot/ReceiveMessage.h
浏览文件 @
07181059
#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
();
...
...
DWeChatRobot/wxdata.h
浏览文件 @
07181059
...
...
@@ -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在内存中的表现形式
...
...
Python/test.py
浏览文件 @
07181059
...
...
@@ -7,16 +7,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
path
=
os
.
path
.
split
(
os
.
path
.
realpath
(
__file__
))[
0
]
...
...
@@ -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
.
StartReceiveM
sgByEvent
()
wx
.
StartService
(
)
wx
.
StartReceiveM
essage
()
wx
.
StopService
()
\ No newline at end of file
Python/wxRobot.py
浏览文件 @
07181059
...
...
@@ -8,13 +8,74 @@ 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
):
self
.
robot
=
robot
...
...
@@ -46,16 +107,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
():
def
__init__
(
self
):
...
...
@@ -63,7 +114,6 @@ class WeChatRobot():
self
.
event
=
comtypes
.
client
.
CreateObject
(
"WeChatRobot.RobotEvent"
)
self
.
AddressBook
=
[]
self
.
myinfo
=
{}
self
.
ReceiveMessageStarted
=
False
def
StartService
(
self
)
->
int
:
"""
...
...
@@ -463,43 +513,21 @@ class WeChatRobot():
"""
return
self
.
robot
.
CCheckFriendStatus
(
wxid
)
def
ReceiveMessage
(
self
,
CallBackFunc
=
None
)
->
None
:
# 接收消息的函数
def
StartReceiveMessage
(
self
,
port
:
int
=
10808
,
RequestHandler
:
'ReceviveMsgBaseServer'
=
ReceviveMsgBaseServer
,
mainThread
=
True
)
->
int
:
"""
消息监听函数
启动接收消息Hook,并创建监听线程
Parameters
----------
CallBackFunc : 'function' or None, optional
消息回调函数. 默认为空
.
port : int
socket的监听端口号
.
Returns
-------
None
.
RequestHandler : ReceviveMsgBaseServer
用于处理消息的类,需要继承自socketserver.BaseRequestHandler或ReceviveMsgBaseServer
"""
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
:
"""
启动接收消息Hook,并创建监听线程
Parameters
----------
CallBackFunc : 'function' or None, optional
指定的回调函数. 默认为空.
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
()
...
...
Release/CWeChatRobot.exe
浏览文件 @
07181059
无法预览此类型文件
Release/DWeChatRobot.dll
浏览文件 @
07181059
无法预览此类型文件
Release/socket/SWeChatRobot.dll
浏览文件 @
07181059
无法预览此类型文件
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录