diff --git a/WeChatFerry/spy/contact_mgmt.cpp b/WeChatFerry/spy/contact_mgmt.cpp index 84f916a..1adae24 100644 --- a/WeChatFerry/spy/contact_mgmt.cpp +++ b/WeChatFerry/spy/contact_mgmt.cpp @@ -1,10 +1,15 @@ #pragma execution_character_set("utf-8") #include "contact_mgmt.h" +#include "fill_response.h" #include "log.hpp" #include "util.h" using namespace std; + +namespace contact_mgmt +{ + extern QWORD g_WeChatWinDllAddr; #define OS_GET_CONTACT_MGR 0x1B417A0 @@ -18,30 +23,29 @@ extern QWORD g_WeChatWinDllAddr; #define OS_CONTACT_GENDER 0x0E #define OS_CONTACT_STEP 0x6A8 -typedef QWORD (*GetContactMgr_t)(); -typedef QWORD (*GetContactList_t)(QWORD, QWORD); +using get_contact_mgr_t = QWORD (*)(); +using get_contact_list_t = QWORD (*)(QWORD, QWORD); #define FEAT_LEN 5 static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 }; static const uint8_t FEAT_PROVINCE[FEAT_LEN] = { 0xE2, 0xEA, 0xA8, 0xD1, 0x18 }; static const uint8_t FEAT_CITY[FEAT_LEN] = { 0x1D, 0x02, 0x5B, 0xBF, 0x18 }; -static QWORD FindMem(QWORD start, QWORD end, const void *target, size_t len) +static QWORD find_mem(QWORD start, QWORD end, const void *target, size_t len) { - uint8_t *p = (uint8_t *)start; - while ((QWORD)p < end) { - if (memcmp((void *)p, target, len) == 0) { - return (QWORD)p; + uint8_t *p = reinterpret_cast(start); + while (reinterpret_cast(p) < end) { + if (memcmp(p, target, len) == 0) { + return reinterpret_cast(p); } p++; } - return 0; } -static string GetCntString(QWORD start, QWORD end, const uint8_t *feat, size_t len) +static string get_cnt_string(QWORD start, QWORD end, const uint8_t *feat, size_t len) { - QWORD pfeat = FindMem(start, end, feat, len); + QWORD pfeat = find_mem(start, end, feat, len); if (pfeat == 0) { return ""; } @@ -54,21 +58,23 @@ static string GetCntString(QWORD start, QWORD end, const uint8_t *feat, size_t l return Wstring2String(wstring(GET_WSTRING_FROM_P(pfeat + FEAT_LEN + 4), lfeat)); } -vector GetContacts() +vector get_contacts() { vector contacts; - GetContactMgr_t funcGetContactMgr = (GetContactMgr_t)(g_WeChatWinDllAddr + OS_GET_CONTACT_MGR); - GetContactList_t funcGetContactList = (GetContactList_t)(g_WeChatWinDllAddr + OS_GET_CONTACT_LIST); + get_contact_mgr_t func_get_contact_mgr + = reinterpret_cast(g_WeChatWinDllAddr + OS_GET_CONTACT_MGR); + get_contact_list_t func_get_contact_list + = reinterpret_cast(g_WeChatWinDllAddr + OS_GET_CONTACT_LIST); - QWORD mgr = funcGetContactMgr(); + QWORD mgr = func_get_contact_mgr(); QWORD addr[3] = { 0 }; - if (funcGetContactList(mgr, (QWORD)addr) != 1) { - LOG_ERROR("GetContacts failed"); + if (func_get_contact_list(mgr, reinterpret_cast(addr)) != 1) { + LOG_ERROR("get_contacts failed"); return contacts; } - QWORD pstart = (QWORD)addr[0]; - QWORD pend = (QWORD)addr[2]; + QWORD pstart = addr[0]; + QWORD pend = addr[2]; while (pstart < pend) { RpcContact_t cnt; QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN); @@ -79,15 +85,11 @@ vector GetContacts() cnt.remark = GetStringByWstrAddr(pstart + OS_CONTACT_REMARK); cnt.name = GetStringByWstrAddr(pstart + OS_CONTACT_NAME); - cnt.country = GetCntString(pbin, pbin + lenbin, FEAT_COUNTRY, FEAT_LEN); - cnt.province = GetCntString(pbin, pbin + lenbin, FEAT_PROVINCE, FEAT_LEN); - cnt.city = GetCntString(pbin, pbin + lenbin, FEAT_CITY, FEAT_LEN); + cnt.country = get_cnt_string(pbin, pbin + lenbin, FEAT_COUNTRY, FEAT_LEN); + cnt.province = get_cnt_string(pbin, pbin + lenbin, FEAT_PROVINCE, FEAT_LEN); + cnt.city = get_cnt_string(pbin, pbin + lenbin, FEAT_CITY, FEAT_LEN); - if (pbin == 0) { - cnt.gender = 0; - } else { - cnt.gender = (DWORD) * (uint8_t *)(pbin + OS_CONTACT_GENDER); - } + cnt.gender = (pbin == 0) ? 0 : static_cast(*(uint8_t *)(pbin + OS_CONTACT_GENDER)); contacts.push_back(cnt); pstart += OS_CONTACT_STEP; @@ -96,68 +98,69 @@ vector GetContacts() return contacts; } -#if 0 -int AcceptNewFriend(string v3, string v4, int scene) +int accept_new_friend(string v3, string v4, int scene) { - int success = 0; - - DWORD acceptNewFriendCall1 = g_WeChatWinDllAddr + g_WxCalls.anf.call1; - DWORD acceptNewFriendCall2 = g_WeChatWinDllAddr + g_WxCalls.anf.call2; - DWORD acceptNewFriendCall3 = g_WeChatWinDllAddr + g_WxCalls.anf.call3; - DWORD acceptNewFriendCall4 = g_WeChatWinDllAddr + g_WxCalls.anf.call4; + int success = -1; +#if 0 + DWORD accept_new_friend_call1 = g_WeChatWinDllAddr + g_WxCalls.anf.call1; + DWORD accept_new_friend_call2 = g_WeChatWinDllAddr + g_WxCalls.anf.call2; + DWORD accept_new_friend_call3 = g_WeChatWinDllAddr + g_WxCalls.anf.call3; + DWORD accept_new_friend_call4 = g_WeChatWinDllAddr + g_WxCalls.anf.call4; char buffer[0x40] = { 0 }; char nullbuffer[0x3CC] = { 0 }; LOG_DEBUG("\nv3: {}\nv4: {}\nscene: {}", v3, v4, scene); - wstring wsV3 = String2Wstring(v3); - wstring wsV4 = String2Wstring(v4); - WxString wxV3(wsV3); - WxString wxV4(wsV4); + wstring ws_v3 = String2Wstring(v3); + wstring ws_v4 = String2Wstring(v4); + WxString wx_v3(ws_v3); + WxString wx_v4(ws_v4); __asm { pushad; pushfd; lea ecx, buffer; - call acceptNewFriendCall1; + call accept_new_friend_call1; mov esi, 0x0; mov edi, scene; push esi; push edi; sub esp, 0x14; mov ecx, esp; - lea eax, wxV4; + lea eax, wx_v4; push eax; - call acceptNewFriendCall2; + call accept_new_friend_call2; sub esp, 0x8; push 0x0; lea eax, nullbuffer; push eax; - lea eax, wxV3; + lea eax, wx_v3; push eax; lea ecx, buffer; - call acceptNewFriendCall3; + call accept_new_friend_call3; mov success, eax; lea ecx, buffer; - call acceptNewFriendCall4; + call accept_new_friend_call4; popfd; popad; } - +#endif return success; // 成功返回 1 } -/*没啥用,非好友获取不到*/ -RpcContact_t GetContactByWxid(string wxid) +RpcContact_t get_contact_by_wxid(string wxid) { RpcContact_t contact; +#if 0 char buff[0x440] = { 0 }; - wstring wsWxid = String2Wstring(wxid); - WxString pri(wsWxid); + wstring ws_wxid = String2Wstring(wxid); + WxString pri(ws_wxid); + DWORD contact_mgr_addr = g_WeChatWinDllAddr + 0x75A4A0; DWORD get_contact_addr = g_WeChatWinDllAddr + 0xC04E00; DWORD free_contact_addr = g_WeChatWinDllAddr + 0xEA7880; + __asm { PUSHAD PUSHFD @@ -173,10 +176,10 @@ RpcContact_t GetContactByWxid(string wxid) } contact.wxid = wxid; - contact.code = GetStringByWstrAddr((DWORD)buff + g_WxCalls.contact.wxCode); - contact.remark = GetStringByWstrAddr((DWORD)buff + g_WxCalls.contact.wxRemark); - contact.name = GetStringByWstrAddr((DWORD)buff + g_WxCalls.contact.wxName); - contact.gender = GET_DWORD((DWORD)buff + 0x148); + contact.code = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxCode); + contact.remark = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxRemark); + contact.name = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxName); + contact.gender = GET_DWORD(reinterpret_cast(buff) + 0x148); __asm { PUSHAD @@ -186,7 +189,32 @@ RpcContact_t GetContactByWxid(string wxid) POPFD POPAD } - +#endif return contact; } -#endif + +bool rpc_get_contacts(uint8_t *out, size_t *len) +{ + return fill_response(out, len, [](Response &rsp) { + vector contacts = get_contacts(); + rsp.msg.contacts.contacts.funcs.encode = encode_contacts; + rsp.msg.contacts.contacts.arg = &contacts; + }); +} + +bool rpc_get_contact_info(const string &wxid, uint8_t *out, size_t *len) +{ + return fill_response(out, len, [&](Response &rsp) { + vector contacts = { get_contact_by_wxid(wxid) }; + rsp.msg.contacts.contacts.funcs.encode = encode_contacts; + rsp.msg.contacts.contacts.arg = &contacts; + }); +} + +bool rpc_accept_friend(const string &v3, const string &v4, int scene, uint8_t *out, size_t *len) +{ + return fill_response( + out, len, [&](Response &rsp) { rsp.msg.status = accept_friend(v3, v4, scene); }); +} + +} // namespace contact_mgmt diff --git a/WeChatFerry/spy/contact_mgmt.h b/WeChatFerry/spy/contact_mgmt.h index 460bf89..3ff0662 100644 --- a/WeChatFerry/spy/contact_mgmt.h +++ b/WeChatFerry/spy/contact_mgmt.h @@ -1,11 +1,28 @@ #pragma once -#include "string" +#include #include #include "pb_types.h" -vector GetContacts(); -int AcceptNewFriend(std::string v3, std::string v4, int scene); -int AddFriendByWxid(std::string wxid, std::string msg); -RpcContact_t GetContactByWxid(std::string wxid); +namespace contact_mgmt +{ + +// 获取所有联系人 +std::vector get_contacts(); + +// 根据 wxid 获取联系人信息 +RpcContact_t get_contact_by_wxid(const std::string &wxid); + +// 接受好友请求 +int accept_friend(const std::string &v3, const std::string &v4, int scene); + +// 发送好友请求 +// int add_friend_by_wxid(const std::string &wxid, const std::string &msg); + +// RPC 方法 +bool rpc_get_contacts(uint8_t *out, size_t *len); +bool rpc_get_contact_info(const std::string &wxid, uint8_t *out, size_t *len); +bool rpc_accept_friend(const std::string &v3, const std::string &v4, int scene, uint8_t *out, size_t *len); + +} // namespace contact_mgmt diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index ab99536..e90fa6a 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -103,7 +103,7 @@ static bool func_get_msg_types(uint8_t *out, size_t *len) static bool func_get_contacts(uint8_t *out, size_t *len) { return FillResponse(Response_contacts_tag, out, len, [](Response &rsp) { - static std::vector contacts = GetContacts(); + static std::vector contacts = contact_mgmt::get_contacts(); rsp.msg.contacts.contacts.funcs.encode = encode_contacts; rsp.msg.contacts.contacts.arg = &contacts; }); @@ -410,7 +410,6 @@ static bool func_receive_transfer(char *wxid, char *tfid, char *taid, uint8_t *o }); } -#if 0 static bool func_accept_friend(char *v3, char *v4, int32_t scene, uint8_t *out, size_t *len) { return FillResponse(Response_status_tag, out, len, [v3, v4, scene](Response &rsp) { @@ -418,7 +417,7 @@ static bool func_accept_friend(char *v3, char *v4, int32_t scene, uint8_t *out, LOG_ERROR("Empty V3 or V4."); rsp.msg.status = -1; } else { - rsp.msg.status = AcceptNewFriend(v3, v4, scene); + rsp.msg.status = contact_mgmt::accept_friend(v3, v4, scene); } }); } @@ -426,15 +425,11 @@ static bool func_accept_friend(char *v3, char *v4, int32_t scene, uint8_t *out, static bool func_get_contact_info(std::string wxid, uint8_t *out, size_t *len) { return FillResponse(Response_contacts_tag, out, len, [wxid](Response &rsp) { - static std::vector contacts; - contacts.clear(); - contacts.push_back(GetContactByWxid(wxid)); - + std::vector contacts = contact_mgmt::get_contact_by_wxid(wxid); rsp.msg.contacts.contacts.funcs.encode = encode_contacts; rsp.msg.contacts.contacts.arg = &contacts; }); } -#endif static bool func_decrypt_image(DecPath dec, uint8_t *out, size_t *len) {