diff --git a/CWeChatRobot/ForwardMessage.cpp b/CWeChatRobot/ForwardMessage.cpp index ceed05a944665dcc527c3458f732ee0290d586c7..a07c6698a47e22272eeea18269aafb72a3c65a18 100644 --- a/CWeChatRobot/ForwardMessage.cpp +++ b/CWeChatRobot/ForwardMessage.cpp @@ -3,10 +3,10 @@ struct ForwardMessageStruct { DWORD wxid; - DWORD localId; + ULONG64 msgid; }; -BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId) +BOOL ForwardMessage(DWORD pid, wchar_t *wxid, ULONG64 msgid) { WeChatProcess hp(pid); if (!hp.m_init) @@ -19,7 +19,7 @@ BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId) ForwardMessageStruct params = {0}; WeChatData r_wxid(hp.GetHandle(), wxid, TEXTLENGTH(wxid)); params.wxid = (DWORD)r_wxid.GetAddr(); - params.localId = localId; + params.msgid = msgid; WeChatData r_params(hp.GetHandle(), ¶ms, sizeof(params)); if (!params.wxid || !r_params.GetAddr()) { diff --git a/CWeChatRobot/ForwardMessage.h b/CWeChatRobot/ForwardMessage.h index ec56a9ec26410d9ce3074941aed50b0d62a020a4..aa1233895a43aaffb487283222f557ba3fecd680 100644 --- a/CWeChatRobot/ForwardMessage.h +++ b/CWeChatRobot/ForwardMessage.h @@ -1,4 +1,4 @@ #pragma once #include -BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId); +BOOL ForwardMessage(DWORD pid, wchar_t *wxid, ULONG64 msgid); diff --git a/CWeChatRobot/GetQrcodeImage.cpp b/CWeChatRobot/GetQrcodeImage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d85f8154e0d60fa14b564af4de2266b410dbf27 --- /dev/null +++ b/CWeChatRobot/GetQrcodeImage.cpp @@ -0,0 +1,31 @@ +#include "pch.h" + +VARIANT GetQrcodeImage(DWORD pid) +{ + VARIANT vsa; + vsa.vt = VT_ARRAY | VT_UI1; + V_ARRAY(&vsa) = NULL; + WeChatProcess hp(pid); + if (!hp.m_init) + return vsa; + DWORD GetQrcodeImageAddr = hp.GetProcAddr(GetQrcodeImageRemote); + DWORD ret = CallRemoteFunction(hp.GetHandle(), GetQrcodeImageAddr, NULL); + if (ret == 0) + return vsa; + DWORD ret_info[2] = {0}; + ReadProcessMemory(hp.GetHandle(), (LPCVOID)ret, &ret_info, sizeof(ret_info), 0); + DWORD buf_addr = ret_info[0]; + int size = ret_info[1]; + if (size == 0 || buf_addr == 0) + return vsa; + unique_ptr image(new BYTE[size + 1]()); + ReadProcessMemory(hp.GetHandle(), (LPCVOID)buf_addr, image.get(), size, 0); + SAFEARRAYBOUND rgsaBound = {(ULONG)size, 0}; + SAFEARRAY *psaValue = SafeArrayCreate(VT_UI1, 1, &rgsaBound); + BYTE *buf = NULL; + ::SafeArrayAccessData(psaValue, (void **)&buf); + memcpy(buf, image.get(), size); + ::SafeArrayUnaccessData(psaValue); + V_ARRAY(&vsa) = psaValue; + return vsa; +} diff --git a/CWeChatRobot/GetQrcodeImage.h b/CWeChatRobot/GetQrcodeImage.h new file mode 100644 index 0000000000000000000000000000000000000000..b3aafb8876bf7118f97ed516d76257ca1f61d41e --- /dev/null +++ b/CWeChatRobot/GetQrcodeImage.h @@ -0,0 +1,3 @@ +#pragma once +#include +VARIANT GetQrcodeImage(DWORD pid); diff --git a/CWeChatRobot/WeChatRobot.cpp b/CWeChatRobot/WeChatRobot.cpp index 9321dc7c474e0711fc9858d076c4521732149d24..e9d91c54a9d217ad74c7db3ad3ab72bbb5e6dae2 100644 --- a/CWeChatRobot/WeChatRobot.cpp +++ b/CWeChatRobot/WeChatRobot.cpp @@ -558,8 +558,24 @@ STDMETHODIMP CWeChatRobot::CGetHistoryPublicMsg(DWORD pid, BSTR PublicId, BSTR O return S_OK; } -STDMETHODIMP CWeChatRobot::CForwardMessage(DWORD pid, BSTR wxid, int localId, int *__result) +/* + * 参数0:目标进程pid + * 参数1:消息接收人wxid + * 参数2:要转发的消息id + * 参数3:预返回的值,调用时无需提供 + */ +STDMETHODIMP CWeChatRobot::CForwardMessage(DWORD pid, BSTR wxid, ULONG64 msgid, int *__result) +{ + *__result = ForwardMessage(pid, wxid, msgid); + return S_OK; +} + +/* + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ +STDMETHODIMP CWeChatRobot::CGetQrcodeImage(DWORD pid, VARIANT *__result) { - *__result = ForwardMessage(pid, wxid, localId); + *__result = GetQrcodeImage(pid); return S_OK; } diff --git a/CWeChatRobot/WeChatRobot.h b/CWeChatRobot/WeChatRobot.h index 8fb612e68ae6284c897cfea587627e9b8ca982c5..45d7b15b9c3b9f13d6298f1219649a49ba68197a 100644 --- a/CWeChatRobot/WeChatRobot.h +++ b/CWeChatRobot/WeChatRobot.h @@ -85,7 +85,8 @@ 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); + STDMETHODIMP CForwardMessage(DWORD pid, BSTR wxid, ULONG64 msgid, int *__result); + STDMETHODIMP CGetQrcodeImage(DWORD pid, VARIANT *__result); }; OBJECT_ENTRY_AUTO(__uuidof(WeChatRobot), CWeChatRobot) diff --git a/CWeChatRobot/WeChatRobotCOM.idl b/CWeChatRobot/WeChatRobotCOM.idl index 8e7d990a358d28f583b0e1ee6584a0f687322b31..7ab41878f0e8a6d6accaa4f72767c3081d02fe05 100644 --- a/CWeChatRobot/WeChatRobotCOM.idl +++ b/CWeChatRobot/WeChatRobotCOM.idl @@ -60,7 +60,8 @@ interface IWeChatRobot : IDispatch [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(48), helpstring("转发消息") ] HRESULT CForwardMessage([in] DWORD pid, [in] BSTR wxid, [in] int localId, [out, retval] int * __result); + [id(48), helpstring("转发消息") ] HRESULT CForwardMessage([in] DWORD pid, [in] BSTR wxid, [in] unsigned long long localId, [out, retval] int * __result); + [id(49), helpstring("获取二维码")] HRESULT CGetQrcodeImage([in] DWORD pid, [out, retval] VARIANT * __result); }; [ object, diff --git a/CWeChatRobot/WeChatRobotCOM.vcxproj b/CWeChatRobot/WeChatRobotCOM.vcxproj index 956eba37a4c1ca63d8a6a517af639b450860139f..fb12f5f246dd395517bd0c05864ccfb73ad197b0 100644 --- a/CWeChatRobot/WeChatRobotCOM.vcxproj +++ b/CWeChatRobot/WeChatRobotCOM.vcxproj @@ -240,6 +240,7 @@ + @@ -294,6 +295,7 @@ Create Create + diff --git a/CWeChatRobot/WeChatRobotCOM.vcxproj.filters b/CWeChatRobot/WeChatRobotCOM.vcxproj.filters index 58e690a6d8ba88a0c65c41bc4ad71e37e0c08ed9..017328ee656422619662d0630b9aa6f6a196ac66 100644 --- a/CWeChatRobot/WeChatRobotCOM.vcxproj.filters +++ b/CWeChatRobot/WeChatRobotCOM.vcxproj.filters @@ -128,6 +128,9 @@ {f44839a7-3cf0-415f-886e-22a8635c3dbd} + + {fb5a07d9-648d-4e1c-aed3-158f872c3d3e} + @@ -262,6 +265,9 @@ 发送消息\转发消息 + + 二维码 + @@ -396,6 +402,9 @@ 发送消息\转发消息 + + 二维码 + diff --git a/CWeChatRobot/WeChatRobotCOM_i.h b/CWeChatRobot/WeChatRobotCOM_i.h index 08aeed4255b020e812422a4cd0e70f9f9786c7a3..55e05776ceb3e0d4ec65d5dd1f3797ffc42beebe 100644 --- a/CWeChatRobot/WeChatRobotCOM_i.h +++ b/CWeChatRobot/WeChatRobotCOM_i.h @@ -348,9 +348,13 @@ EXTERN_C const IID IID_IWeChatRobot; virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CForwardMessage( /* [in] */ DWORD pid, /* [in] */ BSTR wxid, - /* [in] */ int localId, + /* [in] */ unsigned long long localId, /* [retval][out] */ int *__result) = 0; + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CGetQrcodeImage( + /* [in] */ DWORD pid, + /* [retval][out] */ VARIANT *__result) = 0; + }; @@ -688,9 +692,14 @@ EXTERN_C const IID IID_IWeChatRobot; IWeChatRobot * This, /* [in] */ DWORD pid, /* [in] */ BSTR wxid, - /* [in] */ int localId, + /* [in] */ unsigned long long localId, /* [retval][out] */ int *__result); + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CGetQrcodeImage )( + IWeChatRobot * This, + /* [in] */ DWORD pid, + /* [retval][out] */ VARIANT *__result); + END_INTERFACE } IWeChatRobotVtbl; @@ -862,6 +871,9 @@ EXTERN_C const IID IID_IWeChatRobot; #define IWeChatRobot_CForwardMessage(This,pid,wxid,localId,__result) \ ( (This)->lpVtbl -> CForwardMessage(This,pid,wxid,localId,__result) ) +#define IWeChatRobot_CGetQrcodeImage(This,pid,__result) \ + ( (This)->lpVtbl -> CGetQrcodeImage(This,pid,__result) ) + #endif /* COBJMACROS */ diff --git a/CWeChatRobot/WeChatRobotCOM_p.c b/CWeChatRobot/WeChatRobotCOM_p.c index 8ceb1bcaead58e346a2c9700a950717745eb8330..4c5bae7d96d038295dae3f7eeb0a45dd5fa4273b 100644 --- a/CWeChatRobot/WeChatRobotCOM_p.c +++ b/CWeChatRobot/WeChatRobotCOM_p.c @@ -49,7 +49,7 @@ #include "WeChatRobotCOM_i.h" #define TYPE_FORMAT_STRING_SIZE 1239 -#define PROC_FORMAT_STRING_SIZE 2341 +#define PROC_FORMAT_STRING_SIZE 2383 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 2 @@ -2112,8 +2112,8 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor 0x6c, /* Old Flags: object, Oi2 */ /* 2180 */ NdrFcLong( 0x0 ), /* 0 */ /* 2184 */ NdrFcShort( 0x33 ), /* 51 */ -/* 2186 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 2188 */ NdrFcShort( 0x10 ), /* 16 */ +/* 2186 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 2188 */ NdrFcShort( 0x18 ), /* 24 */ /* 2190 */ NdrFcShort( 0x24 ), /* 36 */ /* 2192 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x5, /* 5 */ @@ -2140,38 +2140,38 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor /* 2214 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ /* 2216 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 2218 */ 0x8, /* FC_LONG */ +/* 2218 */ 0xb, /* FC_HYPER */ 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 */ +/* 2222 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ /* 2224 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Return value */ /* 2226 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 2228 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2228 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ /* 2230 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure CPostMessage */ + /* Procedure CGetQrcodeImage */ /* 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 */ +/* 2238 */ NdrFcShort( 0x34 ), /* 52 */ +/* 2240 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 2242 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2244 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2246 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ /* 2248 */ 0x8, /* 8 */ - 0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */ -/* 2250 */ NdrFcShort( 0x0 ), /* 0 */ -/* 2252 */ NdrFcShort( 0x1 ), /* 1 */ + 0x43, /* Ext Flags: new corr desc, clt corr check, has range on conformance */ +/* 2250 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2252 */ NdrFcShort( 0x0 ), /* 0 */ /* 2254 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter pid */ @@ -2181,83 +2181,120 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor /* 2260 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Parameter msgtype */ + /* Parameter __result */ -/* 2262 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2262 */ NdrFcShort( 0x4113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=16 */ /* 2264 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 2266 */ 0x8, /* FC_LONG */ +/* 2266 */ NdrFcShort( 0x4ac ), /* Type Offset=1196 */ + + /* Return value */ + +/* 2268 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2270 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 2272 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure CPostMessage */ + +/* 2274 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2276 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2280 */ NdrFcShort( 0x7 ), /* 7 */ +/* 2282 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 2284 */ NdrFcShort( 0x20 ), /* 32 */ +/* 2286 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2288 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x6, /* 6 */ +/* 2290 */ 0x8, /* 8 */ + 0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */ +/* 2292 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2294 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2296 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter pid */ + +/* 2298 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2300 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 2302 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter msgtype */ + +/* 2304 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2306 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 2308 */ 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 */ +/* 2310 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2312 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 2314 */ 0xb, /* FC_HYPER */ 0x0, /* 0 */ /* Parameter msg */ -/* 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 */ +/* 2316 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 2318 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2320 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */ /* Parameter __result */ -/* 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 */ +/* 2322 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2324 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 2326 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Return value */ -/* 2286 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 2288 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 2290 */ 0x8, /* FC_LONG */ +/* 2328 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2330 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 2332 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure CRegisterWxPidWithCookie */ -/* 2292 */ 0x33, /* FC_AUTO_HANDLE */ +/* 2334 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 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, */ +/* 2336 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2340 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2342 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2344 */ NdrFcShort( 0x10 ), /* 16 */ +/* 2346 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2348 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x4, /* 4 */ -/* 2308 */ 0x8, /* 8 */ +/* 2350 */ 0x8, /* 8 */ 0x41, /* Ext Flags: new corr desc, has range on conformance */ -/* 2310 */ NdrFcShort( 0x0 ), /* 0 */ -/* 2312 */ NdrFcShort( 0x0 ), /* 0 */ -/* 2314 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2352 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2354 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2356 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter pid */ -/* 2316 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 2318 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 2320 */ 0x8, /* FC_LONG */ +/* 2358 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2360 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 2362 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter cookie */ -/* 2322 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 2324 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 2326 */ 0x8, /* FC_LONG */ +/* 2364 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2366 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 2368 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter __result */ -/* 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 */ +/* 2370 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2372 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 2374 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Return value */ -/* 2334 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 2336 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 2338 */ 0x8, /* FC_LONG */ +/* 2376 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2378 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 2380 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 @@ -3149,7 +3186,8 @@ static const unsigned short IWeChatRobot_FormatStringOffsetTable[] = 2022, 2076, 2124, - 2178 + 2178, + 2232 }; static const MIDL_STUBLESS_PROXY_INFO IWeChatRobot_ProxyInfo = @@ -3173,7 +3211,7 @@ static const MIDL_SERVER_INFO IWeChatRobot_ServerInfo = 0, 0, 0}; -CINTERFACE_PROXY_VTABLE(52) _IWeChatRobotProxyVtbl = +CINTERFACE_PROXY_VTABLE(53) _IWeChatRobotProxyVtbl = { &IWeChatRobot_ProxyInfo, &IID_IWeChatRobot, @@ -3228,7 +3266,8 @@ CINTERFACE_PROXY_VTABLE(52) _IWeChatRobotProxyVtbl = (void *) (INT_PTR) -1 /* IWeChatRobot::CAddChatRoomMember */ , (void *) (INT_PTR) -1 /* IWeChatRobot::COpenBrowser */ , (void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */ , - (void *) (INT_PTR) -1 /* IWeChatRobot::CForwardMessage */ + (void *) (INT_PTR) -1 /* IWeChatRobot::CForwardMessage */ , + (void *) (INT_PTR) -1 /* IWeChatRobot::CGetQrcodeImage */ }; @@ -3282,6 +3321,7 @@ static const PRPC_STUB_FUNCTION IWeChatRobot_table[] = NdrStubCall2, NdrStubCall2, NdrStubCall2, + NdrStubCall2, NdrStubCall2 }; @@ -3289,7 +3329,7 @@ CInterfaceStubVtbl _IWeChatRobotStubVtbl = { &IID_IWeChatRobot, &IWeChatRobot_ServerInfo, - 52, + 53, &IWeChatRobot_table[-3], CStdStubBuffer_DELEGATING_METHODS }; @@ -3305,8 +3345,8 @@ static const unsigned short IRobotEvent_FormatStringOffsetTable[] = (unsigned short) -1, (unsigned short) -1, (unsigned short) -1, - 2232, - 2292 + 2274, + 2334 }; static const MIDL_STUBLESS_PROXY_INFO IRobotEvent_ProxyInfo = diff --git a/CWeChatRobot/robotdata.h b/CWeChatRobot/robotdata.h index 5c22665c9c9f6d4afa93769aff0a9a682b21e981..86c0ee9030f1df70087c70ac9a8f487b4c32d292 100644 --- a/CWeChatRobot/robotdata.h +++ b/CWeChatRobot/robotdata.h @@ -30,6 +30,7 @@ #include "OpenBrowser.h" #include "GetHistoryPublicMsg.h" #include "ForwardMessage.h" +#include "GetQrcodeImage.h" #define DLLNAME L"DWeChatRobot.dll" @@ -89,3 +90,4 @@ #define OpenBrowserRemote "OpenBrowserRemote" #define GetHistoryPublicMsgRemote "GetHistoryPublicMsgRemote" +#define GetQrcodeImageRemote "GetQrcodeImageRemote" diff --git a/DWeChatRobot/DWeChatRobot.vcxproj b/DWeChatRobot/DWeChatRobot.vcxproj index bdee442e0023d4f6b9a7f6af8942dad751e3bb5f..9bc8f32eb0247e63dc5c15b2c3e5acec76b88b53 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj +++ b/DWeChatRobot/DWeChatRobot.vcxproj @@ -328,6 +328,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http + @@ -346,6 +347,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http + @@ -381,6 +383,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http Create Create + diff --git a/DWeChatRobot/DWeChatRobot.vcxproj.filters b/DWeChatRobot/DWeChatRobot.vcxproj.filters index 02e75ed46e155f5f8b6b2b5bc36cc246b18ba932..23738ec48ff921e6e7ded8b22a7ea3e79a961a40 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj.filters +++ b/DWeChatRobot/DWeChatRobot.vcxproj.filters @@ -127,6 +127,9 @@ {da7b0dbb-2d48-473f-9bb9-6d36ec5b02d3} + + {a0a64bc2-f48e-41a0-838a-45b9985f8d68} + @@ -246,6 +249,12 @@ 发送消息\转发消息 + + 二维码 + + + 通用标头 + @@ -371,5 +380,8 @@ 发送消息\转发消息 + + 二维码 + diff --git a/DWeChatRobot/DbExecuteSql.cpp b/DWeChatRobot/DbExecuteSql.cpp index f650488fb6700c1f07c596c21a8feb3ea5e891ad..5398963dc359e852cbfff1008155e2bf9505fc89 100644 --- a/DWeChatRobot/DbExecuteSql.cpp +++ b/DWeChatRobot/DbExecuteSql.cpp @@ -317,7 +317,8 @@ int SelectDataRemote(LPVOID lpParameter) } return 0; } -#else +#endif + vector> SelectData(DWORD db_hanle, const char *sql) { vector> ret; @@ -350,4 +351,3 @@ vector> SelectData(DWORD db_hanle, const char *sql) ClearResultArray(); return ret; } -#endif diff --git a/DWeChatRobot/DbExecuteSql.h b/DWeChatRobot/DbExecuteSql.h index 699f8fdbc5a4191975312f088a89b0544edaf8be..fec779fc7116e0bab0000359d954ef93726db16b 100644 --- a/DWeChatRobot/DbExecuteSql.h +++ b/DWeChatRobot/DbExecuteSql.h @@ -7,8 +7,7 @@ int query(void *data, int argc, char **argv, char **azColName); #ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD ExecuteSQLRemote(LPVOID lpParameter); extern "C" __declspec(dllexport) int SelectDataRemote(LPVOID lpParameter); -#else -vector> SelectData(DWORD db_hanle, const char *sql); #endif +vector> SelectData(DWORD db_hanle, const char *sql); void *ExecuteSQL(DWORD ptrDb, const char *sql, DWORD callback, void *data); void *SelectData(DWORD db, const char *sql, void *data); diff --git a/DWeChatRobot/ForwardMessage.cpp b/DWeChatRobot/ForwardMessage.cpp index 9e3d7340d609cc5bf0c3b69658eccc580b1800d4..00de4acc4d3910bff548c2a9d1d35b54f9d4fd94 100644 --- a/DWeChatRobot/ForwardMessage.cpp +++ b/DWeChatRobot/ForwardMessage.cpp @@ -7,7 +7,7 @@ struct ForwardMessageStruct { wchar_t *wxid; - int localId; + unsigned long long localId; }; BOOL ForwardMessageRemote(LPVOID lpParameter) @@ -17,17 +17,22 @@ BOOL ForwardMessageRemote(LPVOID lpParameter) } #endif -BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId) +BOOL __stdcall ForwardMessage(wchar_t *wxid, unsigned long long msgid) { DWORD WeChatWinBase = GetWeChatWinBase(); DWORD ForwardMessageCall1 = WeChatWinBase + ForwardMessageCall1Offset; DWORD ForwardMessageCall2 = WeChatWinBase + ForwardMessageCall2Offset; + int dbIndex = 0; + int localId = GetLocalIdByMsgId(msgid, dbIndex); + if (localId == 0) + return FALSE; + dbIndex = 0x5000000 + (dbIndex << 8); WxString p_wxid(wxid); int isSuccess = 0; __asm { pushad; pushfd; - mov eax, 0x5000100; + mov eax, dword ptr ds:[dbIndex]; push eax; mov ecx, dword ptr ds:[localId]; push ecx; diff --git a/DWeChatRobot/ForwardMessage.h b/DWeChatRobot/ForwardMessage.h index c533bb7d337dbea2415c344bd7e60839de117d63..c6aeced79be42f82bd19542cd40390e50882203a 100644 --- a/DWeChatRobot/ForwardMessage.h +++ b/DWeChatRobot/ForwardMessage.h @@ -1,6 +1,6 @@ #pragma once #include -BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId); +BOOL __stdcall ForwardMessage(wchar_t *wxid, unsigned long long localId); #ifndef USE_SOCKET extern "C" __declspec(dllexport) BOOL ForwardMessageRemote(LPVOID lpParameter); diff --git a/DWeChatRobot/GetDbHandles.cpp b/DWeChatRobot/GetDbHandles.cpp index 8359937c971e147c75ab7e3e4949e39f97118834..f6d7ceab9340caaaae8c16a164e33c6196adaa32 100644 --- a/DWeChatRobot/GetDbHandles.cpp +++ b/DWeChatRobot/GetDbHandles.cpp @@ -9,20 +9,38 @@ // ݿϢ vector dbs; +map dbmap; /* - * ݿ`dbs`мݿ + * ݿ`dbmap`мݿ * dbnameݿ * returnDWORDɹݿ򷵻`0` */ DWORD GetDbHandleByDbName(wchar_t *dbname) { - if (dbs.size() == 0) + if (dbmap.size() == 0) GetDbHandles(); - for (unsigned int i = 0; i < dbs.size() - 1; i++) + if (dbmap.find(dbname) != dbmap.end()) + return dbmap[dbname].handle; + return 0; +} + +unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex) +{ + char sql[260] = {0}; + sprintf_s(sql, "select localId from MSG where MsgSvrID=%llu;", msgid); + wchar_t dbname[20] = {0}; + for (int i = 0;; i++) { - if (!lstrcmpW(dbs[i].dbname, dbname)) - return dbs[i].handle; + swprintf_s(dbname, L"MSG%d.db", i); + DWORD handle = GetDbHandleByDbName(dbname); + if (handle == 0) + return 0; + vector> result = SelectData(handle, (const char *)sql); + if (result.size() == 0) + continue; + dbIndex = i + 1; + return stoi(result[1][0]); } return 0; } @@ -63,7 +81,6 @@ vector GetDbHandles() mov SqlHandleEndAddr, eax; } DWORD dwHandle = 0x0; - wstring dbnames = L""; // ȡϵݿ while (SqlHandleBeginAddr < SqlHandleEndAddr) { @@ -71,29 +88,31 @@ vector GetDbHandles() SqlHandleBeginAddr += 0x4; if (SqlHandleBeginAddr == SqlHandleEndAddr) break; - if (dbnames.find(L"|" + (wstring)(wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|", 0) != wstring::npos) + wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50))); + if (dbmap.find(dbname) != dbmap.end()) continue; DbInfoStruct db = {0}; - dbnames = dbnames + L"|" + (wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|"; db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50)); db.l_dbname = wcslen(db.dbname); db.handle = *(DWORD *)(dwHandle + 0x3C); ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db); dbs.push_back(db); + dbmap[dbname] = db; } // ȡںݿ for (int i = 1; i < 4; i++) { dwHandle = *((DWORD *)(SqlHandlePublicMsgAddr + i * 0x4)); - if (dbnames.find(L"|" + (wstring)(wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|", 0) != wstring::npos) + wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50))); + if (dbmap.find(dbname) != dbmap.end()) continue; DbInfoStruct db = {0}; - dbnames = dbnames + L"|" + (wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|"; db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50)); db.l_dbname = wcslen(db.dbname); db.handle = *(DWORD *)(dwHandle + 0x3C); ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db); dbs.push_back(db); + dbmap[dbname] = db; } // ȡ¼ݿ int msgdb_count = *(int *)(SqlHandleMSGAddr + 0x4); @@ -103,15 +122,16 @@ vector GetDbHandles() for (int j = 0; j < 4; j++) { dwHandle = *(DWORD *)(MsgdwHandle + 0x14 + j * 4); - if (dbnames.find(L"|" + (wstring)(wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|", 0) != wstring::npos) + wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50))); + if (dbmap.find(dbname) != dbmap.end()) continue; DbInfoStruct db = {0}; - dbnames = dbnames + L"|" + (wchar_t *)(*(DWORD *)(dwHandle + 0x50)) + L"|"; db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50)); db.l_dbname = wcslen(db.dbname); db.handle = *(DWORD *)(dwHandle + 0x3C); ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db); dbs.push_back(db); + dbmap[dbname] = db; } MsgdwHandle += 0x68; } diff --git a/DWeChatRobot/GetDbHandles.h b/DWeChatRobot/GetDbHandles.h index fd992ea23ec40a71c2563c2b2084fad27ff1f01b..384126140986c5cbb62e2a723e97abb7012b202e 100644 --- a/DWeChatRobot/GetDbHandles.h +++ b/DWeChatRobot/GetDbHandles.h @@ -8,3 +8,4 @@ vector GetDbHandles(); extern "C" __declspec(dllexport) DWORD GetDbHandlesRemote(); #endif DWORD GetDbHandleByDbName(wchar_t *dbname); +unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex); diff --git a/DWeChatRobot/GetQrcodeImage.cpp b/DWeChatRobot/GetQrcodeImage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d81522c8388700f937a286f96a01a72b82b09a7 --- /dev/null +++ b/DWeChatRobot/GetQrcodeImage.cpp @@ -0,0 +1,137 @@ +#include "pch.h" + +#define SwitchQrcodeLoginCall1Offset 0x372AA0 +#define SwitchQrcodeLoginCall2Offset 0x5177D0 + +#define SaveQrcodeImageHookOffset 0x2815DA +#define SaveQrcodeImageNextCallOffset 0x76F660 + +static DWORD SaveQrcodeImageHookAddr; +static DWORD SaveQrcodeImageNextCall; +static DWORD SaveQrcodeImageJmpBackAddress; + +static bool SaveQrcodeImageHooked = false; +static char SaveQrcodeImageOldAsmCode[5] = {0}; +static DWORD SignalThreadId = 0; + +struct QrcodeStruct +{ + unsigned char *image = NULL; + int size = 0; + void update(unsigned char *buf, int len) + { + this->free(); + this->image = new unsigned char[len + 1]; + memcpy(this->image, buf, len); + this->size = len; + } + void free() + { + if (this->image != NULL) + { + delete[] this->image; + this->image = NULL; + } + this->size = 0; + } + ~QrcodeStruct() + { + this->free(); + } +}; + +static unique_ptr qc(new QrcodeStruct); + +void SaveQrcodeImage(unsigned char *src, int size) +{ + qc->update(src, size); + SIGNAL(SignalThreadId, WM_WAIT_QRCODE); +} + +_declspec(naked) void dealQrcodeImage() +{ + __asm { + pushad; + pushfd; + push dword ptr[eax + 4]; + push dword ptr[eax]; + call SaveQrcodeImage; + add esp, 0x8; + popfd; + popad; + call SaveQrcodeImageNextCall; + jmp SaveQrcodeImageJmpBackAddress; + } +} + +void HookQrcodeImage() +{ + if (SaveQrcodeImageHooked) + return; + DWORD WeChatWinBase = GetWeChatWinBase(); + SaveQrcodeImageHookAddr = WeChatWinBase + SaveQrcodeImageHookOffset; + SaveQrcodeImageNextCall = WeChatWinBase + SaveQrcodeImageNextCallOffset; + SaveQrcodeImageJmpBackAddress = SaveQrcodeImageHookAddr + 0x5; + HookAnyAddress(SaveQrcodeImageHookAddr, (LPVOID)dealQrcodeImage, SaveQrcodeImageOldAsmCode); + SaveQrcodeImageHooked = true; +} + +void UnHookQrcodeImage() +{ + if (!SaveQrcodeImageHooked) + return; + UnHookAnyAddress(SaveQrcodeImageHookAddr, SaveQrcodeImageOldAsmCode); + SaveQrcodeImageHooked = false; +} + +BOOL __stdcall SwitchToQrcodeLogin() +{ + qc->free(); + DWORD WeChatWinBase = GetWeChatWinBase(); + DWORD SwitchQrcodeLoginCall1 = WeChatWinBase + SwitchQrcodeLoginCall1Offset; + DWORD SwitchQrcodeLoginCall2 = WeChatWinBase + SwitchQrcodeLoginCall2Offset; + int isSuccess = 0; + __asm { + pushad; + pushfd; + call SwitchQrcodeLoginCall1; + mov ecx,eax; + call SwitchQrcodeLoginCall2; + movzx eax,al; + mov isSuccess,eax; + popfd; + popad; + } + return isSuccess == 1; +} + +#ifndef USE_SOCKET +DWORD GetQrcodeImageRemote() +{ + if (isWxLogin()) + return 0; + if (!SaveQrcodeImageHooked) + HookQrcodeImage(); + WxSignal sg(WM_WAIT_QRCODE); + SignalThreadId = sg.GetThreadId(); + SwitchToQrcodeLogin(); + sg.wait(5000); + return (DWORD)qc.get(); +} +#else +BYTE *__stdcall GetQrcodeImage(int &size) +{ + if (isWxLogin()) + return NULL; + if (!SaveQrcodeImageHooked) + HookQrcodeImage(); + WxSignal sg(WM_WAIT_QRCODE); + SignalThreadId = sg.GetThreadId(); + SwitchToQrcodeLogin(); + sg.wait(5000); + size = qc->size; + if (qc->size == 0) + return NULL; + return qc->image; +} +#endif diff --git a/DWeChatRobot/GetQrcodeImage.h b/DWeChatRobot/GetQrcodeImage.h new file mode 100644 index 0000000000000000000000000000000000000000..dcbab1180ba8d0215717b7924bce0314b44425e4 --- /dev/null +++ b/DWeChatRobot/GetQrcodeImage.h @@ -0,0 +1,11 @@ +#pragma once +#include +BOOL __stdcall SwitchToQrcodeLogin(); +void HookQrcodeImage(); +void UnHookQrcodeImage(); + +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) DWORD GetQrcodeImageRemote(); +#else +BYTE *__stdcall GetQrcodeImage(int &size); +#endif diff --git a/DWeChatRobot/ReceiveMessage.cpp b/DWeChatRobot/ReceiveMessage.cpp index 90cab62421c73e8d1ace04401335124c5ee34ca6..7e3cc81f4705f79c8cc59141030ef21fb352b0e3 100644 --- a/DWeChatRobot/ReceiveMessage.cpp +++ b/DWeChatRobot/ReceiveMessage.cpp @@ -13,9 +13,9 @@ using namespace std; #define CLTIP "127.0.0.1" // ϢHOOKַƫ -#define ReceiveMessageHookOffset 0x5D39C359 - 0x5D1F0000 +#define ReceiveMessageHookOffset 0x655F0F4C - 0x650A0000 // 0x5D39C359 - 0x5D1F0000 // ϢHOOKCALLƫ -#define ReceiveMessageNextCallOffset 0x5D5F7F00 - 0x5D1F0000 +#define ReceiveMessageNextCallOffset 0x65B36350 - 0x650A0000 // 0x5D5F7F00 - 0x5D1F0000 // ϢHOOKַƫ #define SendMessageHookOffset 0x78B88E42 - 0x786A0000 @@ -27,7 +27,7 @@ using namespace std; // ϢHOOKCALLƫ #define RevokeMessageNextCallOffset 0x5D6D3430 - 0x5D1F0000 -#define READ_WSTRING(addr, offset) wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)) +#define READ_WSTRING(addr, offset) ((*(DWORD *)(addr + offset + 0x4) == 0) ? wstring(L"") : wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4))) static int SRVPORT = 0; @@ -131,17 +131,24 @@ void SendSocketMessageInThread(SocketMessageStruct *param) if (param == NULL) return; unique_ptr 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) + if (jMsg.is_discarded() == true) { - DWORD type = jMsg["type"].get(); - ULONG64 msgid = (type != 10000) ? jMsg["msgid"].get() : 0; - PostComMessage(jMsg["pid"].get(), WX_MESSAGE, msgid, &vsaValue); + return; } + /*int dbIndex; + while (jMsg["localId"].get() == 0) + { + jMsg["localId"] = GetLocalIdByMsgId(jMsg["msgid"].get(),dbIndex); + Sleep(200); + }*/ + string jstr = jMsg.dump() + "\n"; +#ifdef USE_COM + // ͨӵ㣬Ϣ㲥ͻˣ㲥̷߳ɣͻ˲ſԵȴͼƬ + VARIANT vsaValue = (_variant_t)utf8_to_unicode(jstr.c_str()).c_str(); + DWORD type = jMsg["type"].get(); + ULONG64 msgid = (type != 10000) ? jMsg["msgid"].get() : 0; + PostComMessage(jMsg["pid"].get(), WX_MESSAGE, msgid, &vsaValue); #endif SendSocketMessage(jstr.c_str(), jstr.size()); } @@ -153,17 +160,23 @@ static void dealMessage(DWORD messageAddr) jMsg["pid"] = GetCurrentProcessId(); jMsg["type"] = *(DWORD *)(messageAddr + 0x38); jMsg["isSendMsg"] = *(BOOL *)(messageAddr + 0x3C); + if (jMsg["isSendMsg"].get()) + { + jMsg["isSendByPhone"] = (int)(*(BYTE *)(messageAddr + 0xD8)); + } jMsg["msgid"] = msgid; - jMsg["localId"] = *(unsigned int *)(messageAddr + 0x20); + // 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() : 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["sign"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x184).c_str()); if (jMsg["type"].get() != 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; + /*string extrabuf = base64_encode((BYTE *)(*(DWORD *)(messageAddr + 0x8C)), *(DWORD *)(messageAddr + 0x8C + 0x4)); + jMsg["extrainfo"] = extrabuf;*/ + jMsg["extrainfo"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1EC).c_str()); } else { @@ -190,14 +203,14 @@ static void dealMessage(DWORD messageAddr) * messageAddrϢĻַ * returnvoid */ -// 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ľʵ֣յϢô @@ -208,7 +221,7 @@ _declspec(naked) void dealReceiveMessage() pushad; pushfd; push edi; - call dealMessage; + call ReceiveMessage; add esp, 0x4; popfd; popad; diff --git a/DWeChatRobot/SelfInfo.cpp b/DWeChatRobot/SelfInfo.cpp index bb76211207fa429b10127de264886b3020546121..996ffdb10c9052750959b2bee23ddb6ccf263388 100644 --- a/DWeChatRobot/SelfInfo.cpp +++ b/DWeChatRobot/SelfInfo.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "json/json.hpp" -#include using namespace nlohmann; #define CheckLoginOffset 0x2366538 @@ -8,10 +7,10 @@ using namespace nlohmann; #define SelfWxidAddrOffset 0x236607C /* -* ⲿʱķ -* messageselfinfo.c_str() -* lengthselfinfoַ -*/ + * ⲿʱķ + * messageselfinfo.c_str() + * lengthselfinfoַ + */ #ifndef USE_SOCKET struct SelfInfoStruct { @@ -21,9 +20,9 @@ struct SelfInfoStruct #endif // !USE_SOCKET /* -* ⲿõĻȡϢӿ -* returnDWORDret׵ַ -*/ + * ⲿõĻȡϢӿ + * returnDWORDret׵ַ + */ #ifndef USE_SOCKET DWORD GetSelfInfoRemote() { @@ -39,35 +38,26 @@ DWORD GetSelfInfoRemote() wstring GetSelfWxid() { - DWORD baseAddr = GetWeChatWinBase() + SelfWxidAddrOffset; - char wxidbuffer[0x100] = {0}; - DWORD SelfWxIdAddr = 0x0; - sprintf_s(wxidbuffer, "%s", (char *)baseAddr); - if (strlen(wxidbuffer) < 0x6 || strlen(wxidbuffer) > 0x14) + DWORD addr = GetWeChatWinBase() + SelfWxidAddrOffset; + string wxid; + if (*(DWORD *)(addr + 0x14) == 0xF) { - SelfWxIdAddr = *(DWORD *)baseAddr; + wxid = string((char *)addr, *(int *)(addr + 0x10)); } else { - SelfWxIdAddr = baseAddr; + wxid = string((char *)(*(DWORD *)addr), *(int *)(addr + 0x10)); } - if (SelfWxIdAddr == 0) - { - return L""; - } - char *sselfwxid = (char *)SelfWxIdAddr; - wchar_t *wselfwxid = new wchar_t[strlen(sselfwxid) + 1]; - MultiByteToWideChar(CP_ACP, 0, sselfwxid, -1, wselfwxid, strlen(sselfwxid) + 1); - wstring wxid(wselfwxid); - delete[] wselfwxid; - return wxid; + return utf8_to_unicode(wxid.c_str()); } /* -* ȡϢ -*/ + * ȡϢ + */ wstring GetSelfInfo() { + if (!isWxLogin()) + return L"ȵ¼΢."; json jData; map self_info_addr; DWORD WeChatWinBase = GetWeChatWinBase(); @@ -75,70 +65,44 @@ wstring GetSelfInfo() self_info_addr["wxNumber"] = WeChatWinBase + 0x2366548; self_info_addr["wxNickName"] = WeChatWinBase + 0x23660F4; self_info_addr["Sex"] = WeChatWinBase + 0x23661F8; - self_info_addr["wxSignature"] = *(DWORD *)(WeChatWinBase + 0x236622C); - self_info_addr["wxBigAvatar"] = *(DWORD *)(WeChatWinBase + 0x23A111C); - self_info_addr["wxSmallAvatar"] = *(DWORD *)(WeChatWinBase + 0x23663D4); + self_info_addr["wxSignature"] = WeChatWinBase + 0x236622C; + self_info_addr["wxBigAvatar"] = WeChatWinBase + 0x23A111C; + self_info_addr["wxSmallAvatar"] = WeChatWinBase + 0x23663D4; self_info_addr["wxNation"] = WeChatWinBase + 0x23662E8; self_info_addr["wxProvince"] = WeChatWinBase + 0x23661FC; self_info_addr["wxCity"] = WeChatWinBase + 0x2366214; self_info_addr["PhoneNumber"] = WeChatWinBase + 0x2366128; + self_info_addr["wxFilePath"] = *(DWORD *)(WeChatWinBase + 0x2385020); for (auto it = self_info_addr.begin(); it != self_info_addr.end(); it++) { string key = it->first; DWORD addr = it->second; - string temp; - if (!key.compare("wxNickName")) + string utf8_str; + if (key == "Sex") { - if (*(DWORD *)(addr + 0x14) == 0xF) - { - temp = (*((DWORD *)addr) != 0) ? string((char *)addr) : gb2312_to_utf8("null"); - } - else - { - temp = (*((DWORD *)addr) != 0) ? string((char *)(*(DWORD *)addr)) : gb2312_to_utf8("null"); - } + int sex = *(int *)addr; + utf8_str = gb2312_to_utf8(((sex == 1) ? "" : ((sex == 2) ? "Ů" : "δ֪"))); } - else if (!key.compare("wxId")) + else if (key == "wxFilePath") { - char wxidbuffer[0x100] = {0}; - sprintf_s(wxidbuffer, "%s", (char *)addr); - if (strlen(wxidbuffer) < 0x6 || strlen(wxidbuffer) > 0x14) - { - //µ΢ź ΢IDõַ - temp = string((char *)(*(DWORD *)addr)); - } - else - { - temp = string((char *)addr); - } + utf8_str = unicode_to_utf8((wchar_t *)addr); } - else if (!key.compare("Sex")) + else { - int sex = *(int *)addr; - switch (sex) - { - case 1: + if (*(DWORD *)addr == 0) { - temp = gb2312_to_utf8(""); - break; + utf8_str = ""; } - case 2: + else if (*(DWORD *)(addr + 0x14) == 0xF) { - temp = gb2312_to_utf8("Ů"); - break; + utf8_str = string((char *)addr, *(int *)(addr + 0x10)); } - default: + else { - temp = gb2312_to_utf8("δ֪"); - break; - } + utf8_str = string((char *)(*(DWORD *)addr), *(int *)(addr + 0x10)); } } - else - { - temp = addr != 0 ? string((char *)addr) : gb2312_to_utf8("null"); - } - jData[key] = temp.c_str(); + jData[key] = utf8_str.c_str(); } wstring selfinfo = utf8_to_unicode(jData.dump().c_str()); return selfinfo; @@ -151,9 +115,9 @@ BOOL isWxLogin() } /* -* ɾϢ -* returnvoid -*/ + * ɾϢ + * returnvoid + */ #ifndef USE_SOCKET VOID DeleteSelfInfoCacheRemote() { diff --git a/DWeChatRobot/SendAtText.cpp b/DWeChatRobot/SendAtText.cpp index 59ea67482204fa0afe75a4998885b82cb609f193..f8e6a62dddfae3ce8bed4d810cebdb8441274fe0 100644 --- a/DWeChatRobot/SendAtText.cpp +++ b/DWeChatRobot/SendAtText.cpp @@ -81,7 +81,7 @@ BOOL __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsText nickname = L""; } else - nickname = GetUserNickNameByWxId((wchar_t *)wsWxId[i]); + nickname = GetChatRoomMemberNickname(wsChatRoomId, (wchar_t *)wsWxId[i]); if (nickname.length() == 0) continue; WxString temp = {0}; diff --git a/DWeChatRobot/http_overload.hpp b/DWeChatRobot/http_overload.hpp index d25ee8fd41c1dd21b6abc5318d68569a7592f178..b5fa75fedc8cab5fa7d1a33ab731f9a48c521476 100644 --- a/DWeChatRobot/http_overload.hpp +++ b/DWeChatRobot/http_overload.hpp @@ -134,8 +134,8 @@ BOOL __stdcall OpenBrowser(wstring url) return OpenBrowser(WS2LW(url)); } -BOOL __stdcall ForwardMessage(wstring wxid, int localId) +BOOL __stdcall ForwardMessage(wstring wxid, ULONG64 msgid) { - return ForwardMessage(WS2LW(wxid), localId); + return ForwardMessage(WS2LW(wxid), msgid); } #endif diff --git a/DWeChatRobot/pch.cpp b/DWeChatRobot/pch.cpp index 06bd4d8b27687b8f629178e307d1fd84105f24a4..9e8c520154b0fa02045cdfa4c086cfdc08036d76 100644 --- a/DWeChatRobot/pch.cpp +++ b/DWeChatRobot/pch.cpp @@ -188,6 +188,7 @@ void UnHookAll() UnHookVoiceMsg(); UnHookImageMsg(); UnHookH5ExtBuf(); + UnHookQrcodeImage(); return; } diff --git a/DWeChatRobot/pch.h b/DWeChatRobot/pch.h index 9a2529243d2230c3a0f8ed023740a378c2467a3a..4791562c97e7e004161cef5f48605e6d53e852c6 100644 --- a/DWeChatRobot/pch.h +++ b/DWeChatRobot/pch.h @@ -11,12 +11,15 @@ #include "framework.h" #include #include +#include #include #include +#include +#include #include "wxdata.h" #include "wxapi.h" #include "base64/base64.h" -#endif //PCH_H +#endif // PCH_H #ifdef USE_SOCKET #include "wxsocketapi.h" diff --git a/DWeChatRobot/wxapi.h b/DWeChatRobot/wxapi.h index 23918bb9b4cbdb95e9df1722ee5ab0c5b5b0a9e5..aea35744db4da098745bc22d7abbaf84e431a117 100644 --- a/DWeChatRobot/wxapi.h +++ b/DWeChatRobot/wxapi.h @@ -1,4 +1,5 @@ #pragma once +#include "wxsignal.h" #include "SendImage.h" #include "SendText.h" #include "SendFile.h" @@ -31,6 +32,7 @@ #include "OpenBrowser.h" #include "GetHistoryPublicMsg.h" #include "ForwardMessage.h" +#include "GetQrcodeImage.h" using namespace std; #pragma comment(lib, "version.lib") diff --git a/DWeChatRobot/wxdata.h b/DWeChatRobot/wxdata.h index 8cd02d951c5b89a16ff70538fd83a99ed5908808..e2645f59ca3a98f1e4cd9c204e77e2a50db34f9d 100644 --- a/DWeChatRobot/wxdata.h +++ b/DWeChatRobot/wxdata.h @@ -2,15 +2,18 @@ #include using namespace std; +// Hookݺ󣬸̷߳ź +#define WM_WAIT_QRCODE WM_USER + 0x1 + /* -* ΢еĻݽṹ -* bufferUNICODEַ -* length`buffer`ַ -* maxLength`buffer`ַ -* fill1ռλԱ1ĬΪ0 -* fill2ռλԱ2ĬΪ0 -* WxStringĬϹ캯 -*/ + * ΢еĻݽṹ + * bufferUNICODEַ + * length`buffer`ַ + * maxLength`buffer`ַ + * fill1ռλԱ1ĬΪ0 + * fill2ռλԱ2ĬΪ0 + * WxStringĬϹ캯 + */ struct WxString { wchar_t *buffer; @@ -47,13 +50,13 @@ struct WxString }; /* -* 浥ϢĽṹ -* messagetypeϢ -* senderwxid -* wxidsenderȺid˳Ա巢wxid`sender`һ -* messageϢݣıϢxmlʽ -* filepathͼƬļԴı· -*/ + * 浥ϢĽṹ + * messagetypeϢ + * senderwxid + * wxidsenderȺid˳Ա巢wxid`sender`һ + * messageϢݣıϢxmlʽ + * filepathͼƬļԴı· + */ struct ReceiveMsgStruct { DWORD pid = 0; @@ -110,12 +113,12 @@ struct UserInfo }; /* -* ݿⵥϢĽṹ -* namel_name`name`ַ -* tbl_namel_tbl_name`tbl_name`ַ -* sql䣻l_sql`sql`ַ -* rootpageţl_rootpage`rootpage`ַ -*/ + * ݿⵥϢĽṹ + * namel_name`name`ַ + * tbl_namel_tbl_name`tbl_name`ַ + * sql䣻l_sql`sql`ַ + * rootpageţl_rootpage`rootpage`ַ + */ struct TableInfoStruct { char *name; @@ -129,13 +132,13 @@ struct TableInfoStruct }; /* -* ݿϢĽṹ -* handleݿ -* dbnameݿ -* l_dbname`dbname`ַ -* tablesбϢ -* countб -*/ + * ݿϢĽṹ + * handleݿ + * dbnameݿ + * l_dbname`dbname`ַ + * tablesбϢ + * countб + */ struct DbInfoStruct { DWORD handle; @@ -146,13 +149,13 @@ struct DbInfoStruct }; /* -* 浥ϢĽṹ -* wxIdAddrwxidַ -* wxNumberAddr΢źűַ -* wxNickNameAddrdzƱַ -* wxRemarkAddrעַ -* WxFriendStructWĬϹ캯 -*/ + * 浥ϢĽṹ + * wxIdAddrwxidַ + * wxNumberAddr΢źűַ + * wxNickNameAddrdzƱַ + * wxRemarkAddrעַ + * WxFriendStructWĬϹ캯 + */ struct WxFriendStruct { DWORD wxIdAddr; diff --git a/DWeChatRobot/wxsignal.h b/DWeChatRobot/wxsignal.h new file mode 100644 index 0000000000000000000000000000000000000000..9b550b98898567651da0c72ec252d874d2482305 --- /dev/null +++ b/DWeChatRobot/wxsignal.h @@ -0,0 +1,51 @@ +#pragma once +#include + +#define SIGNAL(id, uMsg) PostThreadMessage(id, uMsg, 0, 0) + +class WxSignal +{ +public: + WxSignal(UINT uMsg) + { + this->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)this->Pump, (LPVOID)uMsg, 0, &this->threadId); + } + ~WxSignal() + { + if (this->hThread) + CloseHandle(this->hThread); + SIGNAL(this->threadId, WM_QUIT); + } + static void Pump(UINT uMsg) + { + MSG msg = {0}; + int ret; + while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) + { + if (msg.message == uMsg) + { + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + void wait(int timeout) + { + if (this->hThread) + { + WaitForSingleObject(this->hThread, timeout); + PostThreadMessage(this->threadId, WM_QUIT, 0, 0); + CloseHandle(this->hThread); + this->hThread = NULL; + } + } + DWORD GetThreadId() + { + return this->threadId; + } + +private: + HANDLE hThread; + DWORD threadId; +}; diff --git a/DWeChatRobot/wxsocket.cpp b/DWeChatRobot/wxsocket.cpp index 3de21060288a29e8c79be24742e716b49202e351..e3a271481cf22c127c4a07658913898b33cac866 100644 --- a/DWeChatRobot/wxsocket.cpp +++ b/DWeChatRobot/wxsocket.cpp @@ -108,6 +108,38 @@ static int get_http_param_int(mg_http_message *hm, json jData, string key, int m return result; } +static unsigned long long get_http_param_ulong64(mg_http_message *hm, json jData, string key, int method) +{ + unsigned long long result = 0; + switch (method) + { + case HTTP_METHOD_GET: + { + string value = getMgVarA(hm, key); + istringstream is(value); + is >> result; + break; + } + case HTTP_METHOD_POST: + { + try + { + result = jData[key].get(); + } + catch (json::exception) + { + string value = jData[key].get(); + istringstream is(value); + is >> result; + } + break; + } + default: + break; + } + return result; +} + static vector get_http_param_array(mg_http_message *hm, json jData, string key, int method) { vector result; @@ -129,12 +161,12 @@ static vector get_http_param_array(mg_http_message *hm, json jData, str return result; } -void request_event(mg_http_message *hm, string &ret) +void request_event(mg_http_message *hm, string &ret, struct mg_connection *c) { int method = I_METHOD(getMgStrA(hm->method)); // ĸΪfalse׳쳣 json jData = json::parse(hm->body.ptr, hm->body.ptr + hm->body.len, nullptr, false); - if (jData.is_discarded() == true && method == HTTP_METHOD_POST) + if (hm->body.len != 0 && jData.is_discarded() == true && method == HTTP_METHOD_POST) { json ret_data = {{"result", "ERROR"}, {"err_msg", "json string is invalid."}}; @@ -534,12 +566,36 @@ void request_event(mg_http_message *hm, string &ret) 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); + ULONG64 msgid = get_http_param_ulong64(hm, jData, "msgid", method); + BOOL status = ForwardMessage(wxid, msgid); json ret_data = {{"msg", status}, {"result", "OK"}}; ret = ret_data.dump(); break; } + case WECHAT_GET_QRCODE_IMAGE: + { + int size = 0; + BYTE *image = GetQrcodeImage(size); + // string b64data = base64_encode(image, size,false); + if (image != NULL) + { + mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-Type: image/png\r\n\r\n"); + mg_http_write_chunk(c, (const char *)image, size); + mg_http_printf_chunk(c, ""); + ret = ""; + } + else + { + string message; + if (isWxLogin()) + message = "ȡʧܣ΢ѵ¼."; + else + message = "ȡʧ."; + json ret_data = {{"msg", gb2312_to_utf8(message.c_str())}, {"result", "OK"}}; + ret = ret_data.dump(); + } + break; + } default: // char* wxid = mg_json_get_str(hm->body, "$.wxid"); break; @@ -573,20 +629,15 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { try { - request_event(hm, ret); + request_event(hm, ret, c); } catch (json::exception &e) { json res = {{"result", "ERROR"}, {"err_msg", e.what()}}; ret = res.dump(); } - mg_http_reply(c, 200, "", ret.c_str(), 0, 0); - } - else if (mg_http_match_uri(hm, "/api/f2/*")) - { - mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); - mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n"); - mg_http_printf_chunk(c, ""); + if (ret != "") + mg_http_reply(c, 200, "", ret.c_str(), 0, 0); } else { diff --git a/DWeChatRobot/wxsocketapi.h b/DWeChatRobot/wxsocketapi.h index a8737cb5d94dcb8876d2e7012fb42ea9bd2baa88..1c0acddc90e36ca947906bd83d7612c2bacea346 100644 --- a/DWeChatRobot/wxsocketapi.h +++ b/DWeChatRobot/wxsocketapi.h @@ -72,6 +72,7 @@ typedef enum WECHAT_HTTP_APISTag WECHAT_GET_PUBLIC_MSG, // IJ WECHAT_MSG_FORWARD_MESSAGE, + WECHAT_GET_QRCODE_IMAGE, } WECHAT_HTTP_APIS, *PWECHAT_HTTP_APIS; #endif diff --git a/Python/com/test.py b/Python/com/test.py index ef5ebc8a40f141e9029cbd313c5bcb9c680b89f7..f809ed1f99e7a6eb7bd5cf3414389fba071eeb69 100644 --- a/Python/com/test.py +++ b/Python/com/test.py @@ -88,6 +88,5 @@ 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() diff --git a/Python/com/wxRobot.py b/Python/com/wxRobot.py index 7b07430b73da2a3955aa596a283a906a02a45a78..186911621dfb2c80a6462f0ce370387402188433 100644 --- a/Python/com/wxRobot.py +++ b/Python/com/wxRobot.py @@ -9,7 +9,6 @@ Created on Thu Feb 24 16:19:48 2022 import os import ctypes import json -import base64 import ctypes.wintypes import socketserver import threading @@ -53,7 +52,6 @@ class WeChatEventSink: def OnGetMessageEvent(self, msg): msg = json.loads(msg) - msg['extrainfo'] = base64.b64decode(msg['extrainfo']) print(msg) @@ -84,7 +82,6 @@ class ReceiveMsgBaseServer(socketserver.BaseRequestHandler): @staticmethod def msg_callback(msg): - msg['extrainfo'] = base64.b64decode(msg['extrainfo']) # 主线程中已经注入,此处禁止调用StartService和StopService robot = comtypes.client.CreateObject("WeChatRobot.CWeChatRobot") event = comtypes.client.CreateObject("WeChatRobot.RobotEvent") @@ -1044,7 +1041,7 @@ class WeChatRobot: pass return ret - def ForwardMessage(self,wxid:str,localId:int) -> int: + def ForwardMessage(self,wxid:str,msgid:int) -> int: """ 转发消息,只支持单条转发 @@ -1052,8 +1049,8 @@ class WeChatRobot: ---------- wxid : str 消息接收人wxid. - localId : int - 消息短id,可以在实时消息接口中获取或查询MSG{x}.db. + msgid : int + 消息id,可以在实时消息接口中获取. Returns ------- @@ -1061,7 +1058,26 @@ class WeChatRobot: 成功返回0,失败返回非0值. """ - return self.robot.CForwardMessage(self.pid,wxid,localId) + return self.robot.CForwardMessage(self.pid,wxid,msgid) + + def GetQrcodeImage(self) -> bytes: + """ + 获取二维码,同时切换到扫码登录 + + Returns + ------- + bytes + 二维码bytes数据. + You can convert it to image object,like this: + >>> from io import BytesIO + >>> from PIL import Image + >>> buf = wx.GetQrcodeImage() + >>> image = Image.open(BytesIO(buf)).convert("L") + >>> image.save('./qrcode.png') + + """ + data = self.robot.CGetQrcodeImage(self.pid) + return bytes(data) def get_wechat_pid_list() -> list: diff --git a/Python/http/wxDriver.py b/Python/http/wxDriver.py index 4978dde1cf44c9e5b55960e32e10948dd4b79564..450a94731a09d638794ba71546c17196a5053f0f 100644 --- a/Python/http/wxDriver.py +++ b/Python/http/wxDriver.py @@ -3,7 +3,6 @@ import json import copy import threading import requests -import base64 import socketserver if ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulonglong): @@ -85,6 +84,7 @@ class WECHAT_HTTP_APIS: WECHAT_GET_PUBLIC_MSG = 39 # 获取公众号历史消息 WECHAT_MSG_FORWARD_MESSAGE = 40 # 转发消息 + WECHAT_GET_QRCODE_IMAGE = 41 # 获取二维码 APIS = WECHAT_HTTP_APIS @@ -188,7 +188,8 @@ class WECHAT_HTTP_API_PARAM_TEMPLATES: APIS.WECHAT_BROWSER_OPEN_WITH_URL: {"url": "https://www.baidu.com/"}, APIS.WECHAT_GET_PUBLIC_MSG: {"public_id": "","offset": ""}, - APIS.WECHAT_MSG_FORWARD_MESSAGE: {"wxid": "filehelper","localId": 1}, + APIS.WECHAT_MSG_FORWARD_MESSAGE: {"wxid": "filehelper","msgid": 2 ** 64 - 1}, + APIS.WECHAT_GET_QRCODE_IMAGE: {} } def get_http_template(self, api_number): @@ -224,11 +225,8 @@ class ReceiveMsgSocketServer(socketserver.BaseRequestHandler): @staticmethod def msg_callback(msg): - # 附加信息是protobuf格式,需要自行处理 - msg['extrainfo'] = base64.b64decode(msg['extrainfo']) - # TODO: 在这里写额外的消息处理逻辑 - print(msg) + # TODO: 在这里写额外的消息处理逻辑 def post_wechat_http_api(api,port,data = {}): url = "http://127.0.0.1:{}/api/?type={}".format(port,api) @@ -334,6 +332,7 @@ if __name__ == '__main__': pids.append(new_wechat()) start_listen(pids[0],port) post_wechat_http_api(APIS.WECHAT_LOG_START_HOOK,8000) + print(post_wechat_http_api(APIS.WECHAT_GET_SELF_INFO, 8000)) post_wechat_http_api(APIS.WECHAT_MSG_START_HOOK,8000,{"port":10808}) start_socket_server() stop_listen(pids[0]) diff --git a/README.md b/README.md index 719166942ba14809e17cd847930a115e1d0fe7c1..68edc155bf08790f0bc197c2337db821bdc56eaa 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,14 @@ CWeChatRobot.exe /unregserver 2. 新增转发消息功能,请勿转发语音、红包等消息 3. 实时消息接口新增`localId`字段,该字段用于转发消息接口;现在也可以接收到撤回消息提醒 4. 优化COM连接点,在线程中进行消息广播,客户端可以阻塞以等待图片、语音等资源落地 +## 2022.09.18 +1. 修复了一个bug,在多个MSG.db存在时,无法转发准确的消息;现在转发消息功能使用msgid作为参数 +2. 修复了一个bug,该bug曾导致微信没有选中的会话时,无法获取实时消息 +3. 修复了一个bug,该bug曾导致部分微信号获取个人信息时出现内存访问冲突 +4. 优化实时消息接口,不再返回localId字段;extrabuf现在返回原始信息而不是base64编码数据;新增一个字段,用于区分是否手机发送的消息(接收到的消息不含该字段) +5. 优化个人信息接口,现在可以返回个人文件夹路径 +6. 优化群艾特接口,优先填充群内昵称 +7. 新增获取二维码接口,调用该接口时会切换到二维码登录 # 打赏作者 请给作者一个star,感谢感谢 diff --git a/Release/CWeChatRobot.exe b/Release/CWeChatRobot.exe index aa51ae83208a1eaf3c1e5169e3afde22b83a14c5..0c2774db7bf4aca1232e0f42dc7da198c545092f 100644 Binary files a/Release/CWeChatRobot.exe and b/Release/CWeChatRobot.exe differ diff --git a/Release/DWeChatRobot.dll b/Release/DWeChatRobot.dll index 469af3ac4fd2dcab1e6bc72d561da66832c8b898..0abb27249051c1039bb01fee91a8061c9e2b7839 100644 Binary files a/Release/DWeChatRobot.dll and b/Release/DWeChatRobot.dll differ diff --git a/Release/socket/SWeChatRobot.dll b/Release/socket/SWeChatRobot.dll index 77a9934bb30fc498df82c91f53566481b8091100..39e3f1648774c1764c33f1d6105104c7255e9f8d 100644 Binary files a/Release/socket/SWeChatRobot.dll and b/Release/socket/SWeChatRobot.dll differ diff --git a/Release/socket/wxDriver.dll b/Release/socket/wxDriver.dll index e3e8fe698f4f8c815b7a1a9aba31b61009f8f1c0..777726c642b2c90643e512c5056881982117f2c8 100644 Binary files a/Release/socket/wxDriver.dll and b/Release/socket/wxDriver.dll differ diff --git a/Release/socket/wxDriver64.dll b/Release/socket/wxDriver64.dll index 2b2e923cacbddd4af519244921afa1157bfc7e1e..ddbda68c2046ffd0676041ac328f0faeec86d794 100644 Binary files a/Release/socket/wxDriver64.dll and b/Release/socket/wxDriver64.dll differ