diff --git a/README.md b/README.md index a2bbd9e..d2fee42 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ wechat hook 。PC端微信逆向学习。 本仓库发布的内容,仅用于学习研究,请勿用于非法用途和商业用途!如因此产生任何法律纠纷,均与作者无关! #### 项目说明: -本项目是逆向练习项目,可能会造成封号等后果。请自行承担风险。仅用于学习研究,请勿于非法用途。 +本项目是逆向学习项目,可能会造成封号等后果。请自行承担风险。仅用于学习研究,请勿于非法用途。 #### 实现原理: 逆向分析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 .. +``` +如果有错误按错误提示修正即可。 #### 讨论组 diff --git a/app/wxhelper/src/chat_controller.cc b/app/wxhelper/src/chat_controller.cc index 8250cfb..242ee74 100644 --- a/app/wxhelper/src/chat_controller.cc +++ b/app/wxhelper/src/chat_controller.cc @@ -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(&temp), 1, 1, 0, 0); free(reinterpret_cast(&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 \ No newline at end of file diff --git a/app/wxhelper/src/chat_controller.h b/app/wxhelper/src/chat_controller.h index 37b2b53..50e359c 100644 --- a/app/wxhelper/src/chat_controller.h +++ b/app/wxhelper/src/chat_controller.h @@ -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 { 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 diff --git a/app/wxhelper/src/client_socket.cc b/app/wxhelper/src/client_socket.cc index ab0268c..00b9f18 100644 --- a/app/wxhelper/src/client_socket.cc +++ b/app/wxhelper/src/client_socket.cc @@ -1,4 +1,4 @@ -#include "client_socket.h" +#include "client_socket.h" #include #include diff --git a/app/wxhelper/src/client_socket.h b/app/wxhelper/src/client_socket.h index 026f7ce..d78589d 100644 --- a/app/wxhelper/src/client_socket.h +++ b/app/wxhelper/src/client_socket.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_CLIENT_SOCKET_H_ +#ifndef WXHELPER_CLIENT_SOCKET_H_ #define WXHELPER_CLIENT_SOCKET_H_ #include diff --git a/app/wxhelper/src/config.cc b/app/wxhelper/src/config.cc index 085a114..7e0806e 100644 --- a/app/wxhelper/src/config.cc +++ b/app/wxhelper/src/config.cc @@ -1,4 +1,4 @@ -#include "config.h" +#include "config.h" #include @@ -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"); diff --git a/app/wxhelper/src/config.h b/app/wxhelper/src/config.h index f7ea25a..778557e 100644 --- a/app/wxhelper/src/config.h +++ b/app/wxhelper/src/config.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_CONFIG_H_ +#ifndef WXHELPER_CONFIG_H_ #define WXHELPER_CONFIG_H_ #include diff --git a/app/wxhelper/src/dllMain.cc b/app/wxhelper/src/dllMain.cc index bc58ba8..910c818 100644 --- a/app/wxhelper/src/dllMain.cc +++ b/app/wxhelper/src/dllMain.cc @@ -1,4 +1,4 @@ - + #include "wxhelper.h" BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call, diff --git a/app/wxhelper/src/hook.cc b/app/wxhelper/src/hook.cc index 800d61a..eac3c1c 100644 --- a/app/wxhelper/src/hook.cc +++ b/app/wxhelper/src/hook.cc @@ -1,4 +1,4 @@ -#include +#include #include "hook.h" diff --git a/app/wxhelper/src/hook.h b/app/wxhelper/src/hook.h index 68c20fe..182350e 100644 --- a/app/wxhelper/src/hook.h +++ b/app/wxhelper/src/hook.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_HOOK_H_ +#ifndef WXHELPER_HOOK_H_ #define WXHELPER_HOOK_H_ #include #include diff --git a/app/wxhelper/src/hook_controller.cc b/app/wxhelper/src/hook_controller.cc index bdff1ce..1a62dff 100644 --- a/app/wxhelper/src/hook_controller.cc +++ b/app/wxhelper/src/hook_controller.cc @@ -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 \ No newline at end of file diff --git a/app/wxhelper/src/hook_controller.h b/app/wxhelper/src/hook_controller.h index 771625a..a524fcc 100644 --- a/app/wxhelper/src/hook_controller.h +++ b/app/wxhelper/src/hook_controller.h @@ -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 { 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 diff --git a/app/wxhelper/src/http_client.cc b/app/wxhelper/src/http_client.cc index 176106c..9194cf4 100644 --- a/app/wxhelper/src/http_client.cc +++ b/app/wxhelper/src/http_client.cc @@ -1,4 +1,4 @@ -#include "http_client.h" +#include "http_client.h" namespace http { diff --git a/app/wxhelper/src/http_client.h b/app/wxhelper/src/http_client.h index 1ec422a..900bde7 100644 --- a/app/wxhelper/src/http_client.h +++ b/app/wxhelper/src/http_client.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_HTTP_CLIENT_H_ +#ifndef WXHELPER_HTTP_CLIENT_H_ #define WXHELPER_HTTP_CLIENT_H_ #include diff --git a/app/wxhelper/src/http_controller.h b/app/wxhelper/src/http_controller.h index 24d4396..4f8bc13 100644 --- a/app/wxhelper/src/http_controller.h +++ b/app/wxhelper/src/http_controller.h @@ -1,4 +1,4 @@ - + #ifndef WXHELPER_HTTP_CONTROLLER_H_ #define WXHELPER_HTTP_CONTROLLER_H_ diff --git a/app/wxhelper/src/http_router.cc b/app/wxhelper/src/http_router.cc index b70a168..525197e 100644 --- a/app/wxhelper/src/http_router.cc +++ b/app/wxhelper/src/http_router.cc @@ -1,4 +1,4 @@ -#include "http_router.h" +#include "http_router.h" #include diff --git a/app/wxhelper/src/http_router.h b/app/wxhelper/src/http_router.h index 8ab4645..2cca129 100644 --- a/app/wxhelper/src/http_router.h +++ b/app/wxhelper/src/http_router.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_HTTP_ROUTER_H_ +#ifndef WXHELPER_HTTP_ROUTER_H_ #define WXHELPER_HTTP_ROUTER_H_ #include #include diff --git a/app/wxhelper/src/http_server.cc b/app/wxhelper/src/http_server.cc index 04cdc79..be20543 100644 --- a/app/wxhelper/src/http_server.cc +++ b/app/wxhelper/src/http_server.cc @@ -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); } diff --git a/app/wxhelper/src/http_server.h b/app/wxhelper/src/http_server.h index b52b559..296787a 100644 --- a/app/wxhelper/src/http_server.h +++ b/app/wxhelper/src/http_server.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_HTTP_SERVER_H_ +#ifndef WXHELPER_HTTP_SERVER_H_ #define WXHELPER_HTTP_SERVER_H_ #include #include diff --git a/app/wxhelper/src/json_utils.cc b/app/wxhelper/src/json_utils.cc index a1a0166..1aefa20 100644 --- a/app/wxhelper/src/json_utils.cc +++ b/app/wxhelper/src/json_utils.cc @@ -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) diff --git a/app/wxhelper/src/json_utils.h b/app/wxhelper/src/json_utils.h index d466066..35555bc 100644 --- a/app/wxhelper/src/json_utils.h +++ b/app/wxhelper/src/json_utils.h @@ -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 { diff --git a/app/wxhelper/src/offset.h b/app/wxhelper/src/offset.h index 93612af..3b851c5 100644 --- a/app/wxhelper/src/offset.h +++ b/app/wxhelper/src/offset.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_OFFSET_H_ +#ifndef WXHELPER_OFFSET_H_ #define WXHELPER_OFFSET_H_ #include 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; diff --git a/app/wxhelper/src/sqlite_function.h b/app/wxhelper/src/sqlite_function.h index 6ff68f1..2b2b351 100644 --- a/app/wxhelper/src/sqlite_function.h +++ b/app/wxhelper/src/sqlite_function.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_SQLITE_FUNCTION_H_ +#ifndef WXHELPER_SQLITE_FUNCTION_H_ #define WXHELPER_SQLITE_FUNCTION_H_ #include #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(base_addr + offset::k_sqlite3_exec); diff --git a/app/wxhelper/src/sync_msg_hook.cc b/app/wxhelper/src/sync_msg_hook.cc index 3ff90b3..aa5ba6e 100644 --- a/app/wxhelper/src/sync_msg_hook.cc +++ b/app/wxhelper/src/sync_msg_hook.cc @@ -1,4 +1,4 @@ -#include "sync_msg_hook.h" +#include "sync_msg_hook.h" #include "base64.h" #include "config.h" diff --git a/app/wxhelper/src/sync_msg_hook.h b/app/wxhelper/src/sync_msg_hook.h index e80e9b5..9566e56 100644 --- a/app/wxhelper/src/sync_msg_hook.h +++ b/app/wxhelper/src/sync_msg_hook.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" diff --git a/app/wxhelper/src/wechat_db.cc b/app/wxhelper/src/wechat_db.cc index 184303c..71070bd 100644 --- a/app/wxhelper/src/wechat_db.cc +++ b/app/wxhelper/src/wechat_db.cc @@ -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> &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().swap(row); + } + std::vector>().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 WeChatDb::GetWeChatDbHandles() { + std::lock_guard lock(m); + dbs_.clear(); + dbmap_.clear(); + uint64_t p_contact_addr = *(uint64_t *)(base_addr_ + offset::kGPInstance); + std::vector 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 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> &query_result) { + std::vector> data; + int status = ExecSelect(db_hanle, sql, data); + if (status != SQLITE_OK) { + return 0; + } + if (data.size() == 0) { + return 1; + } + std::vector 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 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> &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 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 \ No newline at end of file diff --git a/app/wxhelper/src/wechat_db.h b/app/wxhelper/src/wechat_db.h index 5b270ee..d3eabb4 100644 --- a/app/wxhelper/src/wechat_db.h +++ b/app/wxhelper/src/wechat_db.h @@ -1,7 +1,8 @@ -#ifndef WXHELPER_WECHAT_DB_H_ +#ifndef WXHELPER_WECHAT_DB_H_ #define WXHELPER_WECHAT_DB_H_ -#include +#include #include +#include #include #include "singleton.h" @@ -12,16 +13,24 @@ namespace wechat { class WeChatDb : public base::Singleton { public: - void init(uint64_t base); - int ExecuteSQL(uint64_t db, const char *sql, - sqlite3::sqlite3_callback callback, void *data); - + void Init(); + std::vector GetWeChatDbHandles(); + int Select(uint64_t db_hanle, const std::string &sql, + std::vector> &query_result); private: - std::map dbmap_; + void AddDatebaseInfo(uint64_t storage); + int ExecSelect(uint64_t db, const std::string &sql, + std::vector> &data); + int ExecuteSQL(uint64_t db, const char *sql, + sqlite3::sqlite3_callback callback, void *data); + + private: + std::unordered_map dbmap_; std::vector dbs_; sqlite3::SqliteFunction func_; uint64_t base_addr_; + mutable std::mutex m; }; } // namespace wechat diff --git a/app/wxhelper/src/wechat_interface.h b/app/wxhelper/src/wechat_interface.h index d6af82c..5fc2d8b 100644 --- a/app/wxhelper/src/wechat_interface.h +++ b/app/wxhelper/src/wechat_interface.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_WECHAT_INNER_H_ +#ifndef WXHELPER_WECHAT_INNER_H_ #define WXHELPER_WECHAT_INNER_H_ #include #include diff --git a/app/wxhelper/src/wxhelper.cc b/app/wxhelper/src/wxhelper.cc index 3f82e8b..2a9bdc0 100644 --- a/app/wxhelper/src/wxhelper.cc +++ b/app/wxhelper/src/wxhelper.cc @@ -1,23 +1,22 @@ -#include +#include #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()); diff --git a/app/wxhelper/src/wxhelper.h b/app/wxhelper/src/wxhelper.h index fc14fac..49b80f5 100644 --- a/app/wxhelper/src/wxhelper.h +++ b/app/wxhelper/src/wxhelper.h @@ -1,4 +1,4 @@ - + #ifndef WXHELPER_WXHELPER_H_ #define WXHELPER_WXHELPER_H_ #include diff --git a/app/wxhelper/src/wxutils.cc b/app/wxhelper/src/wxutils.cc index 2d67542..2ca2a33 100644 --- a/app/wxhelper/src/wxutils.cc +++ b/app/wxhelper/src/wxutils.cc @@ -1,4 +1,4 @@ -#include "wxutils.h" +#include "wxutils.h" #include "utils.h" #define BUFSIZE 1024 diff --git a/app/wxhelper/src/wxutils.h b/app/wxhelper/src/wxutils.h index 5c9c498..bad00e0 100644 --- a/app/wxhelper/src/wxutils.h +++ b/app/wxhelper/src/wxutils.h @@ -1,4 +1,4 @@ -#ifndef WXHELPER_WXUTILS_H_ +#ifndef WXHELPER_WXUTILS_H_ #define WXHELPER_WXUTILS_H_ #include diff --git a/cmake/detours.cmake b/cmake/detours.cmake new file mode 100644 index 0000000..6fc1e00 --- /dev/null +++ b/cmake/detours.cmake @@ -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) + diff --git a/doc/3.9.9.43.md b/doc/3.9.9.43.md new file mode 100644 index 0000000..12e59fa --- /dev/null +++ b/doc/3.9.9.43.md @@ -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} +``` \ No newline at end of file