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

Merge pull request #132 from ljc545w/fix_and_enhancement

优化与新增功能
......@@ -29,3 +29,15 @@ VARIANT GetQrcodeImage(DWORD pid)
V_ARRAY(&vsa) = psaValue;
return vsa;
}
BOOL isWxLogin(DWORD pid)
{
WeChatProcess hp(pid);
if (!hp.m_init)
return 1;
DWORD isWxLoginRemoteAddr = hp.GetProcAddr(isWxLoginRemote);
if (isWxLoginRemoteAddr == 0)
return 1;
DWORD ret = CallRemoteFunction(hp.GetHandle(), isWxLoginRemoteAddr, NULL);
return ret == 1;
}
#pragma once
#include <windows.h>
VARIANT GetQrcodeImage(DWORD pid);
BOOL isWxLogin(DWORD pid);
#include "pch.h"
BOOL Logout(DWORD pid)
{
WeChatProcess hp(pid);
if (!hp.m_init)
return 1;
DWORD WxLogoutRemoteAddr = hp.GetProcAddr(LogoutRemote);
if (WxLogoutRemoteAddr == 0)
return 1;
DWORD ret = CallRemoteFunction(hp.GetHandle(), WxLogoutRemoteAddr, NULL);
return ret != 1;
}
#pragma once
#include <windows.h>
BOOL Logout(DWORD pid);
#include "pch.h"
struct GetSelfInfoStruct {
struct GetSelfInfoStruct
{
DWORD message;
DWORD length;
};
std::wstring GetSelfInfo(DWORD pid) {
std::wstring GetSelfInfo(DWORD pid)
{
wstring SelfInfoString = L"";
DWORD dwReadSize = 0;
WeChatProcess hp(pid);
if (!hp.m_init) return L"{}";
if (!hp.m_init)
return L"{}";
DWORD GetSelfInfoRemoteAddr = hp.GetProcAddr(GetSelfInfoRemote);
DWORD DeleteSelfInfoCacheRemoteAddr = hp.GetProcAddr(DeleteSelfInfoCacheRemote);
if (GetSelfInfoRemoteAddr == 0)
......@@ -17,10 +20,11 @@ std::wstring GetSelfInfo(DWORD pid) {
DWORD ret = CallRemoteFunction(hp.GetHandle(), GetSelfInfoRemoteAddr, NULL);
if (ret == 0)
return L"{}";
GetSelfInfoStruct selfinfo = { 0 };
GetSelfInfoStruct selfinfo = {0};
ReadProcessMemory(hp.GetHandle(), (LPCVOID)ret, &selfinfo, sizeof(GetSelfInfoStruct), &dwReadSize);
if (selfinfo.length) {
wchar_t* wmessage = new wchar_t[selfinfo.length + 1];
if (selfinfo.length)
{
wchar_t *wmessage = new wchar_t[selfinfo.length + 1];
ZeroMemory(wmessage, (selfinfo.length + 1) * 2);
ReadProcessMemory(hp.GetHandle(), (LPCVOID)selfinfo.message, wmessage, selfinfo.length * 2, &dwReadSize);
SelfInfoString = (wstring)wmessage;
......@@ -30,13 +34,3 @@ std::wstring GetSelfInfo(DWORD pid) {
CallRemoteFunction(hp.GetHandle(), DeleteSelfInfoCacheRemoteAddr, NULL);
return SelfInfoString;
}
BOOL isWxLogin(DWORD pid) {
WeChatProcess hp(pid);
if (!hp.m_init) return 1;
DWORD isWxLoginRemoteAddr = hp.GetProcAddr(isWxLoginRemote);
if (isWxLoginRemoteAddr == 0)
return 1;
DWORD ret = CallRemoteFunction(hp.GetHandle(), isWxLoginRemoteAddr, NULL);
return ret == 1;
}
\ No newline at end of file
......@@ -3,4 +3,3 @@
#include <iostream>
using namespace std;
std::wstring GetSelfInfo(DWORD pid);
BOOL isWxLogin(DWORD pid);
\ No newline at end of file
#include "pch.h"
struct SendXmlMsgStruct
{
DWORD wxid;
DWORD xml;
DWORD imgpath;
};
BOOL SendXmlMsg(DWORD pid, wchar_t *wxid, wchar_t *xml, wchar_t *imgpath)
{
WeChatProcess hp(pid);
if (!hp.m_init)
return 1;
DWORD SendXmlMsgRemoteAddr = hp.GetProcAddr(SendXmlMsgRemote);
if (SendXmlMsgRemoteAddr == 0)
{
return 1;
}
SendXmlMsgStruct params = {0};
WeChatData<wchar_t *> r_wxid(hp.GetHandle(), wxid, TEXTLENGTH(wxid));
WeChatData<wchar_t *> r_xml(hp.GetHandle(), xml, TEXTLENGTH(xml));
WeChatData<wchar_t *> r_imgpath(hp.GetHandle(), imgpath, TEXTLENGTH(imgpath));
params.wxid = (DWORD)r_wxid.GetAddr();
params.xml = (DWORD)r_xml.GetAddr();
params.imgpath = (DWORD)r_imgpath.GetAddr();
WeChatData<SendXmlMsgStruct *> r_params(hp.GetHandle(), &params, sizeof(params));
if (!r_wxid.GetAddr() || !r_xml.GetAddr() || !r_params.GetAddr())
{
return 1;
}
DWORD dwRet = CallRemoteFunction(hp.GetHandle(), SendXmlMsgRemoteAddr, r_params.GetAddr());
return dwRet != 1;
}
#pragma once
#include <windows.h>
BOOL SendXmlMsg(DWORD pid, wchar_t *wxid, wchar_t *xml, wchar_t *imgpath);
......@@ -590,3 +590,26 @@ STDMETHODIMP CWeChatRobot::CGetA8Key(DWORD pid, BSTR url, BSTR *__result)
*__result = (_bstr_t)GetA8Key(pid, url).c_str();
return S_OK;
}
/*
* 参数0:目标进程pid
* 参数1:消息接收人wxid
* 参数2:xml内容
* 参数3:图片绝对路径
* 参数4:预返回的值,调用时无需提供
*/
STDMETHODIMP CWeChatRobot::CSendXmlMsg(DWORD pid, BSTR wxid, BSTR xml, BSTR imgpath, int *__result)
{
*__result = SendXmlMsg(pid, wxid, xml, imgpath);
return S_OK;
}
/*
* 参数0:目标进程pid
* 参数1:预返回的值,调用时无需提供
*/
STDMETHODIMP CWeChatRobot::CLogout(DWORD pid, int *__result)
{
*__result = Logout(pid);
return S_OK;
}
......@@ -88,6 +88,8 @@ public:
STDMETHODIMP CForwardMessage(DWORD pid, BSTR wxid, ULONG64 msgid, int *__result);
STDMETHODIMP CGetQrcodeImage(DWORD pid, VARIANT *__result);
STDMETHODIMP CGetA8Key(DWORD pid, BSTR url, BSTR *__result);
STDMETHODIMP CSendXmlMsg(DWORD pid, BSTR wxid, BSTR xml, BSTR imgpath, int *__result);
STDMETHODIMP CLogout(DWORD pid, int *__result);
};
OBJECT_ENTRY_AUTO(__uuidof(WeChatRobot), CWeChatRobot)
......@@ -62,7 +62,9 @@ interface IWeChatRobot : IDispatch
[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] unsigned long long localId, [out, retval] int * __result);
[id(49), helpstring("获取二维码")] HRESULT CGetQrcodeImage([in] DWORD pid, [out, retval] VARIANT * __result);
[id(50), helpstring("获取二维码")] HRESULT CGetA8Key([in] DWORD pid, [in] BSTR url, [ out, retval ] BSTR * __result);
[id(50), helpstring("获取A8Key")] HRESULT CGetA8Key([in] DWORD pid, [in] BSTR url, [ out, retval ] BSTR * __result);
[id(51), helpstring("发送xml消息")] HRESULT CSendXmlMsg([in] DWORD pid, [in] BSTR wxid, [in] BSTR xml, [in] BSTR imgpath,[out, retval] int *__result);
[id(52), helpstring("退出登录")] HRESULT CLogout([in] DWORD pid,[out, retval] int *__result);
};
[
object,
......
......@@ -238,6 +238,7 @@
<ClInclude Include="GetDbHandles.h" />
<ClInclude Include="GetHistoryPublicMsg.h" />
<ClInclude Include="InjectDll.h" />
<ClInclude Include="Logout.h" />
<ClInclude Include="ntapi.h" />
<ClInclude Include="OpenBrowser.h" />
<ClInclude Include="pch.h" />
......@@ -254,6 +255,7 @@
<ClInclude Include="SendFile.h" />
<ClInclude Include="SendImage.h" />
<ClInclude Include="SendText.h" />
<ClInclude Include="SendXmlMsg.h" />
<ClInclude Include="SetChatRoomAnnouncement.h" />
<ClInclude Include="SetChatRoomName.h" />
<ClInclude Include="SetChatRoomSelfNickname.h" />
......@@ -289,6 +291,7 @@
<ClCompile Include="HookImageMessage.cpp" />
<ClCompile Include="HookVoiceMessage.cpp" />
<ClCompile Include="InjectDll.cpp" />
<ClCompile Include="Logout.cpp" />
<ClCompile Include="ntapi.cpp" />
<ClCompile Include="OpenBrowser.cpp" />
<ClCompile Include="pch.cpp">
......@@ -310,6 +313,7 @@
<ClCompile Include="SendImage.cpp" />
<ClCompile Include="SendText.cpp" />
<ClCompile Include="SearchContactByCache.cpp" />
<ClCompile Include="SendXmlMsg.cpp" />
<ClCompile Include="SetChatRoomAnnouncement.cpp" />
<ClCompile Include="SetChatRoomName.cpp" />
<ClCompile Include="SetChatRoomSelfNickname.cpp" />
......
......@@ -128,12 +128,21 @@
<Filter Include="发送消息\转发消息">
<UniqueIdentifier>{f44839a7-3cf0-415f-886e-22a8635c3dbd}</UniqueIdentifier>
</Filter>
<Filter Include="二维码">
<UniqueIdentifier>{fb5a07d9-648d-4e1c-aed3-158f872c3d3e}</UniqueIdentifier>
</Filter>
<Filter Include="浏览器相关\获取A8Key">
<UniqueIdentifier>{caeac105-0e3b-497e-a73e-f1233b3888aa}</UniqueIdentifier>
</Filter>
<Filter Include="发送消息\发送xml">
<UniqueIdentifier>{92135af3-229e-47c3-883f-466aa593d43e}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关">
<UniqueIdentifier>{edd692fc-a34d-4c3d-b2a9-36dd48ec73b9}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关\获取二维码">
<UniqueIdentifier>{fb5a07d9-648d-4e1c-aed3-158f872c3d3e}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关\退出登录">
<UniqueIdentifier>{33279923-8158-4b6f-af06-e7f093852e5d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
......@@ -269,11 +278,17 @@
<Filter>发送消息\转发消息</Filter>
</ClInclude>
<ClInclude Include="GetQrcodeImage.h">
<Filter>二维码</Filter>
<Filter>登录相关\获取二维码</Filter>
</ClInclude>
<ClInclude Include="GetA8Key.h">
<Filter>浏览器相关\获取A8Key</Filter>
</ClInclude>
<ClInclude Include="SendXmlMsg.h">
<Filter>发送消息\发送xml</Filter>
</ClInclude>
<ClInclude Include="Logout.h">
<Filter>登录相关\退出登录</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WeChatRobotCOM.cpp">
......@@ -409,11 +424,17 @@
<Filter>发送消息\转发消息</Filter>
</ClCompile>
<ClCompile Include="GetQrcodeImage.cpp">
<Filter>二维码</Filter>
<Filter>登录相关\获取二维码</Filter>
</ClCompile>
<ClCompile Include="GetA8Key.cpp">
<Filter>浏览器相关\获取A8Key</Filter>
</ClCompile>
<ClCompile Include="SendXmlMsg.cpp">
<Filter>发送消息\发送xml</Filter>
</ClCompile>
<ClCompile Include="Logout.cpp">
<Filter>登录相关\退出登录</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WeChatRobotCOM.rc">
......
......@@ -360,6 +360,17 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [in] */ BSTR url,
/* [retval][out] */ BSTR *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CSendXmlMsg(
/* [in] */ DWORD pid,
/* [in] */ BSTR wxid,
/* [in] */ BSTR xml,
/* [in] */ BSTR imgpath,
/* [retval][out] */ int *__result) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CLogout(
/* [in] */ DWORD pid,
/* [retval][out] */ int *__result) = 0;
};
......@@ -711,6 +722,19 @@ EXTERN_C const IID IID_IWeChatRobot;
/* [in] */ BSTR url,
/* [retval][out] */ BSTR *__result);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CSendXmlMsg )(
IWeChatRobot * This,
/* [in] */ DWORD pid,
/* [in] */ BSTR wxid,
/* [in] */ BSTR xml,
/* [in] */ BSTR imgpath,
/* [retval][out] */ int *__result);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CLogout )(
IWeChatRobot * This,
/* [in] */ DWORD pid,
/* [retval][out] */ int *__result);
END_INTERFACE
} IWeChatRobotVtbl;
......@@ -888,6 +912,12 @@ EXTERN_C const IID IID_IWeChatRobot;
#define IWeChatRobot_CGetA8Key(This,pid,url,__result) \
( (This)->lpVtbl -> CGetA8Key(This,pid,url,__result) )
#define IWeChatRobot_CSendXmlMsg(This,pid,wxid,xml,imgpath,__result) \
( (This)->lpVtbl -> CSendXmlMsg(This,pid,wxid,xml,imgpath,__result) )
#define IWeChatRobot_CLogout(This,pid,__result) \
( (This)->lpVtbl -> CLogout(This,pid,__result) )
#endif /* COBJMACROS */
......
......@@ -49,7 +49,7 @@
#include "WeChatRobotCOM_i.h"
#define TYPE_FORMAT_STRING_SIZE 1239
#define PROC_FORMAT_STRING_SIZE 2431
#define PROC_FORMAT_STRING_SIZE 2533
#define EXPR_FORMAT_STRING_SIZE 1
#define TRANSMIT_AS_TABLE_SIZE 0
#define WIRE_MARSHAL_TABLE_SIZE 2
......@@ -2237,14 +2237,14 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
/* 2320 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CPostMessage */
/* Procedure CSendXmlMsg */
/* 2322 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2324 */ NdrFcLong( 0x0 ), /* 0 */
/* 2328 */ NdrFcShort( 0x7 ), /* 7 */
/* 2330 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */
/* 2332 */ NdrFcShort( 0x20 ), /* 32 */
/* 2328 */ NdrFcShort( 0x36 ), /* 54 */
/* 2330 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */
/* 2332 */ NdrFcShort( 0x8 ), /* 8 */
/* 2334 */ NdrFcShort( 0x24 ), /* 36 */
/* 2336 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */
0x6, /* 6 */
......@@ -2261,51 +2261,49 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
/* 2350 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgtype */
/* Parameter wxid */
/* 2352 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2352 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
/* 2354 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2356 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* 2356 */ NdrFcShort( 0x2a ), /* Type Offset=42 */
/* Parameter msgid */
/* Parameter xml */
/* 2358 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2358 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
/* 2360 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2362 */ 0xb, /* FC_HYPER */
0x0, /* 0 */
/* 2362 */ NdrFcShort( 0x2a ), /* Type Offset=42 */
/* Parameter msg */
/* Parameter imgpath */
/* 2364 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
/* 2366 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2368 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */
/* 2364 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */
/* 2366 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2368 */ NdrFcShort( 0x2a ), /* Type Offset=42 */
/* Parameter __result */
/* 2370 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2372 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2372 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2374 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2376 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2378 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */
/* 2378 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2380 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CRegisterWxPidWithCookie */
/* Procedure CLogout */
/* 2382 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2384 */ NdrFcLong( 0x0 ), /* 0 */
/* 2388 */ NdrFcShort( 0x8 ), /* 8 */
/* 2390 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2392 */ NdrFcShort( 0x10 ), /* 16 */
/* 2388 */ NdrFcShort( 0x37 ), /* 55 */
/* 2390 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2392 */ NdrFcShort( 0x8 ), /* 8 */
/* 2394 */ NdrFcShort( 0x24 ), /* 36 */
/* 2396 */ 0x44, /* Oi2 Flags: has return, has ext, */
0x4, /* 4 */
0x3, /* 3 */
/* 2398 */ 0x8, /* 8 */
0x41, /* Ext Flags: new corr desc, has range on conformance */
/* 2400 */ NdrFcShort( 0x0 ), /* 0 */
......@@ -2319,25 +2317,121 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
/* 2410 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter cookie */
/* Parameter __result */
/* 2412 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2412 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2414 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2416 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter __result */
/* Return value */
/* 2418 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2418 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2420 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2422 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CPostMessage */
/* 2424 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2426 */ NdrFcLong( 0x0 ), /* 0 */
/* 2430 */ NdrFcShort( 0x7 ), /* 7 */
/* 2432 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */
/* 2434 */ NdrFcShort( 0x20 ), /* 32 */
/* 2436 */ NdrFcShort( 0x24 ), /* 36 */
/* 2438 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */
0x6, /* 6 */
/* 2440 */ 0x8, /* 8 */
0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */
/* 2442 */ NdrFcShort( 0x0 ), /* 0 */
/* 2444 */ NdrFcShort( 0x1 ), /* 1 */
/* 2446 */ NdrFcShort( 0x0 ), /* 0 */
/* Parameter pid */
/* 2448 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2450 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
/* 2452 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgtype */
/* 2454 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2456 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2458 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter msgid */
/* 2460 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2462 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2464 */ 0xb, /* FC_HYPER */
0x0, /* 0 */
/* Parameter msg */
/* 2466 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
/* 2468 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2470 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */
/* Parameter __result */
/* 2472 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2474 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
/* 2476 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2478 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2480 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */
/* 2482 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure CRegisterWxPidWithCookie */
/* 2484 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2486 */ NdrFcLong( 0x0 ), /* 0 */
/* 2490 */ NdrFcShort( 0x8 ), /* 8 */
/* 2492 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
/* 2494 */ NdrFcShort( 0x10 ), /* 16 */
/* 2496 */ NdrFcShort( 0x24 ), /* 36 */
/* 2498 */ 0x44, /* Oi2 Flags: has return, has ext, */
0x4, /* 4 */
/* 2500 */ 0x8, /* 8 */
0x41, /* Ext Flags: new corr desc, has range on conformance */
/* 2502 */ NdrFcShort( 0x0 ), /* 0 */
/* 2504 */ NdrFcShort( 0x0 ), /* 0 */
/* 2506 */ NdrFcShort( 0x0 ), /* 0 */
/* Parameter pid */
/* 2508 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2510 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
/* 2512 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter cookie */
/* 2514 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
/* 2516 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 2518 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Parameter __result */
/* 2520 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2522 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
/* 2524 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 2424 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2426 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2428 */ 0x8, /* FC_LONG */
/* 2526 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 2528 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
/* 2530 */ 0x8, /* FC_LONG */
0x0, /* 0 */
0x0
......@@ -3231,7 +3325,9 @@ static const unsigned short IWeChatRobot_FormatStringOffsetTable[] =
2124,
2178,
2232,
2274
2274,
2322,
2382
};
static const MIDL_STUBLESS_PROXY_INFO IWeChatRobot_ProxyInfo =
......@@ -3255,7 +3351,7 @@ static const MIDL_SERVER_INFO IWeChatRobot_ServerInfo =
0,
0,
0};
CINTERFACE_PROXY_VTABLE(54) _IWeChatRobotProxyVtbl =
CINTERFACE_PROXY_VTABLE(56) _IWeChatRobotProxyVtbl =
{
&IWeChatRobot_ProxyInfo,
&IID_IWeChatRobot,
......@@ -3312,7 +3408,9 @@ CINTERFACE_PROXY_VTABLE(54) _IWeChatRobotProxyVtbl =
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CForwardMessage */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetQrcodeImage */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetA8Key */
(void *) (INT_PTR) -1 /* IWeChatRobot::CGetA8Key */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CSendXmlMsg */ ,
(void *) (INT_PTR) -1 /* IWeChatRobot::CLogout */
};
......@@ -3368,6 +3466,8 @@ static const PRPC_STUB_FUNCTION IWeChatRobot_table[] =
NdrStubCall2,
NdrStubCall2,
NdrStubCall2,
NdrStubCall2,
NdrStubCall2,
NdrStubCall2
};
......@@ -3375,7 +3475,7 @@ CInterfaceStubVtbl _IWeChatRobotStubVtbl =
{
&IID_IWeChatRobot,
&IWeChatRobot_ServerInfo,
54,
56,
&IWeChatRobot_table[-3],
CStdStubBuffer_DELEGATING_METHODS
};
......@@ -3391,8 +3491,8 @@ static const unsigned short IRobotEvent_FormatStringOffsetTable[] =
(unsigned short) -1,
(unsigned short) -1,
(unsigned short) -1,
2322,
2382
2424,
2484
};
static const MIDL_STUBLESS_PROXY_INFO IRobotEvent_ProxyInfo =
......
......@@ -32,6 +32,8 @@
#include "ForwardMessage.h"
#include "GetQrcodeImage.h"
#include "GetA8Key.h"
#include "SendXmlMsg.h"
#include "Logout.h"
#define DLLNAME L"DWeChatRobot.dll"
......@@ -93,3 +95,5 @@
#define GetHistoryPublicMsgRemote "GetHistoryPublicMsgRemote"
#define GetQrcodeImageRemote "GetQrcodeImageRemote"
#define GetA8KeyRemote "GetA8KeyRemote"
#define SendXmlMsgRemote "SendXmlMsgRemote"
#define LogoutRemote "Logout"
......@@ -333,6 +333,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClInclude Include="GetHistoryPublicMsg.h" />
<ClInclude Include="LogMsgInfo.h" />
<ClInclude Include="http_overload.hpp" />
<ClInclude Include="Logout.h" />
<ClInclude Include="OpenBrowser.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="GetQrcodeImage.h" />
......@@ -346,6 +347,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClInclude Include="SendImage.h" />
<ClInclude Include="SendText.h" />
<ClInclude Include="SearchContact.h" />
<ClInclude Include="SendXmlMsg.h" />
<ClInclude Include="SetChatRoomAnnouncement.h" />
<ClInclude Include="SetChatRoomName.h" />
<ClInclude Include="SetChatRoomSelfNickname.h" />
......@@ -380,6 +382,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClCompile Include="GetHistoryPublicMsg.cpp" />
<ClCompile Include="HookImageMessage.cpp" />
<ClCompile Include="HookVoiceMessage.cpp" />
<ClCompile Include="Logout.cpp" />
<ClCompile Include="OpenBrowser.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
......@@ -404,6 +407,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http
<ClCompile Include="SendText.cpp" />
<ClCompile Include="SearchContactByCache.cpp" />
<ClCompile Include="LogMsgInfo.cpp" />
<ClCompile Include="SendXmlMsg.cpp" />
<ClCompile Include="SetChatRoomAnnouncement.cpp" />
<ClCompile Include="SetChatRoomName.cpp" />
<ClCompile Include="SetChatRoomSelfNickname.cpp" />
......
......@@ -127,12 +127,21 @@
<Filter Include="发送消息\转发消息">
<UniqueIdentifier>{da7b0dbb-2d48-473f-9bb9-6d36ec5b02d3}</UniqueIdentifier>
</Filter>
<Filter Include="二维码">
<UniqueIdentifier>{a0a64bc2-f48e-41a0-838a-45b9985f8d68}</UniqueIdentifier>
</Filter>
<Filter Include="浏览器相关\获取A8Key">
<UniqueIdentifier>{10054e30-1115-49df-b387-07c207f6cac4}</UniqueIdentifier>
</Filter>
<Filter Include="发送消息\发送xml">
<UniqueIdentifier>{33945d7c-a756-4162-8f3a-bba729746df2}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关">
<UniqueIdentifier>{21c70796-80d4-410d-b077-31f75f24cf9f}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关\获取二维码">
<UniqueIdentifier>{a0a64bc2-f48e-41a0-838a-45b9985f8d68}</UniqueIdentifier>
</Filter>
<Filter Include="登录相关\退出登录">
<UniqueIdentifier>{e00caf3d-a0c2-4915-9ca5-47e429b4fcbf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
......@@ -253,7 +262,7 @@
<Filter>发送消息\转发消息</Filter>
</ClInclude>
<ClInclude Include="GetQrcodeImage.h">
<Filter>二维码</Filter>
<Filter>登录相关\获取二维码</Filter>
</ClInclude>
<ClInclude Include="wxsignal.h">
<Filter>通用标头</Filter>
......@@ -261,6 +270,12 @@
<ClInclude Include="GetA8Key.h">
<Filter>浏览器相关\获取A8Key</Filter>
</ClInclude>
<ClInclude Include="SendXmlMsg.h">
<Filter>发送消息\发送xml</Filter>
</ClInclude>
<ClInclude Include="Logout.h">
<Filter>登录相关\退出登录</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
......@@ -384,7 +399,7 @@
<Filter>发送消息\转发消息</Filter>
</ClCompile>
<ClCompile Include="GetQrcodeImage.cpp">
<Filter>二维码</Filter>
<Filter>登录相关\获取二维码</Filter>
</ClCompile>
<ClCompile Include="GetA8Key.cpp">
<Filter>浏览器相关\获取A8Key</Filter>
......@@ -392,5 +407,11 @@
<ClCompile Include="..\3rdparty\include\base64\base64.cpp">
<Filter>wxsocket</Filter>
</ClCompile>
<ClCompile Include="SendXmlMsg.cpp">
<Filter>发送消息\发送xml</Filter>
</ClCompile>
<ClCompile Include="Logout.cpp">
<Filter>登录相关\退出登录</Filter>
</ClCompile>
</ItemGroup>
</Project>
#include "pch.h"
#define CheckLoginOffset 0x2366538
#define SwitchQrcodeLoginCall1Offset 0x372AA0
#define SwitchQrcodeLoginCall2Offset 0x5177D0
......@@ -42,6 +44,12 @@ struct QrcodeStruct
static unique_ptr<QrcodeStruct> qc(new QrcodeStruct);
BOOL isWxLogin()
{
DWORD CheckLoginAddr = GetWeChatWinBase() + CheckLoginOffset;
return *(BOOL *)CheckLoginAddr;
}
void SaveQrcodeImage(unsigned char *src, int size)
{
qc->update(src, size);
......
......@@ -6,6 +6,8 @@ void UnHookQrcodeImage();
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) DWORD GetQrcodeImageRemote();
extern "C" __declspec(dllexport) BOOL isWxLogin();
#else
BYTE *__stdcall GetQrcodeImage(int &size);
BOOL isWxLogin();
#endif
#include "pch.h"
#define LogoutParam1Offset 0x7AE9C438 - 0x78F80000
#define LogoutParam2Offset 0x7AE9C428 - 0x78F80000
#define LogoutParam3Offset 0x7AE9C47C - 0x78F80000
BOOL Logout()
{
if (!isWxLogin())
return FALSE;
DWORD arr[955] = {0};
DWORD WeChatWin = GetWeChatWinBase();
arr[0] = WeChatWin + LogoutParam1Offset;
arr[1] = WeChatWin + LogoutParam2Offset;
arr[2] = WeChatWin + LogoutParam3Offset;
arr[3] = 0x3C0A16;
arr[4] = 0x1;
__asm {
pushad;
pushfd;
lea esi,arr;
mov eax,dword ptr [esi];
push 0x0;
push 0x0;
push 0x0;
push 0x2C6;
mov ecx,esi;
call dword ptr ds: [eax];
popfd;
popad;
}
return (isWxLogin() == 0);
}
#pragma once
#include <windows.h>
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) BOOL Logout();
#else
BOOL Logout();
#endif
......@@ -6,8 +6,6 @@
#include "json/json.hpp"
using namespace nlohmann;
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define CLTIP "127.0.0.1"
......@@ -177,6 +175,7 @@ static void dealMessage(DWORD messageAddr)
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["sign"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x184).c_str());
jMsg["thumb_path"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x198).c_str());
if (jMsg["type"].get<int>() != 10000)
{
jMsg["filepath"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1AC).c_str());
......
......@@ -2,7 +2,6 @@
#include "json/json.hpp"
using namespace nlohmann;
#define CheckLoginOffset 0x2366538
// 个人WXID偏移
#define SelfWxidAddrOffset 0x236607C
......@@ -114,12 +113,6 @@ wstring GetSelfInfo()
return selfinfo;
}
BOOL isWxLogin()
{
DWORD CheckLoginAddr = GetWeChatWinBase() + CheckLoginOffset;
return *(BOOL *)CheckLoginAddr;
}
/*
* 删除个人信息缓存
* return:void
......
#pragma once
#include<windows.h>
#include<iostream>
#include <windows.h>
#include <iostream>
using namespace std;
wstring GetSelfInfo();
wstring GetSelfWxid();
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) DWORD GetSelfInfoRemote();
extern "C" __declspec(dllexport) VOID DeleteSelfInfoCacheRemote();
extern "C" __declspec(dllexport) BOOL isWxLogin();
#else
BOOL isWxLogin();
#endif
......@@ -70,7 +70,7 @@ BOOL __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
{
WxString pReceiver(receiver);
WxString pFilePath(FilePath);
WxFileStruct esi_(FilePath);
// WxFileStruct esi_(FilePath);
WxString nullbuffer = {0};
DWORD WeChatWinBase = GetWeChatWinBase();
......@@ -83,7 +83,7 @@ BOOL __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
char buffer[0x3B0] = {0};
DWORD edi_ = pReceiver.length;
// DWORD edi_ = pReceiver.length;
DWORD ptrReceiver = (DWORD)pReceiver.buffer;
int isSuccess = 0;
__asm {
......@@ -118,11 +118,15 @@ BOOL __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
lea eax, buffer;
push eax;
call WxSendFileCall3;
mov al,byte ptr [eax + 0x38];
movzx eax,al;
mov isSuccess,eax;
push 200;
call Sleep;
lea ecx, buffer;
call DeleteSendFileCacheCall;
popfd;
popad;
}
return isSuccess == 1;
return (isSuccess == 0x31);
}
#include "pch.h"
// 发送文章CALL1偏移
#define SendXmlCall1Offset 0x78758A70 - 0x786A0000
// 发送文章CALL2偏移
#define SendXmlCall2Offset 0x78A8D5E0 - 0x786A0000
// 发送文章CALL3偏移
#define SendXmlCall3Offset 0x787A7F00 - 0x786A0000
// 发送文章CALL4偏移
#define SendXmlCall4Offset 0x78A8D7B0 - 0x786A0000
// 发送文章CALL参数偏移
#define SendXmlParamOffset 0x7AA26FE4 - 0x786A0000
// 清空缓存CALL1偏移
#define SendXmlClearCacheCall1Offset 0x78D46450 - 0x786A0000
// 清空缓存CALL2偏移
#define SendXmlClearCacheCall2Offset 0x78757780 - 0x786A0000
/*
* 供外部调用的发送文章消息接口
* lparameter:SendXmlStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
struct SendXmlStruct
{
DWORD wxid;
DWORD xml;
DWORD imgpath;
};
VOID SendXmlMsgRemote(LPVOID lparameter)
{
SendXmlStruct *sxs = (SendXmlStruct *)lparameter;
wchar_t *wxid = (wchar_t *)sxs->wxid;
wchar_t *xml = (wchar_t *)sxs->xml;
wchar_t *imgpath = (wchar_t *)sxs->imgpath;
SendXmlMsg(wxid, xml, imgpath);
}
#endif
BOOL __stdcall SendXmlMsg(wchar_t *wxid, wchar_t *xml, wchar_t *imgpath)
{
DWORD WeChatWinBase = GetWeChatWinBase();
DWORD SendXmlCall1 = WeChatWinBase + SendXmlCall1Offset;
DWORD SendXmlCall2 = WeChatWinBase + SendXmlCall2Offset;
DWORD SendXmlCall3 = WeChatWinBase + SendXmlCall3Offset;
DWORD SendXmlCall4 = WeChatWinBase + SendXmlCall4Offset;
DWORD SendXmlParam = WeChatWinBase + SendXmlParamOffset;
DWORD SendXmlClearCacheCall1 = WeChatWinBase + SendXmlClearCacheCall1Offset;
DWORD SendXmlClearCacheCall2 = WeChatWinBase + SendXmlClearCacheCall2Offset;
// 自己的wxid,发送者
wstring wselfwxid = GetSelfWxid();
DWORD sendtype = 0x5;
WxString pSender((wchar_t *)wselfwxid.c_str());
char nullbuffer[0x1C] = {0};
WxString pXml(xml);
WxString pReceiver(wxid);
WxString imgbuffer = {0};
if (imgpath && wcslen(imgpath) != 0)
{
imgbuffer.buffer = imgpath;
imgbuffer.length = wcslen(imgpath);
imgbuffer.maxLength = wcslen(imgpath) * 2;
}
WxString nullStruct = {0};
char buffer[0xFF0] = {0};
int isSuccess = 0x0;
__asm {
pushad;
pushfd;
lea ecx, buffer;
call SendXmlCall1;
mov eax, [sendtype];
push eax;
lea eax, nullbuffer;
lea edx, pSender;
push eax;
lea eax, imgbuffer;
push eax;
lea eax, pXml;
push eax;
lea edi, pReceiver;
push edi;
lea ecx, buffer;
call SendXmlCall2;
add esp, 0x14;
lea eax, nullStruct;
push eax;
lea ecx, buffer;
call SendXmlCall3;
mov dl, 0x0;
lea ecx, buffer;
push SendXmlParam;
push SendXmlParam;
call SendXmlCall4;
mov isSuccess, eax;
add esp, 0x8;
lea ecx, buffer;
call SendXmlClearCacheCall1;
lea ecx, buffer;
call SendXmlClearCacheCall2;
popfd;
popad;
}
return (isSuccess == 0x1);
}
#pragma once
#include <windows.h>
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) VOID SendXmlMsgRemote(LPVOID lparameter);
#endif
BOOL __stdcall SendXmlMsg(wchar_t *wxid, wchar_t *xml, wchar_t *imgpath);
......@@ -138,4 +138,9 @@ BOOL __stdcall ForwardMessage(wstring wxid, ULONG64 msgid)
{
return ForwardMessage(WS2LW(wxid), msgid);
}
BOOL __stdcall SendXmlMsg(wstring wxid, wstring xml, wstring imgpath)
{
return SendXmlMsg(WS2LW(wxid), WS2LW(xml), WS2LW(imgpath));
}
#endif
......@@ -233,15 +233,17 @@ wstring wreplace(wstring source, wchar_t replaced, wstring replaceto)
*/
wstring GetTimeW(long long timestamp)
{
char time_buf[20] = {0};
memset(time_buf, 0, 20);
tm tm_out = {0};
gmtime_s(&tm_out, &timestamp);
// localtime_s(tm_out, &timestamp);
tm_out.tm_hour += 8;
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &tm_out);
string strTime(time_buf);
return utf8_to_unicode(strTime.c_str());
wchar_t *wstr = new wchar_t[20];
memset(wstr, 0, 20 * 2);
// time_t cTime = time(NULL);
tm tm_out;
localtime_s(&tm_out, &timestamp);
swprintf_s(wstr, 20, L"%04d-%02d-%02d %02d:%02d:%02d",
1900 + tm_out.tm_year, tm_out.tm_mon + 1, tm_out.tm_mday,
tm_out.tm_hour, tm_out.tm_min, tm_out.tm_sec);
wstring strTimeW(wstr);
delete[] wstr;
return strTimeW;
}
void PrintProcAddr()
......
......@@ -22,9 +22,14 @@
#include "wxapi.h"
#include "base64/base64.h"
#include <glog/logging.h>
#pragma comment(lib, "glog.lib")
#endif // PCH_H
#ifndef _DEBUG
#pragma comment(lib, "glog.lib")
#else
#pragma comment(lib, "glogd.lib")
#endif
#ifdef USE_SOCKET
#include "wxsocketapi.h"
#else
......
......@@ -4,6 +4,7 @@
#include "SendText.h"
#include "SendFile.h"
#include "SendArticle.h"
#include "SendXmlMsg.h"
#include "FriendList.h"
#include "SearchContact.h"
#include "SelfInfo.h"
......@@ -34,9 +35,11 @@
#include "ForwardMessage.h"
#include "GetQrcodeImage.h"
#include "GetA8Key.h"
#include "Logout.h"
using namespace std;
#pragma comment(lib, "version.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable : 4731 26812)
// 对于导出函数,需要使用此宏修饰
#define DLLEXPORT extern "C" __declspec(dllexport)
......
......@@ -603,6 +603,23 @@ void request_event(mg_http_message *hm, string &ret, struct mg_connection *c)
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_XML:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring xml = get_http_param_str(hm, jData, "xml", method);
wstring img_path = get_http_param_str(hm, jData, "img_path", method);
BOOL response = SendXmlMsg(wxid, xml, img_path);
json ret_data = {{"msg", response}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_LOGOUT:
{
BOOL response = Logout();
json ret_data = {{"msg", response}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
default:
// char* wxid = mg_json_get_str(hm->body, "$.wxid");
break;
......
......@@ -74,6 +74,8 @@ typedef enum WECHAT_HTTP_APISTag
WECHAT_MSG_FORWARD_MESSAGE,
WECHAT_GET_QRCODE_IMAGE,
WECHAT_GET_A8KEY,
WECHAT_MSG_SEND_XML,
WECHAT_LOGOUT,
} WECHAT_HTTP_APIS,
*PWECHAT_HTTP_APIS;
#endif
......@@ -1101,6 +1101,39 @@ class WeChatRobot:
pass
return ret
def SendXmlMsg(self,wxid:str,xml:str,img_path:str="") -> int:
"""
发送原始xml消息
Parameters
----------
wxid : str
消息接收人.
xml : str
xml内容.
img_path : str, optional
图片路径. 默认为空.
Returns
-------
int
发送成功返回0,发送失败返回非0值.
"""
return self.robot.CSendXmlMsg(self.pid,wxid,xml,img_path)
def Logout(self) -> int:
"""
退出登录
Returns
-------
int
成功返回0,失败返回非0值.
"""
return self.robot.CLogout(self.pid)
def get_wechat_pid_list() -> list:
"""
......
......@@ -150,6 +150,11 @@ CWeChatRobot.exe /unregserver
2. 修复了一个bug,该bug曾导致获取数据库句柄接口只能生效一次
## 2022.09.27
1. 优化转发消息接口、获取数据库句柄接口,实时消息添加原始时间戳
## 2022.10.07
1. 新增发送原始xml接口
2. 新增退出登录接口
3. 尝试修复文件发送失败和格式化时间戳导致崩溃问题
4. 实时消息新增一个字段,用于获取视频消息缩略图保存位置
# 打赏作者
请给作者一个star,感谢感谢
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册