提交 04f359eb 编写于 作者: L ljc545w

新增转发消息功能,优化实时消息接口

上级 898743f0
#include "pch.h"
struct ForwardMessageStruct
{
DWORD wxid;
DWORD localId;
};
BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId)
{
WeChatProcess hp(pid);
if (!hp.m_init)
return 1;
DWORD ForwardMessageRemoteAddr = hp.GetProcAddr(ForwardMessageRemote);
if (ForwardMessageRemoteAddr == 0)
{
return 1;
}
ForwardMessageStruct params = {0};
WeChatData<wchar_t *> r_wxid(hp.GetHandle(), wxid, TEXTLENGTH(wxid));
params.wxid = (DWORD)r_wxid.GetAddr();
params.localId = localId;
WeChatData<ForwardMessageStruct *> r_params(hp.GetHandle(), &params, sizeof(params));
if (!params.wxid || !r_params.GetAddr())
{
return 1;
}
DWORD dwRet = CallRemoteFunction(hp.GetHandle(), ForwardMessageRemoteAddr, r_params.GetAddr());
return dwRet == 0;
}
#pragma once
#include <windows.h>
BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId);
此差异已折叠。
......@@ -85,6 +85,7 @@ public:
STDMETHODIMP CAddChatRoomMember(DWORD pid, BSTR chatroomid, VARIANT *wxids, int *__result);
STDMETHODIMP COpenBrowser(DWORD pid, BSTR url, int *__result);
STDMETHODIMP CGetHistoryPublicMsg(DWORD pid, BSTR PublicId, BSTR Offset, VARIANT *__result);
STDMETHODIMP CForwardMessage(DWORD pid, BSTR wxid, int localId, int *__result);
};
OBJECT_ENTRY_AUTO(__uuidof(WeChatRobot), CWeChatRobot)
......@@ -59,7 +59,8 @@ interface IWeChatRobot : IDispatch
[id(44), helpstring("删除群成员")] HRESULT CDelChatRoomMember([in] DWORD pid, [in] BSTR chatroomid, [in] VARIANT* wxids, [out, retval] int* __result);
[id(45), helpstring("添加群成员")] HRESULT CAddChatRoomMember([in] DWORD pid, [in] BSTR chatroomid, [in] VARIANT* wxids, [out, retval] int* __result);
[id(46), helpstring("打开微信内置浏览器")] HRESULT COpenBrowser([in] DWORD pid, [in] BSTR url, [ out, retval ] int *__result);
[id(47), helpstring("获取公众号历史消息")] HRESULT CGetHistoryPublicMsg([in] DWORD pid, [in] BSTR PublicId, [in] BSTR Offset, [ out, retval ] VARIANT * __result);
[id(47), helpstring("获取公众号历史消息")] HRESULT CGetHistoryPublicMsg([in] DWORD pid, [in] BSTR PublicId, [in] BSTR Offset, [out, retval] VARIANT * __result);
[id(48), helpstring("转发消息") ] HRESULT CForwardMessage([in] DWORD pid, [in] BSTR wxid, [in] int localId, [out, retval] int * __result);
};
[
object,
......
......@@ -229,6 +229,7 @@
<ClInclude Include="DelChatRoomMember.h" />
<ClInclude Include="DeleteUser.h" />
<ClInclude Include="EditRemark.h" />
<ClInclude Include="ForwardMessage.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="FriendList.h" />
<ClInclude Include="GetChatRoomMemberNickname.h" />
......@@ -276,6 +277,7 @@
<ClCompile Include="DelChatRoomMember.cpp" />
<ClCompile Include="DeleteUser.cpp" />
<ClCompile Include="EditRemark.cpp" />
<ClCompile Include="ForwardMessage.cpp" />
<ClCompile Include="FriendList.cpp" />
<ClCompile Include="GetChatRoomMemberNickname.cpp" />
<ClCompile Include="GetChatRoomMembers.cpp" />
......
......@@ -125,6 +125,9 @@
<Filter Include="浏览器相关\获取公众号历史消息">
<UniqueIdentifier>{e54ac438-bc4e-46cf-9450-502e35daf385}</UniqueIdentifier>
</Filter>
<Filter Include="发送消息\转发消息">
<UniqueIdentifier>{f44839a7-3cf0-415f-886e-22a8635c3dbd}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
......@@ -256,6 +259,9 @@
<ClInclude Include="GetHistoryPublicMsg.h">
<Filter>浏览器相关\获取公众号历史消息</Filter>
</ClInclude>
<ClInclude Include="ForwardMessage.h">
<Filter>发送消息\转发消息</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WeChatRobotCOM.cpp">
......@@ -387,6 +393,9 @@
<ClCompile Include="GetHistoryPublicMsg.cpp">
<Filter>浏览器相关\获取公众号历史消息</Filter>
</ClCompile>
<ClCompile Include="ForwardMessage.cpp">
<Filter>发送消息\转发消息</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WeChatRobotCOM.rc">
......
......@@ -345,6 +345,12 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [in] */ BSTR Offset,
/* [retval][out] */ VARIANT *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CForwardMessage(
/* [in] */ DWORD pid,
/* [in] */ BSTR wxid,
/* [in] */ int localId,
/* [retval][out] */ int *__result) = 0;
};
......@@ -678,6 +684,13 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [in] */ BSTR Offset,
/* [retval][out] */ VARIANT *__result);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CForwardMessage )(
IWeChatRobot * This,
/* [in] */ DWORD pid,
/* [in] */ BSTR wxid,
/* [in] */ int localId,
/* [retval][out] */ int *__result);
END_INTERFACE
} IWeChatRobotVtbl;
......@@ -846,6 +859,9 @@ EXTERN_C const IID IID_IWeChatRobot;
#define IWeChatRobot_CGetHistoryPublicMsg(This,pid,PublicId,Offset,__result) \
( (This)->lpVtbl -> CGetHistoryPublicMsg(This,pid,PublicId,Offset,__result) )
#define IWeChatRobot_CForwardMessage(This,pid,wxid,localId,__result) \
( (This)->lpVtbl -> CForwardMessage(This,pid,wxid,localId,__result) )
#endif /* COBJMACROS */
......
......@@ -49,7 +49,7 @@
#include "WeChatRobotCOM_i.h"
#define TYPE_FORMAT_STRING_SIZE 1239
#define PROC_FORMAT_STRING_SIZE 2287
#define PROC_FORMAT_STRING_SIZE 2341
#define EXPR_FORMAT_STRING_SIZE 1
#define TRANSMIT_AS_TABLE_SIZE 0
#define WIRE_MARSHAL_TABLE_SIZE 2
......@@ -2106,17 +2106,17 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
/* 2176 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CPostMessage */
/* Procedure CForwardMessage */
/* 2178 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2180 */ NdrFcLong( 0x0 ), /* 0 */
/* 2184 */ NdrFcShort( 0x7 ), /* 7 */
/* 2186 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */
/* 2188 */ NdrFcShort( 0x20 ), /* 32 */
/* 2184 */ NdrFcShort( 0x33 ), /* 51 */
/* 2186 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2188 */ NdrFcShort( 0x10 ), /* 16 */
/* 2190 */ NdrFcShort( 0x24 ), /* 36 */
/* 2192 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */
0x6, /* 6 */
0x5, /* 5 */
/* 2194 */ 0x8, /* 8 */
0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */
/* 2196 */ NdrFcShort( 0x0 ), /* 0 */
......@@ -2130,83 +2130,134 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
/* 2206 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgtype */
/* Parameter wxid */
/* 2208 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2208 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
/* 2210 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2212 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* 2212 */ NdrFcShort( 0x2a ), /* Type Offset=42 */
/* Parameter msgid */
/* Parameter localId */
/* 2214 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2216 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2218 */ 0xb, /* FC_HYPER */
/* 2218 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter __result */
/* 2220 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2222 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2224 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2226 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2228 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2230 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CPostMessage */
/* 2232 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2234 */ NdrFcLong( 0x0 ), /* 0 */
/* 2238 */ NdrFcShort( 0x7 ), /* 7 */
/* 2240 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */
/* 2242 */ NdrFcShort( 0x20 ), /* 32 */
/* 2244 */ NdrFcShort( 0x24 ), /* 36 */
/* 2246 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */
0x6, /* 6 */
/* 2248 */ 0x8, /* 8 */
0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */
/* 2250 */ NdrFcShort( 0x0 ), /* 0 */
/* 2252 */ NdrFcShort( 0x1 ), /* 1 */
/* 2254 */ NdrFcShort( 0x0 ), /* 0 */
/* Parameter pid */
/* 2256 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2258 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
/* 2260 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgtype */
/* 2262 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2264 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2266 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgid */
/* 2268 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2270 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2272 */ 0xb, /* FC_HYPER */
0x0, /* 0 */
/* Parameter msg */
/* 2220 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
/* 2222 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2224 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */
/* 2274 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
/* 2276 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2278 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */
/* Parameter __result */
/* 2226 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2228 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2230 */ 0x8, /* FC_LONG */
/* 2280 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2282 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2284 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2232 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2234 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */
/* 2236 */ 0x8, /* FC_LONG */
/* 2286 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2288 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */
/* 2290 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CRegisterWxPidWithCookie */
/* 2238 */ 0x33, /* FC_AUTO_HANDLE */
/* 2292 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2240 */ NdrFcLong( 0x0 ), /* 0 */
/* 2244 */ NdrFcShort( 0x8 ), /* 8 */
/* 2246 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2248 */ NdrFcShort( 0x10 ), /* 16 */
/* 2250 */ NdrFcShort( 0x24 ), /* 36 */
/* 2252 */ 0x44, /* Oi2 Flags: has return, has ext, */
/* 2294 */ NdrFcLong( 0x0 ), /* 0 */
/* 2298 */ NdrFcShort( 0x8 ), /* 8 */
/* 2300 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2302 */ NdrFcShort( 0x10 ), /* 16 */
/* 2304 */ NdrFcShort( 0x24 ), /* 36 */
/* 2306 */ 0x44, /* Oi2 Flags: has return, has ext, */
0x4, /* 4 */
/* 2254 */ 0x8, /* 8 */
/* 2308 */ 0x8, /* 8 */
0x41, /* Ext Flags: new corr desc, has range on conformance */
/* 2256 */ NdrFcShort( 0x0 ), /* 0 */
/* 2258 */ NdrFcShort( 0x0 ), /* 0 */
/* 2260 */ NdrFcShort( 0x0 ), /* 0 */
/* 2310 */ NdrFcShort( 0x0 ), /* 0 */
/* 2312 */ NdrFcShort( 0x0 ), /* 0 */
/* 2314 */ NdrFcShort( 0x0 ), /* 0 */
/* Parameter pid */
/* 2262 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2264 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
/* 2266 */ 0x8, /* FC_LONG */
/* 2316 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2318 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
/* 2320 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter cookie */
/* 2268 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2270 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2272 */ 0x8, /* FC_LONG */
/* 2322 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2324 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2326 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter __result */
/* 2274 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2276 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2278 */ 0x8, /* FC_LONG */
/* 2328 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2330 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2332 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2280 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2282 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2284 */ 0x8, /* FC_LONG */
/* 2334 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2336 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2338 */ 0x8, /* FC_LONG */
0x0, /* 0 */
0x0
......@@ -3097,7 +3148,8 @@ static const unsigned short IWeChatRobot_FormatStringOffsetTable[] =
1968,
2022,
2076,
2124
2124,
2178
};
static const MIDL_STUBLESS_PROXY_INFO IWeChatRobot_ProxyInfo =
......@@ -3121,7 +3173,7 @@ static const MIDL_SERVER_INFO IWeChatRobot_ServerInfo =
0,
0,
0};
CINTERFACE_PROXY_VTABLE(51) _IWeChatRobotProxyVtbl =
CINTERFACE_PROXY_VTABLE(52) _IWeChatRobotProxyVtbl =
{
&IWeChatRobot_ProxyInfo,
&IID_IWeChatRobot,
......@@ -3175,7 +3227,8 @@ CINTERFACE_PROXY_VTABLE(51) _IWeChatRobotProxyVtbl =
(void *) (INT_PTR) -1 /* IWeChatRobot::CDelChatRoomMember */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CAddChatRoomMember */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::COpenBrowser */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CForwardMessage */
};
......@@ -3228,6 +3281,7 @@ static const PRPC_STUB_FUNCTION IWeChatRobot_table[] =
NdrStubCall2,
NdrStubCall2,
NdrStubCall2,
NdrStubCall2,
NdrStubCall2
};
......@@ -3235,7 +3289,7 @@ CInterfaceStubVtbl _IWeChatRobotStubVtbl =
{
&IID_IWeChatRobot,
&IWeChatRobot_ServerInfo,
51,
52,
&IWeChatRobot_table[-3],
CStdStubBuffer_DELEGATING_METHODS
};
......@@ -3251,8 +3305,8 @@ static const unsigned short IRobotEvent_FormatStringOffsetTable[] =
(unsigned short) -1,
(unsigned short) -1,
(unsigned short) -1,
2178,
2238
2232,
2292
};
static const MIDL_STUBLESS_PROXY_INFO IRobotEvent_ProxyInfo =
......
......@@ -17,7 +17,7 @@ public:
{
HRESULT hr = S_OK;
static ExpireSet es(2000);
if (!es.CheckIfDuplicatedAndAdd(msgid))
if (msgid && !es.CheckIfDuplicatedAndAdd(msgid))
{
return hr;
}
......
......@@ -29,6 +29,7 @@
#include "AddChatRoomMember.h"
#include "OpenBrowser.h"
#include "GetHistoryPublicMsg.h"
#include "ForwardMessage.h"
#define DLLNAME L"DWeChatRobot.dll"
......@@ -39,6 +40,7 @@
#define SendCardRemote "SendCardRemote"
#define SendAtTextRemote "SendAtTextRemote"
#define SendAppMsgRemote "SendAppMsgRemote"
#define ForwardMessageRemote "ForwardMessageRemote"
#define GetFriendListInit "GetFriendListInit"
#define GetFriendListRemote "GetFriendListRemote"
......
......@@ -317,6 +317,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClInclude Include="DelChatRoomMember.h" />
<ClInclude Include="DeleteUser.h" />
<ClInclude Include="EditRemark.h" />
<ClInclude Include="ForwardMessage.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="FriendList.h" />
<ClInclude Include="GetChatRoomMemberNickname.h" />
......@@ -361,6 +362,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClCompile Include="DeleteUser.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="EditRemark.cpp" />
<ClCompile Include="ForwardMessage.cpp" />
<ClCompile Include="FriendList.cpp" />
<ClCompile Include="GetChatRoomMemberNickname.cpp" />
<ClCompile Include="GetChatRoomMemebers.cpp" />
......
......@@ -124,6 +124,9 @@
<Filter Include="浏览器相关\获取公众号历史信息">
<UniqueIdentifier>{05d4d999-8961-4c1a-82fb-a36e3a4965f8}</UniqueIdentifier>
</Filter>
<Filter Include="发送消息\转发消息">
<UniqueIdentifier>{da7b0dbb-2d48-473f-9bb9-6d36ec5b02d3}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
......@@ -240,6 +243,9 @@
<ClInclude Include="GetHistoryPublicMsg.h">
<Filter>浏览器相关\获取公众号历史信息</Filter>
</ClInclude>
<ClInclude Include="ForwardMessage.h">
<Filter>发送消息\转发消息</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
......@@ -362,5 +368,8 @@
<ClCompile Include="GetHistoryPublicMsg.cpp">
<Filter>浏览器相关\获取公众号历史信息</Filter>
</ClCompile>
<ClCompile Include="ForwardMessage.cpp">
<Filter>发送消息\转发消息</Filter>
</ClCompile>
</ItemGroup>
</Project>
#include "pch.h"
#define ForwardMessageCall1Offset 0x771980
#define ForwardMessageCall2Offset 0x521760
#ifndef USE_SOCKET
struct ForwardMessageStruct
{
wchar_t *wxid;
int localId;
};
BOOL ForwardMessageRemote(LPVOID lpParameter)
{
ForwardMessageStruct *fms = (ForwardMessageStruct *)lpParameter;
return ForwardMessage(fms->wxid, fms->localId);
}
#endif
BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId)
{
DWORD WeChatWinBase = GetWeChatWinBase();
DWORD ForwardMessageCall1 = WeChatWinBase + ForwardMessageCall1Offset;
DWORD ForwardMessageCall2 = WeChatWinBase + ForwardMessageCall2Offset;
WxString p_wxid(wxid);
int isSuccess = 0;
__asm {
pushad;
pushfd;
mov eax, 0x5000100;
push eax;
mov ecx, dword ptr ds:[localId];
push ecx;
lea edi, p_wxid;
sub esp, 0x14;
mov ecx, esp;
push edi;
call ForwardMessageCall1;
call ForwardMessageCall2;
movzx eax,al;
mov isSuccess,eax;
add esp, 0x1C;
popfd;
popad;
}
return isSuccess == 0x1;
}
#pragma once
#include <windows.h>
BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId);
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) BOOL ForwardMessageRemote(LPVOID lpParameter);
#endif
......@@ -13,15 +13,20 @@ using namespace std;
#define CLTIP "127.0.0.1"
// 接收消息的HOOK地址偏移
#define ReceiveMessageHookOffset 0x78BF0F4C - 0x786A0000
#define ReceiveMessageHookOffset 0x5D39C359 - 0x5D1F0000
// 接收消息HOOK的CALL偏移
#define ReceiveMessageNextCallOffset 0x79136350 - 0x786A0000
#define ReceiveMessageNextCallOffset 0x5D5F7F00 - 0x5D1F0000
// 发送消息的HOOK地址偏移
#define SendMessageHookOffset 0x78B88E42 - 0x786A0000
// 发送消息HOOK的CALL偏移
#define SendMessageNextCallOffset 0x78AA8170 - 0x786A0000
// 撤回消息的HOOK地址偏移
#define RevokeMessageHookOffset 0x5D6D8A4C - 0x5D1F0000
// 撤回消息HOOK的CALL偏移
#define RevokeMessageNextCallOffset 0x5D6D3430 - 0x5D1F0000
#define READ_WSTRING(addr, offset) wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4))
static int SRVPORT = 0;
......@@ -29,8 +34,9 @@ static int SRVPORT = 0;
// 是否开启接收消息HOOK标志
BOOL ReceiveMessageHooked = false;
// 保存HOOK前的字节码,用于恢复
char OldReceiveMessageAsmCode[5] = {0};
char OldSendMessageAsmCode[5] = {0};
static char OldReceiveMessageAsmCode[5] = {0};
static char OldSendMessageAsmCode[5] = {0};
static char OldRevokeMessageAsmCode[5] = {0};
static DWORD WeChatWinBase = GetWeChatWinBase();
// 接收消息HOOK地址
static DWORD ReceiveMessageHookAddress = WeChatWinBase + ReceiveMessageHookOffset;
......@@ -44,6 +50,12 @@ static DWORD SendMessageHookAddress = WeChatWinBase + SendMessageHookOffset;
static DWORD SendMessageNextCall = WeChatWinBase + SendMessageNextCallOffset;
// 发送HOOK的跳转地址
static DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
// 撤回消息HOOK地址
static DWORD RevokeMessageHookAddress = WeChatWinBase + RevokeMessageHookOffset;
// 撤回消息HOOK的CALL地址
static DWORD RevokeMessageNextCall = WeChatWinBase + RevokeMessageNextCallOffset;
// 撤回HOOK的跳转地址
static DWORD RevokeMessageJmpBackAddress = RevokeMessageHookAddress + 0x5;
struct SocketMessageStruct
{
......@@ -120,6 +132,17 @@ void SendSocketMessageInThread(SocketMessageStruct *param)
return;
unique_ptr<SocketMessageStruct> sms(param);
string jstr(param->buffer, param->length);
#ifdef USE_COM
// 通过连接点,将消息广播给客户端;将广播过程放在线程中完成,客户端才可以等待图片、语音落地
VARIANT vsaValue = (_variant_t)utf8_to_unicode(jstr.c_str()).c_str();
json jMsg = json::parse(param->buffer, param->buffer + param->length, nullptr, false);
if (jMsg.is_discarded() != true)
{
DWORD type = jMsg["type"].get<DWORD>();
ULONG64 msgid = (type != 10000) ? jMsg["msgid"].get<ULONG64>() : 0;
PostComMessage(jMsg["pid"].get<int>(), WX_MESSAGE, msgid, &vsaValue);
}
#endif
SendSocketMessage(jstr.c_str(), jstr.size());
}
......@@ -131,21 +154,25 @@ static void dealMessage(DWORD messageAddr)
jMsg["type"] = *(DWORD *)(messageAddr + 0x38);
jMsg["isSendMsg"] = *(BOOL *)(messageAddr + 0x3C);
jMsg["msgid"] = msgid;
jMsg["localId"] = *(unsigned int *)(messageAddr + 0x20);
jMsg["sender"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x48).c_str());
int length = *(DWORD *)(messageAddr + 0x170 + 0x4);
jMsg["wxid"] = length == 0 ? jMsg["sender"].get<std::string>() : unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x170).c_str());
jMsg["message"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x70).c_str());
jMsg["filepath"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1AC).c_str());
string extrabuf = base64_encode((BYTE *)(*(DWORD *)(messageAddr + 0x8C)), *(DWORD *)(messageAddr + 0x8C + 0x4));
jMsg["extrainfo"] = extrabuf;
if (jMsg["type"].get<int>() != 10000)
{
jMsg["filepath"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1AC).c_str());
string extrabuf = base64_encode((BYTE *)(*(DWORD *)(messageAddr + 0x8C)), *(DWORD *)(messageAddr + 0x8C + 0x4));
jMsg["extrainfo"] = extrabuf;
}
else
{
// 为尊重他人隐私,不提供已撤回消息的原有信息
jMsg["extrainfo"] = "";
}
jMsg["time"] = unicode_to_utf8((wchar_t *)GetTimeW(*(DWORD *)(messageAddr + 0x44)).c_str());
jMsg["self"] = unicode_to_utf8((wchar_t *)GetSelfWxid().c_str());
string jstr = jMsg.dump() + '\n';
#ifdef USE_COM
// 通过连接点,将消息广播给客户端
VARIANT vsaValue = (_variant_t)utf8_to_unicode(jstr.c_str()).c_str();
PostComMessage(jMsg["pid"].get<int>(), WX_MESSAGE, msgid, &vsaValue);
#endif
// 为保证线程安全,需要手动管理内存
SocketMessageStruct *sms = new SocketMessageStruct;
sms->buffer = new char[jstr.size() + 1];
......@@ -163,15 +190,14 @@ static void dealMessage(DWORD messageAddr)
* messageAddr:保存消息的缓冲区地址
* return:void
*/
VOID ReceiveMessage(DWORD messagesAddr)
{
// 此处用于区别是发送的还是接收的消息
DWORD *messages = (DWORD *)messagesAddr;
for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298)
{
dealMessage(messageAddr);
}
}
// VOID ReceiveMessage(DWORD messagesAddr)
//{
// DWORD *messages = (DWORD *)messagesAddr;
// for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298)
// {
// dealMessage(messageAddr);
// }
// }
/*
* HOOK的具体实现,接收到消息后调用处理函数
......@@ -182,7 +208,7 @@ _declspec(naked) void dealReceiveMessage()
pushad;
pushfd;
push edi;
call ReceiveMessage;
call dealMessage;
add esp, 0x4;
popfd;
popad;
......@@ -209,6 +235,24 @@ _declspec(naked) void dealSendMessage()
}
}
/*
* HOOK的具体实现,接收到撤回消息后调用处理函数
*/
_declspec(naked) void dealRevokeMessage()
{
__asm {
pushad;
pushfd;
push edi;
call dealMessage;
add esp, 0x4;
popfd;
popad;
call RevokeMessageNextCall;
jmp RevokeMessageJmpBackAddress;
}
}
/*
* 开始接收消息HOOK
* return:void
......@@ -225,8 +269,12 @@ VOID HookReceiveMessage(int port)
SendMessageHookAddress = WeChatWinBase + SendMessageHookOffset;
SendMessageNextCall = WeChatWinBase + SendMessageNextCallOffset;
SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
RevokeMessageHookAddress = WeChatWinBase + RevokeMessageHookOffset;
RevokeMessageNextCall = WeChatWinBase + RevokeMessageNextCallOffset;
RevokeMessageJmpBackAddress = RevokeMessageHookAddress + 0x5;
HookAnyAddress(ReceiveMessageHookAddress, (LPVOID)dealReceiveMessage, OldReceiveMessageAsmCode);
HookAnyAddress(SendMessageHookAddress, (LPVOID)dealSendMessage, OldSendMessageAsmCode);
HookAnyAddress(RevokeMessageHookAddress, (LPVOID)dealRevokeMessage, OldRevokeMessageAsmCode);
ReceiveMessageHooked = TRUE;
}
......@@ -241,5 +289,6 @@ VOID UnHookReceiveMessage()
return;
UnHookAnyAddress(ReceiveMessageHookAddress, OldReceiveMessageAsmCode);
UnHookAnyAddress(SendMessageHookAddress, OldSendMessageAsmCode);
UnHookAnyAddress(RevokeMessageHookAddress, OldRevokeMessageAsmCode);
ReceiveMessageHooked = FALSE;
}
......@@ -133,4 +133,9 @@ BOOL __stdcall OpenBrowser(wstring url)
{
return OpenBrowser(WS2LW(url));
}
BOOL __stdcall ForwardMessage(wstring wxid, int localId)
{
return ForwardMessage(WS2LW(wxid), localId);
}
#endif
......@@ -30,6 +30,7 @@
#include "GetChatRoomMemberNickname.h"
#include "OpenBrowser.h"
#include "GetHistoryPublicMsg.h"
#include "ForwardMessage.h"
using namespace std;
#pragma comment(lib, "version.lib")
......
......@@ -531,6 +531,15 @@ void request_event(mg_http_message *hm, string &ret)
ret = ret_data.dump();
break;
}
case WECHAT_MSG_FORWARD_MESSAGE:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
int localId = get_http_param_int(hm, jData, "localId", method);
BOOL status = ForwardMessage(wxid, localId);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
default:
// char* wxid = mg_json_get_str(hm->body, "$.wxid");
break;
......
......@@ -70,6 +70,8 @@ typedef enum WECHAT_HTTP_APISTag
// browser
WECHAT_BROWSER_OPEN_WITH_URL,
WECHAT_GET_PUBLIC_MSG,
// IJ
WECHAT_MSG_FORWARD_MESSAGE,
} WECHAT_HTTP_APIS,
*PWECHAT_HTTP_APIS;
#endif
......@@ -88,5 +88,6 @@ if __name__ == '__main__':
wx = WeChatRobot(pid_list[0])
wx.StartService()
wx.StartReceiveMessage()
wx.HookImageMsg(r"D:\wxdata")
wxRobot.register_msg_event(pid_list[0])
wx.StopService()
......@@ -1044,6 +1044,25 @@ class WeChatRobot:
pass
return ret
def ForwardMessage(self,wxid:str,localId:int) -> int:
"""
转发消息,只支持单条转发
Parameters
----------
wxid : str
消息接收人wxid.
localId : int
消息短id,可以在实时消息接口中获取或查询MSG{x}.db.
Returns
-------
int
成功返回0,失败返回非0值.
"""
return self.robot.CForwardMessage(self.pid,wxid,localId)
def get_wechat_pid_list() -> list:
"""
......
......@@ -84,6 +84,8 @@ class WECHAT_HTTP_APIS:
WECHAT_BROWSER_OPEN_WITH_URL = 38 # 打开微信内置浏览器
WECHAT_GET_PUBLIC_MSG = 39 # 获取公众号历史消息
WECHAT_MSG_FORWARD_MESSAGE = 40 # 转发消息
APIS = WECHAT_HTTP_APIS
# http api 参数模板
......@@ -184,7 +186,9 @@ class WECHAT_HTTP_API_PARAM_TEMPLATES:
# browser
APIS.WECHAT_BROWSER_OPEN_WITH_URL: {"url": "https://www.baidu.com/"},
APIS.WECHAT_GET_PUBLIC_MSG: {"public_id": "","offset": ""}
APIS.WECHAT_GET_PUBLIC_MSG: {"public_id": "","offset": ""},
APIS.WECHAT_MSG_FORWARD_MESSAGE: {"wxid": "filehelper","localId": 1},
}
def get_http_template(self, api_number):
......
......@@ -132,6 +132,11 @@ CWeChatRobot.exe /unregserver
3. 修复了一个bug,该bug会导致图片和语音保存到微信安装目录而非指定的目录
4. 优化实时消息接口,现在会带上自己的wxid
5. 优化图片和语音保存路径,方便区分来自不同账号的消息
## 2022.09.10
1. 中秋节快乐
2. 新增转发消息功能,请勿转发语音、红包等消息
3. 实时消息接口新增`localId`字段,该字段用于转发消息接口;现在也可以接收到撤回消息提醒
4. 优化COM连接点,在线程中进行消息广播,客户端可以阻塞以等待图片、语音等资源落地
# 打赏作者
请给作者一个star,感谢感谢
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册