diff --git a/.gitmodules b/.gitmodules index 70782f5..1200276 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,9 @@ path = app/3rdparty/spdlog url = https://github.com/gabime/spdlog.git branch = v1.x +[submodule "app/3rdparty/json"] + path = app/3rdparty/json + url = https://github.com/nlohmann/json +[submodule "app/3rdparty/Detours"] + path = app/3rdparty/Detours + url = https://github.com/microsoft/Detours diff --git a/app/3rdparty/Detours b/app/3rdparty/Detours new file mode 160000 index 0000000..4b8c659 --- /dev/null +++ b/app/3rdparty/Detours @@ -0,0 +1 @@ +Subproject commit 4b8c659f549b0ab21cf649377c7a84eb708f5e68 diff --git a/app/3rdparty/json b/app/3rdparty/json new file mode 160000 index 0000000..199dea1 --- /dev/null +++ b/app/3rdparty/json @@ -0,0 +1 @@ +Subproject commit 199dea11b17c533721b26249e2dcaee6ca1d51d3 diff --git a/app/base/src/include/noncopyable.h b/app/base/src/include/noncopyable.h new file mode 100644 index 0000000..68ef99c --- /dev/null +++ b/app/base/src/include/noncopyable.h @@ -0,0 +1,11 @@ +#ifndef BASE_NONCOPYABLE_H_ +#define BASE_NONCOPYABLE_H_ +class NonCopyable { + protected: + NonCopyable() {} + ~NonCopyable() {} + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; +}; + +#endif \ No newline at end of file diff --git a/app/wxhelper/src/chat_controller.cc b/app/wxhelper/src/chat_controller.cc new file mode 100644 index 0000000..937ffc2 --- /dev/null +++ b/app/wxhelper/src/chat_controller.cc @@ -0,0 +1,22 @@ +#include "chat_controller.h" + +namespace wxhelper { +std::string ChatController::SendTextMsg(std::string, std::string) { + return std::string(); +} +std::string ChatController::SendImageMsg(std::string, std::string) { + return std::string(); +} +std::string ChatController::SendFileMsg(std::string, std::string) { + return std::string(); +} +std::string ChatController::SendAtText(std::string, std::string) { + return std::string(); +} +std::string ChatController::SendMultiAtText(std::string, std::string) { + return std::string(); +} +std::string ChatController::ForwardMsg(std::string, std::string) { + return std::string(); +} +} // namespace wxhelper \ No newline at end of file diff --git a/app/wxhelper/src/chat_controller.h b/app/wxhelper/src/chat_controller.h new file mode 100644 index 0000000..d887f35 --- /dev/null +++ b/app/wxhelper/src/chat_controller.h @@ -0,0 +1,28 @@ +#ifndef WXHELPER_CHAT_CONTROLLER_H_ +#define WXHELPER_CHAT_CONTROLLER_H_ +#include "http_controller.h" +#include "spdlog/spdlog.h" +#include +namespace wxhelper { +class ChatController : public http::HttpController { + public: + PATHS_BEGIN + 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/forwardMsg", ForwardMsg); + PATHS_END + + public: + static std::string SendTextMsg(std::string, std::string); + static std::string SendImageMsg(std::string, std::string); + static std::string SendFileMsg(std::string, std::string); + static std::string SendAtText(std::string, std::string); + static std::string SendMultiAtText(std::string, std::string); + static std::string ForwardMsg(std::string, std::string); +}; +} // namespace wxhelper + +#endif \ No newline at end of file diff --git a/app/wxhelper/src/client_socket.cc b/app/wxhelper/src/client_socket.cc new file mode 100644 index 0000000..ab0268c --- /dev/null +++ b/app/wxhelper/src/client_socket.cc @@ -0,0 +1,70 @@ +#include "client_socket.h" + +#include +#include + +#include "spdlog/spdlog.h" +namespace wxhelper { + +SocketInit::SocketInit() { + WSADATA was_data = {0}; + if (WSAStartup(MAKEWORD(2, 2), &was_data)) { + valid_ = true; + } +} + +SocketInit::~SocketInit() { + if (valid_) { + WSACleanup(); + } +} + +TcpClient::TcpClient(std::string ip, int port) : ip_(ip), port_(port) {} + +void TcpClient::SendAndCloseSocket(std::string& content) { + 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)port_); + InetPtonA(AF_INET, ip_.c_str(), &client_addr.sin_addr.s_addr); + if (connect(client_socket, reinterpret_cast(&client_addr), + sizeof(sockaddr)) < 0) { + SPDLOG_ERROR("socket connect fail. host:{} , port:{},", ip_, port_); + closesocket(client_socket); + return; + } + char recv_buf[1024] = {0}; + int ret = + send(client_socket, content.c_str(), static_cast(content.size()), 0); + if (ret < 0) { + SPDLOG_ERROR("socket send fail ,ret:{}", ret); + closesocket(client_socket); + return; + } + ret = shutdown(client_socket, SD_SEND); + if (ret == SOCKET_ERROR) { + SPDLOG_ERROR("shutdown failed with erro:{}", ret); + closesocket(client_socket); + return; + } + do { + ret = recv(client_socket, recv_buf, sizeof(recv_buf), 0); + if (ret > 0) { + } else if (ret == 0) { + SPDLOG_INFO("Connection closed"); + closesocket(client_socket); + return; + } else { + SPDLOG_ERROR("recv failed with error:{}", WSAGetLastError()); + closesocket(client_socket); + return; + } + } while (ret > 0); +} +} // namespace wxhelper \ No newline at end of file diff --git a/app/wxhelper/src/client_socket.h b/app/wxhelper/src/client_socket.h new file mode 100644 index 0000000..026f7ce --- /dev/null +++ b/app/wxhelper/src/client_socket.h @@ -0,0 +1,30 @@ +#ifndef WXHELPER_CLIENT_SOCKET_H_ +#define WXHELPER_CLIENT_SOCKET_H_ +#include + +#include "noncopyable.h" +namespace wxhelper { +class SocketInit : public NonCopyable { + public: + SocketInit(); + + ~SocketInit(); + + bool valid_{false}; +}; + +static SocketInit kSocketInit; + +class TcpClient : public NonCopyable { + public: + TcpClient()=default; + TcpClient(std::string ip, int port); + void SendAndCloseSocket(std::string& content); + + private: + std::string ip_; + int port_; +}; + +} // namespace wxhelper +#endif \ No newline at end of file diff --git a/app/wxhelper/src/hook.cc b/app/wxhelper/src/hook.cc new file mode 100644 index 0000000..812b1a0 --- /dev/null +++ b/app/wxhelper/src/hook.cc @@ -0,0 +1,145 @@ +#include +#include "hook.h" + + +#include "base64.h" +#include "client_socket.h" +#include "config.h" +#include "detours.h" +#include "http_client.h" +#include "nlohmann/json.hpp" +#include "offset.h" +#include "spdlog/spdlog.h" +#include "thread_pool.h" +#include "utils.h" +#include "wechat_interface.h" +#include "wxutils.h" +namespace hook { + +VOID SendTcpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, + PTP_WORK Work) { + wechat::InnerMessageStruct *msg = (wechat::InnerMessageStruct *)context; + if (msg == NULL) { + SPDLOG_INFO("add work:msg is null"); + return; + } + std::unique_ptr 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"; + std::string ip =wxhelper::Config::GetInstance().GetRecvTcpIp(); + int port = wxhelper::Config::GetInstance().GetRecvTcpPort(); + wxhelper::TcpClient client{ip,port}; + client.SendAndCloseSocket(jstr); +} + +VOID SendHttpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, + PTP_WORK Work) { + wechat::InnerMessageStruct *msg = (wechat::InnerMessageStruct *)context; + if (msg == NULL) { + SPDLOG_INFO("http msg is null"); + return; + } + + std::unique_ptr 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"; + std::string url =wxhelper::Config::GetInstance().GetRecvHttpUrl(); + int timeout = wxhelper::Config::GetInstance().GetRecvHttpTimeout(); + http::HttpClient client{url,timeout}; + client.SendRequest(jstr); +} + +BaseHook::BaseHook(void *origin, void *detour) + : origin_(origin), detour_(detour) {} + +int BaseHook::Hook() { + if (hook_flag_) { + SPDLOG_INFO("hook already called"); + return 2; + } + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach((PVOID *)origin_, (PVOID *)detour_); + LONG ret = DetourTransactionCommit(); + if (ret == NO_ERROR) { + hook_flag_ = true; + } + return ret; +} + +int BaseHook::Unhook() { + if (!hook_flag_) { + SPDLOG_INFO("hook already called"); + return NO_ERROR; + } + UINT64 base = wxhelper::wxutils::GetWeChatWinBase(); + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourDetach((PVOID *)origin_, (PVOID *)detour_); + LONG ret = DetourTransactionCommit(); + if (ret == NO_ERROR) { + hook_flag_ = false; + } + return ret; +} + +SyncMsgHook::SyncMsgHook(void *origin, void *detour) + : BaseHook(origin, detour) {} + +void SyncMsgHook::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'; + wechat::InnerMessageStruct *inner_msg = new wechat::InnerMessageStruct; + inner_msg->buffer = new char[jstr.size() + 1]; + memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1); + inner_msg->length = jstr.size(); + std::string mode = wxhelper::Config::GetInstance().GetRecvMessageMode(); + if (mode == "http") { + bool add = + base::ThreadPool::GetInstance().AddWork(SendHttpMsgCallback, inner_msg); + SPDLOG_INFO("add http msg work:{}", add); + } else if (mode == "tcp") { + bool add = + base::ThreadPool::GetInstance().AddWork(SendTcpMsgCallback, inner_msg); + SPDLOG_INFO("add tcp msg work:{}", add); + } + int64_t addr = + wxhelper::wxutils::GetWeChatWinBase() + wechat::offset::kDoAddMsg; + wechat::function::__DoAddMsg addMsg = (wechat::function::__DoAddMsg)addr; + addMsg(param1, param2, param3); +} + +} // namespace hook \ No newline at end of file diff --git a/app/wxhelper/src/hook.h b/app/wxhelper/src/hook.h new file mode 100644 index 0000000..c22be92 --- /dev/null +++ b/app/wxhelper/src/hook.h @@ -0,0 +1,32 @@ +#ifndef WXHELPER_HOOK_H_ +#define WXHELPER_HOOK_H_ +#include "noncopyable.h" +#include +namespace hook { + +static void SendHttpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, + PTP_WORK Work); + +static void SendTcpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, + PTP_WORK Work); +class BaseHook : public NonCopyable { + public: + BaseHook(void* origin, void* detour); + int Hook(); + int Unhook(); + + protected: + bool hook_flag_; + void* origin_; + void* detour_; +}; + +class SyncMsgHook : public BaseHook { + public: + explicit SyncMsgHook(void* origin, void* detour); + private: + static void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3); +}; + +} // namespace hook +#endif \ No newline at end of file diff --git a/app/wxhelper/src/http_controller.h b/app/wxhelper/src/http_controller.h new file mode 100644 index 0000000..7c42f9d --- /dev/null +++ b/app/wxhelper/src/http_controller.h @@ -0,0 +1,42 @@ + +#ifndef WXHELPER_HTTP_CONTROLLER_H_ +#define WXHELPER_HTTP_CONTROLLER_H_ +#include + +#include "http_router.h" +namespace http { +#define PATHS_BEGIN static void AddPath() { +#define ADD_PATH(path, method) RegisterPath(path, &method) +#define PATHS_END } + +class BaseHttpController { + public: + virtual ~BaseHttpController() {} +}; + +template +class HttpController : public BaseHttpController { + public: + virtual ~HttpController() {} + + protected: + HttpController() {} + + static void RegisterPath(const std::string &path, HttpHandler function) { + HttpRouter::GetInstance().AddPathRouting(path, function); + } + + private: + struct Registrator { + public: + Registrator() { T::AddPath(); } + }; + + static Registrator registrator_; + virtual void *GetRegistrator() { return ®istrator_; } +}; + +template +typename HttpController::Registrator HttpController::registrator_; +} // namespace http +#endif diff --git a/app/wxhelper/src/http_router.cc b/app/wxhelper/src/http_router.cc new file mode 100644 index 0000000..94d08ea --- /dev/null +++ b/app/wxhelper/src/http_router.cc @@ -0,0 +1,24 @@ +#include "http_router.h" + +#include + +#include "nlohmann/json.hpp" +#include "spdlog/spdlog.h" +namespace http { +void HttpRouter::AddPathRouting(const std::string &path, HttpHandler handler) { + route_table_[path] = handler; + SPDLOG_INFO("1route table size={}", route_table_.size()); +} +std::string HttpRouter::HandleHttpRequest(const std::string &path, + const std::string ¶m) { + SPDLOG_INFO("route table size={}", route_table_.size()); + auto it = route_table_.find(path); + if (it != route_table_.end()) { + return it->second(path, param); + } else { + nlohmann::json ret_data = { + {"code", 200}, {"data", {}}, {"msg", "the url is not supported"}}; + return ret_data.dump(); + } +} +} // namespace http \ No newline at end of file diff --git a/app/wxhelper/src/http_router.h b/app/wxhelper/src/http_router.h new file mode 100644 index 0000000..67d6580 --- /dev/null +++ b/app/wxhelper/src/http_router.h @@ -0,0 +1,23 @@ +#ifndef WXHELPER_HTTP_ROUTER_H_ +#define WXHELPER_HTTP_ROUTER_H_ +#include +#include +#include + +#include "singleton.h" + +namespace http { +typedef std::function HttpHandler; + +class HttpRouter : public base::Singleton { + public: + void HttpRouter::AddPathRouting(const std::string &path, HttpHandler handler); + + std::string HandleHttpRequest(const std::string &path, + const std::string ¶m); + + private: + std::unordered_map route_table_{}; +}; +} // namespace http +#endif \ No newline at end of file diff --git a/app/wxhelper/src/offset.h b/app/wxhelper/src/offset.h new file mode 100644 index 0000000..2b0b997 --- /dev/null +++ b/app/wxhelper/src/offset.h @@ -0,0 +1,136 @@ +#ifndef WXHELPER_OFFSET_H_ +#define WXHELPER_OFFSET_H_ +#include +namespace wechat { +#define V_3_9_8_25 39825 +#ifndef WECHAT_VERSION +#error " WECHAT_VERSION not defined ." +#endif +namespace offset { +#if WECHAT_VERSION == V_3_9_8_25 +const uint64_t kGetAccountServiceMgr = 0x94e510; +const uint64_t kSyncMsg = 0xc39680; +const uint64_t kSyncMsgNext = 0xc39680; +const uint64_t kGetCurrentDataPath = 0x101a920; +const uint64_t kGetAppDataSavePath = 0x13a5b90; +const uint64_t kGetSendMessageMgr = 0x94cd10; +const uint64_t kSendTextMsg = 0x1091F70; +const uint64_t kFreeChatMsg = 0x94e590; + +const uint64_t kDoAddMsg = 0x10d9450; +const uint64_t kSendImageMsg = 0x1087950; +const uint64_t kChatMsgInstanceCounter = 0x956e00; +const uint64_t kSendFileMsg = 0xea0850; +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 kGPInstance = 0x3d8b4f8; +const uint64_t kMicroMsgDB = 0xb8; +const uint64_t kChatMsgDB = 0x2c8; +const uint64_t kMiscDB = 0x5f0; +const uint64_t kEmotionDB = 0x888; +const uint64_t kMediaDB = 0xF48; +const uint64_t kBizchatMsgDB = 0x1AC0; +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 kChatRoomMgr = 0x8e9d30; +const uint64_t kGetChatRoomDetailInfo = 0xe73590; +const uint64_t kNewChatRoomInfo = 0x12006b0; +const uint64_t kFreeChatRoomInfo = 0x1200890; +const uint64_t kDoAddMemberToChatRoom = 0xe63c70; +const uint64_t kDoModChatRoomMemberNickName = 0xe6db00; +const uint64_t kDelMemberFromChatRoom = 0xe64290; +const uint64_t kGetMemberFromChatRoom = 0xe74de0; +const uint64_t kNewChatRoom = 0x11fde50; +const uint64_t kFreeChatRoom = 0x11fe030; + +const uint64_t kTopMsg = 0xa5e4f0; +const uint64_t kRemoveTopMsg = 0xe787b0; +const uint64_t kInviteMember = 0xe63650; +const uint64_t kHookLog = 0x1304e60; + +const uint64_t kCreateChatRoom = 0xe63340; +const uint64_t kQuitChatRoom = 0xe6e3b0; +const uint64_t kForwardMsg = 0x1091660; + +const uint64_t kOnSnsTimeLineSceneFinish = 0x1a73150; +const uint64_t kSNSGetFirstPage = 0x1a51dd0; +const uint64_t kSNSGetNextPageScene = 0x1a77240; +const uint64_t kSNSDataMgr = 0xeebda0; +const uint64_t kSNSTimeLineMgr = 0x19e83a0; +const uint64_t kGetMgrByPrefixLocalId = 0xf0ea60; +const uint64_t kAddFavFromMsg = 0x1601520; +const uint64_t kGetChatMgr = 0x97e4d0; +const uint64_t kGetFavoriteMgr = 0x8c69b0; +const uint64_t kAddFavFromImage = 0x160b920; +const uint64_t kGetContact = 0xf67060; +const uint64_t kNewContact = 0x12e01f0; +const uint64_t kFreeContact = 0x12e08a0; +const uint64_t kNewMMReaderItem = 0x8c79a0; +const uint64_t kFreeMMReaderItem = 0x8c6da0; +const uint64_t kForwordPublicMsg = 0xddc6c0; +const uint64_t kParseAppMsgXml = 0x11b0a70; +const uint64_t kNewAppMsgInfo = 0x91a550; +const uint64_t kFreeAppMsgInfo = 0x8fd1a0; +const uint64_t kGetPreDownLoadMgr = 0x9996f0; +const uint64_t kPushAttachTask = 0x9c0080; +const uint64_t kGetCustomSmileyMgr = 0x915c00; +const uint64_t kSendCustomEmotion = 0xec0a40; +const uint64_t kNewJsApiShareAppMessage = 0x13be1a0; +const uint64_t kInitJsConfig = 0x137bc00; +const uint64_t kSendApplet = 0x13c0920; +const uint64_t kSendAppletSecond = 0x13c1150; +const uint64_t kGetAppInfoByWaid = 0x13c5790; +const uint64_t kCopyShareAppMessageRequest = 0x13c0670; +const uint64_t kNewWAUpdatableMsgInfo = 0x919ca0; +const uint64_t kFreeWAUpdatableMsgInfo = 0x8fc230; +const uint64_t kSendPatMsg = 0x195f340; +const uint64_t kGetOCRManager = 0x999780; +const uint64_t kDoOCRTask = 0x190b2a0; + +const uint64_t kGetLockWechatMgr = 0xa727b0; +const uint64_t kRequestLockWechat = 0xa2cc70; +const uint64_t kRequestUnLockWechat = 0xa2cf10; + +const uint64_t kOnLoginBtnClick = 0xe0cf70; + +const uint64_t kGetQRCodeLoginMgr = 0xdff6d0; + +const uint64_t kUpdateMsg = 0xf15c40; +const uint64_t kGetVoiceMgr = 0xbf78f0; +const uint64_t kChatMsg2NetSceneSendMsg = 0x96e8d0; +const uint64_t kTranslateVoice = 0x11217e0; +const uint64_t kNewWebViewPageConfig = 0x9512f0; +const uint64_t kFreeWebViewPageConfig = 0x951520; +const uint64_t kGetWebViewMgr = 0x9412d0; +const uint64_t kShowWebView = 0x1d236b0; +const uint64_t kSetUrl = 0x13dd410; +#elif WECHAT_VERSION == V_3_9_8_25 + +#else +#ifdef WECHAT_VERSION +#error "Unsupported WeChat version." +#endif +#endif +} // namespace offset +} // namespace wxhelper + +#endif \ No newline at end of file diff --git a/app/wxhelper/src/sqlite_function.h b/app/wxhelper/src/sqlite_function.h new file mode 100644 index 0000000..6ff68f1 --- /dev/null +++ b/app/wxhelper/src/sqlite_function.h @@ -0,0 +1,120 @@ +#ifndef WXHELPER_SQLITE_FUNCTION_H_ +#define WXHELPER_SQLITE_FUNCTION_H_ +#include +#include "offset.h" +namespace sqlite3 { +namespace offset = wechat::offset; + +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* Generic error */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Internal use only */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Not used */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#define SQLITE_TEXT 3 + +typedef int (*sqlite3_callback)(void *, int, char **, char **); + +typedef int(__cdecl *sqlite3_exec)(uint64_t, /* An open database */ + const char *sql, /* SQL to be evaluated */ + sqlite3_callback, /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +typedef int(__cdecl *sqlite3_prepare)( + uint64_t db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + uint64_t **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +typedef int(__cdecl *sqlite3_open)(const char *filename, uint64_t **ppDb); + +typedef int(__cdecl *sqlite3_sleep)(int); +typedef int(__cdecl *sqlite3_errcode)(uint64_t *db); +typedef int(__cdecl *sqlite3_close)(uint64_t *); + +typedef int(__cdecl *sqlite3_step)(uint64_t *); +typedef int(__cdecl *sqlite3_column_count)(uint64_t *pStmt); +typedef const char *(__cdecl *sqlite3_column_name)(uint64_t *, int N); +typedef int(__cdecl *sqlite3_column_type)(uint64_t *, int iCol); +typedef const void *(__cdecl *sqlite3_column_blob)(uint64_t *, int iCol); +typedef int(__cdecl *sqlite3_column_bytes)(uint64_t *, int iCol); +typedef int(__cdecl *sqlite3_finalize)(uint64_t *pStmt); + +/***************************sqlite3 end*************************************/ + + +struct SqliteFunction { + SqliteFunction(uint64_t base_addr) { + sqlite3_exec = + reinterpret_cast(base_addr + offset::k_sqlite3_exec); + sqlite3_prepare = reinterpret_cast( + base_addr + offset::k_sqlite3_prepare); + sqlite3_open = + reinterpret_cast(base_addr + offset::k_sqlite3_open); + + sqlite3_step = + reinterpret_cast(base_addr + offset::k_sqlite3_step); + sqlite3_column_count = reinterpret_cast( + base_addr + offset::k_sqlite3_column_count); + sqlite3_column_name = reinterpret_cast( + base_addr + offset::k_sqlite3_column_name); + sqlite3_column_type = reinterpret_cast( + base_addr + offset::k_sqlite3_column_type); + sqlite3_column_blob = reinterpret_cast( + base_addr + offset::k_sqlite3_column_blob); + sqlite3_column_bytes = reinterpret_cast( + base_addr + offset::k_sqlite3_column_bytes); + sqlite3_finalize = reinterpret_cast( + base_addr + offset::k_sqlite3_finalize); + } + sqlite3_exec sqlite3_exec; + sqlite3_prepare sqlite3_prepare; + sqlite3_open sqlite3_open; + sqlite3_sleep sqlite3_sleep; + sqlite3_errcode sqlite3_errcode; + sqlite3_close sqlite3_close; + sqlite3_step sqlite3_step; + sqlite3_column_count sqlite3_column_count; + sqlite3_column_name sqlite3_column_name; + sqlite3_column_type sqlite3_column_type; + sqlite3_column_blob sqlite3_column_blob; + sqlite3_column_bytes sqlite3_column_bytes; + sqlite3_finalize sqlite3_finalize; +}; +} // namespace sqlite3 +#endif \ No newline at end of file diff --git a/app/wxhelper/src/wechat_db.cc b/app/wxhelper/src/wechat_db.cc new file mode 100644 index 0000000..184303c --- /dev/null +++ b/app/wxhelper/src/wechat_db.cc @@ -0,0 +1,27 @@ +#include "wechat_db.h" +#include "wechat_interface.h" +namespace wechat { + +void WeChatDb::init(uint64_t base) { + base_addr_ = base; + func_ = sqlite3::SqliteFunction(base); + dbmap_ = {}; + dbs_ = {}; + +} + + +int WeChatDb::ExecuteSQL(uint64_t db, const char *sql, + sqlite3::sqlite3_callback callback, void *data) { + return func_.sqlite3_exec(db, sql, callback, data, 0); +} + + + + + + + + + +} // namespace wechat \ No newline at end of file diff --git a/app/wxhelper/src/wechat_db.h b/app/wxhelper/src/wechat_db.h new file mode 100644 index 0000000..5b270ee --- /dev/null +++ b/app/wxhelper/src/wechat_db.h @@ -0,0 +1,28 @@ +#ifndef WXHELPER_WECHAT_DB_H_ +#define WXHELPER_WECHAT_DB_H_ +#include +#include +#include + +#include "singleton.h" +#include "sqlite_function.h" +#include "wechat_interface.h" + +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); + + + private: + std::map dbmap_; + std::vector dbs_; + sqlite3::SqliteFunction func_; + uint64_t base_addr_; +}; + +} // namespace wechat +#endif diff --git a/app/wxhelper/src/wechat_interface.h b/app/wxhelper/src/wechat_interface.h new file mode 100644 index 0000000..6680ece --- /dev/null +++ b/app/wxhelper/src/wechat_interface.h @@ -0,0 +1,296 @@ +#ifndef WXHELPER_WECHAT_INNER_H_ +#define WXHELPER_WECHAT_INNER_H_ +#include +#include +#include +namespace wechat { + struct TableInfo { + char *name; + int64_t name_len; + char *table_name; + int64_t table_name_len; + char *sql; + int64_t sql_len; + char *rootpage; + int64_t rootpage_len; +}; + +struct DatabaseInfo { + uint64_t handle = 0; + wchar_t *db_name = NULL; + int64_t db_name_len = 0; + std::vector tables; + int64_t count = 0; + int64_t extrainfo = 0; +}; + +struct SqlResult { + char *column_name; + int64_t column_name_len; + char *content; + int64_t content_len; + bool is_blob; +}; + +struct InnerMessageStruct { + char *buffer; + int64_t length; + ~InnerMessageStruct() { + if (this->buffer != NULL) { + delete[] this->buffer; + this->buffer = NULL; + } + } +}; + +struct SelfInfoInner { + std::string name; + std::string city; + std::string province; + std::string country; + std::string account; + std::string wxid; + std::string mobile; + std::string head_img; + std::string data_save_path; + std::string signature; + std::string current_data_path; + std::string db_key; + std::string public_key; + std::string private_key; +}; + +struct ContactInner { + std::string wxid; + std::string custom_account; + std::string encrypt_name; + std::string nickname; + std::string pinyin; + std::string pinyin_all; + std::string remark; + std::string remark_pinyin; + std::string remark_pinyin_all; + std::string label_ids; + int32_t type; + int32_t verify_flag; + int32_t reserved1; + int32_t reserved2; + ContactInner() { + wxid = ""; + custom_account = ""; + encrypt_name = ""; + nickname = ""; + pinyin = ""; + pinyin_all = ""; + remark = ""; + remark_pinyin = ""; + remark_pinyin_all = ""; + label_ids = ""; + type = -1; + verify_flag = -1; + reserved1 = -1; + reserved2 = -1; + } +}; + +struct ChatRoomInfoInner { + std::string chat_room_id; + std::string notice; + std::string admin; + std::string xml; + ChatRoomInfoInner() { + chat_room_id = ""; + notice = ""; + admin = ""; + xml = ""; + } +}; + +struct VectorInner { +#ifdef _DEBUG + int64_t head; +#endif + int64_t start; + int64_t finsh; + int64_t end; +}; + +struct ChatRoomMemberInner { + std::string chat_room_id; + std::string admin; + std::string admin_nickname; + std::string member_nickname; + std::string member; + ChatRoomMemberInner() + : chat_room_id(""), + admin(""), + admin_nickname(""), + member_nickname(""), + member("") {} +}; + +struct ContactProfileInner { + std::string wxid; + std::string account; + std::string v3; + std::string nickname; + std::string head_image; + ContactProfileInner() + : wxid(""), account(""), v3(""), nickname(""), head_image("") {} +}; + +namespace function { +//hook + typedef uint64_t(*__DoAddMsg)(uint64_t, uint64_t, uint64_t); +//hook end + +typedef uint64_t (*__GetAccountService)(); +typedef uint64_t (*__GetDataSavePath)(uint64_t); +typedef uint64_t (*__GetCurrentDataPath)(uint64_t); +typedef uint64_t (*__GetSendMessageMgr)(); +typedef uint64_t (*__SendTextMsg)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t); +typedef uint64_t (*__FreeChatMsg)(uint64_t); + +typedef uint64_t (*__SendImageMsg)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__NewChatMsg)(uint64_t); +typedef uint64_t (*__SendFile)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetAppMsgMgr)(); +typedef uint64_t (*__OperatorNew)(uint64_t); + +typedef uint64_t (*__Free)(); +typedef uint64_t (*__GetContactMgr)(); +typedef uint64_t (*__GetContactList)(uint64_t, uint64_t); + +typedef uint64_t (*__GetChatRoomMgr)(); +typedef uint64_t (*__NewChatRoomInfo)(uint64_t); +typedef uint64_t (*__FreeChatRoomInfo)(uint64_t); +typedef uint64_t (*__GetChatRoomDetailInfo)(uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__DoAddMemberToChatRoom)(uint64_t, uint64_t, uint64_t, uint64_t); + +typedef uint64_t (*__DoModChatRoomMemberNickName)(uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__DoDelMemberFromChatRoom)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetMemberFromChatRoom)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__NewChatRoom)(uint64_t); +typedef uint64_t (*__FreeChatRoom)(uint64_t); + +typedef uint64_t (*__DoTopMsg)(uint64_t, uint64_t); +typedef uint64_t (*__RemoveTopMsg)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__InviteMemberToChatRoom)(uint64_t, uint64_t, uint64_t, uint64_t); + +typedef uint64_t (*__CreateChatRoom)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__QuitChatRoom)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__ForwardMsg)(uint64_t, uint64_t, uint64_t, uint64_t); + +typedef uint64_t (*__GetSNSFirstPage)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetSNSNextPageScene)(uint64_t, uint64_t); + +typedef uint64_t (*__GetSNSDataMgr)(); +typedef uint64_t (*__GetSnsTimeLineMgr)(); +typedef uint64_t (*__GetMgrByPrefixLocalId)(uint64_t, uint64_t); +typedef uint64_t (*__AddFavFromMsg)(uint64_t, uint64_t); +typedef uint64_t (*__GetChatMgr)(); +typedef uint64_t (*__GetFavoriteMgr)(); +typedef uint64_t (*__AddFavFromImage)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetContact)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__NewContact)(uint64_t); +typedef uint64_t (*__FreeContact)(uint64_t); +typedef uint64_t (*__NewMMReaderItem)(uint64_t); +typedef uint64_t (*__FreeMMReaderItem)(uint64_t); +typedef uint64_t (*__ForwordPublicMsg)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__NewAppMsgInfo)(uint64_t); +typedef uint64_t (*__FreeAppMsgInfo)(uint64_t); +typedef uint64_t (*__ParseAppMsgXml)(uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetPreDownLoadMgr)(); +typedef uint64_t (*__PushAttachTask)(uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__GetCustomSmileyMgr)(); +typedef uint64_t (*__SendCustomEmotion)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__JsApiShareAppMessage)(uint64_t); +typedef uint64_t (*__InitJsConfig)(uint64_t, uint64_t); +typedef uint64_t (*__SendApplet)(uint64_t, uint64_t, uint64_t, uint64_t); +typedef uint64_t (*__SendAppletSecond)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +typedef uint64_t (*__GetAppInfoByWaid)(uint64_t, uint64_t); +typedef uint64_t (*__CopyShareAppMessageRequest)(uint64_t, uint64_t); +typedef uint64_t (*__NewWAUpdatableMsgInfo)(uint64_t); +typedef uint64_t (*__FreeWAUpdatableMsgInfo)(uint64_t); +typedef uint64_t (*__SendPatMsg)(uint64_t, uint64_t); +typedef uint64_t (*__GetOCRManager)(); +typedef uint64_t (*__DoOCRTask)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); + + +typedef uint64_t (*__GetLockWechatMgr)(); +typedef uint64_t (*__RequestLockWechat)(uint64_t); +typedef uint64_t (*__RequestUnLockWechat)(uint64_t); +typedef uint64_t (*__OnLoginBtnClick)(uint64_t); +typedef uint64_t (*__GetQRCodeLoginMgr)(); +typedef uint64_t (*__UpdateMsg)(uint64_t,uint64_t,uint64_t); +typedef uint64_t (*__GetVoiceMgr)(); +typedef uint64_t (*__ChatMsg2NetSceneSendMsg)(uint64_t,uint64_t); +typedef uint64_t (*__TranslateVoice)(uint64_t,uint64_t,uint64_t); +typedef uint64_t (*__ShowWebView)(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +typedef uint64_t (*__NewWebViewPageConfig)(uint64_t); +typedef uint64_t (*__FreeWebViewPageConfig)(uint64_t); +typedef uint64_t (*__GetWebViewMgr)(); +typedef uint64_t (*__SetUrl)(uint64_t,uint64_t,uint64_t); + +} // namespace function + +namespace prototype { +struct WeChatString { + wchar_t *ptr; + int32_t length; + int32_t max_length; + int64_t c_ptr = 0; + int32_t c_len = 0; + WeChatString() { WeChatString(NULL); } + + WeChatString(const std::wstring &s) { + ptr = (wchar_t *)(s.c_str()); + length = static_cast(s.length()); + max_length = static_cast(s.length()); + } + WeChatString(const wchar_t *pStr) { WeChatString((wchar_t *)pStr); } + WeChatString(int tmp) { + ptr = NULL; + length = 0x0; + max_length = 0x0; + } + WeChatString(wchar_t *pStr) { + ptr = pStr; + length = static_cast(wcslen(pStr)); + max_length = static_cast(wcslen(pStr)); + } + void set_value(const wchar_t *pStr) { + ptr = (wchar_t *)pStr; + length = static_cast(wcslen(pStr)); + max_length = static_cast(wcslen(pStr) * 2); + } +}; + +struct WeChatStr { + char *ptr; + int64_t buf; + int64_t len; + int64_t maxlen; + + WeChatStr(const char *p) { + ptr = (char *)p; + buf = 0; + len = strlen(p); + maxlen = len | 0xF; + } + WeChatStr() { + ptr = NULL; + buf = 0; + len = 0; + maxlen = 0xF; + } +}; + +} // namespace prototype + +} // namespace wechat +#endif \ No newline at end of file diff --git a/app/wxhelper/src/wxhelper.cc b/app/wxhelper/src/wxhelper.cc new file mode 100644 index 0000000..3f82e8b --- /dev/null +++ b/app/wxhelper/src/wxhelper.cc @@ -0,0 +1,28 @@ +#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" +namespace wxhelper { + +void WxHelper::init(HMODULE module) { + Config::GetInstance().init(); + if (Config::GetInstance().GetHideDll()) { + // base::utils::HideModule(module); + } + // ChatController chatController; + // http::HttpRouter::GetInstance().init(); + http::HttpServer::GetInstance().init( + Config::GetInstance().GetHttpServerHost(), + Config::GetInstance().GetHttpServerPort()); + http::HttpServer::GetInstance().Start(); + base::ThreadPool::GetInstance().Create(2, 8); +} +void WxHelper::finally() { http::HttpServer::GetInstance().Stop(); } +} // namespace wxhelper \ No newline at end of file diff --git a/app/wxhelper/src/wxhelper.h b/app/wxhelper/src/wxhelper.h new file mode 100644 index 0000000..fc14fac --- /dev/null +++ b/app/wxhelper/src/wxhelper.h @@ -0,0 +1,14 @@ + +#ifndef WXHELPER_WXHELPER_H_ +#define WXHELPER_WXHELPER_H_ +#include +#include "singleton.h" +namespace wxhelper { + class WxHelper : public base::Singleton{ + + public: + void init(HMODULE module); + void finally(); + }; +} +#endif \ No newline at end of file