mirror of
https://github.com/ttttupup/wxhelper.git
synced 2024-11-26 12:19:23 +08:00
feat: 消息同步
This commit is contained in:
parent
2767576351
commit
8ab646be96
@ -56,6 +56,8 @@ bool CreateConsole();
|
|||||||
void CloseConsole();
|
void CloseConsole();
|
||||||
|
|
||||||
void HideModule(HMODULE module);
|
void HideModule(HMODULE module);
|
||||||
|
|
||||||
|
bool IsDigit(const std::string &str);
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
} // namespace base
|
} // namespace base
|
||||||
#endif
|
#endif
|
@ -1,7 +1,10 @@
|
|||||||
#include "include/utils.h"
|
#include "include/utils.h"
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
namespace base {
|
namespace base {
|
||||||
namespace utils {
|
namespace utils {
|
||||||
const std::string hex_table = "0123456789abcdef";
|
const std::string hex_table = "0123456789abcdef";
|
||||||
@ -151,5 +154,18 @@ void HideModule(HMODULE module) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsDigit(const std::string &str) {
|
||||||
|
if (str.length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto it : str) {
|
||||||
|
if (it < '0' || it > '9') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
@ -23,6 +23,7 @@ void GlobalManager::initialize(HMODULE module) {
|
|||||||
http_server = std::unique_ptr<http::HttpServer>(
|
http_server = std::unique_ptr<http::HttpServer>(
|
||||||
new http::HttpServer(config->GetPort()));
|
new http::HttpServer(config->GetPort()));
|
||||||
http_server->AddHttpApiUrl("/api/sendTextMsg", SendTextMsg);
|
http_server->AddHttpApiUrl("/api/sendTextMsg", SendTextMsg);
|
||||||
|
http_server->AddHttpApiUrl("/api/hookSyncMsg", HookSyncMsg);
|
||||||
http_server->Start();
|
http_server->Start();
|
||||||
base::ThreadPool::GetInstance().Create(2, 8);
|
base::ThreadPool::GetInstance().Create(2, 8);
|
||||||
|
|
||||||
|
73
app/wxhelper/src/http_client.cc
Normal file
73
app/wxhelper/src/http_client.cc
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "http_client.h"
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
void HttpClient::SendRequest(const std::string &content) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
Data data;
|
||||||
|
data.done = false;
|
||||||
|
data.post_data = content;
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_connect(&mgr, kUrl.c_str(), OnHttpEvent, &data);
|
||||||
|
while (!data.done) {
|
||||||
|
mg_mgr_poll(&mgr, 500);
|
||||||
|
}
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
data.done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::SetConfig(std::string url, uint64_t timeout) {
|
||||||
|
kUrl = url;
|
||||||
|
kTimeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::OnHttpEvent(struct mg_connection *c, int ev, void *ev_data,
|
||||||
|
void *fn_data) {
|
||||||
|
const char *s_url = kUrl.c_str();
|
||||||
|
Data *data = (Data *)fn_data;
|
||||||
|
if (ev == MG_EV_OPEN) {
|
||||||
|
// Connection created. Store connect expiration time in c->data
|
||||||
|
*(uint64_t *)c->data = mg_millis() + kTimeout;
|
||||||
|
} else if (ev == MG_EV_POLL) {
|
||||||
|
if (mg_millis() > *(uint64_t *)c->data &&
|
||||||
|
(c->is_connecting || c->is_resolving)) {
|
||||||
|
mg_error(c, "Connect timeout");
|
||||||
|
}
|
||||||
|
} else if (ev == MG_EV_CONNECT) {
|
||||||
|
struct mg_str host = mg_url_host(s_url);
|
||||||
|
if (mg_url_is_ssl(s_url)) {
|
||||||
|
// no implement
|
||||||
|
}
|
||||||
|
// Send request
|
||||||
|
size_t content_length = data->post_data.size();
|
||||||
|
mg_printf(c,
|
||||||
|
"POST %s HTTP/1.0\r\n"
|
||||||
|
"Host: %.*s\r\n"
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Content-Length: %d\r\n"
|
||||||
|
"\r\n",
|
||||||
|
mg_url_uri(s_url), (int)host.len, host.ptr, content_length);
|
||||||
|
mg_send(c, data->post_data.c_str(), content_length);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
// Response is received. Print it
|
||||||
|
#ifdef _DEBUG
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *)ev_data;
|
||||||
|
printf("%.*s", (int)hm->message.len, hm->message.ptr);
|
||||||
|
#endif
|
||||||
|
// c->is_closing = 1; // Tell mongoose to close this connection
|
||||||
|
c->is_draining = 1;
|
||||||
|
data->done = true; // Tell event loop to stops
|
||||||
|
} else if (ev == MG_EV_ERROR) {
|
||||||
|
data->done = true; // Error, tell event loop to stop
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
if (!data->done) {
|
||||||
|
data->done = true;
|
||||||
|
}
|
||||||
|
} else if (ev == MG_EV_HTTP_CHUNK) {
|
||||||
|
mg_error(c, "http chunk no implement");
|
||||||
|
c->is_closing = 1;
|
||||||
|
data->done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace http
|
26
app/wxhelper/src/http_client.h
Normal file
26
app/wxhelper/src/http_client.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef WXHELPER_HTTP_CLIENT_H_
|
||||||
|
#define WXHELPER_HTTP_CLIENT_H_
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
static std::string kUrl = "http://127.0.0.1:8000";
|
||||||
|
static uint64_t kTimeout = 3000;
|
||||||
|
struct Data {
|
||||||
|
bool done;
|
||||||
|
std::string post_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HttpClient {
|
||||||
|
public:
|
||||||
|
static void SendRequest(const std::string &content);
|
||||||
|
static void SetConfig(std::string url, uint64_t timeout);
|
||||||
|
static void OnHttpEvent(struct mg_connection *c, int ev, void *ev_data,
|
||||||
|
void *fn_data);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
#endif
|
@ -4,12 +4,34 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "wechat_service.h"
|
#include "wechat_service.h"
|
||||||
#include "windows.h"
|
#include "wechat_hook.h"
|
||||||
|
|
||||||
|
#define STR2ULL(str) (base::utils::IsDigit(str) ? stoull(str) : 0)
|
||||||
|
#define STR2LL(str) (base::utils::IsDigit(str) ? stoll(str) : 0)
|
||||||
|
#define STR2I(str) (base::utils::IsDigit(str) ? stoi(str) : 0)
|
||||||
namespace wxhelper {
|
namespace wxhelper {
|
||||||
std::wstring GetWStringParam(nlohmann::json data, std::string key) {
|
std::wstring GetWStringParam(nlohmann::json data, std::string key) {
|
||||||
return base::utils::Utf8ToWstring(data[key].get<std::string>());
|
return base::utils::Utf8ToWstring(data[key].get<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetIntParam(nlohmann::json data, std::string key) {
|
||||||
|
int result;
|
||||||
|
try {
|
||||||
|
result = data[key].get<int>();
|
||||||
|
} catch (nlohmann::json::exception) {
|
||||||
|
result = STR2I(data[key].get<std::string>());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetBoolParam(nlohmann::json data, std::string key) {
|
||||||
|
return data[key].get<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetStringParam(nlohmann::json data, std::string key) {
|
||||||
|
return data[key].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
std::string SendTextMsg(mg_http_message* hm) {
|
std::string SendTextMsg(mg_http_message* hm) {
|
||||||
nlohmann::json j_param = nlohmann::json::parse(
|
nlohmann::json j_param = nlohmann::json::parse(
|
||||||
hm->body.ptr, hm->body.ptr + hm->body.len, nullptr, false);
|
hm->body.ptr, hm->body.ptr + hm->body.len, nullptr, false);
|
||||||
@ -21,4 +43,27 @@ std::string SendTextMsg(mg_http_message* hm) {
|
|||||||
std::string ret = ret_data.dump();
|
std::string ret = ret_data.dump();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HookSyncMsg(mg_http_message* hm) {
|
||||||
|
nlohmann::json j_param = nlohmann::json::parse(
|
||||||
|
hm->body.ptr, hm->body.ptr + hm->body.len, nullptr, false);
|
||||||
|
int port = GetIntParam(j_param, "port");
|
||||||
|
std::string ip = GetStringParam(j_param, "ip");
|
||||||
|
bool enable = GetBoolParam(j_param, "enableHttp");
|
||||||
|
std::string url = "http:://127.0.0.1:19088";
|
||||||
|
uint64_t timeout = 3000;
|
||||||
|
if (enable) {
|
||||||
|
url = GetStringParam(j_param, "url");
|
||||||
|
timeout = GetIntParam(j_param, "timeout");
|
||||||
|
}
|
||||||
|
hook::WechatHookParam param = {
|
||||||
|
ip, url, port, enable, timeout,
|
||||||
|
};
|
||||||
|
hook::WechatHook::GetInstance().Init(param);
|
||||||
|
INT64 success = hook::WechatHook::GetInstance().HookSyncMsg();
|
||||||
|
nlohmann::json ret_data = {
|
||||||
|
{"code", success}, {"data", {}}, {"msg", "success"}};
|
||||||
|
std::string ret = ret_data.dump();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
} // namespace wxhelper
|
} // namespace wxhelper
|
@ -5,6 +5,7 @@
|
|||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
namespace wxhelper {
|
namespace wxhelper {
|
||||||
std::string SendTextMsg(struct mg_http_message *hm);
|
std::string SendTextMsg(struct mg_http_message *hm);
|
||||||
|
std::string HookSyncMsg(struct mg_http_message *hm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -487,6 +487,7 @@ namespace offset {
|
|||||||
const UINT64 kGetSendMessageMgr = 0x8fe740;
|
const UINT64 kGetSendMessageMgr = 0x8fe740;
|
||||||
const UINT64 kFreeChatMsg = 0x8fffc0;
|
const UINT64 kFreeChatMsg = 0x8fffc0;
|
||||||
const UINT64 kSendTextMsg = 0x1024370;
|
const UINT64 kSendTextMsg = 0x1024370;
|
||||||
|
const UINT64 kDoAddMsg = 0x106b810;
|
||||||
} // namespace offset
|
} // namespace offset
|
||||||
namespace function {
|
namespace function {
|
||||||
typedef UINT64 (*__GetSendMessageMgr)();
|
typedef UINT64 (*__GetSendMessageMgr)();
|
||||||
|
187
app/wxhelper/src/wechat_hook.cc
Normal file
187
app/wxhelper/src/wechat_hook.cc
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include <WS2tcpip.h>
|
||||||
|
#include "wechat_hook.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <detours/detours.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "base64.h"
|
||||||
|
#include "http_client.h"
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "thread_pool.h"
|
||||||
|
#include "wxutils.h"
|
||||||
|
namespace offset = wxhelper::V3_9_7_29::offset;
|
||||||
|
namespace common = wxhelper::common;
|
||||||
|
|
||||||
|
namespace hook {
|
||||||
|
static bool kEnableHttp = false;
|
||||||
|
static bool kLogHookFlag = false;
|
||||||
|
static char kServerIp[20] = "127.0.0.1";
|
||||||
|
static int kServerPort = 19099;
|
||||||
|
|
||||||
|
UINT64(*RealDoAddMsg)
|
||||||
|
(UINT64, UINT64, UINT64) = (UINT64(*)(UINT64, UINT64, UINT64))(
|
||||||
|
wxhelper::wxutils::GetWeChatWinBase() + offset::kDoAddMsg);
|
||||||
|
|
||||||
|
VOID SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
|
||||||
|
PTP_WORK Work) {
|
||||||
|
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
|
||||||
|
if (msg == NULL) {
|
||||||
|
SPDLOG_INFO("add work:msg is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unique_ptr<common::InnerMessageStruct> sms(msg);
|
||||||
|
nlohmann::json j_msg = nlohmann::json::parse(
|
||||||
|
msg->buffer, msg->buffer + msg->length, nullptr, false);
|
||||||
|
if (j_msg.is_discarded() == true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string jstr = j_msg.dump() + "\n";
|
||||||
|
|
||||||
|
WSADATA was_data = {0};
|
||||||
|
int ret = WSAStartup(MAKEWORD(2, 2), &was_data);
|
||||||
|
if (ret != 0) {
|
||||||
|
SPDLOG_ERROR("WSAStartup failed:{}", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (client_socket < 0) {
|
||||||
|
SPDLOG_ERROR("socket init fail");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BOOL status = false;
|
||||||
|
sockaddr_in client_addr;
|
||||||
|
memset(&client_addr, 0, sizeof(client_addr));
|
||||||
|
client_addr.sin_family = AF_INET;
|
||||||
|
client_addr.sin_port = htons((u_short)kServerPort);
|
||||||
|
InetPtonA(AF_INET, kServerIp, &client_addr.sin_addr.s_addr);
|
||||||
|
if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr),
|
||||||
|
sizeof(sockaddr)) < 0) {
|
||||||
|
SPDLOG_ERROR("socket connect fail. host:{} , port:{},",kServerIp,kServerPort);
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
char recv_buf[1024] = {0};
|
||||||
|
ret = send(client_socket, jstr.c_str(), static_cast<int>(jstr.size()), 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
SPDLOG_ERROR("socket send fail ,ret:{}", ret);
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
ret = shutdown(client_socket, SD_SEND);
|
||||||
|
if (ret == SOCKET_ERROR) {
|
||||||
|
SPDLOG_ERROR("shutdown failed with erro:{}", ret);
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
ret = recv(client_socket, recv_buf, sizeof(recv_buf), 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
SPDLOG_ERROR("socket recv fail ,ret:{}", ret);
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
clean:
|
||||||
|
closesocket(client_socket);
|
||||||
|
WSACleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SendHttpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
|
||||||
|
PTP_WORK Work) {
|
||||||
|
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
|
||||||
|
if (msg == NULL) {
|
||||||
|
SPDLOG_INFO("http msg is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<common::InnerMessageStruct> sms(msg);
|
||||||
|
nlohmann::json j_msg = nlohmann::json::parse(
|
||||||
|
msg->buffer, msg->buffer + msg->length, nullptr, false);
|
||||||
|
if (j_msg.is_discarded() == true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string jstr = j_msg.dump() + "\n";
|
||||||
|
http::HttpClient::SendRequest(jstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3) {
|
||||||
|
nlohmann::json msg;
|
||||||
|
|
||||||
|
msg["pid"] = GetCurrentProcessId();
|
||||||
|
msg["fromUser"] =
|
||||||
|
wxhelper::wxutils::ReadSKBuiltinString(*(INT64 *)(param2 + 0x18));
|
||||||
|
msg["toUser"] =
|
||||||
|
wxhelper::wxutils::ReadSKBuiltinString(*(INT64 *)(param2 + 0x28));
|
||||||
|
msg["content"] =
|
||||||
|
wxhelper::wxutils::ReadSKBuiltinString(*(INT64 *)(param2 + 0x30));
|
||||||
|
msg["signature"] =
|
||||||
|
wxhelper::wxutils::ReadWeChatStr(*(INT64 *)(param2 + 0x48));
|
||||||
|
msg["msgId"] = *(INT64 *)(param2 + 0x60);
|
||||||
|
msg["msgSequence"] = *(DWORD *)(param2 + 0x5C);
|
||||||
|
msg["createTime"] = *(DWORD *)(param2 + 0x58);
|
||||||
|
msg["displayFullContent"] =
|
||||||
|
wxhelper::wxutils::ReadWeChatStr(*(INT64 *)(param2 + 0x50));
|
||||||
|
DWORD type = *(DWORD *)(param2 + 0x24);
|
||||||
|
msg["type"] = type;
|
||||||
|
if (type == 3) {
|
||||||
|
int a = 1;
|
||||||
|
std::string img =
|
||||||
|
wxhelper::wxutils::ReadSKBuiltinBuffer(*(INT64 *)(param2 + 0x40));
|
||||||
|
SPDLOG_INFO("encode size:{}", img.size());
|
||||||
|
msg["base64Img"] = base64_encode(img);
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
std::string jstr = msg.dump() + '\n';
|
||||||
|
common::InnerMessageStruct *inner_msg = new common::InnerMessageStruct;
|
||||||
|
inner_msg->buffer = new char[jstr.size() + 1];
|
||||||
|
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
|
||||||
|
inner_msg->length = jstr.size();
|
||||||
|
if (kEnableHttp) {
|
||||||
|
bool add =
|
||||||
|
base::ThreadPool::GetInstance().AddWork(SendHttpMsgCallback, inner_msg);
|
||||||
|
SPDLOG_INFO("add http msg work:{}", add);
|
||||||
|
} else {
|
||||||
|
bool add =
|
||||||
|
base::ThreadPool::GetInstance().AddWork(SendMsgCallback, inner_msg);
|
||||||
|
SPDLOG_INFO("add msg work:{}", add);
|
||||||
|
}
|
||||||
|
RealDoAddMsg(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WechatHook::Init(WechatHookParam param) {
|
||||||
|
if(!init_){
|
||||||
|
param_ = param;
|
||||||
|
kEnableHttp = param.enable_http;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int WechatHook::HookSyncMsg() {
|
||||||
|
if (sync_msg_flag_) {
|
||||||
|
SPDLOG_INFO("recv msg hook already called");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param_.server_ip.size() < 1) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
UINT64 base = wxhelper::wxutils::GetWeChatWinBase();
|
||||||
|
if (!base) {
|
||||||
|
SPDLOG_INFO("base addr is null");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (param_.enable_http) {
|
||||||
|
http::HttpClient::SetConfig(param_.http_url,param_.http_time_out);
|
||||||
|
}else{
|
||||||
|
const char* charPtr = param_.server_ip.c_str();
|
||||||
|
std::strcpy(kServerIp, charPtr);
|
||||||
|
kServerPort = param_.server_port;
|
||||||
|
}
|
||||||
|
DetourTransactionBegin();
|
||||||
|
DetourUpdateThread(GetCurrentThread());
|
||||||
|
DetourAttach(&(PVOID &)RealDoAddMsg, &HandleSyncMsg);
|
||||||
|
LONG ret = DetourTransactionCommit();
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
sync_msg_flag_ = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} // namespace hook
|
34
app/wxhelper/src/wechat_hook.h
Normal file
34
app/wxhelper/src/wechat_hook.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef WXHELPER_WECHAT_HOOK_H_
|
||||||
|
#define WXHELPER_WECHAT_HOOK_H_
|
||||||
|
#include "wechat_function.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
namespace hook {
|
||||||
|
struct WechatHookParam {
|
||||||
|
std::string server_ip = "127.0.0.1";
|
||||||
|
std::string http_url = "http:://127.0.0.1:19088";
|
||||||
|
int server_port = 19099;
|
||||||
|
bool enable_http = false;
|
||||||
|
uint64_t http_time_out = 3000;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WechatHook :public base::Singleton<WechatHook>{
|
||||||
|
public:
|
||||||
|
void Init(WechatHookParam param);
|
||||||
|
|
||||||
|
int HookSyncMsg();
|
||||||
|
int UnHookSyncMsg();
|
||||||
|
|
||||||
|
int HookLog();
|
||||||
|
|
||||||
|
int UnHookLog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WechatHookParam param_;
|
||||||
|
bool sync_msg_flag_;
|
||||||
|
bool init_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hook
|
||||||
|
|
||||||
|
#endif
|
@ -179,4 +179,5 @@ void WechatService::SetBaseAddr(UINT64 addr) { base_addr_ = addr; }
|
|||||||
|
|
||||||
void WechatService::SetJsApiAddr(UINT64 addr) { js_api_addr_ = addr; }
|
void WechatService::SetJsApiAddr(UINT64 addr) { js_api_addr_ = addr; }
|
||||||
|
|
||||||
|
|
||||||
} // namespace wxhelper
|
} // namespace wxhelper
|
@ -1,7 +1,96 @@
|
|||||||
#include "wxutils.h"
|
#include "wxutils.h"
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
#define JPEG0 0xFF
|
||||||
|
#define JPEG1 0xD8
|
||||||
|
#define JPEG2 0xFF
|
||||||
|
#define PNG0 0x89
|
||||||
|
#define PNG1 0x50
|
||||||
|
#define PNG2 0x4E
|
||||||
|
#define BMP0 0x42
|
||||||
|
#define BMP1 0x4D
|
||||||
|
#define GIF0 0x47
|
||||||
|
#define GIF1 0x49
|
||||||
|
#define GIF2 0x46
|
||||||
namespace wxhelper {
|
namespace wxhelper {
|
||||||
namespace wxutils {
|
namespace wxutils {
|
||||||
UINT64 GetWeChatWinBase() { return (UINT64)GetModuleHandleA("WeChatWin.dll"); }
|
UINT64 GetWeChatWinBase() { return (UINT64)GetModuleHandleA("WeChatWin.dll"); }
|
||||||
|
|
||||||
|
std::string ReadSKBuiltinString(INT64 addr) {
|
||||||
|
INT64 inner_string = *(INT64 *)(addr + 0x8);
|
||||||
|
if (inner_string == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return ReadWeChatStr(inner_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ReadSKBuiltinBuffer(INT64 addr) {
|
||||||
|
INT64 len = *(INT64 *)(addr + 0x10);
|
||||||
|
if (len == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
INT64 inner_string = *(INT64 *)(addr + 0x8);
|
||||||
|
if (inner_string == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return ReadWeChatStr(inner_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ReadWeChatStr(INT64 addr) {
|
||||||
|
INT64 len = *(INT64 *)(addr + 0x10);
|
||||||
|
if (len == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
INT64 max_len = *(INT64 *)(addr + 0x18);
|
||||||
|
if ((max_len | 0xF) == 0xF) {
|
||||||
|
return std::string((char *)addr, len);
|
||||||
|
}
|
||||||
|
char *char_from_user = *(char **)(addr);
|
||||||
|
return std::string(char_from_user, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ImageXor(std::string buf) {
|
||||||
|
const char *origin = buf.c_str();
|
||||||
|
short key = 0;
|
||||||
|
if ((*origin ^ JPEG0) == (*(origin + 1) ^ JPEG1)) {
|
||||||
|
key = *origin ^ JPEG0;
|
||||||
|
} else if ((*origin ^ PNG1) == (*(origin + 1) ^ PNG2)) {
|
||||||
|
key = *origin ^ PNG1;
|
||||||
|
} else if ((*origin ^ GIF0) == (*(origin + 1) ^ GIF1)) {
|
||||||
|
key = *origin ^ GIF0;
|
||||||
|
} else if ((*origin ^ BMP0) == (*(origin + 1) ^ BMP1)) {
|
||||||
|
key = *origin ^ BMP0;
|
||||||
|
} else {
|
||||||
|
key = -1;
|
||||||
|
}
|
||||||
|
if (key > 0) {
|
||||||
|
char *img_buf = new char[buf.size()];
|
||||||
|
for (unsigned int i = 0; i < buf.size(); i++) {
|
||||||
|
img_buf[i] = *(origin + i) ^ key;
|
||||||
|
}
|
||||||
|
std::string str(img_buf);
|
||||||
|
delete[] img_buf;
|
||||||
|
img_buf = NULL;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring ReadWstring(INT64 addr) {
|
||||||
|
DWORD len = *(DWORD *)(addr + 0x8);
|
||||||
|
if (len == 0) {
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
wchar_t *str = *(wchar_t **)(addr);
|
||||||
|
if (str == NULL) {
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
return std::wstring(str, len);
|
||||||
|
}
|
||||||
|
std::string ReadWstringThenConvert(INT64 addr) {
|
||||||
|
std::wstring wstr = ReadWstring(addr);
|
||||||
|
return base::utils::WstringToUtf8(wstr);
|
||||||
|
}
|
||||||
} // namespace wxutils
|
} // namespace wxutils
|
||||||
} // namespace wxhelper
|
} // namespace wxhelper
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
#ifndef WXHELPER_WXUTILS_H_
|
#ifndef WXHELPER_WXUTILS_H_
|
||||||
#define WXHELPER_WXUTILS_H_
|
#define WXHELPER_WXUTILS_H_
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <string>
|
||||||
namespace wxhelper {
|
namespace wxhelper {
|
||||||
namespace wxutils {
|
namespace wxutils {
|
||||||
|
|
||||||
UINT64 GetWeChatWinBase();
|
UINT64 GetWeChatWinBase();
|
||||||
}
|
std::string ReadSKBuiltinString(INT64 addr);
|
||||||
|
std::string ReadSKBuiltinBuffer(INT64 addr);
|
||||||
|
std::string ReadWeChatStr(INT64 addr);
|
||||||
|
|
||||||
|
std::string ImageXor(std::string buf);
|
||||||
|
std::wstring ReadWstring(INT64 addr);
|
||||||
|
std::string ReadWstringThenConvert(INT64 addr);
|
||||||
|
|
||||||
|
INT64 DecodeImage(const wchar_t* file_path, const wchar_t* save_dir);
|
||||||
|
} // namespace wxutils
|
||||||
|
|
||||||
} // namespace wxhelper
|
} // namespace wxhelper
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user