From ce0fb49956e5abf997023c8bb9024848b065287d Mon Sep 17 00:00:00 2001 From: Changhua Date: Fri, 7 Mar 2025 18:32:55 +0800 Subject: [PATCH] chore(spy): remove unsed files --- WeChatFerry/spy/contact_mgmt.cpp | 193 -------------- WeChatFerry/spy/exec_sql.cpp | 233 ---------------- WeChatFerry/spy/funcs.cpp | 445 ------------------------------- WeChatFerry/spy/receive_msg.cpp | 379 -------------------------- WeChatFerry/spy/send_msg.cpp | 274 ------------------- WeChatFerry/spy/user_info.cpp | 59 ---- 6 files changed, 1583 deletions(-) delete mode 100644 WeChatFerry/spy/contact_mgmt.cpp delete mode 100644 WeChatFerry/spy/exec_sql.cpp delete mode 100644 WeChatFerry/spy/funcs.cpp delete mode 100644 WeChatFerry/spy/receive_msg.cpp delete mode 100644 WeChatFerry/spy/send_msg.cpp delete mode 100644 WeChatFerry/spy/user_info.cpp diff --git a/WeChatFerry/spy/contact_mgmt.cpp b/WeChatFerry/spy/contact_mgmt.cpp deleted file mode 100644 index b00152d..0000000 --- a/WeChatFerry/spy/contact_mgmt.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#pragma execution_character_set("utf-8") - -#include "contact_mgmt.h" -#include "log.h" -#include "util.h" - -using namespace std; -extern QWORD g_WeChatWinDllAddr; - -#define OS_GET_CONTACT_MGR 0x1B470B0 -#define OS_GET_CONTACT_LIST 0x21A49D0 -#define OS_CONTACT_BIN 0x200 -#define OS_CONTACT_BIN_LEN 0x208 -#define OS_CONTACT_WXID 0x10 -#define OS_CONTACT_CODE 0x30 -#define OS_CONTACT_REMARK 0x80 -#define OS_CONTACT_NAME 0xA0 -#define OS_CONTACT_GENDER 0x0E -#define OS_CONTACT_STEP 0x6A8 - -typedef QWORD (*GetContactMgr_t)(); -typedef QWORD (*GetContactList_t)(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) -{ - uint8_t *p = (uint8_t *)start; - while ((QWORD)p < end) { - if (memcmp((void *)p, target, len) == 0) { - return (QWORD)p; - } - p++; - } - - return 0; -} - -static string GetCntString(QWORD start, QWORD end, const uint8_t *feat, size_t len) -{ - QWORD pfeat = FindMem(start, end, feat, len); - if (pfeat == 0) { - return ""; - } - - DWORD lfeat = GET_DWORD(pfeat + len); - if (lfeat <= 2) { - return ""; - } - - return Wstring2String(wstring(GET_WSTRING_FROM_P(pfeat + FEAT_LEN + 4), lfeat)); -} - -vector GetContacts() -{ - vector contacts; - GetContactMgr_t funcGetContactMgr = (GetContactMgr_t)(g_WeChatWinDllAddr + OS_GET_CONTACT_MGR); - GetContactList_t funcGetContactList = (GetContactList_t)(g_WeChatWinDllAddr + OS_GET_CONTACT_LIST); - - QWORD mgr = funcGetContactMgr(); - QWORD addr[3] = { 0 }; - if (funcGetContactList(mgr, (QWORD)addr) != 1) { - LOG_ERROR("GetContacts failed"); - return contacts; - } - - QWORD pstart = (QWORD)addr[0]; - QWORD pend = (QWORD)addr[2]; - while (pstart < pend) { - RpcContact_t cnt; - QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN); - QWORD lenbin = GET_DWORD(pstart + OS_CONTACT_BIN_LEN); - - cnt.wxid = GetStringByWstrAddr(pstart + OS_CONTACT_WXID); - cnt.code = GetStringByWstrAddr(pstart + OS_CONTACT_CODE); - 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); - - if (pbin == 0) { - cnt.gender = 0; - } else { - cnt.gender = (DWORD) * (uint8_t *)(pbin + OS_CONTACT_GENDER); - } - - contacts.push_back(cnt); - pstart += OS_CONTACT_STEP; - } - - return contacts; -} - -#if 0 -int AcceptNewFriend(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; - - 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); - - __asm { - pushad; - pushfd; - lea ecx, buffer; - call acceptNewFriendCall1; - mov esi, 0x0; - mov edi, scene; - push esi; - push edi; - sub esp, 0x14; - mov ecx, esp; - lea eax, wxV4; - push eax; - call acceptNewFriendCall2; - sub esp, 0x8; - push 0x0; - lea eax, nullbuffer; - push eax; - lea eax, wxV3; - push eax; - lea ecx, buffer; - call acceptNewFriendCall3; - mov success, eax; - lea ecx, buffer; - call acceptNewFriendCall4; - popfd; - popad; - } - - return success; // 成功返回 1 -} - -/*没啥用,非好友获取不到*/ -RpcContact_t GetContactByWxid(string wxid) -{ - RpcContact_t contact; - char buff[0x440] = { 0 }; - wstring wsWxid = String2Wstring(wxid); - WxString pri(wsWxid); - DWORD contact_mgr_addr = g_WeChatWinDllAddr + 0x75A4A0; - DWORD get_contact_addr = g_WeChatWinDllAddr + 0xC04E00; - DWORD free_contact_addr = g_WeChatWinDllAddr + 0xEA7880; - __asm { - PUSHAD - PUSHFD - CALL contact_mgr_addr - LEA ECX,buff - PUSH ECX - LEA ECX,pri - PUSH ECX - MOV ECX,EAX - CALL get_contact_addr - POPFD - POPAD - } - - 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); - - __asm { - PUSHAD - PUSHFD - LEA ECX,buff - CALL free_contact_addr - POPFD - POPAD - } - - return contact; -} -#endif - diff --git a/WeChatFerry/spy/exec_sql.cpp b/WeChatFerry/spy/exec_sql.cpp deleted file mode 100644 index 5e8b857..0000000 --- a/WeChatFerry/spy/exec_sql.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include - -#include "exec_sql.h" -#include "log.h" -#include "sqlite3.h" -#include "util.h" - -#define OFFSET_DB_INSTANCE 0x59C5B48 -#define OFFSET_DB_MICROMSG 0xB8 -#define OFFSET_DB_CHAT_MSG 0x2C8 -#define OFFSET_DB_MISC 0x5F0 -#define OFFSET_DB_EMOTION 0x15F0 -#define OFFSET_DB_MEDIA 0xF48 -#define OFFSET_DB_BIZCHAT_MSG 0x1A70 -#define OFFSET_DB_FUNCTION_MSG 0x1B98 -#define OFFSET_DB_NAME 0x28 -#define OFFSET_DB_MSG_MGR 0x5A23888 - -extern UINT64 g_WeChatWinDllAddr; - -typedef map dbMap_t; -static dbMap_t dbMap; - -static void GetDbHandle(QWORD base, QWORD offset) -{ - wchar_t *wsp = (wchar_t *)(*(QWORD *)(base + offset + OFFSET_DB_NAME)); - string dbname = Wstring2String(wstring(wsp)); - dbMap[dbname] = GET_QWORD(base + offset); -} - -static void GetMsgDbHandle(QWORD msgMgrAddr) -{ - QWORD dbIndex = GET_QWORD(msgMgrAddr + 0x68); - QWORD pStart = GET_QWORD(msgMgrAddr + 0x50); - for (uint32_t i = 0; i < dbIndex; i++) { - QWORD dbAddr = GET_QWORD(pStart + i * 0x08); - if (dbAddr) { - // MSGi.db - string dbname = Wstring2String(GET_WSTRING(dbAddr)); - dbMap[dbname] = GET_QWORD(dbAddr + 0x78); - - // MediaMsgi.db - QWORD mmdbAddr = GET_QWORD(dbAddr + 0x20); - string mmdbname = Wstring2String(GET_WSTRING(mmdbAddr + 0x78)); - dbMap[mmdbname] = GET_QWORD(mmdbAddr + 0x50); - } - } -} - -dbMap_t GetDbHandles() -{ - dbMap.clear(); - - QWORD dbInstanceAddr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_INSTANCE); - - GetDbHandle(dbInstanceAddr, OFFSET_DB_MICROMSG); // MicroMsg.db - GetDbHandle(dbInstanceAddr, OFFSET_DB_CHAT_MSG); // ChatMsg.db - GetDbHandle(dbInstanceAddr, OFFSET_DB_MISC); // Misc.db - GetDbHandle(dbInstanceAddr, OFFSET_DB_EMOTION); // Emotion.db - GetDbHandle(dbInstanceAddr, OFFSET_DB_MEDIA); // Media.db - GetDbHandle(dbInstanceAddr, OFFSET_DB_FUNCTION_MSG); // Function.db - - GetMsgDbHandle(GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR)); // MSGi.db & MediaMsgi.db - - return dbMap; -} - -DbNames_t GetDbNames() -{ - DbNames_t names; - if (dbMap.empty()) { - dbMap = GetDbHandles(); - } - - for (auto &[k, v] : dbMap) { - names.push_back(k); - } - - return names; -} - -static int cbGetTables(void *ret, int argc, char **argv, char **azColName) -{ - DbTables_t *tbls = (DbTables_t *)ret; - DbTable_t tbl; - for (int i = 0; i < argc; i++) { - if (strcmp(azColName[i], "name") == 0) { - tbl.name = argv[i] ? argv[i] : ""; - } else if (strcmp(azColName[i], "sql") == 0) { - string sql(argv[i]); - sql.erase(std::remove(sql.begin(), sql.end(), '\t'), sql.end()); - tbl.sql = sql.c_str(); - } - } - tbls->push_back(tbl); - return 0; -} - -DbTables_t GetDbTables(const string db) -{ - DbTables_t tables; - if (dbMap.empty()) { - dbMap = GetDbHandles(); - } - - auto it = dbMap.find(db); - if (it == dbMap.end()) { - return tables; // DB not found - } - - const char *sql = "select name, sql from sqlite_master where type=\"table\";"; - Sqlite3_exec p_Sqlite3_exec = (Sqlite3_exec)(g_WeChatWinDllAddr + SQLITE3_EXEC_OFFSET); - - p_Sqlite3_exec(it->second, sql, (Sqlite3_callback)cbGetTables, (void *)&tables, 0); - - return tables; -} - -DbRows_t ExecDbQuery(const string db, const string sql) -{ - DbRows_t rows; - Sqlite3_prepare func_prepare = (Sqlite3_prepare)(g_WeChatWinDllAddr + SQLITE3_PREPARE_OFFSET); - Sqlite3_step func_step = (Sqlite3_step)(g_WeChatWinDllAddr + SQLITE3_STEP_OFFSET); - Sqlite3_column_count func_column_count = (Sqlite3_column_count)(g_WeChatWinDllAddr + SQLITE3_COLUMN_COUNT_OFFSET); - Sqlite3_column_name func_column_name = (Sqlite3_column_name)(g_WeChatWinDllAddr + SQLITE3_COLUMN_NAME_OFFSET); - Sqlite3_column_type func_column_type = (Sqlite3_column_type)(g_WeChatWinDllAddr + SQLITE3_COLUMN_TYPE_OFFSET); - Sqlite3_column_blob func_column_blob = (Sqlite3_column_blob)(g_WeChatWinDllAddr + SQLITE3_COLUMN_BLOB_OFFSET); - Sqlite3_column_bytes func_column_bytes = (Sqlite3_column_bytes)(g_WeChatWinDllAddr + SQLITE3_COLUMN_BYTES_OFFSET); - Sqlite3_finalize func_finalize = (Sqlite3_finalize)(g_WeChatWinDllAddr + SQLITE3_FINALIZE_OFFSET); - - if (dbMap.empty()) { - dbMap = GetDbHandles(); - } - - QWORD *stmt; - QWORD handle = dbMap[db]; - if (handle == 0) { - LOG_WARN("Empty handle, retrying..."); - dbMap = GetDbHandles(); - } - - int rc = func_prepare(dbMap[db], sql.c_str(), -1, &stmt, 0); - if (rc != SQLITE_OK) { - return rows; - } - - while (func_step(stmt) == SQLITE_ROW) { - DbRow_t row; - int col_count = func_column_count(stmt); - for (int i = 0; i < col_count; i++) { - DbField_t field; - field.type = func_column_type(stmt, i); - field.column = func_column_name(stmt, i); - - int length = func_column_bytes(stmt, i); - const void *blob = func_column_blob(stmt, i); - if (length && (field.type != 5)) { - field.content.reserve(length); - copy((uint8_t *)blob, (uint8_t *)blob + length, back_inserter(field.content)); - } - row.push_back(field); - } - rows.push_back(row); - } - return rows; -} - -int GetLocalIdandDbidx(uint64_t id, uint64_t *localId, uint32_t *dbIdx) -{ - QWORD msgMgrAddr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR); - int dbIndex = (int)GET_QWORD(msgMgrAddr + 0x68); // 总不能 int 还不够吧? - QWORD pStart = GET_QWORD(msgMgrAddr + 0x50); - - *dbIdx = 0; - for (int i = dbIndex - 1; i >= 0; i--) { // 从后往前遍历 - QWORD dbAddr = GET_QWORD(pStart + i * 0x08); - if (dbAddr) { - string dbname = Wstring2String(GET_WSTRING(dbAddr)); - dbMap[dbname] = GET_QWORD(dbAddr + 0x78); - string sql = "SELECT localId FROM MSG WHERE MsgSvrID=" + to_string(id) + ";"; - DbRows_t rows = ExecDbQuery(dbname, sql); - if (rows.empty()) { - continue; - } - DbRow_t row = rows.front(); - if (row.empty()) { - continue; - } - DbField_t field = row.front(); - if ((field.column.compare("localId") != 0) && (field.type != 1)) { - continue; - } - - *localId = strtoull((const char *)(field.content.data()), NULL, 10); - *dbIdx = (uint32_t)(GET_QWORD(GET_QWORD(dbAddr + 0x28) + 0x1E8) >> 32); - - return 0; - } - } - - return -1; -} - -vector GetAudioData(uint64_t id) -{ - QWORD msgMgrAddr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR); - int dbIndex = (int)GET_QWORD(msgMgrAddr + 0x68); - - string sql = "SELECT Buf FROM Media WHERE Reserved0=" + to_string(id) + ";"; - for (int i = dbIndex - 1; i >= 0; i--) { - string dbname = "MediaMSG" + to_string(i) + ".db"; - DbRows_t rows = ExecDbQuery(dbname, sql); - if (rows.empty()) { - continue; - } - DbRow_t row = rows.front(); - if (row.empty()) { - continue; - } - DbField_t field = row.front(); - if (field.column.compare("Buf") != 0) { - continue; - } - - // 首字节为 0x02,估计是混淆用的?去掉。 - vector rv(field.content.begin() + 1, field.content.end()); - - return rv; - } - - return vector(); -} - diff --git a/WeChatFerry/spy/funcs.cpp b/WeChatFerry/spy/funcs.cpp deleted file mode 100644 index 7eefed7..0000000 --- a/WeChatFerry/spy/funcs.cpp +++ /dev/null @@ -1,445 +0,0 @@ -#pragma warning(disable : 4244) - -#include "framework.h" -#include -#include -#include -#include - -#include "codec.h" -#include "exec_sql.h" -#include "funcs.h" -#include "log.h" -#include "spy_types.h" -#include "util.h" - -using namespace std; -namespace fs = std::filesystem; - -extern bool gIsListeningPyq; -extern QWORD g_WeChatWinDllAddr; - -#define HEADER_PNG1 0x89 -#define HEADER_PNG2 0x50 -#define HEADER_JPG1 0xFF -#define HEADER_JPG2 0xD8 -#define HEADER_GIF1 0x47 -#define HEADER_GIF2 0x49 - -#define OS_LOGIN_STATUS 0x5A20978 -#define OS_GET_SNS_DATA_MGR 0x21E7EC0 -#define OS_GET_SNS_FIRST_PAGE 0x2E37960 -#define OS_GET_SNS_TIMELINE_MGR 0x2DC9470 -#define OS_GET_SNS_NEXT_PAGE 0x2EDF4D0 -#define OS_NEW_CHAT_MSG 0x1B63A50 -#define OS_FREE_CHAT_MSG 0x1B5B160 -#define OS_GET_CHAT_MGR 0x1B8CFD0 -#define OS_GET_MGR_BY_PREFIX_LOCAL_ID 0x2145220 -#define OS_GET_PRE_DOWNLOAD_MGR 0x1C14930 -#define OS_PUSH_ATTACH_TASK 0x1CE57B0 -#define OS_LOGIN_QR_CODE 0x5A26440 - -typedef QWORD (*GetSNSDataMgr_t)(); -typedef QWORD (*GetSnsTimeLineMgr_t)(); -typedef QWORD (*GetSNSFirstPage_t)(QWORD, QWORD, QWORD); -typedef QWORD (*GetSNSNextPageScene_t)(QWORD, QWORD); -typedef QWORD (*GetChatMgr_t)(); -typedef QWORD (*NewChatMsg_t)(QWORD); -typedef QWORD (*FreeChatMsg_t)(QWORD); -typedef QWORD (*GetPreDownLoadMgr_t)(); -typedef QWORD (*GetMgrByPrefixLocalId_t)(QWORD, QWORD); -typedef QWORD (*PushAttachTask_t)(QWORD, QWORD, QWORD, QWORD); -typedef QWORD (*GetOCRManager_t)(); -typedef QWORD (*DoOCRTask_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); - -int IsLogin(void) { return (int)GET_QWORD(g_WeChatWinDllAddr + OS_LOGIN_STATUS); } - -static string get_key(uint8_t header1, uint8_t header2, uint8_t *key) -{ - // PNG? - *key = HEADER_PNG1 ^ header1; - if ((HEADER_PNG2 ^ *key) == header2) { - return ".png"; - } - - // JPG? - *key = HEADER_JPG1 ^ header1; - if ((HEADER_JPG2 ^ *key) == header2) { - return ".jpg"; - } - - // GIF? - *key = HEADER_GIF1 ^ header1; - if ((HEADER_GIF2 ^ *key) == header2) { - return ".gif"; - } - - return ""; // 错误 -} - -// 创建多级目录 -bool CreateDir(const char* dir) -{ - int m = 0, n; - string str1, str2; - str1 = dir; - str2 = str1.substr(0, 2); - str1 = str1.substr(3, str1.size()); - while (m >= 0) - { - m = str1.find('/'); - - str2 += '/' + str1.substr(0, m); - //判断该目录是否存在 - n = _access(str2.c_str(), 0); - if (n == -1) - { - //创建目录文件 - int flag = _mkdir(str2.c_str()); - if (flag != 0) { //创建失败 - LOG_ERROR("Failed to CreateDir:{}", dir); - return false; - } - } - - str1 = str1.substr(m + 1, str1.size()); - } - LOG_DEBUG("CreateDir {} success.", dir); - return true; -} - -string DecryptImage(string src, string dir) -{ - if (!fs::exists(src)) { - LOG_ERROR("File not exists: {}", src); - return ""; - } - - ifstream in(src.c_str(), ios::binary); - if (!in.is_open()) { - LOG_ERROR("Failed to read file {}", src); - return ""; - } - - filebuf *pfb = in.rdbuf(); - size_t size = pfb->pubseekoff(0, ios::end, ios::in); - pfb->pubseekpos(0, ios::in); - - vector buff; - buff.reserve(size); - char *pBuf = buff.data(); - pfb->sgetn(pBuf, size); - in.close(); - - uint8_t key = 0x00; - string ext = get_key(pBuf[0], pBuf[1], &key); - if (ext.empty()) { - LOG_ERROR("Failed to get key."); - return ""; - } - - for (size_t i = 0; i < size; i++) { - pBuf[i] ^= key; - } - - string dst = ""; - - try { - if (dir.empty()) { - dst = fs::path(src).replace_extension(ext).string(); - } else { - dst = (dir.back() == '\\' || dir.back() == '/') ? dir : (dir + "/"); - replace(dst.begin(), dst.end(), '\\', '/'); - - // 判断dir文件夹是否存在,若不存在则创建(否则将无法创建出文件) - if (_access(dst.c_str(), 0) == -1) {//判断该文件夹是否存在 - bool success = CreateDir(dst.c_str()); //Windows创建文件夹 - if (!success) { //创建失败 - LOG_ERROR("Failed to mkdir:{}", dst); - return ""; - } - } - - dst += fs::path(src).stem().string() + ext; - } - - replace(dst.begin(), dst.end(), '\\', '/'); - } catch (const std::exception &e) { - LOG_ERROR(GB2312ToUtf8(e.what())); - } catch (...) { - LOG_ERROR("Unknow exception."); - return ""; - } - - ofstream out(dst.c_str(), ios::binary); - if (!out.is_open()) { - LOG_ERROR("Failed to write file {}", dst); - return ""; - } - - out.write(pBuf, size); - out.close(); - - return dst; -} - -static int GetFirstPage() -{ - int status = -1; - - GetSNSDataMgr_t GetSNSDataMgr = (GetSNSDataMgr_t)(g_WeChatWinDllAddr + OS_GET_SNS_DATA_MGR); - GetSNSFirstPage_t GetSNSFirstPage = (GetSNSFirstPage_t)(g_WeChatWinDllAddr + OS_GET_SNS_FIRST_PAGE); - - QWORD buff[16] = { 0 }; - QWORD mgr = GetSNSDataMgr(); - status = (int)GetSNSFirstPage(mgr, (QWORD)buff, 1); - - return status; -} - -static int GetNextPage(QWORD id) -{ - int status = -1; - - GetSnsTimeLineMgr_t GetSnsTimeLineMgr = (GetSnsTimeLineMgr_t)(g_WeChatWinDllAddr + OS_GET_SNS_TIMELINE_MGR); - GetSNSNextPageScene_t GetSNSNextPageScene = (GetSNSNextPageScene_t)(g_WeChatWinDllAddr + OS_GET_SNS_NEXT_PAGE); - - QWORD mgr = GetSnsTimeLineMgr(); - status = (int)GetSNSNextPageScene(mgr, id); - - return status; -} - -int RefreshPyq(QWORD id) -{ - if (!gIsListeningPyq) { - LOG_ERROR("没有启动朋友圈消息接收,参考:enable_receiving_msg"); - return -1; - } - - if (id == 0) { - return GetFirstPage(); - } - - return GetNextPage(id); -} - -/******************************************************************************* - * 都说我不写注释,写一下吧 - * 其实也没啥好写的,就是下载资源 - * 主要介绍一下几个参数: - * id:好理解,消息 id - * thumb:图片或者视频的缩略图路径;如果是视频,后缀为 mp4 后就是存在路径了 - * extra:图片、文件的路径 - *******************************************************************************/ -int DownloadAttach(QWORD id, string thumb, string extra) -{ - int status = -1; - QWORD localId; - uint32_t dbIdx; - - if (fs::exists(extra)) { // 第一道,不重复下载。TODO: 通过文件大小来判断 - return 0; - } - - if (GetLocalIdandDbidx(id, &localId, &dbIdx) != 0) { - LOG_ERROR("Failed to get localId, Please check id: {}", to_string(id)); - return status; - } - - NewChatMsg_t NewChatMsg = (NewChatMsg_t)(g_WeChatWinDllAddr + OS_NEW_CHAT_MSG); - FreeChatMsg_t FreeChatMsg = (FreeChatMsg_t)(g_WeChatWinDllAddr + OS_FREE_CHAT_MSG); - GetChatMgr_t GetChatMgr = (GetChatMgr_t)(g_WeChatWinDllAddr + OS_GET_CHAT_MGR); - GetPreDownLoadMgr_t GetPreDownLoadMgr = (GetPreDownLoadMgr_t)(g_WeChatWinDllAddr + OS_GET_PRE_DOWNLOAD_MGR); - PushAttachTask_t PushAttachTask = (PushAttachTask_t)(g_WeChatWinDllAddr + OS_PUSH_ATTACH_TASK); - GetMgrByPrefixLocalId_t GetMgrByPrefixLocalId - = (GetMgrByPrefixLocalId_t)(g_WeChatWinDllAddr + OS_GET_MGR_BY_PREFIX_LOCAL_ID); - - LARGE_INTEGER l; - l.HighPart = dbIdx; - l.LowPart = (DWORD)localId; - - char *buff = (char *)HeapAlloc(GetProcessHeap(), 0, 0x460); - if (buff == nullptr) { - LOG_ERROR("Failed to allocate memory."); - return status; - } - - QWORD pChatMsg = NewChatMsg((QWORD)buff); - GetChatMgr(); - GetMgrByPrefixLocalId(l.QuadPart, pChatMsg); - - QWORD type = GET_QWORD(buff + 0x38); - - string save_path = ""; - string thumb_path = ""; - - switch (type) { - case 0x03: { // Image: extra - save_path = extra; - break; - } - case 0x3E: - case 0x2B: { // Video: thumb - thumb_path = thumb; - save_path = fs::path(thumb).replace_extension("mp4").string(); - break; - } - case 0x31: { // File: extra - save_path = extra; - break; - } - default: - break; - } - - if (fs::exists(save_path)) { // 不重复下载。TODO: 通过文件大小来判断 - return 0; - } - - LOG_DEBUG("path: {}", save_path); - // 创建父目录,由于路径来源于微信,不做检查 - fs::create_directory(fs::path(save_path).parent_path().string()); - - int temp = 1; - WxString *pSavePath = NewWxStringFromStr(save_path); - WxString *pThumbPath = NewWxStringFromStr(thumb_path); - - memcpy(&buff[0x280], pThumbPath, sizeof(WxString)); - memcpy(&buff[0x2A0], pSavePath, sizeof(WxString)); - memcpy(&buff[0x40C], &temp, sizeof(temp)); - - QWORD mgr = GetPreDownLoadMgr(); - status = (int)PushAttachTask(mgr, pChatMsg, 0, 1); - FreeChatMsg(pChatMsg); - - return status; -} - -string GetAudio(QWORD id, string dir) -{ - string mp3path = (dir.back() == '\\' || dir.back() == '/') ? dir : (dir + "/"); - mp3path += to_string(id) + ".mp3"; - replace(mp3path.begin(), mp3path.end(), '\\', '/'); - if (fs::exists(mp3path)) { // 不重复下载 - return mp3path; - } - - vector silk = GetAudioData(id); - if (silk.size() == 0) { - LOG_ERROR("Empty audio data."); - return ""; - } - - Silk2Mp3(silk, mp3path, 24000); - - return mp3path; -} - -string GetPCMAudio(uint64_t id, string dir, int32_t sr) -{ - string pcmpath = (dir.back() == '\\' || dir.back() == '/') ? dir : (dir + "/"); - pcmpath += to_string(id) + ".pcm"; - replace(pcmpath.begin(), pcmpath.end(), '\\', '/'); - if (fs::exists(pcmpath)) { // 不重复下载 - return pcmpath; - } - vector pcm; - vector silk = GetAudioData(id); - if (silk.size() == 0) { - LOG_ERROR("Empty audio data."); - return ""; - } - - SilkDecode(silk, pcm, sr); - errno_t err; - FILE* fPCM; - err = fopen_s(&fPCM, pcmpath.c_str(), "wb"); - if (err != 0) { - printf("Error: could not open input file %s\n", pcmpath.c_str()); - exit(0); - } - - fwrite(pcm.data(), sizeof(uint8_t), pcm.size(), fPCM); - fclose(fPCM); - - return pcmpath; -} - - -OcrResult_t GetOcrResult(string path) -{ - OcrResult_t ret = { -1, "" }; -#if 0 // 参数没调好,会抛异常,看看有没有好心人来修复 - if (!fs::exists(path)) { - LOG_ERROR("Can not find: {}", path); - return ret; - } - - GetOCRManager_t GetOCRManager = (GetOCRManager_t)(g_WeChatWinDllAddr + 0x1D6C3C0); - DoOCRTask_t DoOCRTask = (DoOCRTask_t)(g_WeChatWinDllAddr + 0x2D10BC0); - - QWORD unk1 = 0, unk2 = 0, unused = 0; - QWORD *pUnk1 = &unk1; - QWORD *pUnk2 = &unk2; - // 路径分隔符有要求,必须为 `\` - wstring wsPath = String2Wstring(fs::path(path).make_preferred().string()); - WxString wxPath(wsPath); - vector *pv = (vector *)HeapAlloc(GetProcessHeap(), 0, 0x20); - RawVector_t *pRv = (RawVector_t *)pv; - pRv->finish = pRv->start; - char buff[0x98] = { 0 }; - memcpy(buff, &pRv->start, sizeof(QWORD)); - - QWORD mgr = GetOCRManager(); - ret.status = (int)DoOCRTask(mgr, (QWORD)&wxPath, unused, (QWORD)buff, (QWORD)&pUnk1, (QWORD)&pUnk2); - - QWORD count = GET_QWORD(buff + 0x8); - if (count > 0) { - QWORD header = GET_QWORD(buff); - for (QWORD i = 0; i < count; i++) { - QWORD content = GET_QWORD(header); - ret.result += Wstring2String(GET_WSTRING(content + 0x28)); - ret.result += "\n"; - header = content; - } - } -#endif - return ret; -} - -int RevokeMsg(QWORD id) -{ - int status = -1; -#if 0 // 这个挺鸡肋的,因为自己发的消息没法直接获得 msgid,就这样吧 - QWORD localId; - uint32_t dbIdx; - if (GetLocalIdandDbidx(id, &localId, &dbIdx) != 0) { - LOG_ERROR("Failed to get localId, Please check id: {}", to_string(id)); - return status; - } -#endif - return status; -} - -string GetLoginUrl() -{ - LPVOID targetAddress = reinterpret_cast(g_WeChatWinDllAddr) + OS_LOGIN_QR_CODE; - - char *dataPtr = *reinterpret_cast(targetAddress); // 读取指针内容 - if (!dataPtr) { - LOG_ERROR("Failed to get login url"); - return "error"; - } - - // 读取字符串内容 - std::string data(dataPtr, 22); - return "http://weixin.qq.com/x/" + data; -} - -int ReceiveTransfer(string wxid, string transferid, string transactionid) -{ - // 别想了,这个不实现了 - return -1; -} - diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp deleted file mode 100644 index 5a7867a..0000000 --- a/WeChatFerry/spy/receive_msg.cpp +++ /dev/null @@ -1,379 +0,0 @@ -#pragma execution_character_set("utf-8") - -#include "MinHook.h" -#include "framework.h" -#include -#include -#include - -#include "log.h" -#include "receive_msg.h" -#include "user_info.h" -#include "util.h" - -// Defined in rpc_server.cpp -extern bool gIsLogging, gIsListening, gIsListeningPyq; -extern mutex gMutex; -extern condition_variable gCV; -extern queue gMsgQueue; - -// Defined in spy.cpp -extern QWORD g_WeChatWinDllAddr; - -#define OS_RECV_MSG_ID 0x30 -#define OS_RECV_MSG_TYPE 0x38 -#define OS_RECV_MSG_SELF 0x3C -#define OS_RECV_MSG_TS 0x44 -#define OS_RECV_MSG_ROOMID 0x48 -#define OS_RECV_MSG_CONTENT 0x88 -#define OS_RECV_MSG_WXID 0x240 -#define OS_RECV_MSG_SIGN 0x260 -#define OS_RECV_MSG_THUMB 0x280 -#define OS_RECV_MSG_EXTRA 0x2A0 -#define OS_RECV_MSG_XML 0x308 -#define OS_RECV_MSG_CALL 0x21444B0 -#define OS_PYQ_MSG_START 0x30 -#define OS_PYQ_MSG_END 0x38 -#define OS_PYQ_MSG_TS 0x38 -#define OS_PYQ_MSG_XML 0x9B8 -#define OS_PYQ_MSG_SENDER 0x18 -#define OS_PYQ_MSG_CONTENT 0x48 -#define OS_PYQ_MSG_CALL 0x2E59320 -#define OS_WXLOG 0x261E760 - -typedef QWORD (*RecvMsg_t)(QWORD, QWORD); -typedef QWORD (*WxLog_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); -typedef QWORD (*RecvPyq_t)(QWORD, QWORD, QWORD); - -static RecvMsg_t funcRecvMsg = nullptr; -static RecvMsg_t realRecvMsg = nullptr; -static WxLog_t funcWxLog = nullptr; -static WxLog_t realWxLog = nullptr; -static RecvPyq_t funcRecvPyq = nullptr; -static RecvPyq_t realRecvPyq = nullptr; -static bool isMH_Initialized = false; - -MsgTypes_t GetMsgTypes() -{ - const MsgTypes_t m = { - { 0x00, "朋友圈消息" }, - { 0x01, "文字" }, - { 0x03, "图片" }, - { 0x22, "语音" }, - { 0x25, "好友确认" }, - { 0x28, "POSSIBLEFRIEND_MSG" }, - { 0x2A, "名片" }, - { 0x2B, "视频" }, - { 0x2F, "石头剪刀布 | 表情图片" }, - { 0x30, "位置" }, - { 0x31, "共享实时位置、文件、转账、链接" }, - { 0x32, "VOIPMSG" }, - { 0x33, "微信初始化" }, - { 0x34, "VOIPNOTIFY" }, - { 0x35, "VOIPINVITE" }, - { 0x3E, "小视频" }, - { 0x42, "微信红包" }, - { 0x270F, "SYSNOTICE" }, - { 0x2710, "红包、系统消息" }, - { 0x2712, "撤回消息" }, - { 0x100031, "搜狗表情" }, - { 0x1000031, "链接" }, - { 0x1A000031, "微信红包" }, - { 0x20010031, "红包封面" }, - { 0x2D000031, "视频号视频" }, - { 0x2E000031, "视频号名片" }, - { 0x31000031, "引用消息" }, - { 0x37000031, "拍一拍" }, - { 0x3A000031, "视频号直播" }, - { 0x3A100031, "商品链接" }, - { 0x3A200031, "视频号直播" }, - { 0x3E000031, "音乐链接" }, - { 0x41000031, "文件" }, - }; - - return m; -} - -static QWORD DispatchMsg(QWORD arg1, QWORD arg2) -{ - WxMsg_t wxMsg = { 0 }; - try { - wxMsg.id = GET_QWORD(arg2 + OS_RECV_MSG_ID); - wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE); - wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF); - wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS); - wxMsg.content = GetStringByWstrAddr(arg2 + OS_RECV_MSG_CONTENT); - wxMsg.sign = GetStringByWstrAddr(arg2 + OS_RECV_MSG_SIGN); - wxMsg.xml = GetStringByWstrAddr(arg2 + OS_RECV_MSG_XML); - - string roomid = GetStringByWstrAddr(arg2 + OS_RECV_MSG_ROOMID); - wxMsg.roomid = roomid; - if (roomid.find("@chatroom") != string::npos) { // 群 ID 的格式为 xxxxxxxxxxx@chatroom - wxMsg.is_group = true; - if (wxMsg.is_self) { - wxMsg.sender = GetSelfWxid(); - } else { - wxMsg.sender = GetStringByWstrAddr(arg2 + OS_RECV_MSG_WXID); - } - } else { - wxMsg.is_group = false; - if (wxMsg.is_self) { - wxMsg.sender = GetSelfWxid(); - } else { - wxMsg.sender = roomid; - } - } - - wxMsg.thumb = GetStringByWstrAddr(arg2 + OS_RECV_MSG_THUMB); - if (!wxMsg.thumb.empty()) { - wxMsg.thumb = GetHomePath() + wxMsg.thumb; - replace(wxMsg.thumb.begin(), wxMsg.thumb.end(), '\\', '/'); - } - - wxMsg.extra = GetStringByWstrAddr(arg2 + OS_RECV_MSG_EXTRA); - if (!wxMsg.extra.empty()) { - wxMsg.extra = GetHomePath() + wxMsg.extra; - replace(wxMsg.extra.begin(), wxMsg.extra.end(), '\\', '/'); - } - } catch (const std::exception &e) { - LOG_ERROR(GB2312ToUtf8(e.what())); - } catch (...) { - LOG_ERROR("Unknow exception."); - } - - { - unique_lock lock(gMutex); - gMsgQueue.push(wxMsg); // 推送到队列 - } - - gCV.notify_all(); // 通知各方消息就绪 - return realRecvMsg(arg1, arg2); -} - -static QWORD PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a5, QWORD a6, QWORD a7, QWORD a8, QWORD a9, - QWORD a10, QWORD a11, QWORD a12) -{ - QWORD p = realWxLog(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); - if (p == 0 || p == 1) { - return p; - } - - LOG_INFO("【WX】\n{}", GB2312ToUtf8((char *)p)); - - return p; -} - -static void DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3) -{ - QWORD startAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_START); - QWORD endAddr = *(QWORD *)(arg2 + OS_PYQ_MSG_END); - - if (startAddr == 0) { - return; - } - - while (startAddr < endAddr) { - WxMsg_t wxMsg; - - wxMsg.type = 0x00; // 朋友圈消息 - wxMsg.is_self = false; - wxMsg.is_group = false; - wxMsg.id = GET_QWORD(startAddr); - wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS); - wxMsg.xml = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_XML); - wxMsg.sender = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_SENDER); - wxMsg.content = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_CONTENT); - - { - unique_lock lock(gMutex); - gMsgQueue.push(wxMsg); // 推送到队列 - } - - gCV.notify_all(); // 通知各方消息就绪 - - startAddr += 0x1618; - } -} - -static MH_STATUS InitializeHook() -{ - if (isMH_Initialized) { - return MH_OK; - } - MH_STATUS status = MH_Initialize(); - if (status == MH_OK) { - isMH_Initialized = true; - } - return status; -} - -static MH_STATUS UninitializeHook() -{ - if (!isMH_Initialized) { - return MH_OK; - } - if (gIsLogging || gIsListening || gIsListeningPyq) { - return MH_OK; - } - MH_STATUS status = MH_Uninitialize(); - if (status == MH_OK) { - isMH_Initialized = false; - } - return status; -} - -void EnableLog() -{ - MH_STATUS status = MH_UNKNOWN; - if (gIsLogging) { - LOG_WARN("gIsLogging"); - return; - } - WxLog_t funcWxLog = (WxLog_t)(g_WeChatWinDllAddr + OS_WXLOG); - - status = InitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Initialize failed: {}", to_string(status)); - return; - } - - status = MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast(&realWxLog)); - if (status != MH_OK) { - LOG_ERROR("MH_CreateHook failed: {}", to_string(status)); - return; - } - - status = MH_EnableHook(funcWxLog); - if (status != MH_OK) { - LOG_ERROR("MH_EnableHook failed: {}", to_string(status)); - return; - } - gIsLogging = true; -} - -void DisableLog() -{ - MH_STATUS status = MH_UNKNOWN; - if (!gIsLogging) { - return; - } - - status = MH_DisableHook(funcWxLog); - if (status != MH_OK) { - LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); - return; - } - - gIsLogging = false; - - status = UninitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Uninitialize failed: {}", to_string(status)); - return; - } -} - -void ListenMessage() -{ - MH_STATUS status = MH_UNKNOWN; - if (gIsListening) { - LOG_WARN("gIsListening"); - return; - } - funcRecvMsg = (RecvMsg_t)(g_WeChatWinDllAddr + OS_RECV_MSG_CALL); - - status = InitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Initialize failed: {}", to_string(status)); - return; - } - - status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast(&realRecvMsg)); - if (status != MH_OK) { - LOG_ERROR("MH_CreateHook failed: {}", to_string(status)); - return; - } - - status = MH_EnableHook(funcRecvMsg); - if (status != MH_OK) { - LOG_ERROR("MH_EnableHook failed: {}", to_string(status)); - return; - } - - gIsListening = true; -} - -void UnListenMessage() -{ - MH_STATUS status = MH_UNKNOWN; - if (!gIsListening) { - return; - } - - status = MH_DisableHook(funcRecvMsg); - if (status != MH_OK) { - LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); - return; - } - - gIsListening = false; - - status = UninitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Uninitialize failed: {}", to_string(status)); - return; - } -} - -void ListenPyq() -{ - MH_STATUS status = MH_UNKNOWN; - if (gIsListeningPyq) { - LOG_WARN("gIsListeningPyq"); - return; - } - funcRecvPyq = (RecvPyq_t)(g_WeChatWinDllAddr + OS_PYQ_MSG_CALL); - - status = InitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Initialize failed: {}", to_string(status)); - return; - } - - status = MH_CreateHook(funcRecvPyq, &DispatchPyq, reinterpret_cast(&realRecvPyq)); - if (status != MH_OK) { - LOG_ERROR("MH_CreateHook failed: {}", to_string(status)); - return; - } - - status = MH_EnableHook(funcRecvPyq); - if (status != MH_OK) { - LOG_ERROR("MH_EnableHook failed: {}", to_string(status)); - return; - } - - gIsListeningPyq = true; -} - -void UnListenPyq() -{ - MH_STATUS status = MH_UNKNOWN; - if (!gIsListeningPyq) { - return; - } - - status = MH_DisableHook(funcRecvPyq); - if (status != MH_OK) { - LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); - return; - } - - gIsListeningPyq = false; - - status = UninitializeHook(); - if (status != MH_OK) { - LOG_ERROR("MH_Uninitialize failed: {}", to_string(status)); - return; - } -} - diff --git a/WeChatFerry/spy/send_msg.cpp b/WeChatFerry/spy/send_msg.cpp deleted file mode 100644 index 75cf6d6..0000000 --- a/WeChatFerry/spy/send_msg.cpp +++ /dev/null @@ -1,274 +0,0 @@ - -#include "framework.h" -#include -#include - -#include "exec_sql.h" -#include "log.h" -#include "send_msg.h" -#include "spy_types.h" -#include "util.h" - -extern HANDLE g_hEvent; -extern QWORD g_WeChatWinDllAddr; -extern string GetSelfWxid(); // Defined in spy.cpp - -#define SRTM_SIZE 0x3F0 - -#define OS_NEW 0x1B63A50 -#define OS_FREE 0x1B5B160 -#define OS_SEND_MSG_MGR 0x1B598E0 -#define OS_SEND_TEXT 0x22CC660 -#define OS_SEND_IMAGE 0x22C1E70 -#define OS_GET_APP_MSG_MGR 0x1B5E880 -#define OS_SEND_FILE 0x20D5FF0 -#define OS_RTM_NEW 0x1B62FA0 -#define OS_RTM_FREE 0x1B62370 -#define OS_SEND_RICH_TEXT 0x20DFFD0 -#define OS_SEND_PAT_MSG 0x2CC4F10 -#define OS_FORWARD_MSG 0x22CBBE0 -#define OS_GET_EMOTION_MGR 0x1BD49A0 -#define OS_SEND_EMOTION 0x21BACD0 -#define OS_XML_BUFSIGN 0x24FB330 -#define OS_SEND_XML 0x20D5120 - -typedef QWORD (*New_t)(QWORD); -typedef QWORD (*Free_t)(QWORD); -typedef QWORD (*SendMsgMgr_t)(); -typedef QWORD (*GetAppMsgMgr_t)(); -typedef QWORD (*SendTextMsg_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); -typedef QWORD (*SendImageMsg_t)(QWORD, QWORD, QWORD, QWORD, QWORD); -typedef QWORD (*SendFileMsg_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD *, QWORD, QWORD *, QWORD, QWORD *, QWORD, - QWORD); -typedef QWORD (*SendRichTextMsg_t)(QWORD, QWORD, QWORD); -typedef QWORD (*SendPatMsg_t)(QWORD, QWORD); -typedef QWORD (*ForwardMsg_t)(QWORD, QWORD, QWORD, QWORD); -typedef QWORD (*GetEmotionMgr_t)(); -typedef QWORD (*SendEmotion_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); - -typedef QWORD (*XmlBufSign_t)(QWORD, QWORD, QWORD); -typedef QWORD (*SendXmlMsg_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); - -void SendTextMessage(string wxid, string msg, string atWxids) -{ - QWORD success = 0; - wstring wsWxid = String2Wstring(wxid); - wstring wsMsg = String2Wstring(msg); - WxString wxMsg(wsMsg); - WxString wxWxid(wsWxid); - - vector vAtWxids; - vector vWxAtWxids; - if (!atWxids.empty()) { - wstringstream wss(String2Wstring(atWxids)); - while (wss.good()) { - wstring wstr; - getline(wss, wstr, L','); - vAtWxids.push_back(wstr); - WxString wxAtWxid(vAtWxids.back()); - vWxAtWxids.push_back(wxAtWxid); - } - } else { - WxString wxEmpty = WxString(); - vWxAtWxids.push_back(wxEmpty); - } - - QWORD wxAters = (QWORD) & ((RawVector_t *)&vWxAtWxids)->start; - - char buffer[0x460] = { 0 }; - SendMsgMgr_t funcSendMsgMgr = (SendMsgMgr_t)(g_WeChatWinDllAddr + OS_SEND_MSG_MGR); - SendTextMsg_t funcSendTextMsg = (SendTextMsg_t)(g_WeChatWinDllAddr + OS_SEND_TEXT); - Free_t funcFree = (Free_t)(g_WeChatWinDllAddr + OS_FREE); - funcSendMsgMgr(); - success = funcSendTextMsg((QWORD)(&buffer), (QWORD)(&wxWxid), (QWORD)(&wxMsg), wxAters, 1, 1, 0, 0); - funcFree((QWORD)(&buffer)); -} - -void SendImageMessage(string wxid, string path) -{ - wstring wsWxid = String2Wstring(wxid); - wstring wsPath = String2Wstring(path); - - WxString wxWxid(wsWxid); - WxString wxPath(wsPath); - - New_t funcNew = (New_t)(g_WeChatWinDllAddr + OS_NEW); - Free_t funcFree = (Free_t)(g_WeChatWinDllAddr + OS_FREE); - SendMsgMgr_t funcSendMsgMgr = (SendMsgMgr_t)(g_WeChatWinDllAddr + OS_SEND_MSG_MGR); - SendImageMsg_t funcSendImage = (SendImageMsg_t)(g_WeChatWinDllAddr + OS_SEND_IMAGE); - - char msg[0x460] = { 0 }; - char msgTmp[0x460] = { 0 }; - QWORD *flag[10] = { 0 }; - - QWORD tmp1 = 0, tmp2 = 0; - QWORD pMsgTmp = funcNew((QWORD)(&msgTmp)); - flag[8] = &tmp1; - flag[9] = &tmp2; - flag[1] = (QWORD *)(pMsgTmp); - - QWORD pMsg = funcNew((QWORD)(&msg)); - QWORD sendMgr = funcSendMsgMgr(); - funcSendImage(sendMgr, pMsg, (QWORD)(&wxWxid), (QWORD)(&wxPath), (QWORD)(&flag)); - funcFree(pMsg); - funcFree(pMsgTmp); -} - -void SendFileMessage(string wxid, string path) -{ - wstring wsWxid = String2Wstring(wxid); - wstring wsPath = String2Wstring(path); - - WxString wxWxid(wsWxid); - WxString wxPath(wsPath); - - New_t funcNew = (New_t)(g_WeChatWinDllAddr + OS_NEW); - Free_t funcFree = (Free_t)(g_WeChatWinDllAddr + OS_FREE); - GetAppMsgMgr_t funcGetAppMsgMgr = (GetAppMsgMgr_t)(g_WeChatWinDllAddr + OS_GET_APP_MSG_MGR); - SendFileMsg_t funcSendFile = (SendFileMsg_t)(g_WeChatWinDllAddr + OS_SEND_FILE); - - char msg[0x460] = { 0 }; - QWORD tmp1[4] = { 0 }; - QWORD tmp2[4] = { 0 }; - QWORD tmp3[4] = { 0 }; - - QWORD pMsg = funcNew((QWORD)(&msg)); - QWORD appMgr = funcGetAppMsgMgr(); - funcSendFile(appMgr, pMsg, (QWORD)(&wxWxid), (QWORD)(&wxPath), 1, tmp1, 0, tmp2, 0, tmp3, 0, 0); - funcFree(pMsg); -} - -int SendRichTextMessage(RichText_t &rt) -{ // TODO: Fix memory leak - QWORD status = -1; - - New_t funcNew = (New_t)(g_WeChatWinDllAddr + OS_RTM_NEW); - Free_t funcFree = (Free_t)(g_WeChatWinDllAddr + OS_RTM_FREE); - GetAppMsgMgr_t funcGetAppMsgMgr = (GetAppMsgMgr_t)(g_WeChatWinDllAddr + OS_GET_APP_MSG_MGR); - SendRichTextMsg_t funcForwordPublicMsg = (SendRichTextMsg_t)(g_WeChatWinDllAddr + OS_SEND_RICH_TEXT); - - char *buff = (char *)HeapAlloc(GetProcessHeap(), 0, SRTM_SIZE); - if (buff == NULL) { - LOG_ERROR("Out of Memory..."); - return -1; - } - - memset(buff, 0, SRTM_SIZE); - funcNew((QWORD)buff); - WxString *pReceiver = NewWxStringFromStr(rt.receiver); - WxString *pTitle = NewWxStringFromStr(rt.title); - WxString *pUrl = NewWxStringFromStr(rt.url); - WxString *pThumburl = NewWxStringFromStr(rt.thumburl); - WxString *pDigest = NewWxStringFromStr(rt.digest); - WxString *pAccount = NewWxStringFromStr(rt.account); - WxString *pName = NewWxStringFromStr(rt.name); - - memcpy(buff + 0x8, pTitle, sizeof(WxString)); - memcpy(buff + 0x48, pUrl, sizeof(WxString)); - memcpy(buff + 0xB0, pThumburl, sizeof(WxString)); - memcpy(buff + 0xF0, pDigest, sizeof(WxString)); - memcpy(buff + 0x2C0, pAccount, sizeof(WxString)); - memcpy(buff + 0x2E0, pName, sizeof(WxString)); - - QWORD mgr = funcGetAppMsgMgr(); - status = funcForwordPublicMsg(mgr, (QWORD)(pReceiver), (QWORD)(buff)); - funcFree((QWORD)buff); - - return (int)status; -} - -int SendPatMessage(string roomid, string wxid) -{ - QWORD status = -1; - - wstring wsRoomid = String2Wstring(roomid); - wstring wsWxid = String2Wstring(wxid); - WxString wxRoomid(wsRoomid); - WxString wxWxid(wsWxid); - - SendPatMsg_t funcSendPatMsg = (SendPatMsg_t)(g_WeChatWinDllAddr + OS_SEND_PAT_MSG); - - status = funcSendPatMsg((QWORD)(&wxRoomid), (QWORD)(&wxWxid)); - return (int)status; -} - -int ForwardMessage(QWORD msgid, string receiver) -{ - int status = -1; - uint32_t dbIdx = 0; - QWORD localId = 0; - - ForwardMsg_t funcForwardMsg = (ForwardMsg_t)(g_WeChatWinDllAddr + OS_FORWARD_MSG); - if (GetLocalIdandDbidx(msgid, &localId, &dbIdx) != 0) { - LOG_ERROR("Failed to get localId, Please check id: {}", to_string(msgid)); - return status; - } - - WxString *pReceiver = NewWxStringFromStr(receiver); - - LARGE_INTEGER l; - l.HighPart = dbIdx; - l.LowPart = (DWORD)localId; - - status = (int)funcForwardMsg((QWORD)pReceiver, l.QuadPart, 0x4, 0x0); - - return status; -} - -void SendEmotionMessage(string wxid, string path) -{ - GetEmotionMgr_t GetEmotionMgr = (GetEmotionMgr_t)(g_WeChatWinDllAddr + OS_GET_EMOTION_MGR); - SendEmotion_t SendEmotion = (SendEmotion_t)(g_WeChatWinDllAddr + OS_SEND_EMOTION); - - WxString *pWxPath = NewWxStringFromStr(path); - WxString *pWxWxid = NewWxStringFromStr(wxid); - - QWORD *buff = (QWORD *)HeapAlloc(GetProcessHeap(), 0, 0x20); - if (buff == NULL) { - LOG_ERROR("Out of Memory..."); - return; - } - - memset(buff, 0, 0x20); - QWORD mgr = GetEmotionMgr(); - SendEmotion(mgr, (QWORD)pWxPath, (QWORD)buff, (QWORD)pWxWxid, 2, (QWORD)buff, 0, (QWORD)buff); -} - -void SendXmlMessage(string receiver, string xml, string path, QWORD type) -{ - if (g_WeChatWinDllAddr == 0) { - return; - } - - New_t funcNew = (New_t)(g_WeChatWinDllAddr + OS_NEW); - Free_t funcFree = (Free_t)(g_WeChatWinDllAddr + OS_FREE); - - XmlBufSign_t xmlBufSign = (XmlBufSign_t)(g_WeChatWinDllAddr + OS_XML_BUFSIGN); - SendXmlMsg_t sendXmlMsg = (SendXmlMsg_t)(g_WeChatWinDllAddr + OS_SEND_XML); - - char buff[0x500] = { 0 }; - char buff2[0x500] = { 0 }; - char nullBuf[0x1C] = { 0 }; - - QWORD pBuf = (QWORD)(&buff); - QWORD pBuf2 = (QWORD)(&buff2); - - funcNew(pBuf); - funcNew(pBuf2); - - QWORD sbuf[4] = { 0, 0, 0, 0 }; - - QWORD sign = xmlBufSign(pBuf2, (QWORD)(&sbuf), 0x1); - - WxString *pReceiver = NewWxStringFromStr(receiver); - WxString *pXml = NewWxStringFromStr(xml); - WxString *pPath = NewWxStringFromStr(path); - WxString *pSender = NewWxStringFromStr(GetSelfWxid()); - - sendXmlMsg(pBuf, (QWORD)pSender, (QWORD)pReceiver, (QWORD)pXml, (QWORD)pPath, (QWORD)(&nullBuf), type, 0x4, sign, - pBuf2); - - funcFree((QWORD)&buff); - funcFree((QWORD)&buff2); -} - diff --git a/WeChatFerry/spy/user_info.cpp b/WeChatFerry/spy/user_info.cpp deleted file mode 100644 index a5c132e..0000000 --- a/WeChatFerry/spy/user_info.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "user_info.h" -#include "log.h" -#include "util.h" - -extern UINT64 g_WeChatWinDllAddr; - -#define OS_USER_HOME 0x59F6330 -#define OS_USER_WXID 0x5A20200 -#define OS_USER_NAME 0x5A20368 -#define OS_USER_MOBILE 0x595C318 - -static char home[MAX_PATH] = { 0 }; - -string GetHomePath() -{ - if (home[0] == 0) { - string path = Wstring2String(GET_WSTRING(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\"; - strncpy_s(home, path.c_str(), path.size()); - } - - return string(home); -} - -string GetSelfWxid() -{ - UINT64 wxidType = 0; - try { - wxidType = GET_UINT64(g_WeChatWinDllAddr + OS_USER_WXID + 0x18); - if (wxidType == 0xF) { - return GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_WXID); - } else { - return GET_STRING(g_WeChatWinDllAddr + OS_USER_WXID); - } - } catch (...) { - LOG_ERROR("wxid type: {:#x}", wxidType); - LOG_BUFFER((uint8_t *)(g_WeChatWinDllAddr + OS_USER_WXID), 20); - return "empty_wxid"; - } -} - -UserInfo_t GetUserInfo() -{ - UserInfo_t ui; - - ui.wxid = GetSelfWxid(); - - UINT64 nameType = GET_UINT64(g_WeChatWinDllAddr + OS_USER_NAME + 0x18); - if (nameType == 0xF) { - ui.name = GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_NAME); - } else { // 0x1F - ui.name = GET_STRING(g_WeChatWinDllAddr + OS_USER_NAME); - } - - ui.mobile = GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_MOBILE); - ui.home = GetHomePath(); - - return ui; -} -