Refactor: replace C-style code with modern C++ idioms
This commit is contained in:
parent
65670b4ea7
commit
554d62efcf
@ -1,23 +1,15 @@
|
|||||||
#pragma execution_character_set("utf-8")
|
|
||||||
|
|
||||||
#include "MinHook.h"
|
|
||||||
#include "framework.h"
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "receive_msg.h"
|
#include "receive_msg.h"
|
||||||
#include "user_info.h"
|
#include "user_info.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
// Defined in rpc_server.cpp
|
|
||||||
extern bool gIsLogging, gIsListening, gIsListeningPyq;
|
|
||||||
extern mutex gMutex;
|
|
||||||
extern condition_variable gCV;
|
|
||||||
extern queue<WxMsg_t> gMsgQueue;
|
|
||||||
|
|
||||||
// Defined in spy.cpp
|
|
||||||
extern QWORD g_WeChatWinDllAddr;
|
extern QWORD g_WeChatWinDllAddr;
|
||||||
|
|
||||||
#define OS_RECV_MSG_ID 0x30
|
#define OS_RECV_MSG_ID 0x30
|
||||||
@ -41,22 +33,109 @@ extern QWORD g_WeChatWinDllAddr;
|
|||||||
#define OS_PYQ_MSG_CALL 0x2E42C90
|
#define OS_PYQ_MSG_CALL 0x2E42C90
|
||||||
#define OS_WXLOG 0x2613D20
|
#define OS_WXLOG 0x2613D20
|
||||||
|
|
||||||
typedef QWORD (*RecvMsg_t)(QWORD, QWORD);
|
QWORD MessageHandler::DispatchMsg(QWORD arg1, QWORD arg2)
|
||||||
typedef QWORD (*WxLog_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
|
||||||
typedef QWORD (*RecvPyq_t)(QWORD, QWORD, QWORD);
|
|
||||||
|
|
||||||
static RecvMsg_t funcRecvMsg = nullptr;
|
|
||||||
static RecvMsg_t realRecvMsg = nullptr;
|
|
||||||
static WxLog_t funcWxLog = nullptr;
|
|
||||||
static WxLog_t realWxLog = nullptr;
|
|
||||||
static RecvPyq_t funcRecvPyq = nullptr;
|
|
||||||
static RecvPyq_t realRecvPyq = nullptr;
|
|
||||||
static bool isMH_Initialized = false;
|
|
||||||
|
|
||||||
MsgTypes_t GetMsgTypes()
|
|
||||||
{
|
{
|
||||||
const MsgTypes_t m = {
|
auto &handler = getInstance();
|
||||||
{ 0x00, "朋友圈消息" },
|
WxMsg_t wxMsg = {};
|
||||||
|
try {
|
||||||
|
wxMsg.id = GET_QWORD(arg2 + OS_RECV_MSG_ID);
|
||||||
|
wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE);
|
||||||
|
wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF);
|
||||||
|
wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS);
|
||||||
|
wxMsg.content = GetStringByWstrAddr(arg2 + OS_RECV_MSG_CONTENT);
|
||||||
|
wxMsg.sign = GetStringByWstrAddr(arg2 + OS_RECV_MSG_SIGN);
|
||||||
|
wxMsg.xml = GetStringByWstrAddr(arg2 + OS_RECV_MSG_XML);
|
||||||
|
wxMsg.roomid = GetStringByWstrAddr(arg2 + OS_RECV_MSG_ROOMID);
|
||||||
|
|
||||||
|
if (wxMsg.roomid.find("@chatroom") != std::string::npos) {
|
||||||
|
wxMsg.is_group = true;
|
||||||
|
wxMsg.sender = wxMsg.is_self ? GetSelfWxid() : GetStringByWstrAddr(arg2 + OS_RECV_MSG_WXID);
|
||||||
|
} else {
|
||||||
|
wxMsg.is_group = false;
|
||||||
|
wxMsg.sender = wxMsg.is_self ? GetSelfWxid() : wxMsg.roomid;
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LOG_ERROR(GB2312ToUtf8(e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(handler.mutex_);
|
||||||
|
handler.msgQueue_.push(wxMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.cv_.notify_all();
|
||||||
|
return handler.realRecvMsg(arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWORD MessageHandler::PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a5, QWORD a6, QWORD a7, QWORD a8,
|
||||||
|
QWORD a9, QWORD a10, QWORD a11, QWORD a12)
|
||||||
|
{
|
||||||
|
auto &handler = getInstance();
|
||||||
|
|
||||||
|
QWORD p = handler.realWxLog(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
|
||||||
|
if (p == 0 || p == 1) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("【WX】\n{}", GB2312ToUtf8((char *)p));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageHandler::DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3)
|
||||||
|
{
|
||||||
|
auto &handler = getInstance();
|
||||||
|
QWORD startAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_START);
|
||||||
|
QWORD endAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_END);
|
||||||
|
|
||||||
|
if (startAddr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (startAddr < endAddr) {
|
||||||
|
WxMsg_t wxMsg;
|
||||||
|
|
||||||
|
wxMsg.type = 0x00;
|
||||||
|
wxMsg.is_self = false;
|
||||||
|
wxMsg.is_group = false;
|
||||||
|
wxMsg.id = GET_QWORD(startAddr);
|
||||||
|
wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS);
|
||||||
|
wxMsg.xml = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_XML);
|
||||||
|
wxMsg.sender = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_SENDER);
|
||||||
|
wxMsg.content = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_CONTENT);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(handler.mutex_);
|
||||||
|
handler.msgQueue_.push(wxMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.cv_.notify_all();
|
||||||
|
startAddr += 0x1618;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHandler &MessageHandler::getInstance()
|
||||||
|
{
|
||||||
|
static MessageHandler instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHandler::MessageHandler()
|
||||||
|
{
|
||||||
|
isLogging = false;
|
||||||
|
isListeningMsg = false;
|
||||||
|
isListeningPyq = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHandler::~MessageHandler()
|
||||||
|
{
|
||||||
|
DisableLog();
|
||||||
|
UnListenMsg();
|
||||||
|
UnListenPyq();
|
||||||
|
}
|
||||||
|
|
||||||
|
MsgTypes_t MessageHandler::GetMsgTypes()
|
||||||
|
{
|
||||||
|
return { { 0x00, "朋友圈消息" },
|
||||||
{ 0x01, "文字" },
|
{ 0x01, "文字" },
|
||||||
{ 0x03, "图片" },
|
{ 0x03, "图片" },
|
||||||
{ 0x22, "语音" },
|
{ 0x22, "语音" },
|
||||||
@ -88,291 +167,99 @@ MsgTypes_t GetMsgTypes()
|
|||||||
{ 0x3A100031, "商品链接" },
|
{ 0x3A100031, "商品链接" },
|
||||||
{ 0x3A200031, "视频号直播" },
|
{ 0x3A200031, "视频号直播" },
|
||||||
{ 0x3E000031, "音乐链接" },
|
{ 0x3E000031, "音乐链接" },
|
||||||
{ 0x41000031, "文件" },
|
{ 0x41000031, "文件" } };
|
||||||
};
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QWORD DispatchMsg(QWORD arg1, QWORD arg2)
|
std::optional<WxMsg_t> MessageHandler::popMessage()
|
||||||
{
|
{
|
||||||
WxMsg_t wxMsg = { 0 };
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
try {
|
if (msgQueue_.empty()) {
|
||||||
wxMsg.id = GET_QWORD(arg2 + OS_RECV_MSG_ID);
|
return std::nullopt;
|
||||||
wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE);
|
|
||||||
wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF);
|
|
||||||
wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS);
|
|
||||||
wxMsg.content = GetStringByWstrAddr(arg2 + OS_RECV_MSG_CONTENT);
|
|
||||||
wxMsg.sign = GetStringByWstrAddr(arg2 + OS_RECV_MSG_SIGN);
|
|
||||||
wxMsg.xml = GetStringByWstrAddr(arg2 + OS_RECV_MSG_XML);
|
|
||||||
|
|
||||||
string roomid = GetStringByWstrAddr(arg2 + OS_RECV_MSG_ROOMID);
|
|
||||||
wxMsg.roomid = roomid;
|
|
||||||
if (roomid.find("@chatroom") != string::npos) { // 群 ID 的格式为 xxxxxxxxxxx@chatroom
|
|
||||||
wxMsg.is_group = true;
|
|
||||||
if (wxMsg.is_self) {
|
|
||||||
wxMsg.sender = GetSelfWxid();
|
|
||||||
} else {
|
|
||||||
wxMsg.sender = GetStringByWstrAddr(arg2 + OS_RECV_MSG_WXID);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wxMsg.is_group = false;
|
|
||||||
if (wxMsg.is_self) {
|
|
||||||
wxMsg.sender = GetSelfWxid();
|
|
||||||
} else {
|
|
||||||
wxMsg.sender = roomid;
|
|
||||||
}
|
}
|
||||||
|
WxMsg_t msg = std::move(msgQueue_.front());
|
||||||
|
msgQueue_.pop();
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMsg.thumb = GetStringByWstrAddr(arg2 + OS_RECV_MSG_THUMB);
|
int MessageHandler::EnableLog()
|
||||||
if (!wxMsg.thumb.empty()) {
|
|
||||||
wxMsg.thumb = GetHomePath() + wxMsg.thumb;
|
|
||||||
replace(wxMsg.thumb.begin(), wxMsg.thumb.end(), '\\', '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
wxMsg.extra = GetStringByWstrAddr(arg2 + OS_RECV_MSG_EXTRA);
|
|
||||||
if (!wxMsg.extra.empty()) {
|
|
||||||
wxMsg.extra = GetHomePath() + wxMsg.extra;
|
|
||||||
replace(wxMsg.extra.begin(), wxMsg.extra.end(), '\\', '/');
|
|
||||||
}
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LOG_ERROR(GB2312ToUtf8(e.what()));
|
|
||||||
} catch (...) {
|
|
||||||
LOG_ERROR("Unknow exception.");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lock(gMutex);
|
if (isLogging) return 1;
|
||||||
gMsgQueue.push(wxMsg); // 推送到队列
|
|
||||||
|
funcWxLog = reinterpret_cast<funcWxLog_t>(g_WeChatWinDllAddr + OS_WXLOG);
|
||||||
|
|
||||||
|
if (InitializeHook() != MH_OK) return -1;
|
||||||
|
if (MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast<LPVOID *>(&realWxLog)) != MH_OK) return -1;
|
||||||
|
if (MH_EnableHook(funcWxLog) != MH_OK) return -1;
|
||||||
|
|
||||||
|
isLogging = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gCV.notify_all(); // 通知各方消息就绪
|
int MessageHandler::DisableLog()
|
||||||
return realRecvMsg(arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QWORD PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a5, QWORD a6, QWORD a7, QWORD a8, QWORD a9,
|
|
||||||
QWORD a10, QWORD a11, QWORD a12)
|
|
||||||
{
|
{
|
||||||
QWORD p = realWxLog(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
|
if (!isLogging) return 1;
|
||||||
if (p == 0 || p == 1) {
|
if (MH_DisableHook(funcWxLog) != MH_OK) return -1;
|
||||||
return p;
|
if (UninitializeHook() != MH_OK) return -1;
|
||||||
|
isLogging = false;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("【WX】\n{}", GB2312ToUtf8((char *)p));
|
int MessageHandler::ListenMsg()
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3)
|
|
||||||
{
|
{
|
||||||
QWORD startAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_START);
|
if (isListeningMsg) return 1;
|
||||||
QWORD endAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_END);
|
|
||||||
|
|
||||||
if (startAddr == 0) {
|
funcRecvMsg = reinterpret_cast<funcRecvMsg_t>(g_WeChatWinDllAddr + OS_RECV_MSG_CALL);
|
||||||
return;
|
if (InitializeHook() != MH_OK) return -1;
|
||||||
|
if (MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast<LPVOID *>(&realRecvMsg)) != MH_OK) return -1;
|
||||||
|
if (MH_EnableHook(funcRecvMsg) != MH_OK) return -1;
|
||||||
|
|
||||||
|
isListeningMsg = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (startAddr < endAddr) {
|
int MessageHandler::UnListenMsg()
|
||||||
WxMsg_t wxMsg;
|
|
||||||
|
|
||||||
wxMsg.type = 0x00; // 朋友圈消息
|
|
||||||
wxMsg.is_self = false;
|
|
||||||
wxMsg.is_group = false;
|
|
||||||
wxMsg.id = GET_QWORD(startAddr);
|
|
||||||
wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS);
|
|
||||||
wxMsg.xml = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_XML);
|
|
||||||
wxMsg.sender = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_SENDER);
|
|
||||||
wxMsg.content = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_CONTENT);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lock(gMutex);
|
if (!isListeningMsg) return 1;
|
||||||
gMsgQueue.push(wxMsg); // 推送到队列
|
if (MH_DisableHook(funcRecvMsg) != MH_OK) return -1;
|
||||||
|
if (UninitializeHook() != MH_OK) return -1;
|
||||||
|
isListeningMsg = false;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gCV.notify_all(); // 通知各方消息就绪
|
int MessageHandler::ListenPyq()
|
||||||
|
|
||||||
startAddr += 0x1618;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static MH_STATUS InitializeHook()
|
|
||||||
{
|
{
|
||||||
if (isMH_Initialized) {
|
if (isListeningPyq) return 1;
|
||||||
return MH_OK;
|
|
||||||
|
funcRecvPyq = reinterpret_cast<funcRecvPyq_t>(g_WeChatWinDllAddr + OS_PYQ_MSG_CALL);
|
||||||
|
if (InitializeHook() != MH_OK) return -1;
|
||||||
|
if (MH_CreateHook(funcRecvPyq, &DispatchPyq, reinterpret_cast<LPVOID *>(&realRecvPyq)) != MH_OK) return -1;
|
||||||
|
if (MH_EnableHook(funcRecvPyq) != MH_OK) return -1;
|
||||||
|
|
||||||
|
isListeningPyq = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MessageHandler::UnListenPyq()
|
||||||
|
{
|
||||||
|
if (!isListeningPyq) return 1;
|
||||||
|
if (MH_DisableHook(funcRecvPyq) != MH_OK) return -1;
|
||||||
|
if (UninitializeHook() != MH_OK) return -1;
|
||||||
|
isListeningPyq = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MH_STATUS MessageHandler::InitializeHook()
|
||||||
|
{
|
||||||
|
if (isMH_Initialized) return MH_OK;
|
||||||
MH_STATUS status = MH_Initialize();
|
MH_STATUS status = MH_Initialize();
|
||||||
if (status == MH_OK) {
|
if (status == MH_OK) isMH_Initialized = true;
|
||||||
isMH_Initialized = true;
|
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MH_STATUS UninitializeHook()
|
MH_STATUS MessageHandler::UninitializeHook()
|
||||||
{
|
{
|
||||||
if (!isMH_Initialized) {
|
if (!isMH_Initialized || isLogging || isListeningMsg || isListeningPyq) return MH_OK;
|
||||||
return MH_OK;
|
|
||||||
}
|
|
||||||
if (gIsLogging || gIsListening || gIsListeningPyq) {
|
|
||||||
return MH_OK;
|
|
||||||
}
|
|
||||||
MH_STATUS status = MH_Uninitialize();
|
MH_STATUS status = MH_Uninitialize();
|
||||||
if (status == MH_OK) {
|
if (status == MH_OK) isMH_Initialized = false;
|
||||||
isMH_Initialized = false;
|
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnableLog()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (gIsLogging) {
|
|
||||||
LOG_WARN("gIsLogging");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WxLog_t funcWxLog = (WxLog_t)(g_WeChatWinDllAddr + OS_WXLOG);
|
|
||||||
|
|
||||||
status = InitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast<LPVOID *>(&realWxLog));
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_CreateHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_EnableHook(funcWxLog);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_EnableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gIsLogging = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisableLog()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (!gIsLogging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_DisableHook(funcWxLog);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_DisableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gIsLogging = false;
|
|
||||||
|
|
||||||
status = UninitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListenMessage()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (gIsListening) {
|
|
||||||
LOG_WARN("gIsListening");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
funcRecvMsg = (RecvMsg_t)(g_WeChatWinDllAddr + OS_RECV_MSG_CALL);
|
|
||||||
|
|
||||||
status = InitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast<LPVOID *>(&realRecvMsg));
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_CreateHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_EnableHook(funcRecvMsg);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_EnableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gIsListening = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnListenMessage()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (!gIsListening) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_DisableHook(funcRecvMsg);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_DisableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gIsListening = false;
|
|
||||||
|
|
||||||
status = UninitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListenPyq()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (gIsListeningPyq) {
|
|
||||||
LOG_WARN("gIsListeningPyq");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
funcRecvPyq = (RecvPyq_t)(g_WeChatWinDllAddr + OS_PYQ_MSG_CALL);
|
|
||||||
|
|
||||||
status = InitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_CreateHook(funcRecvPyq, &DispatchPyq, reinterpret_cast<LPVOID *>(&realRecvPyq));
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_CreateHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_EnableHook(funcRecvPyq);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_EnableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gIsListeningPyq = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnListenPyq()
|
|
||||||
{
|
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
|
||||||
if (!gIsListeningPyq) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = MH_DisableHook(funcRecvPyq);
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_DisableHook failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gIsListeningPyq = false;
|
|
||||||
|
|
||||||
status = UninitializeHook();
|
|
||||||
if (status != MH_OK) {
|
|
||||||
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,66 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <queue>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "MinHook.h"
|
||||||
|
|
||||||
#include "pb_types.h"
|
#include "pb_types.h"
|
||||||
|
|
||||||
void EnableLog();
|
class MessageHandler
|
||||||
void DisableLog();
|
{
|
||||||
void ListenPyq();
|
public:
|
||||||
void UnListenPyq();
|
static MessageHandler &getInstance();
|
||||||
void ListenMessage();
|
|
||||||
void UnListenMessage();
|
// 0: 成功, -1: 失败, 1: 已经开启
|
||||||
|
int EnableLog();
|
||||||
|
int DisableLog();
|
||||||
|
int ListenPyq();
|
||||||
|
int UnListenPyq();
|
||||||
|
int ListenMsg();
|
||||||
|
int UnListenMsg();
|
||||||
|
|
||||||
MsgTypes_t GetMsgTypes();
|
MsgTypes_t GetMsgTypes();
|
||||||
|
|
||||||
|
bool isLoggingEnabled() const { return isLogging.load(); }
|
||||||
|
bool isMessageListening() const { return isListeningMsg.load(); }
|
||||||
|
bool isPyqListening() const { return isListeningPyq.load(); }
|
||||||
|
|
||||||
|
std::optional<WxMsg_t> popMessage();
|
||||||
|
std::condition_variable &getConditionVariable() { return cv_; };
|
||||||
|
std::mutex &getMutex() { return mutex_; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
MessageHandler();
|
||||||
|
~MessageHandler();
|
||||||
|
|
||||||
|
mutable std::mutex mutex_;
|
||||||
|
std::condition_variable cv_;
|
||||||
|
std::queue<WxMsg_t> msgQueue_;
|
||||||
|
|
||||||
|
std::atomic<bool> isLogging { false };
|
||||||
|
std::atomic<bool> isListeningMsg { false };
|
||||||
|
std::atomic<bool> isListeningPyq { false };
|
||||||
|
|
||||||
|
using funcRecvMsg_t = QWORD (*)(QWORD, QWORD);
|
||||||
|
using funcWxLog_t = QWORD (*)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
||||||
|
using funcRecvPyq_t = QWORD (*)(QWORD, QWORD, QWORD);
|
||||||
|
|
||||||
|
funcWxLog_t funcWxLog, realWxLog;
|
||||||
|
funcRecvMsg_t funcRecvMsg, realRecvMsg;
|
||||||
|
funcRecvPyq_t funcRecvPyq, realRecvPyq;
|
||||||
|
|
||||||
|
bool isMH_Initialized { false };
|
||||||
|
|
||||||
|
MH_STATUS InitializeHook();
|
||||||
|
MH_STATUS UninitializeHook();
|
||||||
|
|
||||||
|
static QWORD DispatchMsg(QWORD arg1, QWORD arg2);
|
||||||
|
static QWORD PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a5, QWORD a6, QWORD a7, QWORD a8, QWORD a9,
|
||||||
|
QWORD a10, QWORD a11, QWORD a12);
|
||||||
|
static void DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3);
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user