feat(account): add user info retrieval and RPC methods

This commit is contained in:
Changhua 2025-02-12 00:47:54 +08:00
parent f5d9528e1a
commit 32876209a4
3 changed files with 63 additions and 49 deletions

View File

@ -1,9 +1,9 @@
#include "account_manager.h"
#include <filesystem>
#include <mutex>
#include "log.hpp"
#include "offsets.h"
#include "rpc_helper.h"
#include "util.h"
@ -11,63 +11,56 @@ extern UINT64 g_WeChatWinDllAddr;
namespace account
{
#define OS_LOGIN_STATUS 0x595C9E8
#define OS_USER_HOME 0x5932770
#define OS_USER_WXID 0x595C270
#define OS_USER_NAME 0x595C3D8
#define OS_USER_MOBILE 0x595C318
bool is_logged_in() { return util::get_qword(g_WeChatWinDllAddr + OS_LOGIN_STATUS) != 0; }
namespace OsAcc = Offsets::Account;
std::string get_home_path()
using get_account_service_t = QWORD (*)();
using get_current_data_path_t = QWORD (*)(QWORD);
static uint64_t get_account_service()
{
static std::once_flag flag;
static std::string home_path;
static auto GetService = reinterpret_cast<get_account_service_t>(g_WeChatWinDllAddr + OsAcc::SERVICE);
return GetService ? GetService() : 0;
}
std::call_once(flag, [] {
std::string path = util::w2s(util::get_pp_wstring(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\";
home_path = std::filesystem::absolute(path).string();
});
static std::string get_string_value(uint64_t base_addr, uint64_t offset)
{
uint64_t type = util::get_qword(base_addr + offset + 0x18);
return (type == 0xF) ? util::get_p_string(base_addr + offset) : util::get_pp_string(base_addr + offset);
}
return home_path;
bool is_logged_in()
{
uint64_t service_addr = get_account_service();
return service_addr && util::get_qword(service_addr + OsAcc::LOGIN) != 0;
}
std::string get_self_wxid()
{
static std::once_flag flag;
static std::string wxid;
uint64_t service_addr = get_account_service();
if (!service_addr) return "";
std::call_once(flag, [] {
UINT64 wxid_type = 0;
try {
wxid_type = util::get_qword(g_WeChatWinDllAddr + OS_USER_WXID + 0x18);
if (wxid_type == 0xF) {
wxid = util::get_p_string(g_WeChatWinDllAddr + OS_USER_WXID);
} else {
wxid = util::get_pp_string(g_WeChatWinDllAddr + OS_USER_WXID);
}
} catch (...) {
LOG_ERROR("Failed to get wxid, type: {:#x}", wxid_type);
LOG_BUFFER(reinterpret_cast<uint8_t *>(g_WeChatWinDllAddr + OS_USER_WXID), 20);
wxid = "获取wxid失败";
}
});
return wxid;
return get_string_value(service_addr, OsAcc::WXID);
}
UserInfo_t get_user_info()
{
UserInfo_t ui;
WxString home;
auto GetDataPath = reinterpret_cast<get_current_data_path_t>(g_WeChatWinDllAddr + OsAcc::PATH);
uint64_t service_addr = get_account_service();
if (!service_addr) return ui;
ui.wxid = get_self_wxid();
UINT64 name_type = util::get_qword(g_WeChatWinDllAddr + OS_USER_NAME + 0x18);
ui.name = (name_type == 0xF) ? util::get_p_string(g_WeChatWinDllAddr + OS_USER_NAME)
: util::get_pp_string(g_WeChatWinDllAddr + OS_USER_NAME);
ui.mobile = util::get_p_string(g_WeChatWinDllAddr + OS_USER_MOBILE);
ui.home = get_home_path();
GetDataPath((QWORD)&home);
if (home.wptr) {
std::filesystem::path path = util::w2s(std::wstring(home.wptr, home.size));
ui.home = path.generic_string();
}
ui.name = get_string_value(service_addr, OsAcc::NAME);
ui.mobile = get_string_value(service_addr, OsAcc::MOBILE);
return ui;
}
@ -85,7 +78,7 @@ bool rpc_get_self_wxid(uint8_t *out, size_t *len)
bool rpc_get_user_info(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_GET_USER_INFO>(out, len, [](Response &rsp) {
UserInfo_t ui = get_user_info();
static UserInfo_t ui = get_user_info();
rsp.msg.ui.wxid = (char *)ui.wxid.c_str();
rsp.msg.ui.name = (char *)ui.name.c_str();
rsp.msg.ui.mobile = (char *)ui.mobile.c_str();

21
WeChatFerry/spy/offsets.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef OFFSETS_H
#define OFFSETS_H
#include <cstdint>
namespace Offsets
{
namespace Account
{
constexpr uint64_t SERVICE = 0x1B58B50; // 账户服务
constexpr uint64_t PATH = 0x2250920; // 数据路径
constexpr uint64_t WXID = 0x80; // WXID
constexpr uint64_t NAME = 0x1E8; // 昵称
constexpr uint64_t MOBILE = 0x128; // 手机号
constexpr uint64_t LOGIN = 0x7F8; // 登录状态
}
}
#endif // OFFSETS_H

View File

@ -221,8 +221,8 @@ bool RpcServer::disableRecvMsg(uint8_t *out, size_t *len)
const std::unordered_map<Functions, RpcServer::FunctionHandler> RpcServer::rpcFunctionMap = {
// clang-format off
{ Functions_FUNC_IS_LOGIN, [](const Request &r, uint8_t *out, size_t *len) { return account::rpc_is_logged_in(out, len); } },
// { Functions_FUNC_GET_SELF_WXID, [](const Request &r, uint8_t *out, size_t *len) { return account::rpc_get_self_wxid(out, len); } },
// { Functions_FUNC_GET_USER_INFO, [](const Request &r, uint8_t *out, size_t *len) { return account::rpc_get_user_info(out, len); } },
{ Functions_FUNC_GET_SELF_WXID, [](const Request &r, uint8_t *out, size_t *len) { return account::rpc_get_self_wxid(out, len); } },
{ Functions_FUNC_GET_USER_INFO, [](const Request &r, uint8_t *out, size_t *len) { return account::rpc_get_user_info(out, len); } },
// { Functions_FUNC_GET_MSG_TYPES, [](const Request &r, uint8_t *out, size_t *len) { return handler.rpc_get_msg_types(out, len); } },
// { Functions_FUNC_GET_CONTACTS, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_get_contacts(out, len); } },
// { Functions_FUNC_GET_DB_NAMES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_names(out, len); } },