mirror of
https://github.com/ttttupup/wxhelper.git
synced 2024-11-05 18:09:24 +08:00
feat:增加3.9.9.43空实现
This commit is contained in:
parent
9836771ef7
commit
493d8aa0c8
32
README.md
32
README.md
@ -4,7 +4,7 @@ wechat hook 。PC端微信逆向学习。
|
||||
本仓库发布的内容,仅用于学习研究,请勿用于非法用途和商业用途!如因此产生任何法律纠纷,均与作者无关!
|
||||
|
||||
#### 项目说明:
|
||||
<font color= "#dd0000">本项目是逆向练习项目,可能会造成封号等后果。请自行承担风险。仅用于学习研究,请勿于非法用途。</font>
|
||||
<font color= "#dd0000">本项目是逆向学习项目,可能会造成封号等后果。请自行承担风险。仅用于学习研究,请勿于非法用途。</font>
|
||||
|
||||
#### 实现原理:
|
||||
逆向分析PC端微信客户端,定位相关功能关键Call,编写dll调用关键Call。然后将该dll文件注入到微信进程。
|
||||
@ -38,7 +38,7 @@ curl --location --request POST '127.0.0.1:19088/api/userInfo'
|
||||
|
||||
|
||||
#### 参与项目
|
||||
个人精力和水平有限,项目还有许多不足,欢迎提出 issues 或 pr。期待你的贡献。
|
||||
个人精力和水平有限,项目还有许多不足,欢迎提出 issues 或 pr。
|
||||
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ curl --location --request POST '127.0.0.1:19088/api/userInfo'
|
||||
个人常用的方法,请参考https://github.com/ttttupup/wxhelper/wiki
|
||||
使用上的问题,可查询https://github.com/ttttupup/wxhelper/discussions
|
||||
数据库解密,请参考https://github.com/ttttupup/wxhelper/wiki
|
||||
个人精力有限,只维护最新版本,旧版本的bug会在新版本中修复,不维护旧版本。
|
||||
个人精力有限,该项目随缘更新。
|
||||
|
||||
|
||||
#### 编译环境
|
||||
@ -59,18 +59,34 @@ cmake
|
||||
|
||||
vcpkg
|
||||
#### 编译构建
|
||||
|
||||
```
|
||||
cd wxhelper/app/3rdparty
|
||||
git clone https://github.com/microsoft/Detours.git
|
||||
git clone https://github.com/gabime/spdlog.git
|
||||
git clone https://github.com/nlohmann/json.git
|
||||
或者使用vcpkg 安装相应库
|
||||
vcpkg install detours:x64-windows
|
||||
vcpkg install nlohmann-json:x64-windows
|
||||
vcpkg install spdlog:x64-windows
|
||||
|
||||
cd wxhelper/cmake
|
||||
copy detours.cmake wxhelper/app/3rdparty/Detours/CMakeLists.txt
|
||||
|
||||
cd wxhelper
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=cl.exe \
|
||||
-DCMAKE_CXX_COMPILER=cl.exe \
|
||||
-DCMAKE_ASM_MASM_COMPILER=ml64.exe \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${vcpkg install dir}/scripts/buildsystems/vcpkg.cmake \
|
||||
-SC:/wxhelper \
|
||||
-BC:/wxhelper/build/x64-debug\
|
||||
-G Ninja
|
||||
-DCMAKE_INSTALL_PREFIX=${SOURCE_DIR}/wxhelper/install/x64-debug \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${VCPKG_INSTALL_DIR}/scripts/buildsystems/vcpkg.cmake \
|
||||
-SC:${SOURCE_DIR}/wxhelper \
|
||||
-BC:${SOURCE_DIR}/wxhelper/build/x64-debug\
|
||||
-G Ninja
|
||||
cmake --build ..
|
||||
```
|
||||
如果有错误按错误提示修正即可。
|
||||
|
||||
|
||||
#### 讨论组
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "chat_controller.h"
|
||||
#include "chat_controller.h"
|
||||
|
||||
#include "json_utils.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@ -18,7 +18,7 @@ namespace wxhelper {
|
||||
std::string ChatController::SendTextMsg(std::string params) {
|
||||
int64_t base_addr = wxutils::GetWeChatWinBase();
|
||||
nlohmann::json jp = nlohmann::json::parse(params);
|
||||
SPDLOG_INFO("sendTextMsg wxid={},msg={}",jp["wxid"],jp["msg"]);
|
||||
SPDLOG_INFO("sendTextMsg wxid={},msg={}", jp["wxid"], jp["msg"]);
|
||||
std::wstring wxid = jsonutils::GetWStringParam(jp, "wxid");
|
||||
std::wstring msg = jsonutils::GetWStringParam(jp, "msg");
|
||||
prototype::WeChatString to_user(wxid);
|
||||
@ -41,22 +41,70 @@ std::string ChatController::SendTextMsg(std::string params) {
|
||||
reinterpret_cast<UINT64>(&temp), 1, 1, 0, 0);
|
||||
free(reinterpret_cast<UINT64>(&chat_msg));
|
||||
|
||||
nlohmann::json ret_data = {{"code", success}, {"data", {}}, {"msg", "success"}};
|
||||
nlohmann::json ret_data = {
|
||||
{"code", success}, {"data", {}}, {"msg", "success"}};
|
||||
return ret_data.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendImageMsg(std::string params) {
|
||||
return std::string();
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendFileMsg(std::string params) {
|
||||
return std::string();
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendAtText(std::string params) {
|
||||
return std::string();
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendMultiAtText(std::string params) {
|
||||
return std::string();
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendCustomEmotion(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendApplet(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::SendPatMsg(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::ForwardMsg(std::string params) {
|
||||
return std::string();
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::ForwardPublicMsgByMsgId(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
std::string ChatController::ForwardPublicMsg(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
|
||||
|
||||
} // namespace wxhelper
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_CHAT_CONTROLLER_H_
|
||||
#ifndef WXHELPER_CHAT_CONTROLLER_H_
|
||||
#define WXHELPER_CHAT_CONTROLLER_H_
|
||||
|
||||
#include "http_controller.h"
|
||||
@ -10,18 +10,67 @@ class ChatController : public http::HttpController<ChatController> {
|
||||
ADD_PATH("/api/sendTextMsg", SendTextMsg);
|
||||
ADD_PATH("/api/sendImagesMsg", SendImageMsg);
|
||||
ADD_PATH("/api/sendFileMsg", SendFileMsg);
|
||||
|
||||
ADD_PATH("/api/sendAtText", SendAtText);
|
||||
ADD_PATH("/api/sendMultiAtText", SendMultiAtText);
|
||||
ADD_PATH("/api/sendCustomEmotion", SendCustomEmotion);
|
||||
ADD_PATH("/api/sendApplet", SendApplet);
|
||||
ADD_PATH("/api/sendPatMsg", SendPatMsg);
|
||||
|
||||
ADD_PATH("/api/forwardMsg", ForwardMsg);
|
||||
ADD_PATH("/api/forwardPublicMsgByMsgId", ForwardPublicMsgByMsgId);
|
||||
ADD_PATH("/api/forwardPublicMsg", ForwardPublicMsg);
|
||||
|
||||
PATHS_END
|
||||
|
||||
public:
|
||||
/// @brief 发送文本
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendTextMsg(std::string params);
|
||||
/// @brief 发送图片
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendImageMsg(std::string params);
|
||||
/// @brief 发送文件
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendFileMsg(std::string params);
|
||||
|
||||
/// @brief 发送@文本
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendAtText(std::string params);
|
||||
/// @brief 发送多个@文本
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendMultiAtText(std::string params);
|
||||
/// @brief 发送自定义表情
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendCustomEmotion(std::string params);
|
||||
/// @brief 发送小程序
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendApplet(std::string params);
|
||||
/// @brief 拍一拍
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string SendPatMsg(std::string params);
|
||||
|
||||
|
||||
/// @brief 转发消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string ForwardMsg(std::string params);
|
||||
/// @brief 转发公众号消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string ForwardPublicMsgByMsgId(std::string params);
|
||||
/// @brief 发送公众号消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string ForwardPublicMsg(std::string params);
|
||||
};
|
||||
} // namespace wxhelper
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "client_socket.h"
|
||||
#include "client_socket.h"
|
||||
|
||||
#include <WS2tcpip.h>
|
||||
#include <Winsock2.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_CLIENT_SOCKET_H_
|
||||
#ifndef WXHELPER_CLIENT_SOCKET_H_
|
||||
#define WXHELPER_CLIENT_SOCKET_H_
|
||||
#include <string>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
@ -20,7 +20,7 @@ void Config::init() {
|
||||
spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
|
||||
http_server_port_ =
|
||||
GetPrivateProfileInt("config", "HttpServerPort", 19088, "./config.ini");
|
||||
hidden_dll_ = GetPrivateProfileInt("config", "HiddenDll", 1, "./config.ini");
|
||||
hidden_dll_ = GetPrivateProfileInt("config", "HiddenDll", 0, "./config.ini");
|
||||
TCHAR host[MAX_PATH];
|
||||
GetPrivateProfileStringA("config", "HttpServerHost", "http://0.0.0.0", host,
|
||||
sizeof(host), "./config.ini");
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_CONFIG_H_
|
||||
#ifndef WXHELPER_CONFIG_H_
|
||||
#define WXHELPER_CONFIG_H_
|
||||
#include <string>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
|
||||
#include "wxhelper.h"
|
||||
BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call,
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <WinSock2.h>
|
||||
#include <WinSock2.h>
|
||||
#include "hook.h"
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_HOOK_H_
|
||||
#ifndef WXHELPER_HOOK_H_
|
||||
#define WXHELPER_HOOK_H_
|
||||
#include <Windows.h>
|
||||
#include <stdint.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "hook_controller.h"
|
||||
#include "hook_controller.h"
|
||||
|
||||
#include "json_utils.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@ -7,10 +7,25 @@
|
||||
namespace jsonutils = wxhelper::jsonutils;
|
||||
namespace wxhelper {
|
||||
std::string HookController::HookSyncMsg(std::string params) {
|
||||
SyncMsgHook::GetInstance().Init();
|
||||
int success = SyncMsgHook::GetInstance().Hook();
|
||||
nlohmann::json ret_data = {
|
||||
{"code", success}, {"data", {}}, {"msg", "success"}};
|
||||
return ret_data.dump();
|
||||
}
|
||||
std::string HookController::UnHookSyncMsg(std::string params) {
|
||||
int success = SyncMsgHook::GetInstance().Unhook();
|
||||
nlohmann::json ret_data = {
|
||||
{"code", success}, {"data", {}}, {"msg", "success"}};
|
||||
return ret_data.dump();
|
||||
}
|
||||
std::string HookController::HookLog(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
std::string HookController::UnHookLog(std::string params) {
|
||||
nlohmann::json ret = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "Not Implemented"}};
|
||||
return ret.dump();
|
||||
}
|
||||
} // namespace wxhelper
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_HOOK_CONTROLLER_H_
|
||||
#ifndef WXHELPER_HOOK_CONTROLLER_H_
|
||||
#define WXHELPER_HOOK_CONTROLLER_H_
|
||||
|
||||
#include "http_controller.h"
|
||||
@ -8,10 +8,28 @@ class HookController : public http::HttpController<HookController> {
|
||||
public:
|
||||
PATHS_BEGIN
|
||||
ADD_PATH("/api/hookSyncMsg", HookSyncMsg);
|
||||
ADD_PATH("/api/unhookSyncMsg", UnHookSyncMsg);
|
||||
ADD_PATH("/api/hookLog", HookLog);
|
||||
ADD_PATH("/api/unhookLog", UnHookLog);
|
||||
PATHS_END
|
||||
|
||||
public:
|
||||
/// @brief hook消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string HookSyncMsg(std::string params);
|
||||
/// @brief 取消hook消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string UnHookSyncMsg(std::string params);
|
||||
/// @brief hook日志消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string HookLog(std::string params);
|
||||
/// @brief 取消hook日志消息
|
||||
/// @param params json
|
||||
/// @return json
|
||||
static std::string UnHookLog(std::string params);
|
||||
};
|
||||
} // namespace wxhelper
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "http_client.h"
|
||||
#include "http_client.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_HTTP_CLIENT_H_
|
||||
#ifndef WXHELPER_HTTP_CLIENT_H_
|
||||
#define WXHELPER_HTTP_CLIENT_H_
|
||||
#include <string>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#ifndef WXHELPER_HTTP_CONTROLLER_H_
|
||||
#define WXHELPER_HTTP_CONTROLLER_H_
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "http_router.h"
|
||||
#include "http_router.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_HTTP_ROUTER_H_
|
||||
#ifndef WXHELPER_HTTP_ROUTER_H_
|
||||
#define WXHELPER_HTTP_ROUTER_H_
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "http_server.h"
|
||||
#include "http_server.h"
|
||||
|
||||
#include "http_router.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
@ -105,9 +105,12 @@ void HttpServer::HandleHttpRequest(struct mg_connection *c, void *ev_data,
|
||||
ret = ret_data.dump();
|
||||
} else if (mg_vcasecmp(&hm->method, "POST") == 0) {
|
||||
std::string url(hm->uri.ptr, hm->uri.len);
|
||||
nlohmann::json params =
|
||||
nlohmann::json::parse(hm->body.ptr, hm->body.ptr + hm->body.len);
|
||||
std::string p = params.dump();
|
||||
std::string p = "{}";
|
||||
if (hm->body.len > 0){
|
||||
nlohmann::json params =
|
||||
nlohmann::json::parse(hm->body.ptr, hm->body.ptr + hm->body.len);
|
||||
p = params.dump();
|
||||
}
|
||||
ret = HttpRouter::GetInstance().HandleHttpRequest(url, p);
|
||||
}
|
||||
} catch (nlohmann::json::exception &e) {
|
||||
@ -121,11 +124,17 @@ void HttpServer::HandleHttpRequest(struct mg_connection *c, void *ev_data,
|
||||
void HttpServer::HandleWebsocketRequest(struct mg_connection *c, void *ev_data,
|
||||
void *fn_data) {
|
||||
struct mg_ws_message *wm = (struct mg_ws_message *)ev_data;
|
||||
nlohmann::json params =
|
||||
nlohmann::json::parse(wm->data.ptr, wm->data.ptr + wm->data.len);
|
||||
std::string cmd = params["cmd"];
|
||||
std::string p = params.dump();
|
||||
std::string ret = HttpRouter::GetInstance().HandleHttpRequest(cmd, p);
|
||||
std::string ret = R"({"code":200,"msg":"success"})";
|
||||
try {
|
||||
nlohmann::json params =
|
||||
nlohmann::json::parse(wm->data.ptr, wm->data.ptr + wm->data.len);
|
||||
std::string cmd = params["cmd"];
|
||||
std::string p = params.dump();
|
||||
ret = HttpRouter::GetInstance().HandleHttpRequest(cmd, p);
|
||||
} catch (nlohmann::json::exception &e) {
|
||||
nlohmann::json res = {{"code", "500"}, {"msg", e.what()}, {"data", NULL}};
|
||||
ret = res.dump();
|
||||
}
|
||||
mg_ws_send(c, ret.c_str(), ret.size(), WEBSOCKET_OP_TEXT);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_HTTP_SERVER_H_
|
||||
#ifndef WXHELPER_HTTP_SERVER_H_
|
||||
#define WXHELPER_HTTP_SERVER_H_
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "json_utils.h"
|
||||
#include "json_utils.h"
|
||||
#include "utils.h"
|
||||
#define STR2ULL(str) (base::utils::IsDigit(str) ? stoull(str) : 0)
|
||||
#define STR2LL(str) (base::utils::IsDigit(str) ? stoll(str) : 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_JSON_UTILS_H_
|
||||
#ifndef WXHELPER_JSON_UTILS_H_
|
||||
#define WXHELPER_JSON_UTILS_H_
|
||||
#include "nlohmann/json.hpp"
|
||||
namespace wxhelper {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_OFFSET_H_
|
||||
#ifndef WXHELPER_OFFSET_H_
|
||||
#define WXHELPER_OFFSET_H_
|
||||
#include <cstdint>
|
||||
namespace wechat {
|
||||
@ -142,18 +142,18 @@ const uint64_t kGetAppMsgMgr = 0x951cb0;
|
||||
const uint64_t kGetContactMgr = 0x93a570;
|
||||
const uint64_t kGetContactList = 0xf6cb70;
|
||||
|
||||
const uint64_t k_sqlite3_exec = 0x26e4f20;
|
||||
const uint64_t k_sqlite3_prepare = 0x26ecaa0;
|
||||
const uint64_t k_sqlite3_open = 0x27242a0;
|
||||
const uint64_t k_sqlite3_step = 0x26a8f30;
|
||||
const uint64_t k_sqlite3_column_count = 0x26a9750;
|
||||
const uint64_t k_sqlite3_column_name = 0x26aa150;
|
||||
const uint64_t k_sqlite3_column_type = 0x26a9fa0;
|
||||
const uint64_t k_sqlite3_column_blob = 0x26a9780;
|
||||
const uint64_t k_sqlite3_column_bytes = 0x26a9870;
|
||||
const uint64_t k_sqlite3_finalize = 0x26a7fe0;
|
||||
const uint64_t k_sqlite3_exec = 0x288ea10;
|
||||
const uint64_t k_sqlite3_prepare = 0x2896590;
|
||||
const uint64_t k_sqlite3_open = 0x28cdd90;
|
||||
const uint64_t k_sqlite3_step = 0x2852a20;
|
||||
const uint64_t k_sqlite3_column_count = 0x2853240;
|
||||
const uint64_t k_sqlite3_column_name = 0x2853c40;
|
||||
const uint64_t k_sqlite3_column_type = 0x2853a90;
|
||||
const uint64_t k_sqlite3_column_blob = 0x2853270;
|
||||
const uint64_t k_sqlite3_column_bytes = 0x2853360;
|
||||
const uint64_t k_sqlite3_finalize = 0x2851ad0;
|
||||
|
||||
const uint64_t kGPInstance = 0x3d8b4f8;
|
||||
const uint64_t kGPInstance = 0x4076558;
|
||||
const uint64_t kMicroMsgDB = 0xb8;
|
||||
const uint64_t kChatMsgDB = 0x2c8;
|
||||
const uint64_t kMiscDB = 0x5f0;
|
||||
@ -164,9 +164,10 @@ const uint64_t kFunctionMsgDB = 0x1b98;
|
||||
const uint64_t kDBName = 0x28;
|
||||
const uint64_t kStorageStart = 0x0;
|
||||
const uint64_t kStorageEnd = 0x0;
|
||||
const uint64_t kMultiDBMgr = 0x3e00910;
|
||||
const uint64_t kPublicMsgMgr = 0x3dfe098;
|
||||
const uint64_t kFavoriteStorageMgr = 0x3e01478;
|
||||
const uint64_t kMultiDBMgr = 0x40ecf98;
|
||||
const uint64_t kPublicMsgMgr = 0x40ea558;
|
||||
const uint64_t kFavoriteStorageMgr = 0x40edb28;
|
||||
const uint64_t kHardLinkMgr = 0x40ecec0;
|
||||
|
||||
const uint64_t kChatRoomMgr = 0x8e9d30;
|
||||
const uint64_t kGetChatRoomDetailInfo = 0xe73590;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_SQLITE_FUNCTION_H_
|
||||
#ifndef WXHELPER_SQLITE_FUNCTION_H_
|
||||
#define WXHELPER_SQLITE_FUNCTION_H_
|
||||
#include <cstdint>
|
||||
#include "offset.h"
|
||||
@ -79,6 +79,7 @@ typedef int(__cdecl *sqlite3_finalize)(uint64_t *pStmt);
|
||||
|
||||
|
||||
struct SqliteFunction {
|
||||
SqliteFunction(){}
|
||||
SqliteFunction(uint64_t base_addr) {
|
||||
sqlite3_exec =
|
||||
reinterpret_cast<sqlite3::sqlite3_exec>(base_addr + offset::k_sqlite3_exec);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "sync_msg_hook.h"
|
||||
#include "sync_msg_hook.h"
|
||||
|
||||
#include "base64.h"
|
||||
#include "config.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_SYNC_MSG_HOOK_H_
|
||||
#ifndef WXHELPER_SYNC_MSG_HOOK_H_
|
||||
#define WXHELPER_SYNC_MSG_HOOK_H_
|
||||
#include "hook.h"
|
||||
#include "singleton.h"
|
||||
|
@ -1,27 +1,284 @@
|
||||
#include "wechat_db.h"
|
||||
#include "wechat_interface.h"
|
||||
namespace wechat {
|
||||
#include "wechat_db.h"
|
||||
|
||||
void WeChatDb::init(uint64_t base) {
|
||||
base_addr_ = base;
|
||||
func_ = sqlite3::SqliteFunction(base);
|
||||
dbmap_ = {};
|
||||
dbs_ = {};
|
||||
|
||||
#include "base64.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "utils.h"
|
||||
#include "wechat_interface.h"
|
||||
#include "wxutils.h"
|
||||
|
||||
namespace wechat {
|
||||
void FreeResult(std::vector<std::vector<wechat::SqlResult>> &data) {
|
||||
if (data.empty()) {
|
||||
return;
|
||||
}
|
||||
for (auto &row : data) {
|
||||
for (auto &item : row) {
|
||||
if (item.column_name) {
|
||||
delete[] item.column_name;
|
||||
item.column_name = nullptr;
|
||||
}
|
||||
if (item.content) {
|
||||
delete[] item.content;
|
||||
item.content = nullptr;
|
||||
}
|
||||
}
|
||||
std::vector<wechat::SqlResult>().swap(row);
|
||||
}
|
||||
std::vector<std::vector<wechat::SqlResult>>().swap(data);
|
||||
}
|
||||
|
||||
int GetDbInfoCallback(void *data, int argc, char **argv, char **name) {
|
||||
DatabaseInfo *pdata = (DatabaseInfo *)data;
|
||||
TableInfo tb = {0};
|
||||
if (argv[1]) {
|
||||
tb.name = new char[strlen(argv[1]) + 1];
|
||||
memcpy(tb.name, argv[1], strlen(argv[1]) + 1);
|
||||
} else {
|
||||
tb.name = (char *)"NULL";
|
||||
}
|
||||
if (argv[2]) {
|
||||
tb.table_name = new char[strlen(argv[2]) + 1];
|
||||
memcpy(tb.table_name, argv[2], strlen(argv[2]) + 1);
|
||||
} else {
|
||||
tb.table_name = (char *)"NULL";
|
||||
}
|
||||
if (argv[3]) {
|
||||
tb.rootpage = new char[strlen(argv[3]) + 1];
|
||||
memcpy(tb.rootpage, argv[3], strlen(argv[3]) + 1);
|
||||
} else {
|
||||
tb.rootpage = (char *)"NULL";
|
||||
}
|
||||
if (argv[4]) {
|
||||
tb.sql = new char[strlen(argv[4]) + 1];
|
||||
memcpy(tb.sql, argv[4], strlen(argv[4]) + 1);
|
||||
} else {
|
||||
tb.sql = (char *)"NULL";
|
||||
}
|
||||
tb.name_len = strlen(tb.name);
|
||||
tb.table_name_len = strlen(tb.table_name);
|
||||
tb.sql_len = strlen(tb.sql);
|
||||
tb.rootpage_len = strlen(tb.rootpage);
|
||||
pdata->tables.push_back(tb);
|
||||
pdata->count = pdata->tables.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WeChatDb::Init() {
|
||||
base_addr_ = wxhelper::wxutils::GetWeChatWinBase();
|
||||
func_ = sqlite3::SqliteFunction(base_addr_);
|
||||
dbmap_ = {};
|
||||
dbs_ = {};
|
||||
}
|
||||
|
||||
int WeChatDb::ExecuteSQL(uint64_t db, const char *sql,
|
||||
sqlite3::sqlite3_callback callback, void *data) {
|
||||
sqlite3::sqlite3_callback callback, void *data) {
|
||||
return func_.sqlite3_exec(db, sql, callback, data, 0);
|
||||
}
|
||||
|
||||
std::vector<void *> WeChatDb::GetWeChatDbHandles() {
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
dbs_.clear();
|
||||
dbmap_.clear();
|
||||
uint64_t p_contact_addr = *(uint64_t *)(base_addr_ + offset::kGPInstance);
|
||||
std::vector<uint64_t> addr_vector{
|
||||
0x180, 0x278, 0x3a0, 0x4c8, 0x5a0, 0x6e0, 0x838, 0x958, 0xa40,
|
||||
0xb28, 0xd00, 0xe10, 0xef8, 0xfd0, 0x10e8, 0x1200, 0x13d0, 0x15a0,
|
||||
0x1678, 0x17a8, 0x18c0, 0x1998, 0x1a70, 0x1b48, 0x1c48, 0x1d60, 0x1e38};
|
||||
|
||||
for (uint64_t elem : addr_vector) {
|
||||
uint64_t db_addr = *(uint64_t *)(p_contact_addr + elem + 0x50);
|
||||
if (db_addr == 0) {
|
||||
continue;
|
||||
}
|
||||
std::wstring name =
|
||||
std::wstring((wchar_t *)(*(uint64_t *)(p_contact_addr + elem + 0x78)),
|
||||
*(uint32_t *)(p_contact_addr + elem + 0x80));
|
||||
auto it = dbmap_.find(name);
|
||||
if (it != dbmap_.end()) {
|
||||
continue;
|
||||
} else {
|
||||
DatabaseInfo db{0};
|
||||
db.db_name = (wchar_t *)(*(uint64_t *)(p_contact_addr + elem + 0x78));
|
||||
db.db_name_len = *(int32_t *)(p_contact_addr + elem + 0x80);
|
||||
db.handle = db_addr;
|
||||
ExecuteSQL(db_addr, "select * from sqlite_master where type=\"table\";",
|
||||
GetDbInfoCallback, &db);
|
||||
dbs_.push_back(db);
|
||||
dbmap_[name] = db;
|
||||
}
|
||||
}
|
||||
|
||||
// MsgX.db
|
||||
uint64_t multi_db_mgr_addr = base_addr_ + offset::kMultiDBMgr;
|
||||
uint64_t wrap_ptr = *(uint64_t *)(multi_db_mgr_addr);
|
||||
uint64_t current_db_num = *(uint64_t *)(wrap_ptr + 0x68);
|
||||
uint64_t begin_ptr = *(uint64_t *)(wrap_ptr + 0x50);
|
||||
|
||||
for (unsigned int i = 0; i < current_db_num; ++i) {
|
||||
uint64_t next_addr = begin_ptr + i * 0x8;
|
||||
uint64_t db_addr = *(uint64_t *)next_addr;
|
||||
if (db_addr) {
|
||||
uint64_t msg0_db_addr = *(uint64_t *)(db_addr + 0x78);
|
||||
DatabaseInfo msg0_db{0};
|
||||
msg0_db.db_name = (wchar_t *)(*(uint64_t *)(db_addr));
|
||||
msg0_db.db_name_len = *(int32_t *)(db_addr + 0x8);
|
||||
msg0_db.handle = msg0_db_addr;
|
||||
msg0_db.extrainfo = *(uint64_t *)(*(uint64_t *)(db_addr + 0x28) + 0x1E8);
|
||||
ExecuteSQL(msg0_db_addr,
|
||||
"select * from sqlite_master where type=\"table\";",
|
||||
GetDbInfoCallback, &msg0_db);
|
||||
dbs_.push_back(msg0_db);
|
||||
std::wstring msg_db_name =
|
||||
std::wstring(msg0_db.db_name, msg0_db.db_name_len);
|
||||
dbmap_[msg_db_name] = msg0_db;
|
||||
// BufInfoStorage
|
||||
uint64_t buf_info_addr = *(uint64_t *)(db_addr + 0x20);
|
||||
if (buf_info_addr) {
|
||||
AddDatebaseInfo(buf_info_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// publicMsg.db
|
||||
uint64_t public_msg_mgr_addr = base_addr_ + offset::kPublicMsgMgr;
|
||||
uint64_t public_msg_mgr_ptr = *(uint64_t *)(public_msg_mgr_addr);
|
||||
for (unsigned int i = 1; i < 4; ++i) {
|
||||
uint64_t public_msg_ptr = *(uint64_t *)(public_msg_mgr_ptr + i * 0x8);
|
||||
if (public_msg_ptr) {
|
||||
AddDatebaseInfo(public_msg_ptr);
|
||||
}
|
||||
}
|
||||
// Favorite.db
|
||||
uint64_t favoite = base_addr_ + offset::kFavoriteStorageMgr;
|
||||
uint64_t item_ptr =
|
||||
*(uint64_t *)(*(uint64_t *)(*(uint64_t *)(favoite) + 0x10) + 0x8);
|
||||
if (item_ptr) {
|
||||
AddDatebaseInfo(item_ptr);
|
||||
}
|
||||
|
||||
// HardLinkMgr
|
||||
uint64_t link = base_addr_ + offset::kHardLinkMgr;
|
||||
uint64_t link_ptr = *(uint64_t *)(*(uint64_t *)(link) + 0x158);
|
||||
for (unsigned int i = 0; i < 6; ++i) {
|
||||
uint64_t hard_link_ptr = *(uint64_t *)(link_ptr + i * 0x8);
|
||||
SPDLOG_INFO("hardlinkxxxdb :{}", hard_link_ptr);
|
||||
if (hard_link_ptr) {
|
||||
AddDatebaseInfo(hard_link_ptr);
|
||||
}
|
||||
}
|
||||
SPDLOG_INFO("db number:{}", dbs_.size());
|
||||
std::vector<void *> ret;
|
||||
for (unsigned int i = 0; i < dbs_.size(); ++i) {
|
||||
ret.push_back(&dbs_[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WeChatDb::Select(uint64_t db_hanle, const std::string &sql,
|
||||
std::vector<std::vector<std::string>> &query_result) {
|
||||
std::vector<std::vector<wechat::SqlResult>> data;
|
||||
int status = ExecSelect(db_hanle, sql, data);
|
||||
if (status != SQLITE_OK) {
|
||||
return 0;
|
||||
}
|
||||
if (data.size() == 0) {
|
||||
return 1;
|
||||
}
|
||||
std::vector<std::string> index;
|
||||
for (size_t i = 0; i < data[0].size(); i++) {
|
||||
index.push_back(data[0][i].column_name);
|
||||
}
|
||||
query_result.push_back(index);
|
||||
|
||||
for (auto it : data) {
|
||||
std::vector<std::string> item;
|
||||
for (size_t i = 0; i < it.size(); i++) {
|
||||
if (!it[i].is_blob) {
|
||||
bool is_utf8 =
|
||||
base::utils::IsTextUtf8(it[i].content, it[i].content_len);
|
||||
if (is_utf8) {
|
||||
std::string content(it[i].content);
|
||||
item.push_back(content);
|
||||
} else {
|
||||
std::string base64_str =
|
||||
base64_encode((BYTE *)it[i].content, it[i].content_len);
|
||||
item.push_back(base64_str);
|
||||
}
|
||||
|
||||
} else {
|
||||
std::string b64_str =
|
||||
base64_encode((BYTE *)it[i].content, it[i].content_len);
|
||||
item.push_back(b64_str);
|
||||
}
|
||||
}
|
||||
query_result.push_back(item);
|
||||
}
|
||||
FreeResult(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WeChatDb::AddDatebaseInfo(uint64_t storage) {
|
||||
uint64_t storage_addr = *(uint64_t *)(storage + 0x50);
|
||||
std::wstring name = std::wstring((wchar_t *)(*(uint64_t *)(storage + 0x78)),
|
||||
*(int32_t *)(storage + 0x80));
|
||||
auto it = dbmap_.find(name);
|
||||
if (it == dbmap_.end()) {
|
||||
DatabaseInfo db{0};
|
||||
db.db_name = (wchar_t *)(*(uint64_t *)(storage + 0x78));
|
||||
db.db_name_len = *(int32_t *)(storage + 0x80);
|
||||
db.handle = storage_addr;
|
||||
ExecuteSQL(storage_addr,
|
||||
"select * from sqlite_master where type=\"table\";",
|
||||
GetDbInfoCallback, &db);
|
||||
dbs_.push_back(db);
|
||||
dbmap_[name] = db;
|
||||
}
|
||||
}
|
||||
|
||||
int WeChatDb::ExecSelect(uint64_t db, const std::string &sql,
|
||||
std::vector<std::vector<wechat::SqlResult>> &data) {
|
||||
uint64_t *stmt;
|
||||
int rc = func_.sqlite3_prepare(db, sql.c_str(), -1, &stmt, 0);
|
||||
if (rc != SQLITE_OK) {
|
||||
return rc;
|
||||
}
|
||||
while (func_.sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int col_count = func_.sqlite3_column_count(stmt);
|
||||
std::vector<wechat::SqlResult> res;
|
||||
for (unsigned int i = 0; i < col_count; ++i) {
|
||||
wechat::SqlResult temp = {0};
|
||||
const char *col_name = func_.sqlite3_column_name(stmt, i);
|
||||
int ntype = func_.sqlite3_column_type(stmt, i);
|
||||
const void *p_blob_data = func_.sqlite3_column_blob(stmt, i);
|
||||
int nlength = func_.sqlite3_column_bytes(stmt, i);
|
||||
temp.column_name = new char[strlen(col_name) + 1];
|
||||
memcpy(temp.column_name, col_name, strlen(col_name) + 1);
|
||||
temp.column_name_len = strlen(col_name);
|
||||
temp.content_len = nlength;
|
||||
switch (ntype) {
|
||||
case SQLITE_BLOB: {
|
||||
temp.content = new char[nlength];
|
||||
memcpy(temp.content, p_blob_data, nlength);
|
||||
temp.is_blob = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (nlength != 0) {
|
||||
temp.content = new char[nlength + 1];
|
||||
memcpy(temp.content, p_blob_data, nlength + 1);
|
||||
} else {
|
||||
temp.content = new char[2];
|
||||
ZeroMemory(temp.content, 2);
|
||||
}
|
||||
temp.is_blob = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
res.push_back(temp);
|
||||
}
|
||||
data.push_back(res);
|
||||
}
|
||||
func_.sqlite3_finalize(stmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
} // namespace wechat
|
@ -1,7 +1,8 @@
|
||||
#ifndef WXHELPER_WECHAT_DB_H_
|
||||
#ifndef WXHELPER_WECHAT_DB_H_
|
||||
#define WXHELPER_WECHAT_DB_H_
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "singleton.h"
|
||||
@ -12,16 +13,24 @@ namespace wechat {
|
||||
|
||||
class WeChatDb : public base::Singleton<WeChatDb> {
|
||||
public:
|
||||
void init(uint64_t base);
|
||||
int ExecuteSQL(uint64_t db, const char *sql,
|
||||
sqlite3::sqlite3_callback callback, void *data);
|
||||
|
||||
void Init();
|
||||
std::vector<void *> GetWeChatDbHandles();
|
||||
int Select(uint64_t db_hanle, const std::string &sql,
|
||||
std::vector<std::vector<std::string>> &query_result);
|
||||
|
||||
private:
|
||||
std::map<std::wstring,DatabaseInfo> dbmap_;
|
||||
void AddDatebaseInfo(uint64_t storage);
|
||||
int ExecSelect(uint64_t db, const std::string &sql,
|
||||
std::vector<std::vector<wechat::SqlResult>> &data);
|
||||
int ExecuteSQL(uint64_t db, const char *sql,
|
||||
sqlite3::sqlite3_callback callback, void *data);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::wstring, DatabaseInfo> dbmap_;
|
||||
std::vector<DatabaseInfo> dbs_;
|
||||
sqlite3::SqliteFunction func_;
|
||||
uint64_t base_addr_;
|
||||
mutable std::mutex m;
|
||||
};
|
||||
|
||||
} // namespace wechat
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_WECHAT_INNER_H_
|
||||
#ifndef WXHELPER_WECHAT_INNER_H_
|
||||
#define WXHELPER_WECHAT_INNER_H_
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -1,23 +1,22 @@
|
||||
#include <winsock2.h>
|
||||
#include <winsock2.h>
|
||||
#include "wxhelper.h"
|
||||
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "http_server.h"
|
||||
#include "thread_pool.h"
|
||||
#include "utils.h"
|
||||
#include "wxutils.h"
|
||||
#include "chat_controller.h"
|
||||
#include "wechat_db.h"
|
||||
#include "sync_msg_hook.h"
|
||||
namespace wxhelper {
|
||||
|
||||
void WxHelper::init(HMODULE module) {
|
||||
Config::GetInstance().init();
|
||||
if (Config::GetInstance().GetHideDll()) {
|
||||
// base::utils::HideModule(module);
|
||||
base::utils::HideModule(module);
|
||||
}
|
||||
// ChatController chatController;
|
||||
// http::HttpRouter::GetInstance().init();
|
||||
wechat::WeChatDb::GetInstance().Init();
|
||||
SyncMsgHook::GetInstance().Init();
|
||||
http::HttpServer::GetInstance().init(
|
||||
Config::GetInstance().GetHttpServerHost(),
|
||||
Config::GetInstance().GetHttpServerPort());
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#ifndef WXHELPER_WXHELPER_H_
|
||||
#define WXHELPER_WXHELPER_H_
|
||||
#include <Windows.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "wxutils.h"
|
||||
#include "wxutils.h"
|
||||
|
||||
#include "utils.h"
|
||||
#define BUFSIZE 1024
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef WXHELPER_WXUTILS_H_
|
||||
#ifndef WXHELPER_WXUTILS_H_
|
||||
#define WXHELPER_WXUTILS_H_
|
||||
#include <windows.h>
|
||||
|
||||
|
108
cmake/detours.cmake
Normal file
108
cmake/detours.cmake
Normal file
@ -0,0 +1,108 @@
|
||||
cmake_minimum_required(VERSION 3.10...3.27)
|
||||
|
||||
# 设置项目名称和版本
|
||||
project(detours VERSION 4.0.1 LANGUAGES C CXX)
|
||||
|
||||
MACRO(GET_WIN32_WINNT version)
|
||||
IF(WIN32 AND CMAKE_SYSTEM_VERSION)
|
||||
SET(ver ${CMAKE_SYSTEM_VERSION})
|
||||
STRING(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
|
||||
STRING(REGEX MATCH "^([0-9]+)" verMajor ${ver})
|
||||
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
|
||||
IF("${verMajor}" MATCHES "10")
|
||||
SET(verMajor "A")
|
||||
STRING(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
|
||||
ENDIF("${verMajor}" MATCHES "10")
|
||||
# Remove all remaining '.' characters.
|
||||
STRING(REPLACE "." "" ver ${ver})
|
||||
# Prepend each digit with a zero.
|
||||
STRING(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
|
||||
SET(${version} "0x${ver}")
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
# 根据配置设置DEBUG标志
|
||||
set(DETOURS_CONFIG ${CMAKE_BUILD_TYPE})
|
||||
if("${DETOURS_CONFIG}" STREQUAL "Debug")
|
||||
set(DETOURS_DEBUG 1)
|
||||
else()
|
||||
set(DETOURS_DEBUG 0)
|
||||
endif()
|
||||
|
||||
####################################################
|
||||
|
||||
# 设置编译器标志
|
||||
set(CMAKE_CXX_FLAGS "/nologo /W4 /WX /we4777 /we4800 /Zi /MT /Gy /Gm- /Zl /Od /DDETOUR_DEBUG=${DETOURS_DEBUG}")
|
||||
|
||||
|
||||
if(WIN32)
|
||||
IF(MSVC_VERSION GREATER_EQUAL 1700)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D DETOURS_CL_17_OR_NEWER")
|
||||
ENDIF()
|
||||
GET_WIN32_WINNT(ver)
|
||||
message(STATUS "Windows OS Version: ${ver}")
|
||||
if(ver EQUAL 0x0700)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _USING_V110_SDK71_ /D DETOURS_WIN_7")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _WIN32_WINNT=${ver}")
|
||||
else()
|
||||
message(FATAL_ERROR "Only Win32 platforms are supported.")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i386")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _X86_ ")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _AMD64_ ")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "IA64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _IA64_ ")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _X86_ ")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _AMD64_ ")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "AMD64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _AMD64_ ")
|
||||
else()
|
||||
message("Unknown architecture (x86, amd64, ia64, arm, arm64)")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D DETOURS_VERSION=0x4c0c1 /D WIN32_LEAN_AND_MEAN")
|
||||
|
||||
|
||||
if(MSVC)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _CRT_SECURE_NO_WARNINGS /EHsc")
|
||||
|
||||
else()
|
||||
# TODO: Shall we support gcc with MinGW, Cygwin or Clang based building system on Windows?
|
||||
endif()
|
||||
|
||||
if(ENABLE_VERBOSELOG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D ENABLE_VERBOSELOG")
|
||||
endif()
|
||||
|
||||
# 设置源文件和目标
|
||||
|
||||
|
||||
set(SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/detours.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/modules.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disasm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/image.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/creatwth.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disolx86.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disolx64.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disolia64.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disolarm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/disolarm64.cpp
|
||||
)
|
||||
|
||||
# 添加库目标
|
||||
add_library(detours ${SOURCES})
|
||||
target_include_directories(detours INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
341
doc/3.9.9.43.md
Normal file
341
doc/3.9.9.43.md
Normal file
@ -0,0 +1,341 @@
|
||||
#### 编译构建
|
||||
环境:
|
||||
cl.exe目录= c:/cl.exe
|
||||
ml64.exe目录 =c:/ml64.exe
|
||||
vcpkg目录 = c:/vcpkg
|
||||
wxhelper目录 = c:/wxhelper
|
||||
```
|
||||
|
||||
cd wxhelper/app/3rdparty
|
||||
git clone https://github.com/microsoft/Detours.git
|
||||
git clone https://github.com/gabime/spdlog.git
|
||||
git clone https://github.com/nlohmann/json.git
|
||||
或者使用vcpkg 安装相应库
|
||||
vcpkg install detours:x64-windows
|
||||
vcpkg install nlohmann-json:x64-windows
|
||||
vcpkg install spdlog:x64-windows
|
||||
|
||||
cd wxhelper/cmake
|
||||
copy detours.cmake wxhelper/app/3rdparty/Detours/CMakeLists.txt
|
||||
|
||||
cd wxhelper
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=cl.exe \
|
||||
-DCMAKE_CXX_COMPILER=cl.exe \
|
||||
-DCMAKE_ASM_MASM_COMPILER=ml64.exe \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_INSTALL_PREFIX=C:/wxhelper/install/x64-debug \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=C:/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-SC:c:/wxhelper \
|
||||
-BC:c:/wxhelper/build/x64-debug\
|
||||
-G Ninja
|
||||
cmake --build ..
|
||||
```
|
||||
如果有错误按错误提示修正即可。
|
||||
|
||||
## 3.9.9.43版本,http接口文档,文档仅供参考。
|
||||
|
||||
### 简单说明:
|
||||
所有接口只支持post方法。
|
||||
全部使用json格式。
|
||||
格式: http://host:port/api/xxxx
|
||||
host: 绑定的host
|
||||
port: 监听的端口
|
||||
xxxx: 对应的功能路径
|
||||
返回结构的json格式:
|
||||
``` javascript
|
||||
{
|
||||
"code": 1,
|
||||
"data": {},
|
||||
"msg": "success"
|
||||
}
|
||||
```
|
||||
code: 错误码
|
||||
msg: 成功/错误信息
|
||||
data: 接口返回的数据
|
||||
|
||||
### 配置文件
|
||||
wechat目录下config.ini 配置文件的默认配置
|
||||
// HiddenDll : 0.不隐藏注入dll 1.隐藏dll
|
||||
// HttpServerPort :dll自身提供的http服务的端口
|
||||
// HttpServerHost :dll自身提供的http服务的监听地址
|
||||
// RecvMessageMode:开启消息hook时使用接收消息的方式. tcp | http
|
||||
// tcp模式下通过tcp连接发送消息,http模式下通过http发送消息
|
||||
// RecvTcpIp :接收消息绑定的ip
|
||||
// RecvTcpPort:tcp模式下绑定的端口
|
||||
// RecvHttpUrl:http模式下推送的接口地址
|
||||
// RecvHttpTimeout: http模式下的超时时间
|
||||
|
||||
HiddenDll=0,
|
||||
HttpServerPort=80,
|
||||
HttpServerHost=http://0.0.0.0,
|
||||
RecvMessageMode=tcp,
|
||||
RecvTcpIp=127.0.0.1,
|
||||
RecvTcpPort=19099,
|
||||
RecvHttpUrl=127.0.0.1,
|
||||
RecvHttpTimeout=3000,
|
||||
|
||||
|
||||
|
||||
#### 1.hook消息**
|
||||
###### 接口功能
|
||||
> hook接收文本消息,图片消息,群消息.该接口将hook的消息通过tcp回传给本地的端口。
|
||||
enableHttp=1时,使用url,timeout参数配置服务端的接收地址。请求为post,Content-Type 为json。
|
||||
enableHttp=0时,使用ip,port的tcp服务回传消息。
|
||||
|
||||
###### 接口地址
|
||||
> [/api/hookSyncMsg](/api/hookSyncMsg)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,0成功, 非0失败|
|
||||
|data|object|null|
|
||||
|msg|string|成功提示|
|
||||
|
||||
###### 接口示例
|
||||
入参:
|
||||
``` javascript
|
||||
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{"code":0,"msg":"success","data":null}
|
||||
```
|
||||
|
||||
#### 2.取消hook消息**
|
||||
###### 接口功能
|
||||
> 取消hook消息
|
||||
|
||||
###### 接口地址
|
||||
> [/api/unhookSyncMsg](/api/unhookSyncMsg)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,0成功, 非0失败|
|
||||
|data|object|null|
|
||||
|msg|string|成功提示|
|
||||
|
||||
|
||||
###### 接口示例
|
||||
入参:
|
||||
``` javascript
|
||||
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{"code":0,"msg":"success","data":null}
|
||||
```
|
||||
#### 3.获取数据库信息**
|
||||
###### 接口功能
|
||||
> 获取数据库信息和句柄
|
||||
|
||||
###### 接口地址
|
||||
> [/api/getDBInfo](/api/getDBInfo)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,0成功, 非0失败|
|
||||
|msg|string|返回信息|
|
||||
|data|array|好友信息|
|
||||
|  databaseName|string|数据库名称|
|
||||
|  handle|number|句柄|
|
||||
|  tables|array|表信息|
|
||||
|    name|string|表名|
|
||||
|    rootpage|string|rootpage|
|
||||
|    sql|string|ddl语句|
|
||||
|    tableName|string|表名|
|
||||
|
||||
|
||||
###### 接口示例
|
||||
入参:
|
||||
``` javascript
|
||||
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{
|
||||
"code": 1,
|
||||
"data": [
|
||||
{
|
||||
"databaseName": "MicroMsg.db",
|
||||
"handle": 1755003930784,
|
||||
"tables": [
|
||||
{
|
||||
"name": "Contact",
|
||||
"rootpage": "2",
|
||||
"sql": "CREATE TABLE Contact(UserName TEXT PRIMARY KEY ,Alias TEXT,EncryptUserName TEXT,DelFlag INTEGER DEFAULT 0,Type INTEGER DEFAULT 0,VerifyFlag INTEGER DEFAULT 0,Reserved1 INTEGER DEFAULT 0,Reserved2 INTEGER DEFAULT 0,Reserved3 TEXT,Reserved4 TEXT,Remark TEXT,NickName TEXT,LabelIDList TEXT,DomainList TEXT,ChatRoomType int,PYInitial TEXT,QuanPin TEXT,RemarkPYInitial TEXT,RemarkQuanPin TEXT,BigHeadImgUrl TEXT,SmallHeadImgUrl TEXT,HeadImgMd5 TEXT,ChatRoomNotify INTEGER DEFAULT 0,Reserved5 INTEGER DEFAULT 0,Reserved6 TEXT,Reserved7 TEXT,ExtraBuf BLOB,Reserved8 INTEGER DEFAULT 0,Reserved9 INTEGER DEFAULT 0,Reserved10 TEXT,Reserved11 TEXT)",
|
||||
"tableName": "Contact"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"msg":"success"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 4.查询数据库**
|
||||
###### 接口功能
|
||||
> 查询数据库
|
||||
|
||||
###### 接口地址
|
||||
> [/api/execSql](/api/execSql)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|dbHandle |true |number| |
|
||||
|sql |true |string| 执行的sql |
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,0成功, 非0失败|
|
||||
|msg|string|返回信息|
|
||||
|data|array|sqlite返回的结果|
|
||||
|
||||
|
||||
|
||||
###### 接口示例
|
||||
入参:
|
||||
``` javascript
|
||||
{
|
||||
"dbHandle":2006119800400,
|
||||
"sql":"select * from MSG where localId =301;"
|
||||
}
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{
|
||||
"code": 1,
|
||||
"data": [
|
||||
[
|
||||
"localId",
|
||||
"TalkerId",
|
||||
"MsgSvrID",
|
||||
"Type",
|
||||
"SubType",
|
||||
"IsSender",
|
||||
"CreateTime",
|
||||
"Sequence",
|
||||
"StatusEx",
|
||||
"FlagEx",
|
||||
"Status",
|
||||
"MsgServerSeq",
|
||||
"MsgSequence",
|
||||
"StrTalker",
|
||||
"StrContent",
|
||||
"DisplayContent",
|
||||
"Reserved0",
|
||||
"Reserved1",
|
||||
"Reserved2",
|
||||
"Reserved3",
|
||||
"Reserved4",
|
||||
"Reserved5",
|
||||
"Reserved6",
|
||||
"CompressContent",
|
||||
"BytesExtra",
|
||||
"BytesTrans"
|
||||
],
|
||||
[
|
||||
"301",
|
||||
"1",
|
||||
"8824834301214701891",
|
||||
"1",
|
||||
"0",
|
||||
"0",
|
||||
"1685401473",
|
||||
"1685401473000",
|
||||
"0",
|
||||
"0",
|
||||
"2",
|
||||
"1",
|
||||
"795781866",
|
||||
"wxid_123",
|
||||
"testtest",
|
||||
"",
|
||||
"0",
|
||||
"2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"CgQIEBAAGo0BCAcSiAE8bXNnc291cmNlPJPHNpZ25hdHVyZT52MV9wd12bTZyRzwvc2lnbmF0dXJPgoJPHRtcF9ub2RlPgoJCTxwsaXNoZXItaWQ+Jmx0OyFbQ0RBVEFbXV0mZ3Q7PC9wdWJsaXNoZXItaWQ+Cgk8L3RtcF9ub2RlPgo8L21zZ3NvdXJjZT4KGiQIAhIgNDE1MDA0NjRhZTRmMjk2NjhjMzY2ZjFkOTdmMjAwNDg=",
|
||||
""
|
||||
]
|
||||
],
|
||||
"msg": "success"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 5.发送文本消息**
|
||||
###### 接口功能
|
||||
> 发送文本消息
|
||||
|
||||
###### 接口地址
|
||||
> [/api/sendTextMsg](/api/sendTextMsg)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|wxid |true |string| 接收人wxid |
|
||||
|msg|true |string|消息文本内容|
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,不为0成功, 0失败|
|
||||
|msg|string|成功提示|
|
||||
|data|object|null|
|
||||
|
||||
|
||||
###### 接口示例
|
||||
|
||||
入参:
|
||||
``` javascript
|
||||
{
|
||||
"wxid": "filehelper",
|
||||
"msg": "1112222"
|
||||
}
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{"code":345686720,"msg":"success","data":null}
|
||||
```
|
Loading…
Reference in New Issue
Block a user