feat(message): impl send text

This commit is contained in:
Changhua 2025-02-21 00:25:29 +08:00
parent 62d2703f56
commit b282c9f9f5
4 changed files with 39 additions and 30 deletions

View File

@ -3,19 +3,17 @@
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include "account_manager.h"
#include "database_executor.h" #include "database_executor.h"
#include "log.hpp" #include "log.hpp"
#include "offsets.h"
#include "rpc_helper.h" #include "rpc_helper.h"
#include "spy_types.h" #include "spy_types.h"
#include "account_manager.h"
#include "util.h" #include "util.h"
extern QWORD g_WeChatWinDllAddr; extern QWORD g_WeChatWinDllAddr;
#define OS_NEW 0x1B5E140 #define OS_NEW 0x1B5E140
#define OS_FREE 0x1B55850
#define OS_SEND_MSG_MGR 0x1B53FD0
#define OS_SEND_TEXT 0x22C6B60
#define OS_SEND_IMAGE 0x22BC2F0 #define OS_SEND_IMAGE 0x22BC2F0
#define OS_GET_APP_MSG_MGR 0x1B58F70 #define OS_GET_APP_MSG_MGR 0x1B58F70
#define OS_SEND_FILE 0x20D0230 #define OS_SEND_FILE 0x20D0230
@ -32,6 +30,8 @@ extern QWORD g_WeChatWinDllAddr;
namespace message namespace message
{ {
namespace OsSend = Offsets::Message::Send;
Sender &Sender::get_instance() Sender &Sender::get_instance()
{ {
static Sender instance; static Sender instance;
@ -41,9 +41,9 @@ Sender &Sender::get_instance()
Sender::Sender() Sender::Sender()
{ {
func_new = reinterpret_cast<New_t>(g_WeChatWinDllAddr + OS_NEW); func_new = reinterpret_cast<New_t>(g_WeChatWinDllAddr + OS_NEW);
func_free = reinterpret_cast<Free_t>(g_WeChatWinDllAddr + OS_FREE); func_free = reinterpret_cast<Free_t>(g_WeChatWinDllAddr + OsSend::FREE);
func_send_msg_mgr = reinterpret_cast<SendMsgMgr_t>(g_WeChatWinDllAddr + OS_SEND_MSG_MGR); func_send_msg_mgr = reinterpret_cast<SendMsgMgr_t>(g_WeChatWinDllAddr + OsSend::MGR);
func_send_text = reinterpret_cast<SendText_t>(g_WeChatWinDllAddr + OS_SEND_TEXT); func_send_text = reinterpret_cast<SendText_t>(g_WeChatWinDllAddr + OsSend::TEXT);
func_send_image = reinterpret_cast<SendImage_t>(g_WeChatWinDllAddr + OS_SEND_IMAGE); func_send_image = reinterpret_cast<SendImage_t>(g_WeChatWinDllAddr + OS_SEND_IMAGE);
func_send_file = reinterpret_cast<SendFile_t>(g_WeChatWinDllAddr + OS_SEND_FILE); func_send_file = reinterpret_cast<SendFile_t>(g_WeChatWinDllAddr + OS_SEND_FILE);
func_send_rich_text = reinterpret_cast<SendRichText_t>(g_WeChatWinDllAddr + OS_SEND_RICH_TEXT); func_send_rich_text = reinterpret_cast<SendRichText_t>(g_WeChatWinDllAddr + OS_SEND_RICH_TEXT);
@ -62,35 +62,42 @@ std::unique_ptr<WxString> Sender::new_wx_string(const std::string &str)
return std::make_unique<WxString>(util::s2w(str)); return std::make_unique<WxString>(util::s2w(str));
} }
std::vector<WxString> Sender::parse_wxids(const string &wxids) template <typename T> struct WxStringHolder {
std::wstring ws;
WxString wx;
explicit WxStringHolder(const T &str) : ws(util::s2w(str)), wx(ws) { }
};
template <typename StringT = std::wstring> struct AtWxidSplitResult {
std::vector<StringT> wxids;
std::vector<WxString> wxWxids;
};
AtWxidSplitResult<> parse_wxids(const std::string &atWxids)
{ {
vector<WxString> wx_members; AtWxidSplitResult<> result;
wstringstream wss(util::s2w(wxids)); if (!atWxids.empty()) {
wstring wstr; std::wstringstream wss(util::s2w(atWxids));
while (getline(wss, wstr, L',')) { for (std::wstring wxid; std::getline(wss, wxid, L',');) {
wx_members.emplace_back(wstr); result.wxids.push_back(wxid);
result.wxWxids.emplace_back(result.wxids.back());
} }
return wx_members; }
return result;
} }
void Sender::send_text(const std::string &wxid, const std::string &msg, const std::string &at_wxids) void Sender::send_text(const std::string &wxid, const std::string &msg, const std::string &at_wxids)
{ {
auto wxWxid = new_wx_string(wxid); WxStringHolder<std::string> holderMsg(msg);
auto wxMsg = new_wx_string(msg); WxStringHolder<std::string> holderWxid(wxid);
std::vector<WxString> wx_at_wxids; auto wxAtWxids = parse_wxids(at_wxids).wxWxids;
if (!at_wxids.empty()) { QWORD pWxAtWxids = wxAtWxids.empty() ? 0 : reinterpret_cast<QWORD>(&wxAtWxids);
wx_at_wxids = parse_wxids(at_wxids);
} else {
wx_at_wxids.emplace_back();
}
QWORD wx_ater_list = reinterpret_cast<QWORD>(&(wx_at_wxids.front())); char buffer[1104] = { 0 };
char buffer[0x460] = { 0 };
func_send_msg_mgr(); func_send_msg_mgr();
func_send_text(reinterpret_cast<QWORD>(&buffer), reinterpret_cast<QWORD>(wxWxid.get()), func_send_text(reinterpret_cast<QWORD>(&buffer), reinterpret_cast<QWORD>(&holderWxid.wx),
reinterpret_cast<QWORD>(wxMsg.get()), wx_ater_list, 1, 1, 0, 0); reinterpret_cast<QWORD>(&holderMsg.wx), pWxAtWxids, 1, 1, 0, 0);
func_free(reinterpret_cast<QWORD>(&buffer)); func_free(reinterpret_cast<QWORD>(&buffer));
} }

View File

@ -75,6 +75,5 @@ private:
std::unique_ptr<WxString> new_wx_string(const char *str); std::unique_ptr<WxString> new_wx_string(const char *str);
std::unique_ptr<WxString> new_wx_string(const std::string &str); std::unique_ptr<WxString> new_wx_string(const std::string &str);
std::vector<WxString> parse_wxids(const std::string &wxids);
}; };
} }

