diff --git a/App/App.cpp b/App/App.cpp index ce5c043..1b7c148 100644 --- a/App/App.cpp +++ b/App/App.cpp @@ -20,6 +20,14 @@ void printContacts(ContactMap_t contacts) } } +void printDbNames(vector vDbs) +{ + wprintf(L"db numbers: %ld\n", vDbs.size()); + for (auto it = vDbs.begin(); it != vDbs.end(); ++it) { + wprintf(L"%s\n", (*it).c_str()); + } +} + int onTextMsg(WxMessage_t msg) { wprintf(L"%s msgType: %d, msgSource: %d, isSelf: %d\n", msg.id.c_str(), msg.type, msg.source, msg.self); @@ -45,14 +53,14 @@ int main() wprintf(L"%d\n", status); if (status != 0) { return 0; - } + } - // 获取消息类型 + // 获取消息类型 wprintf(L"获取消息类型\n"); const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes(); for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) { wprintf(L"%d: %s\n", it->first, it->second.c_str()); - } + } wprintf(L"Message: 接收通知中......\n"); WxSetTextMsgCb(onTextMsg); @@ -71,6 +79,11 @@ int main() // 测试获取联系人 auto mContact = WxGetContacts(); printContacts(mContact); + Sleep(1000); // 等待1秒 + + // 测试获取数据库名 + auto vDbNames = WxGetDbNames(); + printDbNames(vDbNames); while (1) { Sleep(10000); // 休眠,释放CPU diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl index 3b55c2a..138dede 100644 --- a/Rpc/rpc.idl +++ b/Rpc/rpc.idl @@ -6,7 +6,7 @@ interface ISpy { - import "oaidl.idl"; + import "oaidl.idl"; typedef struct RpcMessage { int self; // 是否自己发的消息:0=否,1=是 @@ -17,33 +17,36 @@ interface ISpy BSTR wxId; // 发送人微信ID BSTR roomId; // 群ID BSTR content; // 消息内容,MAC版最大:16384,即16KB - } RpcMessage_t; - + } RpcMessage_t; + + // 模拟 map typedef struct RpcIntBstrPair { - int key; + int key; BSTR value; - } RpcIntBstrPair_t; - typedef RpcIntBstrPair_t* PRpcIntBstrPair; - typedef RpcIntBstrPair_t** PPRpcIntBstrPair; - + } RpcIntBstrPair_t; + typedef RpcIntBstrPair_t *PRpcIntBstrPair; + typedef RpcIntBstrPair_t **PPRpcIntBstrPair; + typedef struct RpcContact { - BSTR wxId; - BSTR wxCode; - BSTR wxName; - BSTR wxCountry; - BSTR wxProvince; - BSTR wxCity; - BSTR wxGender; - } RpcContact_t; - typedef RpcContact_t *PRpcContact; - typedef RpcContact_t **PPRpcContact; + BSTR wxId; // 微信ID + BSTR wxCode; // 微信号 + BSTR wxName; // 微信昵称 + BSTR wxCountry; // 国家 + BSTR wxProvince; // 省/州 + BSTR wxCity; // 城市 + BSTR wxGender; // 性别 + } RpcContact_t; + typedef RpcContact_t *PRpcContact; + typedef RpcContact_t **PPRpcContact; int IsLogin(); - int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg); + int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, + [ in, string ] const wchar_t *msg); int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path); - int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes); - int GetContacts([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts); + int GetMsgTypes([out] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes); + int GetContacts([out] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts); + int GetDbNames([out] int *pNum, [ out, size_is(, *pNum) ] BSTR **dbs); void EnableReceiveMsg(); - [callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg); + [callback] int ReceiveMsg([in] RpcMessage_t rpcMsg); }; diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp index 269e656..ced9cc7 100644 --- a/SDK/rpc_client.cpp +++ b/SDK/rpc_client.cpp @@ -153,6 +153,27 @@ PPRpcContact RpcGetContacts(int *pNum) return ppRpcContacts; } +BSTR *RpcGetDbNames(int *pNum) +{ + int ret = 0; + unsigned long ulCode = 0; + BSTR *pBstr = NULL; + + RpcTryExcept { ret = client_GetDbNames(pNum, &pBstr); } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("RpcGetDbNames exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + if (ret != 0) { + printf("RpcGetDbNames Failed: %d\n", ret); + return NULL; + } + + return pBstr; +} + int server_ReceiveMsg(RpcMessage_t rpcMsg) { WxMessage_t msg; diff --git a/SDK/rpc_client.h b/SDK/rpc_client.h index 800d02c..8e9c9b2 100644 --- a/SDK/rpc_client.h +++ b/SDK/rpc_client.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "rpc_h.h" @@ -11,3 +11,4 @@ int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *m int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path); PPRpcIntBstrPair RpcGetMsgTypes(int *pNum); PPRpcContact RpcGetContacts(int *pNum); +BSTR *RpcGetDbNames(int *pNum); diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index de7e39f..f773100 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -171,3 +171,19 @@ ContactMap_t WxGetContacts() return mContact; } + +std::vector WxGetDbNames() +{ + std::vector vDbs; + int size = 0; + BSTR *pBstr = RpcGetDbNames(&size); + for (int i = 0; i < size; i++) { + vDbs.push_back(GetWstringFromBstr(pBstr[i])); + } + + if (pBstr) { + midl_user_free(pBstr); + } + + return vDbs; +} diff --git a/SDK/sdk.def b/SDK/sdk.def index 5e4375c..0ab525a 100644 --- a/SDK/sdk.def +++ b/SDK/sdk.def @@ -1,7 +1,8 @@ -EXPORTS +EXPORTS WxInitSDK WxSetTextMsgCb WxSendTextMsg WxGetMsgTypes WxSendImageMsg - WxGetContacts + WxGetContacts + WxGetDbNames diff --git a/SDK/sdk.h b/SDK/sdk.h index 06d1a87..f748d21 100644 --- a/SDK/sdk.h +++ b/SDK/sdk.h @@ -3,6 +3,7 @@ #include #include #include +#include using namespace std; @@ -18,13 +19,13 @@ typedef struct WxMessage { } WxMessage_t; typedef struct WxContact { - wstring wxId; - wstring wxCode; - wstring wxName; - wstring wxCountry; - wstring wxProvince; - wstring wxCity; - wstring wxGender; + wstring wxId; // 微信ID + wstring wxCode; // 微信号 + wstring wxName; // 微信昵称 + wstring wxCountry; // 国家 + wstring wxProvince; // 省/州 + wstring wxCity; // 城市 + wstring wxGender; // 性别 } WxContact_t; typedef map MsgTypesMap_t; @@ -36,3 +37,4 @@ int WxSendTextMsg(wstring wxid, wstring at_wxid, wstring msg); int WxSendImageMsg(wstring wxid, wstring path); ContactMap_t WxGetContacts(); MsgTypesMap_t WxGetMsgTypes(); +vector WxGetDbNames(); diff --git a/SDK/util.cpp b/SDK/util.cpp index 61100be..b3731de 100644 --- a/SDK/util.cpp +++ b/SDK/util.cpp @@ -187,6 +187,14 @@ wstring GetWstringFromBstr(BSTR p) return ws; } +BSTR GetBstrFromWstring(wstring ws) +{ + if (!ws.empty()) { + return SysAllocStringLen(ws.data(), ws.size()); + } + return NULL; +} + void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg) { wxMsg->self = rpcMsg.self; diff --git a/SDK/util.h b/SDK/util.h index 0579361..15194d1 100644 --- a/SDK/util.h +++ b/SDK/util.h @@ -1,9 +1,9 @@ -#pragma once +#pragma once + +#include -#include - -#include "sdk.h" #include "rpc_h.h" +#include "sdk.h" #define WECHAREXE L"WeChat.exe" #define WECHATWINDLL L"WeChatWin.dll" @@ -19,9 +19,10 @@ int GetWeChatPath(wchar_t *path); int GetWeChatWinDLLPath(wchar_t *path); int GetWeChatVersion(wchar_t *version); bool GetFileVersion(const wchar_t *filePath, wchar_t *version); -int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size); -BSTR GetBstrByAddress(DWORD address); +int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size); +BSTR GetBstrByAddress(DWORD address); void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg); -DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address); +DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address); std::wstring GetWstringFromBstr(BSTR p); +BSTR GetBstrFromWstring(std::wstring ws); std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address); diff --git a/Spy/Spy.vcxproj b/Spy/Spy.vcxproj index 8eae960..7c79f57 100644 --- a/Spy/Spy.vcxproj +++ b/Spy/Spy.vcxproj @@ -166,6 +166,7 @@ + @@ -180,6 +181,7 @@ + diff --git a/Spy/Spy.vcxproj.filters b/Spy/Spy.vcxproj.filters index be1f776..0988c9e 100644 --- a/Spy/Spy.vcxproj.filters +++ b/Spy/Spy.vcxproj.filters @@ -48,6 +48,9 @@ 头文件 + + 头文件 + @@ -80,6 +83,9 @@ 源文件 + + 源文件 + diff --git a/Spy/exec_sql.cpp b/Spy/exec_sql.cpp new file mode 100644 index 0000000..f2f4d3e --- /dev/null +++ b/Spy/exec_sql.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "exec_sql.h" +#include "load_calls.h" + +using namespace std; + +extern WxCalls_t g_WxCalls; +extern DWORD g_WeChatWinDllAddr; + +typedef map dbMap_t; +static dbMap_t dbMap; + +vector GetDbNames() +{ + vector vDbs; + if (dbMap.empty()) { + DWORD sqlHandleBaseAddr = *(DWORD *)(g_WeChatWinDllAddr + g_WxCalls.sql.base); + DWORD sqlHandleBeginAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.start); + DWORD sqlHandleEndAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.end); + while (sqlHandleBeginAddr < sqlHandleEndAddr) { + DWORD dwHandle = *(DWORD *)sqlHandleBeginAddr; + dbMap[wstring((wchar_t *)(*(DWORD *)(dwHandle + g_WxCalls.sql.name)))] + = *(DWORD *)(dwHandle + g_WxCalls.sql.slot); + sqlHandleBeginAddr += 0x04; + } + } + for (auto it = dbMap.begin(); it != dbMap.end(); it++) { + vDbs.push_back(it->first); + } + return vDbs; +} diff --git a/Spy/exec_sql.h b/Spy/exec_sql.h new file mode 100644 index 0000000..d004b23 --- /dev/null +++ b/Spy/exec_sql.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +#include "rpc_h.h" + +std::vector GetDbNames(); diff --git a/Spy/load_calls.cpp b/Spy/load_calls.cpp index 0145286..e484f30 100644 --- a/Spy/load_calls.cpp +++ b/Spy/load_calls.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "load_calls.h" @@ -13,7 +13,10 @@ WxCalls_t wxCalls = { 0x23631D0, // Login Status { 0xBD780, 0x770120, 0x521640 }, // Send Image Message /* Get Contacts: Base, head, wxId, Code, Name, Gender, Country, Province, City*/ - { 0x23638F4, 0x4C, 0x30, 0x44, 0x8C, 0x184, 0x1D0, 0x1E4, 0x1F8 } }; + { 0x23638F4, 0x4C, 0x30, 0x44, 0x8C, 0x184, 0x1D0, 0x1E4, 0x1F8 }, + /* Exec Sql: + Exec, base, start, end, slot, name*/ + { 0x141A4D0, 0x2363934, 0x1428, 0x142C, 0x3C, 0x50 } }; int LoadCalls(const wchar_t *version, WxCalls_t *calls) { diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp index 972d8d3..d6e9a97 100644 --- a/Spy/rpc_server.cpp +++ b/Spy/rpc_server.cpp @@ -1,6 +1,7 @@ #include #include +#include "exec_sql.h" #include "get_contacts.h" #include "monitor.h" #include "rpc_h.h" @@ -8,6 +9,9 @@ #include "sdk.h" #include "send_msg.h" #include "spy_types.h" +#include "util.h" + +using namespace std; extern HANDLE g_hEvent; extern MsgQueue_t g_MsgQueue; @@ -82,7 +86,7 @@ int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes) int server_GetContacts(int *pNum, PPRpcContact *contacts) { - std::vector vContacts = GetContacts(); + vector vContacts = GetContacts(); *pNum = vContacts.size(); PPRpcContact pp = (PPRpcContact)midl_user_allocate(*pNum * sizeof(RpcContact_t)); @@ -115,6 +119,26 @@ int server_GetContacts(int *pNum, PPRpcContact *contacts) return 0; } +int server_GetDbNames(int *pNum, BSTR **dbs) +{ + vector vDbs = GetDbNames(); + *pNum = vDbs.size(); + BSTR *pp = (BSTR *)midl_user_allocate(*pNum * sizeof(BSTR)); + if (pp == NULL) { + printf("server_GetMsgTypes midl_user_allocate Failed for pp\n"); + return -2; + } + + int index = 0; + for (auto it = vDbs.begin(); it != vDbs.end(); it++) { + pp[index++] = GetBstrFromWstring(*it); + } + + *dbs = pp; + + return 0; +} + RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/) { return RPC_S_OK; // Always allow anyone. diff --git a/Spy/spy_types.h b/Spy/spy_types.h index a565153..a56754c 100644 --- a/Spy/spy_types.h +++ b/Spy/spy_types.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "framework.h" #include @@ -41,6 +41,15 @@ typedef struct Contact { DWORD wxCity; } Contact_t; +typedef struct Sql { + DWORD exec; + DWORD base; + DWORD start; + DWORD end; + DWORD slot; + DWORD name; +} Sql_t; + typedef struct WxCalls { DWORD login; // 登录状态 UserInfoCall_t ui; // 用户信息 @@ -48,7 +57,8 @@ typedef struct WxCalls { RecvMsg_t recvMsg; // 接收消息 SendImg_t sendImg; // 发送图片 Contact_t contact; // 获取联系人 -} WxCalls_t; + Sql_t sql; // 执行 SQL +} WxCalls_t; typedef struct TextStruct { wchar_t *text;