View File

@ -54,7 +54,8 @@ void RpcServer::destroyInstance()
} }
} }
RpcServer::RpcServer(int port) : port_(port), handler_(message::Handler::getInstance()) RpcServer::RpcServer(int port)
: port_(port), handler_(message::Handler::getInstance()), sender_(message::Sender::get_instance())
{ {
LOG_DEBUG("RpcServer 构造: 端口 {}", port_); LOG_DEBUG("RpcServer 构造: 端口 {}", port_);
} }
@ -247,7 +248,7 @@ const std::unordered_map<Functions, RpcServer::FunctionHandler> RpcServer::rpcFu
// { Functions_FUNC_GET_DB_NAMES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_names(out, len); } }, // { Functions_FUNC_GET_DB_NAMES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_names(out, len); } },
// { Functions_FUNC_GET_DB_TABLES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_tables(r.msg.str, out, len); } }, // { Functions_FUNC_GET_DB_TABLES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_tables(r.msg.str, out, len); } },
// { Functions_FUNC_GET_AUDIO_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_audio(r.msg.am, out, len); } }, // { Functions_FUNC_GET_AUDIO_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_audio(r.msg.am, out, len); } },
// { Functions_FUNC_SEND_TXT, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_text(r.msg.txt, out, len); } }, { Functions_FUNC_SEND_TXT, [](const Request &r, uint8_t *out, size_t *len) { return RpcServer::getInstance().sender_.rpc_send_text(r.msg.txt, out, len); } },
// { Functions_FUNC_SEND_IMG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_image(r.msg.file, out, len); } }, // { Functions_FUNC_SEND_IMG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_image(r.msg.file, out, len); } },
// { Functions_FUNC_SEND_FILE, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_file(r.msg.file, out, len); } }, // { Functions_FUNC_SEND_FILE, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_file(r.msg.file, out, len); } },
// { Functions_FUNC_SEND_XML, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_xml(r.msg.xml, out, len); } }, // { Functions_FUNC_SEND_XML, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_xml(r.msg.xml, out, len); } },

View File

@ -10,6 +10,7 @@
#include "wcf.pb.h" #include "wcf.pb.h"
#include "message_handler.h" #include "message_handler.h"
#include "message_sender.h"
class RpcServer class RpcServer
{ {
@ -46,6 +47,7 @@ private:
std::thread msgThread_; std::thread msgThread_;
message::Handler &handler_; message::Handler &handler_;
message::Sender &sender_;
struct Deleter { struct Deleter {
void operator()(RpcServer *server) const { delete server; } void operator()(RpcServer *server) const { delete server; }