mirror of
https://github.com/laomms/wxhelper.git
synced 2025-04-19 19:59:15 +08:00
1598 lines
61 KiB
C++
1598 lines
61 KiB
C++
#include "wechat_service.h"
|
|
|
|
#include "json_utils.h"
|
|
#include "memory.h"
|
|
#include "spdlog/spdlog.h"
|
|
#include "tinyxml2.h"
|
|
#include "utils.h"
|
|
#include "wechat_db.h"
|
|
#include "wxutils.h"
|
|
|
|
#define BUFSIZE 1024
|
|
#define JPEG0 0xFF
|
|
#define JPEG1 0xD8
|
|
#define JPEG2 0xFF
|
|
#define PNG0 0x89
|
|
#define PNG1 0x50
|
|
#define PNG2 0x4E
|
|
#define BMP0 0x42
|
|
#define BMP1 0x4D
|
|
#define GIF0 0x47
|
|
#define GIF1 0x49
|
|
#define GIF2 0x46
|
|
|
|
namespace offset = wechat::offset;
|
|
namespace prototype = wechat::prototype;
|
|
namespace func = wechat::function;
|
|
namespace utils = base::utils;
|
|
namespace jsonutils = wxhelper::jsonutils;
|
|
namespace wxutils = wxhelper::wxutils;
|
|
prototype::WeChatString* BuildWechatString(const std::wstring& ws) {
|
|
prototype::WeChatString* p =
|
|
base::utils::WxHeapAlloc<prototype::WeChatString>(
|
|
sizeof(prototype::WeChatString));
|
|
wchar_t* p_chat_room_id =
|
|
base::utils::WxHeapAlloc<wchar_t>((ws.size() + 1) * 2);
|
|
wmemcpy(p_chat_room_id, ws.c_str(), ws.size() + 1);
|
|
p->ptr = p_chat_room_id;
|
|
p->length = static_cast<int32_t>(ws.size());
|
|
p->max_length = static_cast<int32_t>(ws.size());
|
|
p->c_len = 0;
|
|
p->c_ptr = 0;
|
|
return p;
|
|
}
|
|
wechat::WeChatService::~WeChatService() {}
|
|
|
|
void wechat::WeChatService::Init() { base_addr_ = wxutils::GetWeChatWinBase(); }
|
|
|
|
int64_t wechat::WeChatService::CheckLogin() {
|
|
int64_t success = -1;
|
|
|
|
uint64_t accout_service_addr = base_addr_ + offset::kGetAccountServiceMgr;
|
|
func::__GetAccountService GetSevice =
|
|
(func::__GetAccountService)accout_service_addr;
|
|
uint64_t service_addr = GetSevice();
|
|
if (service_addr) {
|
|
success = *(uint64_t*)(service_addr + 0x7F8);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::GetSelfInfo(SelfInfoInner& out) {
|
|
int64_t success = -1;
|
|
uint64_t accout_service_addr = base_addr_ + offset::kGetAccountServiceMgr;
|
|
uint64_t get_app_data_save_path_addr =
|
|
base_addr_ + offset::kGetAppDataSavePath;
|
|
uint64_t get_current_data_path_addr =
|
|
base_addr_ + offset::kGetCurrentDataPath;
|
|
func::__GetAccountService GetSevice =
|
|
(func::__GetAccountService)accout_service_addr;
|
|
func::__GetDataSavePath GetDataSavePath =
|
|
(func::__GetDataSavePath)get_app_data_save_path_addr;
|
|
func::__GetCurrentDataPath GetCurrentDataPath =
|
|
(func::__GetCurrentDataPath)get_current_data_path_addr;
|
|
uint64_t service_addr = GetSevice();
|
|
if (service_addr) {
|
|
if (*(int64_t*)(service_addr + 0x80) == 0 ||
|
|
*(int64_t*)(service_addr + 0x80 + 0x10) == 0) {
|
|
out.wxid = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x80 + 0x18) == 0xF) {
|
|
out.wxid = std::string((char*)(service_addr + 0x80),
|
|
*(int64_t*)(service_addr + 0x80 + 0x10));
|
|
} else {
|
|
out.wxid = std::string(*(char**)(service_addr + 0x80),
|
|
*(int64_t*)(service_addr + 0x80 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x108) == 0 ||
|
|
*(int64_t*)(service_addr + 0x108 + 0x10) == 0) {
|
|
out.account = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x108 + 0x18) == 0xF) {
|
|
out.account = std::string((char*)(service_addr + 0x108),
|
|
*(int64_t*)(service_addr + 0x108 + 0x10));
|
|
} else {
|
|
out.account = std::string(*(char**)(service_addr + 0x108),
|
|
*(int64_t*)(service_addr + 0x108 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x128) == 0 ||
|
|
*(int64_t*)(service_addr + 0x128 + 0x10) == 0) {
|
|
out.mobile = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x128 + 0x18) == 0xF) {
|
|
out.mobile = std::string((char*)(service_addr + 0x128),
|
|
*(int64_t*)(service_addr + 0x128 + 0x10));
|
|
} else {
|
|
out.mobile = std::string(*(char**)(service_addr + 0x128),
|
|
*(int64_t*)(service_addr + 0x128 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x148) == 0 ||
|
|
*(int64_t*)(service_addr + 0x148 + 0x10) == 0) {
|
|
out.signature = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x148 + 0x18) == 0xF) {
|
|
out.signature = std::string((char*)(service_addr + 0x148),
|
|
*(int64_t*)(service_addr + 0x148 + 0x10));
|
|
} else {
|
|
out.signature = std::string(*(char**)(service_addr + 0x148),
|
|
*(int64_t*)(service_addr + 0x148 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x168) == 0 ||
|
|
*(int64_t*)(service_addr + 0x168 + 0x10) == 0) {
|
|
out.country = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x168 + 0x18) == 0xF) {
|
|
out.country = std::string((char*)(service_addr + 0x168),
|
|
*(int64_t*)(service_addr + 0x168 + 0x10));
|
|
} else {
|
|
out.country = std::string(*(char**)(service_addr + 0x168),
|
|
*(int64_t*)(service_addr + 0x168 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x188) == 0 ||
|
|
*(int64_t*)(service_addr + 0x188 + 0x10) == 0) {
|
|
out.province = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x188 + 0x18) == 0xF) {
|
|
out.province = std::string((char*)(service_addr + 0x188),
|
|
*(int64_t*)(service_addr + 0x188 + 0x10));
|
|
} else {
|
|
out.province = std::string(*(char**)(service_addr + 0x188),
|
|
*(int64_t*)(service_addr + 0x188 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x1A8) == 0 ||
|
|
*(int64_t*)(service_addr + 0x1A8 + 0x10) == 0) {
|
|
out.city = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x1A8 + 0x18) == 0xF) {
|
|
out.city = std::string((char*)(service_addr + 0x1A8),
|
|
*(int64_t*)(service_addr + 0x1A8 + 0x10));
|
|
} else {
|
|
out.city = std::string(*(char**)(service_addr + 0x1A8),
|
|
*(int64_t*)(service_addr + 0x1A8 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x1E8) == 0 ||
|
|
*(int64_t*)(service_addr + 0x1E8 + 0x10) == 0) {
|
|
out.name = std::string();
|
|
} else {
|
|
if (*(int64_t*)(service_addr + 0x1E8 + 0x18) == 0xF) {
|
|
out.name = std::string((char*)(service_addr + 0x1E8),
|
|
*(int64_t*)(service_addr + 0x1E8 + 0x10));
|
|
} else {
|
|
out.name = std::string(*(char**)(service_addr + 0x1E8),
|
|
*(int64_t*)(service_addr + 0x1E8 + 0x10));
|
|
}
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x450) == 0 ||
|
|
*(int64_t*)(service_addr + 0x450 + 0x10) == 0) {
|
|
out.head_img = std::string();
|
|
} else {
|
|
out.head_img = std::string(*(char**)(service_addr + 0x450),
|
|
*(int64_t*)(service_addr + 0x450 + 0x10));
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x7B8) == 0 ||
|
|
*(int64_t*)(service_addr + 0x7B8 + 0x10) == 0) {
|
|
out.public_key = std::string();
|
|
} else {
|
|
out.public_key = std::string(*(char**)(service_addr + 0x7B8),
|
|
*(int64_t*)(service_addr + 0x7B8 + 0x10));
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x7D8) == 0 ||
|
|
*(int64_t*)(service_addr + 0x7D8 + 0x10) == 0) {
|
|
out.private_key = std::string();
|
|
} else {
|
|
out.private_key = std::string(*(char**)(service_addr + 0x7D8),
|
|
*(int64_t*)(service_addr + 0x7D8 + 0x10));
|
|
}
|
|
|
|
if (*(int64_t*)(service_addr + 0x6E0) == 0 ||
|
|
*(int64_t*)(service_addr + 0x6E8) == 0) {
|
|
out.db_key = std::string();
|
|
} else {
|
|
int64_t byte_addr = *(int64_t*)(service_addr + 0x6E0);
|
|
int64_t len = *(int64_t*)(service_addr + 0x6E8);
|
|
out.db_key =
|
|
base::utils::Bytes2Hex((BYTE*)byte_addr, static_cast<int>(len));
|
|
}
|
|
|
|
uint64_t flag = *(uint64_t*)(service_addr + 0x7F8);
|
|
if (flag == 1) {
|
|
prototype::WeChatString current_data_path;
|
|
GetCurrentDataPath(reinterpret_cast<ULONG_PTR>(¤t_data_path));
|
|
if (current_data_path.ptr) {
|
|
out.current_data_path = base::utils::WstringToUtf8(
|
|
std::wstring(current_data_path.ptr, current_data_path.length));
|
|
} else {
|
|
out.current_data_path = std::string();
|
|
}
|
|
}
|
|
}
|
|
prototype::WeChatString data_save_path;
|
|
GetCurrentDataPath(reinterpret_cast<ULONG_PTR>(&data_save_path));
|
|
if (data_save_path.ptr) {
|
|
out.data_save_path = base::utils::WstringToUtf8(
|
|
std::wstring(data_save_path.ptr, data_save_path.length));
|
|
} else {
|
|
out.data_save_path = std::string();
|
|
}
|
|
success = 1;
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::SendTextMsg(const std::wstring& wxid,
|
|
const std::wstring& msg) {
|
|
prototype::WeChatString to_user(wxid);
|
|
prototype::WeChatString text_msg(msg);
|
|
uint64_t send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
|
|
uint64_t send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
char chat_msg[0x460] = {0};
|
|
uint64_t temp[3] = {0};
|
|
func::__GetSendMessageMgr mgr;
|
|
mgr = (func::__GetSendMessageMgr)send_message_mgr_addr;
|
|
func::__SendTextMsg send;
|
|
send = (func::__SendTextMsg)send_text_msg_addr;
|
|
func::__FreeChatMsg free;
|
|
free = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
mgr();
|
|
uint64_t success = send(reinterpret_cast<uint64_t>(&chat_msg),
|
|
reinterpret_cast<uint64_t>(&to_user),
|
|
reinterpret_cast<uint64_t>(&text_msg),
|
|
reinterpret_cast<uint64_t>(&temp), 1, 1, 0, 0);
|
|
free(reinterpret_cast<uint64_t>(&chat_msg));
|
|
return 0;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::SendImageMsg(const std::wstring& wxid,
|
|
const std::wstring& image_path) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString to_user(wxid);
|
|
prototype::WeChatString image_full_path(image_path);
|
|
uint64_t send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
|
|
uint64_t send_img_addr = base_addr_ + offset::kSendImageMsg;
|
|
uint64_t new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
|
|
func::__GetSendMessageMgr mgr =
|
|
(func::__GetSendMessageMgr)send_message_mgr_addr;
|
|
func::__SendImageMsg send_img = (func::__SendImageMsg)send_img_addr;
|
|
func::__FreeChatMsg free = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
|
|
char chat_msg[0x460] = {0};
|
|
char chat_msg_temp[0x460] = {0};
|
|
|
|
uint64_t p_chat_msg_temp =
|
|
new_chat_msg(reinterpret_cast<uint64_t>(&chat_msg_temp));
|
|
uint64_t temp1 = 0;
|
|
uint64_t temp2 = 0;
|
|
uint64_t temp3 = 1;
|
|
uint64_t* flag[10] = {};
|
|
flag[0] = reinterpret_cast<uint64_t*>(temp3);
|
|
flag[8] = &temp1;
|
|
flag[9] = &temp2;
|
|
flag[1] = reinterpret_cast<uint64_t*>(p_chat_msg_temp);
|
|
|
|
uint64_t p_chat_msg = new_chat_msg(reinterpret_cast<uint64_t>(&chat_msg));
|
|
uint64_t send_mgr = mgr();
|
|
success = send_img(send_mgr, p_chat_msg, reinterpret_cast<uint64_t>(&to_user),
|
|
reinterpret_cast<uint64_t>(&image_full_path),
|
|
reinterpret_cast<uint64_t>(&flag));
|
|
free(p_chat_msg);
|
|
free(p_chat_msg_temp);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::SendFileMsg(const std::wstring& wxid,
|
|
const std::wstring& file_path) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString* to_user = (prototype::WeChatString*)HeapAlloc(
|
|
GetProcessHeap(), 0, sizeof(prototype::WeChatString));
|
|
wchar_t* ptr_wxid =
|
|
(wchar_t*)HeapAlloc(GetProcessHeap(), 0, (wxid.length() + 1) * 2);
|
|
wmemcpy(ptr_wxid, wxid.c_str(), wxid.length() + 1);
|
|
to_user->ptr = ptr_wxid;
|
|
to_user->length = static_cast<DWORD>(wxid.length());
|
|
to_user->max_length = static_cast<DWORD>(wxid.length());
|
|
to_user->c_len = 0;
|
|
to_user->c_ptr = 0;
|
|
prototype::WeChatString* file_full_path = (prototype::WeChatString*)HeapAlloc(
|
|
GetProcessHeap(), 0, sizeof(prototype::WeChatString));
|
|
wchar_t* ptr_path =
|
|
(wchar_t*)HeapAlloc(GetProcessHeap(), 0, (file_path.length() + 1) * 2);
|
|
wmemcpy(ptr_path, file_path.c_str(), file_path.length() + 1);
|
|
file_full_path->ptr = ptr_path;
|
|
file_full_path->length = static_cast<DWORD>(file_path.length());
|
|
file_full_path->max_length = static_cast<DWORD>(file_path.length());
|
|
file_full_path->c_len = 0;
|
|
file_full_path->c_ptr = 0;
|
|
|
|
uint64_t get_app_msg_mgr_addr = base_addr_ + offset::kGetAppMsgMgr;
|
|
uint64_t send_file_addr = base_addr_ + offset::kSendFileMsg;
|
|
uint64_t new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
|
|
func::__GetAppMsgMgr get_app_mgr = (func::__GetAppMsgMgr)get_app_msg_mgr_addr;
|
|
func::__SendFile send_file = (func::__SendFile)send_file_addr;
|
|
func::__FreeChatMsg free = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
|
|
char* chat_msg = (char*)HeapAlloc(GetProcessHeap(), 0, 0x460);
|
|
|
|
uint64_t* temp1 =
|
|
(uint64_t*)HeapAlloc(GetProcessHeap(), 0, sizeof(uint64_t) * 4);
|
|
uint64_t* temp2 =
|
|
(uint64_t*)HeapAlloc(GetProcessHeap(), 0, sizeof(uint64_t) * 4);
|
|
uint64_t* temp3 =
|
|
(uint64_t*)HeapAlloc(GetProcessHeap(), 0, sizeof(uint64_t) * 4);
|
|
|
|
ZeroMemory(temp1, sizeof(uint64_t) * 4);
|
|
ZeroMemory(temp2, sizeof(uint64_t) * 4);
|
|
ZeroMemory(temp3, sizeof(uint64_t) * 4);
|
|
|
|
uint64_t app_mgr = get_app_mgr();
|
|
success = send_file(app_mgr, reinterpret_cast<uint64_t>(chat_msg),
|
|
reinterpret_cast<uint64_t>(to_user),
|
|
reinterpret_cast<uint64_t>(file_full_path), 1,
|
|
reinterpret_cast<uint64_t>(temp1), 0,
|
|
reinterpret_cast<uint64_t>(temp2), 0,
|
|
reinterpret_cast<uint64_t>(temp3), 0, 0xC);
|
|
free(reinterpret_cast<uint64_t>(chat_msg));
|
|
HeapFree(GetProcessHeap(), 0, to_user);
|
|
HeapFree(GetProcessHeap(), 0, file_full_path);
|
|
HeapFree(GetProcessHeap(), 0, temp1);
|
|
HeapFree(GetProcessHeap(), 0, temp2);
|
|
HeapFree(GetProcessHeap(), 0, temp3);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::GetContacts(std::vector<ContactInner>& vec) {
|
|
int64_t success = -1;
|
|
int64_t base_addr = wxutils::GetWeChatWinBase();
|
|
uint64_t get_contact_mgr_addr = base_addr + offset::kGetContactMgr;
|
|
uint64_t get_contact_list_addr = base_addr + offset::kGetContactList;
|
|
func::__GetContactMgr get_contact_mgr =
|
|
(func::__GetContactMgr)get_contact_mgr_addr;
|
|
func::__GetContactList get_contact_list =
|
|
(func::__GetContactList)get_contact_list_addr;
|
|
uint64_t mgr = get_contact_mgr();
|
|
uint64_t contact_vec[3] = {0, 0, 0};
|
|
success = get_contact_list(mgr, reinterpret_cast<uint64_t>(&contact_vec));
|
|
|
|
uint64_t start = contact_vec[0];
|
|
uint64_t end = contact_vec[2];
|
|
while (start < end) {
|
|
wechat::ContactInner temp;
|
|
temp.wxid = wxutils::ReadWstringThenConvert(start + 0x10);
|
|
temp.custom_account = wxutils::ReadWstringThenConvert(start + 0x30);
|
|
temp.encrypt_name = wxutils::ReadWstringThenConvert(start + 0x50);
|
|
temp.remark = wxutils::ReadWstringThenConvert(start + 0x80);
|
|
temp.remark_pinyin = wxutils::ReadWstringThenConvert(start + 0x148);
|
|
temp.remark_pinyin_all = wxutils::ReadWstringThenConvert(start + 0x168);
|
|
temp.label_ids = wxutils::ReadWstringThenConvert(start + 0xc0);
|
|
temp.nickname = wxutils::ReadWstringThenConvert(start + 0xA0);
|
|
temp.pinyin = wxutils::ReadWstringThenConvert(start + 0x108);
|
|
temp.pinyin_all = wxutils::ReadWstringThenConvert(start + 0x128);
|
|
temp.verify_flag = *(int32_t*)(start + 0x70);
|
|
temp.type = *(int32_t*)(start + 0x74);
|
|
temp.reserved1 = *(int32_t*)(start + 0x1F0);
|
|
temp.reserved2 = *(int32_t*)(start + 0x1F4);
|
|
vec.push_back(temp);
|
|
start += 0x6A8;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::GetChatRoomDetailInfo(
|
|
const std::wstring& room_id, ChatRoomInfoInner& room_info) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString chat_room_id(room_id);
|
|
int64_t base_addr = wxutils::GetWeChatWinBase();
|
|
uint64_t get_chat_room_mgr_addr = base_addr + offset::kChatRoomMgr;
|
|
uint64_t get_chat_room_detail_addr =
|
|
base_addr + offset::kGetChatRoomDetailInfo;
|
|
uint64_t create_chat_room_info_addr = base_addr + offset::kNewChatRoomInfo;
|
|
uint64_t free_chat_room_info_addr = base_addr + offset::kFreeChatRoomInfo;
|
|
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__NewChatRoomInfo new_chat_room_info =
|
|
(func::__NewChatRoomInfo)create_chat_room_info_addr;
|
|
func::__FreeChatRoomInfo free_chat_room_info =
|
|
(func::__FreeChatRoomInfo)free_chat_room_info_addr;
|
|
func::__GetChatRoomDetailInfo get_chat_room_detail =
|
|
(func::__GetChatRoomDetailInfo)get_chat_room_detail_addr;
|
|
|
|
char chat_room_info[0x144] = {0};
|
|
|
|
uint64_t new_room_info =
|
|
new_chat_room_info(reinterpret_cast<uint64_t>(&chat_room_info));
|
|
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
success = get_chat_room_detail(mgr, reinterpret_cast<uint64_t>(&chat_room_id),
|
|
new_room_info, 1);
|
|
|
|
room_info.chat_room_id = wxutils::ReadWstringThenConvert(new_room_info + 0x8);
|
|
room_info.notice = wxutils::ReadWstringThenConvert(new_room_info + 0x28);
|
|
room_info.admin = wxutils::ReadWstringThenConvert(new_room_info + 0x48);
|
|
room_info.xml = wxutils::ReadWstringThenConvert(new_room_info + 0x78);
|
|
free_chat_room_info(new_room_info);
|
|
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::AddMemberToChatRoom(
|
|
const std::wstring& room_id, const std::vector<std::wstring>& members) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
|
|
uint64_t add_members_addr = base_addr_ + offset::kDoAddMemberToChatRoom;
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__DoAddMemberToChatRoom add_members =
|
|
(func::__DoAddMemberToChatRoom)add_members_addr;
|
|
|
|
prototype::WeChatString* chat_room_id = (prototype::WeChatString*)HeapAlloc(
|
|
GetProcessHeap(), 0, sizeof(prototype::WeChatString));
|
|
wchar_t* p_chat_room_id =
|
|
(wchar_t*)HeapAlloc(GetProcessHeap(), 0, (room_id.size() + 1) * 2);
|
|
wmemcpy(p_chat_room_id, room_id.c_str(), room_id.size() + 1);
|
|
chat_room_id->ptr = p_chat_room_id;
|
|
chat_room_id->length = static_cast<int32_t>(room_id.size());
|
|
chat_room_id->max_length = static_cast<int32_t>(room_id.size());
|
|
chat_room_id->c_len = 0;
|
|
chat_room_id->c_ptr = 0;
|
|
|
|
std::vector<prototype::WeChatString> member_list;
|
|
uint64_t temp[2] = {0};
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&member_list;
|
|
int64_t members_ptr = (int64_t)&list->start;
|
|
for (int i = 0; i < members.size(); i++) {
|
|
prototype::WeChatString member(members[i]);
|
|
member_list.push_back(member);
|
|
}
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
success =
|
|
add_members(mgr, members_ptr, reinterpret_cast<uint64_t>(chat_room_id),
|
|
reinterpret_cast<uint64_t>(&temp));
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::ModChatRoomMemberNickName(
|
|
const std::wstring& room_id, const std::wstring& wxid,
|
|
const std::wstring& nickname) {
|
|
int64_t success = -1;
|
|
uint64_t mod_addr = base_addr_ + offset::kDoModChatRoomMemberNickName;
|
|
func::__DoModChatRoomMemberNickName modify =
|
|
(func::__DoModChatRoomMemberNickName)mod_addr;
|
|
const wchar_t* p = room_id.c_str();
|
|
prototype::WeChatString* chat_room_id = BuildWechatString(room_id);
|
|
prototype::WeChatString* self_id = BuildWechatString(wxid);
|
|
prototype::WeChatString* name = BuildWechatString(nickname);
|
|
success = modify(
|
|
reinterpret_cast<UINT64>(p), reinterpret_cast<UINT64>(chat_room_id),
|
|
reinterpret_cast<UINT64>(self_id), reinterpret_cast<UINT64>(name));
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::DelMemberFromChatRoom(
|
|
const std::wstring& room_id, const std::vector<std::wstring>& members) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
|
|
uint64_t del_members_addr = base_addr_ + offset::kDelMemberFromChatRoom;
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__DoDelMemberFromChatRoom del_members =
|
|
(func::__DoDelMemberFromChatRoom)del_members_addr;
|
|
|
|
prototype::WeChatString* chat_room_id = BuildWechatString(room_id);
|
|
std::vector<prototype::WeChatString> member_list;
|
|
uint64_t temp[2] = {0};
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&member_list;
|
|
int64_t members_ptr = (int64_t)&list->start;
|
|
for (int i = 0; i < members.size(); i++) {
|
|
prototype::WeChatString member(members[i]);
|
|
member_list.push_back(member);
|
|
}
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
success =
|
|
del_members(mgr, members_ptr, reinterpret_cast<uint64_t>(chat_room_id));
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::GetMemberFromChatRoom(
|
|
const std::wstring& room_id, ChatRoomMemberInner& member) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
|
|
uint64_t get_members_addr = base_addr_ + offset::kGetMemberFromChatRoom;
|
|
uint64_t new_chat_room_addr = base_addr_ + offset::kNewChatRoom;
|
|
uint64_t free_chat_room_addr = base_addr_ + offset::kFreeChatRoom;
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__GetMemberFromChatRoom get_members =
|
|
(func::__GetMemberFromChatRoom)get_members_addr;
|
|
func::__NewChatRoom new_chat_room = (func::__NewChatRoom)new_chat_room_addr;
|
|
func::__FreeChatRoom free_chat_room =
|
|
(func::__FreeChatRoom)free_chat_room_addr;
|
|
|
|
prototype::WeChatString chat_room_id(room_id);
|
|
char chat_room_info[0x308] = {0};
|
|
uint64_t addr = new_chat_room(reinterpret_cast<uint64_t>(&chat_room_info));
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
success = get_members(mgr, reinterpret_cast<uint64_t>(&chat_room_id), addr);
|
|
member.chat_room_id = wxutils::ReadWstringThenConvert(addr + 0x10);
|
|
member.admin = wxutils::ReadWstringThenConvert(addr + 0x78);
|
|
member.member_nickname = wxutils::ReadWstringThenConvert(addr + 0x50);
|
|
member.admin_nickname = wxutils::ReadWstringThenConvert(addr + 0xA0);
|
|
member.member = wxutils::ReadWeChatStr(addr + 0x30);
|
|
free_chat_room(addr);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::SetTopMsg(uint64_t msg_id) {
|
|
int64_t success = -1;
|
|
uint64_t top_addr = base_addr_ + offset::kTopMsg;
|
|
func::__DoTopMsg top_msg = (func::__DoTopMsg)top_addr;
|
|
int64_t index = 0;
|
|
int64_t local_id =
|
|
wechat::WeChatDb::GetInstance().GetLocalIdByMsgId(msg_id, index);
|
|
if (local_id <= 0 || index >> 32 == 0) {
|
|
success = -2;
|
|
return success;
|
|
}
|
|
LARGE_INTEGER l;
|
|
l.HighPart = index >> 32;
|
|
l.LowPart = (DWORD)local_id;
|
|
uint64_t ptr = reinterpret_cast<uint64_t>(&l);
|
|
success = top_msg(ptr, 1);
|
|
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::RemoveTopMsg(const std::wstring& room_id,
|
|
uint64_t msg_id) {
|
|
int64_t success = -1;
|
|
uint64_t remove_addr = base_addr_ + offset::kRemoveTopMsg;
|
|
func::__RemoveTopMsg remove_top_msg = (func::__RemoveTopMsg)remove_addr;
|
|
prototype::WeChatString* chat_room_id = BuildWechatString(room_id);
|
|
const wchar_t* w_room = room_id.c_str();
|
|
success = remove_top_msg(reinterpret_cast<UINT64>(w_room), msg_id,
|
|
reinterpret_cast<UINT64>(chat_room_id));
|
|
return success;
|
|
}
|
|
TODO("InviteMemberToChatRoom")
|
|
int64_t wechat::WeChatService::InviteMemberToChatRoom(
|
|
const std::wstring& room_id, const std::vector<std::wstring>& wxids) {
|
|
int64_t success = -1;
|
|
uint64_t invite_addr = base_addr_ + offset::kInviteMember;
|
|
func::__InviteMemberToChatRoom invite =
|
|
(func::__InviteMemberToChatRoom)invite_addr;
|
|
const wchar_t* w_room = room_id.c_str();
|
|
prototype::WeChatString* chat_room_id = BuildWechatString(room_id);
|
|
std::vector<prototype::WeChatString> wxid_list;
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&wxid_list;
|
|
int64_t head = (int64_t)&list->start;
|
|
for (int i = 0; i < wxids.size(); i++) {
|
|
prototype::WeChatString id(wxids[i]);
|
|
wxid_list.push_back(id);
|
|
}
|
|
uint64_t temp[2] = {0};
|
|
success = invite(reinterpret_cast<uint64_t>(w_room), head,
|
|
reinterpret_cast<uint64_t>(chat_room_id),
|
|
reinterpret_cast<uint64_t>(&temp));
|
|
return success;
|
|
}
|
|
|
|
TODO("CreateChatRoom")
|
|
int64_t wechat::WeChatService::CreateChatRoom(
|
|
const std::vector<std::wstring>& wxids) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
|
|
uint64_t create_chat_room_addr = base_addr_ + offset::kCreateChatRoom;
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__CreateChatRoom create_chat_room =
|
|
(func::__CreateChatRoom)create_chat_room_addr;
|
|
std::vector<prototype::WeChatString> wxid_list;
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&wxid_list;
|
|
int64_t head = (int64_t)&list->start;
|
|
for (int i = 0; i < wxids.size(); i++) {
|
|
prototype::WeChatString id(wxids[i]);
|
|
wxid_list.push_back(id);
|
|
}
|
|
int64_t end = list->end;
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
success = create_chat_room(mgr, head, end);
|
|
return success;
|
|
}
|
|
|
|
TODO("QuitChatRoom")
|
|
int64_t wechat::WeChatService::QuitChatRoom(const std::wstring& room_id) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
|
|
uint64_t quit_chat_room_addr = base_addr_ + offset::kQuitChatRoom;
|
|
func::__GetChatRoomMgr get_chat_room_mgr =
|
|
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
|
|
func::__QuitChatRoom quit_chat_room =
|
|
(func::__QuitChatRoom)quit_chat_room_addr;
|
|
uint64_t mgr = get_chat_room_mgr();
|
|
prototype::WeChatString chat_room_id(room_id);
|
|
success = quit_chat_room(mgr, reinterpret_cast<uint64_t>(&chat_room_id), 0);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::ForwardMsg(uint64_t msg_id,
|
|
const std::wstring& wxid) {
|
|
int64_t success = -1;
|
|
uint64_t forward_addr = base_addr_ + offset::kForwardMsg;
|
|
func::__ForwardMsg forward_msg = (func::__ForwardMsg)forward_addr;
|
|
int64_t index = 0;
|
|
int64_t local_id =
|
|
wechat::WeChatDb::GetInstance().GetLocalIdByMsgId(msg_id, index);
|
|
if (local_id <= 0 || index >> 32 == 0) {
|
|
success = -2;
|
|
|
|
return success;
|
|
}
|
|
LARGE_INTEGER l;
|
|
l.HighPart = index >> 32;
|
|
l.LowPart = (DWORD)local_id;
|
|
prototype::WeChatString* recv = BuildWechatString(wxid);
|
|
success = forward_msg(reinterpret_cast<uint64_t>(recv), l.QuadPart, 0x4, 0x0);
|
|
return success;
|
|
}
|
|
|
|
TODO("GetSNSFirstPage")
|
|
int64_t wechat::WeChatService::GetSNSFirstPage() {
|
|
int64_t success = -1;
|
|
uint64_t sns_data_mgr_addr = base_addr_ + offset::kSNSDataMgr;
|
|
uint64_t sns_first_page_addr = base_addr_ + offset::kSNSGetFirstPage;
|
|
func::__GetSNSDataMgr sns_data_mgr = (func::__GetSNSDataMgr)sns_data_mgr_addr;
|
|
func::__GetSNSFirstPage sns_first_page =
|
|
(func::__GetSNSFirstPage)sns_first_page_addr;
|
|
uint64_t mgr = sns_data_mgr();
|
|
int64_t buff[16] = {0};
|
|
success = sns_first_page(mgr, reinterpret_cast<uint64_t>(&buff), 1);
|
|
return success;
|
|
}
|
|
|
|
TODO("GetSNSNextPage")
|
|
int64_t wechat::WeChatService::GetSNSNextPage(uint64_t sns_id) {
|
|
int64_t success = -1;
|
|
uint64_t time_line_mgr_addr = base_addr_ + offset::kSNSTimeLineMgr;
|
|
uint64_t sns_next_page_addr = base_addr_ + offset::kSNSGetNextPageScene;
|
|
func::__GetSnsTimeLineMgr time_line_mgr =
|
|
(func::__GetSnsTimeLineMgr)time_line_mgr_addr;
|
|
func::__GetSNSNextPageScene sns_next_page =
|
|
(func::__GetSNSNextPageScene)sns_next_page_addr;
|
|
uint64_t mgr = time_line_mgr();
|
|
success = sns_next_page(mgr, sns_id);
|
|
return success;
|
|
}
|
|
|
|
|
|
int64_t wechat::WeChatService::AddFavFromMsg(uint64_t msg_id) {
|
|
int64_t success = -1;
|
|
uint64_t get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
|
|
uint64_t get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
|
|
uint64_t add_fav_addr = base_addr_ + offset::kAddFavFromMsg;
|
|
uint64_t get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
func::__GetMgrByPrefixLocalId get_by_local_id =
|
|
(func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
|
|
uint64_t new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
|
|
|
|
func::__AddFavFromMsg add_fav = (func::__AddFavFromMsg)add_fav_addr;
|
|
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
|
|
func::__GetFavoriteMgr get_favorite_mgr =
|
|
(func::__GetFavoriteMgr)get_favorite_mgr_addr;
|
|
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
|
|
|
|
int64_t index = 0;
|
|
int64_t local_id =
|
|
wechat::WeChatDb::GetInstance().GetLocalIdByMsgId(msg_id, index);
|
|
if (local_id <= 0 || index >> 32 == 0) {
|
|
success = -2;
|
|
return success;
|
|
}
|
|
char chat_msg[0x460] = {0};
|
|
LARGE_INTEGER l;
|
|
l.HighPart = index >> 32;
|
|
l.LowPart = (DWORD)local_id;
|
|
uint64_t p_chat_msg = new_chat_msg(reinterpret_cast<uint64_t>(&chat_msg));
|
|
|
|
get_chat_mgr();
|
|
get_by_local_id(l.QuadPart, p_chat_msg);
|
|
uint64_t mgr = get_favorite_mgr();
|
|
success = add_fav(mgr, p_chat_msg);
|
|
free_chat_msg(p_chat_msg);
|
|
return success;
|
|
}
|
|
|
|
|
|
int64_t wechat::WeChatService::AddFavFromImage(const std::wstring& wxid,
|
|
const std::wstring& image_path) {
|
|
int64_t success = -1;
|
|
uint64_t get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
|
|
uint64_t add_fav_from_image_addr = base_addr_ + offset::kAddFavFromImage;
|
|
prototype::WeChatString* send_id = BuildWechatString(wxid);
|
|
prototype::WeChatString* path = BuildWechatString(image_path);
|
|
func::__GetFavoriteMgr get_favorite_mgr =
|
|
(func::__GetFavoriteMgr)get_favorite_mgr_addr;
|
|
func::__AddFavFromImage add_fav_from_image =
|
|
(func::__AddFavFromImage)add_fav_from_image_addr;
|
|
uint64_t mgr = get_favorite_mgr();
|
|
success = add_fav_from_image(mgr, reinterpret_cast<uint64_t>(path),
|
|
reinterpret_cast<uint64_t>(send_id));
|
|
return success;
|
|
}
|
|
int64_t wechat::WeChatService::SendAtText(
|
|
const std::wstring& room_id, const std::vector<std::wstring>& wxids,
|
|
const std::wstring& msg) {
|
|
int64_t success = -1;
|
|
std::vector<prototype::WeChatString> wxid_list;
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&wxid_list;
|
|
std::wstring at_msg = L"";
|
|
int number = 0;
|
|
for (unsigned int i = 0; i < wxids.size(); i++) {
|
|
std::wstring nickname;
|
|
std::wstring at_all = L"notify@all";
|
|
if (at_all.compare(wxids[i]) == 0) {
|
|
nickname = L"\u6240\u6709\u4eba";
|
|
} else {
|
|
nickname = GetContactOrChatRoomNickname(wxids[i]);
|
|
}
|
|
if (nickname.length() == 0) {
|
|
continue;
|
|
}
|
|
prototype::WeChatString id(wxids[i]);
|
|
wxid_list.push_back(id);
|
|
at_msg = at_msg + L"@" + nickname + L" ";
|
|
number++;
|
|
}
|
|
if (number < 1) {
|
|
success = -2;
|
|
return success;
|
|
}
|
|
at_msg += msg;
|
|
|
|
INT64 head = (INT64)&list->start;
|
|
prototype::WeChatString to_user(room_id);
|
|
prototype::WeChatString text_msg(at_msg);
|
|
uint64_t send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
|
|
uint64_t send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
char chat_msg[0x460] = {0};
|
|
func::__GetSendMessageMgr mgr =
|
|
(func::__GetSendMessageMgr)send_message_mgr_addr;
|
|
func::__SendTextMsg send = (func::__SendTextMsg)send_text_msg_addr;
|
|
func::__FreeChatMsg free = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
mgr();
|
|
success = send(reinterpret_cast<uint64_t>(&chat_msg),
|
|
reinterpret_cast<uint64_t>(&to_user),
|
|
reinterpret_cast<uint64_t>(&text_msg), head, 1, 1, 0, 0);
|
|
free(reinterpret_cast<uint64_t>(&chat_msg));
|
|
return 0;
|
|
}
|
|
TODO("GetContactOrChatRoomNickname")
|
|
std::wstring wechat::WeChatService::GetContactOrChatRoomNickname(
|
|
const std::wstring& wxid) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString to_user(wxid);
|
|
uint64_t get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
|
|
uint64_t new_contact_addr = base_addr_ + offset::kNewContact;
|
|
uint64_t get_contact_addr = base_addr_ + offset::kGetContact;
|
|
uint64_t free_contact_addr = base_addr_ + offset::kFreeContact;
|
|
func::__GetContactMgr get_contact_mgr =
|
|
(func::__GetContactMgr)get_contact_mgr_addr;
|
|
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
|
|
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
|
|
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
|
|
char buff[0x6A9] = {0};
|
|
uint64_t contact = new_contact(reinterpret_cast<uint64_t>(&buff));
|
|
uint64_t mgr = get_contact_mgr();
|
|
success = get_contact(mgr, reinterpret_cast<uint64_t>(&to_user), contact);
|
|
|
|
if (success == 1) {
|
|
std::wstring nickname = wxutils::ReadWstring(contact + 0xA0);
|
|
free_contact(contact);
|
|
return nickname;
|
|
} else {
|
|
free_contact(contact);
|
|
return L"";
|
|
}
|
|
}
|
|
|
|
|
|
int64_t wechat::WeChatService::GetContactByWxid(const std::wstring& wxid,
|
|
ContactProfileInner& profile) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString to_user(wxid);
|
|
uint64_t get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
|
|
uint64_t new_contact_addr = base_addr_ + offset::kNewContact;
|
|
uint64_t get_contact_addr = base_addr_ + offset::kGetContact;
|
|
uint64_t free_contact_addr = base_addr_ + offset::kFreeContact;
|
|
func::__GetContactMgr get_contact_mgr =
|
|
(func::__GetContactMgr)get_contact_mgr_addr;
|
|
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
|
|
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
|
|
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
|
|
char buff[0x6A9] = {0};
|
|
uint64_t contact = new_contact(reinterpret_cast<uint64_t>(&buff));
|
|
uint64_t mgr = get_contact_mgr();
|
|
success = get_contact(mgr, reinterpret_cast<uint64_t>(&to_user), contact);
|
|
profile.wxid = wxutils::ReadWstringThenConvert(contact + 0x10);
|
|
profile.account = wxutils::ReadWstringThenConvert(contact + 0x30);
|
|
profile.v3 = wxutils::ReadWstringThenConvert(contact + 0x50);
|
|
profile.nickname = wxutils::ReadWstringThenConvert(contact + 0xA0);
|
|
profile.head_image = wxutils::ReadWstringThenConvert(contact + 0x188);
|
|
free_contact(contact);
|
|
return success;
|
|
}
|
|
|
|
std::wstring combineAndRemoveDuplicate(const std::wstring& basePath, const std::wstring& resultPath) {
|
|
std::wstring cleanedBasePath = basePath;
|
|
if (cleanedBasePath.back() == L'\\') {
|
|
cleanedBasePath.pop_back();
|
|
}
|
|
size_t pos = resultPath.find(cleanedBasePath);
|
|
if (pos != std::wstring::npos) {
|
|
std::wstring adjustedResultPath = resultPath.substr(pos + cleanedBasePath.length());
|
|
return cleanedBasePath + L'\\' + adjustedResultPath;
|
|
}
|
|
|
|
return basePath + L'\\' + resultPath;
|
|
}
|
|
TODO("DoDownloadTask")
|
|
|
|
std::wstring wechat::WeChatService::DoDownloadTask(uint64_t msg_id) {
|
|
|
|
uint64_t get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
|
|
func::__GetMgrByPrefixLocalId get_by_local_id =
|
|
(func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
|
|
|
|
uint64_t get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
|
|
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
|
|
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
|
|
uint64_t new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
|
|
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
|
|
|
|
uint64_t get_current_data_path_addr =
|
|
base_addr_ + offset::kGetCurrentDataPath;
|
|
func::__GetCurrentDataPath GetCurrentDataPath =
|
|
(func::__GetCurrentDataPath)get_current_data_path_addr;
|
|
|
|
uint64_t new_app_msg_info_addr = base_addr_ + offset::kNewAppMsgInfo;
|
|
func::__NewAppMsgInfo new_app_msg_info =
|
|
(func::__NewAppMsgInfo)new_app_msg_info_addr;
|
|
|
|
uint64_t free_app_msg_info_addr = base_addr_ + offset::kFreeAppMsgInfo;
|
|
func::__FreeAppMsgInfo free_app_msg_info =
|
|
(func::__NewAppMsgInfo)free_app_msg_info_addr;
|
|
|
|
uint64_t xml_to_app_info_addr = base_addr_ + offset::kParseAppMsgXml;
|
|
func::__ParseAppMsgXml xml_to_app_info =
|
|
(func::__ParseAppMsgXml)xml_to_app_info_addr;
|
|
|
|
uint64_t get_pre_download_mgr_addr = base_addr_ + offset::kGetPreDownLoadMgr;
|
|
func::__GetPreDownLoadMgr get_pre_download_mgr =
|
|
(func::__GetPreDownLoadMgr)get_pre_download_mgr_addr;
|
|
|
|
uint64_t push_attach_task_addr = base_addr_ + offset::kPushAttachTask;
|
|
func::__PushAttachTask push_attach_task =
|
|
(func::__PushAttachTask)push_attach_task_addr;
|
|
|
|
int64_t index = 0;
|
|
int64_t local_id =
|
|
wechat::WeChatDb::GetInstance().GetLocalIdByMsgId(msg_id, index);
|
|
if (local_id <= 0 || index >> 32 == 0) {
|
|
return L"-2";
|
|
}
|
|
char* chat_msg = base::utils::WxHeapAlloc<char>(0x460);
|
|
LARGE_INTEGER l;
|
|
l.HighPart = index >> 32;
|
|
l.LowPart = (DWORD)local_id;
|
|
uint64_t p_chat_msg = new_chat_msg(reinterpret_cast<uint64_t>(chat_msg));
|
|
|
|
get_chat_mgr();
|
|
get_by_local_id(l.QuadPart, p_chat_msg);
|
|
|
|
std::wstring save_path = L"";
|
|
std::wstring thumb_path = L"";
|
|
|
|
prototype::WeChatString current_data_path;
|
|
GetCurrentDataPath(reinterpret_cast<ULONG_PTR>(¤t_data_path));
|
|
|
|
if (current_data_path.length > 0) {
|
|
save_path += current_data_path.ptr;
|
|
} else {
|
|
return L"-1";
|
|
}
|
|
|
|
int64_t type = *(int64_t*)(chat_msg + 0x38);
|
|
wchar_t* content = *(wchar_t**)(chat_msg + 0x88);
|
|
DWORD len = *(DWORD*)(chat_msg + 0x94);
|
|
std::wstring tmp_content(content, len);
|
|
prototype::WeChatString* we_content = BuildWechatString(tmp_content);
|
|
|
|
switch (type) {
|
|
case 0x3: {
|
|
if (!save_path.empty() && save_path.back() == L'\\') {
|
|
save_path.pop_back();
|
|
}
|
|
size_t pos = save_path.find_last_of(L'\\');
|
|
if (pos != std::wstring::npos) {
|
|
save_path = save_path.substr(0, pos + 1);
|
|
}
|
|
break;
|
|
}
|
|
case 0x3E:
|
|
case 0x2B: {
|
|
save_path += L"\\video";
|
|
if (!wxutils::FindOrCreateDirectory(save_path)) {
|
|
return L"-3" ;
|
|
}
|
|
thumb_path = save_path + L"\\" + std::to_wstring(msg_id) + L".jpg";
|
|
save_path = save_path + L"\\" + std::to_wstring(msg_id) + L".mp4";
|
|
|
|
break;
|
|
}
|
|
case 0x31: {
|
|
save_path += L"\\file";
|
|
if (!wxutils::FindOrCreateDirectory(save_path)) {
|
|
return L"-3";
|
|
}
|
|
char* p_xml_app_msg = base::utils::WxHeapAlloc<char>(0x3000);
|
|
uint64_t xml_msg =
|
|
new_app_msg_info(reinterpret_cast<uint64_t>(p_xml_app_msg));
|
|
uint64_t result =
|
|
xml_to_app_info(xml_msg, reinterpret_cast<uint64_t>(we_content), 1);
|
|
if (result != 1) {
|
|
return L"-4";
|
|
}
|
|
std::wstring file_name = wxutils::ReadWstring(xml_msg + 0x70);
|
|
save_path =
|
|
save_path + L"\\" + std::to_wstring(msg_id) + L"_" + file_name;
|
|
free_app_msg_info(xml_msg);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
int temp = 1;
|
|
memcpy(chat_msg + 0x40C, &temp, sizeof(temp));
|
|
UINT64 mgr = get_pre_download_mgr();
|
|
INT64 success = push_attach_task(mgr, p_chat_msg, 0, 1);
|
|
std::wstring result = *(wchar_t**)(chat_msg + 0x2A0);
|
|
free_chat_msg(p_chat_msg);
|
|
return save_path + result;
|
|
}
|
|
|
|
TODO("ForwardPublicMsg")
|
|
int64_t wechat::WeChatService::ForwardPublicMsg(const std::wstring& wxid,
|
|
const std::wstring& title,
|
|
const std::wstring& url,
|
|
const std::wstring& thumb_url,
|
|
const std::wstring& sender_id,
|
|
const std::wstring& sender_name,
|
|
const std::wstring& digest) {
|
|
return 0;
|
|
}
|
|
|
|
TODO("ForwardPublicMsgByMsgId")
|
|
int64_t wechat::WeChatService::ForwardPublicMsgByMsgId(const std::wstring& wxid,
|
|
uint64_t msg_id) {
|
|
return 0;
|
|
}
|
|
TODO("DecodeImage")
|
|
int64_t wechat::WeChatService::DecodeImage(const std::wstring& file_path,
|
|
const std::wstring& save_dir) {
|
|
if (!wxutils::FindOrCreateDirectory(save_dir)) {
|
|
return 0;
|
|
}
|
|
|
|
int64_t pos_begin = file_path.find_last_of(L"\\") + 1;
|
|
int64_t pos_end = file_path.find_last_of(L".");
|
|
std::wstring file_name = file_path.substr(pos_begin, pos_end - pos_begin);
|
|
HANDLE h_origin_file =
|
|
CreateFileW(file_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
char buffer[BUFSIZE] = {0};
|
|
DWORD bytes_read = 0;
|
|
DWORD bytes_write = 0;
|
|
unsigned char magic_head[4] = {0};
|
|
std::wstring suffix;
|
|
short key = 0;
|
|
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
|
|
memcpy(magic_head, buffer, 3);
|
|
} else {
|
|
CloseHandle(h_origin_file);
|
|
return 0;
|
|
}
|
|
if ((magic_head[0] ^ JPEG0) == (magic_head[1] ^ JPEG1)) {
|
|
key = magic_head[0] ^ JPEG0;
|
|
suffix = L".jpg";
|
|
} else if ((magic_head[0] ^ PNG1) == (magic_head[1] ^ PNG2)) {
|
|
key = magic_head[0] ^ PNG1;
|
|
suffix = L".png";
|
|
} else if ((magic_head[0] ^ GIF0) == (magic_head[1] ^ GIF1)) {
|
|
key = magic_head[0] ^ GIF0;
|
|
suffix = L".gif";
|
|
} else if ((magic_head[0] ^ BMP0) == (magic_head[1] ^ BMP1)) {
|
|
key = magic_head[0] ^ BMP0;
|
|
suffix = L".bmp";
|
|
} else {
|
|
key = -1;
|
|
suffix = L".dat";
|
|
}
|
|
std::wstring save_img_path = save_dir + L"\\" + file_name + suffix;
|
|
HANDLE save_img = CreateFileW(save_img_path.c_str(), GENERIC_ALL, 0, NULL,
|
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (save_img == INVALID_HANDLE_VALUE) {
|
|
return 0;
|
|
}
|
|
if (key > 0) {
|
|
for (unsigned int i = 0; i < bytes_read; i++) {
|
|
buffer[i] ^= key;
|
|
}
|
|
}
|
|
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
|
|
CloseHandle(h_origin_file);
|
|
CloseHandle(save_img);
|
|
return 0;
|
|
}
|
|
|
|
do {
|
|
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
|
|
if (key > 0) {
|
|
for (unsigned int i = 0; i < bytes_read; i++) {
|
|
buffer[i] ^= key;
|
|
}
|
|
}
|
|
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
|
|
CloseHandle(h_origin_file);
|
|
CloseHandle(save_img);
|
|
return 0;
|
|
}
|
|
}
|
|
} while (bytes_read == BUFSIZE);
|
|
CloseHandle(h_origin_file);
|
|
CloseHandle(save_img);
|
|
return 1;
|
|
}
|
|
TODO("GetVoiceByDB")
|
|
int64_t wechat::WeChatService::GetVoiceByDB(ULONG64 msg_id,
|
|
const std::wstring& dir) {
|
|
return 0;
|
|
}
|
|
TODO("SendCustomEmotion")
|
|
int64_t wechat::WeChatService::SendCustomEmotion(const std::wstring& file_path,
|
|
const std::wstring& wxid) {
|
|
int64_t success = -1;
|
|
uint64_t get_custom_smiley_mgr_addr =
|
|
base_addr_ + offset::kGetCustomSmileyMgr;
|
|
func::__GetCustomSmileyMgr get_custom_smiley_mgr =
|
|
(func::__GetCustomSmileyMgr)get_custom_smiley_mgr_addr;
|
|
uint64_t send_custom_emotion_addr = base_addr_ + offset::kSendCustomEmotion;
|
|
func::__SendCustomEmotion send_custom_emotion =
|
|
(func::__SendCustomEmotion)send_custom_emotion_addr;
|
|
prototype::WeChatString* path = BuildWechatString(file_path);
|
|
prototype::WeChatString* recv = BuildWechatString(wxid);
|
|
int64_t* temp = base::utils::WxHeapAlloc<int64_t>(0x20);
|
|
memset(temp, 0, 0x20);
|
|
uint64_t mgr = get_custom_smiley_mgr();
|
|
success = send_custom_emotion(
|
|
mgr, reinterpret_cast<uint64_t>(path), reinterpret_cast<uint64_t>(temp),
|
|
reinterpret_cast<uint64_t>(recv), 2, reinterpret_cast<uint64_t>(temp), 0,
|
|
reinterpret_cast<uint64_t>(temp));
|
|
return success;
|
|
}
|
|
|
|
TODO("SendApplet")
|
|
int64_t wechat::WeChatService::SendApplet(
|
|
const std::wstring& recv_wxid, const std::wstring& waid_suff,
|
|
const std::wstring& waid_w, const std::wstring& waid_s,
|
|
const std::wstring& wa_wxid, const std::wstring& json_param,
|
|
const std::wstring& head_image, const std::wstring& big_image,
|
|
const std::wstring& index_page) {
|
|
int64_t success = -1;
|
|
if (js_api_addr_ == 0) {
|
|
auto vec2 =
|
|
base::memory::ScanAndMatchValue(base_addr_ + 0x32D1318, 0x1000, 0x8);
|
|
for (int i = 0; i < vec2.size(); i++) {
|
|
int64_t ptr = vec2.at(i);
|
|
if (*(int64_t*)ptr == base_addr_ + 0x32D1318) {
|
|
js_api_addr_ = ptr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (js_api_addr_ == 0) {
|
|
success = -2;
|
|
return success;
|
|
}
|
|
|
|
uint64_t share_app_msg_addr = base_addr_ + offset::kNewJsApiShareAppMessage;
|
|
func::__JsApiShareAppMessage share_app_msg =
|
|
(func::__JsApiShareAppMessage)share_app_msg_addr;
|
|
|
|
uint64_t init_addr = base_addr_ + offset::kInitJsConfig;
|
|
func::__InitJsConfig init = (func::__InitJsConfig)init_addr;
|
|
|
|
uint64_t send_applet_addr = base_addr_ + offset::kSendApplet;
|
|
func::__SendApplet send_applet = (func::__SendApplet)send_applet_addr;
|
|
|
|
uint64_t get_by_waid_addr = base_addr_ + offset::kGetAppInfoByWaid;
|
|
func::__GetAppInfoByWaid get_app_info =
|
|
(func::__GetAppInfoByWaid)get_by_waid_addr;
|
|
|
|
uint64_t copy_app_req_addr = base_addr_ + offset::kCopyShareAppMessageRequest;
|
|
func::__CopyShareAppMessageRequest copy_app_req =
|
|
(func::__CopyShareAppMessageRequest)copy_app_req_addr;
|
|
|
|
uint64_t new_wa_msg_addr = base_addr_ + offset::kNewWAUpdatableMsgInfo;
|
|
func::__NewWAUpdatableMsgInfo new_wa_msg =
|
|
(func::__NewWAUpdatableMsgInfo)new_wa_msg_addr;
|
|
|
|
uint64_t free_wa_msg_addr = base_addr_ + offset::kFreeWAUpdatableMsgInfo;
|
|
func::__FreeWAUpdatableMsgInfo free_wa_msg =
|
|
(func::__FreeWAUpdatableMsgInfo)free_wa_msg_addr;
|
|
|
|
std::vector<prototype::WeChatString>* temp =
|
|
base::utils::WxHeapAlloc<std::vector<prototype::WeChatString>>(0x20);
|
|
// std::vector<prototype::WeChatString>* temp = new
|
|
// std::vector<prototype::WeChatString>();
|
|
wechat::VectorInner* list = (wechat::VectorInner*)temp;
|
|
|
|
prototype::WeChatString* member = BuildWechatString(recv_wxid);
|
|
#ifdef _DEBUG
|
|
list->head = reinterpret_cast<uint64_t>(member);
|
|
#endif
|
|
list->start = reinterpret_cast<uint64_t>(member);
|
|
list->finsh = reinterpret_cast<uint64_t>(member) + 0x20;
|
|
list->end = reinterpret_cast<uint64_t>(member) + 0x20;
|
|
|
|
uint64_t head = reinterpret_cast<uint64_t>(&(list->start));
|
|
|
|
prototype::WeChatString* waid_cat = BuildWechatString(waid_suff);
|
|
prototype::WeChatString* waid = BuildWechatString(waid_w);
|
|
|
|
prototype::WeChatString* waid_2 = BuildWechatString(waid_suff);
|
|
|
|
prototype::WeChatString* waid_str = BuildWechatString(waid_s);
|
|
prototype::WeChatString* app_wxid = BuildWechatString(wa_wxid);
|
|
prototype::WeChatString* json_str = BuildWechatString(json_param);
|
|
prototype::WeChatString* head_image_url = BuildWechatString(head_image);
|
|
prototype::WeChatString* image = BuildWechatString(big_image);
|
|
prototype::WeChatString* index = BuildWechatString(index_page);
|
|
|
|
uint64_t app_msg = js_api_addr_;
|
|
|
|
uint64_t data = *(uint64_t*)(app_msg + 0x8);
|
|
char* share_req = base::utils::WxHeapAlloc<char>(0x2000);
|
|
|
|
char* mid_ptr = base::utils::WxHeapAlloc<char>(0x18);
|
|
memcpy(mid_ptr, &share_req, sizeof(INT64));
|
|
memcpy(mid_ptr + 0x8, &share_req, sizeof(INT64));
|
|
memcpy(mid_ptr + 0x10, &share_req, sizeof(INT64));
|
|
|
|
memcpy((void*)data, mid_ptr, 0x18);
|
|
|
|
memcpy(share_req, (void*)(app_msg + 0x8), sizeof(uint64_t));
|
|
memcpy(share_req + 0x8, (void*)(app_msg + 0x8), sizeof(uint64_t));
|
|
memcpy(share_req + 0x10, (void*)(app_msg + 0x8), sizeof(uint64_t));
|
|
memcpy(share_req + 0x20, waid_2, sizeof(prototype::WeChatString));
|
|
memcpy(share_req + 0x48, waid_str, sizeof(prototype::WeChatStr));
|
|
memcpy(share_req + 0x98, app_wxid, sizeof(prototype::WeChatStr));
|
|
memcpy(share_req + 0xF8, json_str, sizeof(prototype::WeChatStr));
|
|
memcpy(share_req + 0x178, head_image_url, sizeof(prototype::WeChatStr));
|
|
memcpy(share_req + 0x198, image, sizeof(prototype::WeChatStr));
|
|
memcpy(share_req + 0x1c0, index, sizeof(prototype::WeChatStr));
|
|
|
|
success = send_applet(app_msg, reinterpret_cast<uint64_t>(waid_cat), head, 0);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::SendPatMsg(const std::wstring& room_id,
|
|
const std::wstring& wxid) {
|
|
int64_t success = -1;
|
|
uint64_t send_pat_msg_addr = base_addr_ + offset::kSendPatMsg;
|
|
func::__SendPatMsg send_pat_msg = (func::__SendPatMsg)send_pat_msg_addr;
|
|
prototype::WeChatString chat_room(room_id);
|
|
prototype::WeChatString target(wxid);
|
|
success = send_pat_msg(reinterpret_cast<uint64_t>(&chat_room),
|
|
reinterpret_cast<uint64_t>(&target));
|
|
return success;
|
|
}
|
|
|
|
TODO("DoOCRTask")
|
|
int64_t wechat::WeChatService::DoOCRTask(const std::wstring& img_path,
|
|
std::string& result) {
|
|
int64_t success = -1;
|
|
uint64_t ocr_manager_addr = base_addr_ + offset::kGetOCRManager;
|
|
func::__GetOCRManager ocr_manager = (func::__GetOCRManager)ocr_manager_addr;
|
|
|
|
uint64_t do_ocr_task_addr = base_addr_ + offset::kDoOCRTask;
|
|
func::__DoOCRTask do_ocr_task = (func::__DoOCRTask)do_ocr_task_addr;
|
|
|
|
prototype::WeChatString img(img_path);
|
|
std::vector<INT64>* temp =
|
|
base::utils::WxHeapAlloc<std::vector<int64_t>>(0x20);
|
|
int64_t unkonwn = 0;
|
|
wechat::VectorInner* list = (wechat::VectorInner*)temp;
|
|
list->start = reinterpret_cast<INT64>(&list->start);
|
|
list->finsh = list->start;
|
|
char buff[0x28] = {0};
|
|
memcpy(buff, &list->start, sizeof(INT64));
|
|
uint64_t mgr = ocr_manager();
|
|
success = do_ocr_task(mgr, reinterpret_cast<uint64_t>(&img), 1,
|
|
reinterpret_cast<uint64_t>(buff),
|
|
reinterpret_cast<uint64_t>(&unkonwn));
|
|
int64_t number = *(int64_t*)(buff + 0x8);
|
|
if (number > 0) {
|
|
int64_t header = *(int64_t*)(buff);
|
|
for (unsigned int i = 0; i < number; i++) {
|
|
int64_t content = *(int64_t*)header;
|
|
result += wxutils::ReadWstringThenConvert(content + 0x28);
|
|
result += "\r\n";
|
|
header = content;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::LockWeChat() {
|
|
int64_t success = -1;
|
|
uint64_t lock_mgr_addr = base_addr_ + offset::kGetLockWechatMgr;
|
|
uint64_t request_lock_addr = base_addr_ + offset::kRequestLockWechat;
|
|
func::__GetLockWechatMgr get_lock_mgr =
|
|
(func::__GetLockWechatMgr)lock_mgr_addr;
|
|
func::__RequestLockWechat request_lock =
|
|
(func::__RequestLockWechat)request_lock_addr;
|
|
uint64_t mgr = get_lock_mgr();
|
|
success = request_lock(mgr);
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::UnlockWeChat() {
|
|
int64_t success = -1;
|
|
uint64_t lock_mgr_addr = base_addr_ + offset::kGetLockWechatMgr;
|
|
uint64_t request_unlock_addr = base_addr_ + offset::kRequestUnLockWechat;
|
|
func::__GetLockWechatMgr get_lock_mgr =
|
|
(func::__GetLockWechatMgr)lock_mgr_addr;
|
|
func::__RequestUnLockWechat request_unlock =
|
|
(func::__RequestUnLockWechat)request_unlock_addr;
|
|
uint64_t mgr = get_lock_mgr();
|
|
success = request_unlock(mgr);
|
|
|
|
return success;
|
|
}
|
|
|
|
int64_t wechat::WeChatService::EnterWeChat() {
|
|
int64_t success = -1;
|
|
int64_t base_addr = wxutils::GetWeChatWinBase();
|
|
uint64_t click_cb_addr = base_addr + offset::kOnLoginBtnClick;
|
|
func::__OnLoginBtnClick cb = (func::__OnLoginBtnClick)click_cb_addr;
|
|
auto vec =
|
|
base::memory::ScanAndMatchValue(base_addr + 0x4ecedf8, 0x1000, 0x8);
|
|
for (int i = 0; i < vec.size(); i++) {
|
|
int64_t ptr = vec.at(i);
|
|
if (*(int64_t*)ptr == base_addr + 0x4ecedf8) {
|
|
int64_t login_wnd = ptr;
|
|
success = cb(ptr);
|
|
break;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
TODO("SendMultiAtText")
|
|
int64_t wechat::WeChatService::SendMultiAtText(
|
|
const std::wstring& room_id,
|
|
const std::vector<std::pair<std::wstring, std::wstring>>& at) {
|
|
int64_t success = -1;
|
|
std::vector<prototype::WeChatString> wxid_list;
|
|
wechat::VectorInner* list = (wechat::VectorInner*)&wxid_list;
|
|
std::wstring at_msg = L"";
|
|
int number = 0;
|
|
for (unsigned int i = 0; i < at.size(); i++) {
|
|
std::wstring nickname;
|
|
std::wstring at_all = L"notify@all";
|
|
if (at_all.compare(at[i].first) == 0) {
|
|
nickname = L"\u6240\u6709\u4eba";
|
|
} else {
|
|
// nickname = GetContactOrChatRoomNickname(at[i].first);
|
|
nickname = L"";
|
|
}
|
|
if (nickname.length() == 0) {
|
|
continue;
|
|
}
|
|
prototype::WeChatString id(at[i].first);
|
|
wxid_list.push_back(id);
|
|
at_msg = at_msg + L"@" + nickname + L" " + at[i].second + L" ";
|
|
number++;
|
|
}
|
|
if (number < 1) {
|
|
success = -2;
|
|
return success;
|
|
}
|
|
int64_t head = (int64_t)&list->start;
|
|
prototype::WeChatString to_user(room_id);
|
|
prototype::WeChatString text_msg(at_msg);
|
|
uint64_t send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
|
|
uint64_t send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
char chat_msg[0x460] = {0};
|
|
func::__GetSendMessageMgr mgr =
|
|
(func::__GetSendMessageMgr)send_message_mgr_addr;
|
|
func::__SendTextMsg send = (func::__SendTextMsg)send_text_msg_addr;
|
|
func::__FreeChatMsg free = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
mgr();
|
|
success = send(reinterpret_cast<uint64_t>(&chat_msg),
|
|
reinterpret_cast<uint64_t>(&to_user),
|
|
reinterpret_cast<uint64_t>(&text_msg), head, 1, 1, 0, 0);
|
|
free(reinterpret_cast<uint64_t>(&chat_msg));
|
|
return success;
|
|
}
|
|
|
|
std::string wechat::WeChatService::GetLoginUrl() {
|
|
uint64_t login_mgr_addr = base_addr_ + offset::kGetQRCodeLoginMgr;
|
|
func::__GetQRCodeLoginMgr get = (func::__GetQRCodeLoginMgr)login_mgr_addr;
|
|
uint64_t addr = get();
|
|
std::string login_url = wxutils::ReadWeChatStr(addr + 0x68);
|
|
return "http://weixin.qq.com/x/" + login_url;
|
|
}
|
|
|
|
void wechat::WeChatService::SetBaseAddr(uint64_t addr) {
|
|
this->base_addr_ = addr;
|
|
}
|
|
|
|
void wechat::WeChatService::SetJsApiAddr(uint64_t addr) {
|
|
this->js_api_addr_ = addr;
|
|
}
|
|
|
|
TODO("TranslateVoice")
|
|
int64_t wechat::WeChatService::TranslateVoice(uint64_t msg_id) {
|
|
int64_t success = -1;
|
|
uint64_t get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
|
|
func::__GetMgrByPrefixLocalId get_by_local_id =
|
|
(func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
|
|
|
|
uint64_t get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
|
|
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
|
|
|
|
uint64_t free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
|
|
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
|
|
|
|
uint64_t new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
|
|
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
|
|
|
|
uint64_t update_addr = base_addr_ + offset::kUpdateMsg;
|
|
func::__UpdateMsg update = (func::__UpdateMsg)update_addr;
|
|
|
|
uint64_t get_voice_mgr_addr = base_addr_ + offset::kGetVoiceMgr;
|
|
func::__GetVoiceMgr get_voice_mgr = (func::__GetVoiceMgr)get_voice_mgr_addr;
|
|
|
|
uint64_t to_msg_addr = base_addr_ + offset::kChatMsg2NetSceneSendMsg;
|
|
func::__ChatMsg2NetSceneSendMsg to_msg =
|
|
(func::__ChatMsg2NetSceneSendMsg)to_msg_addr;
|
|
|
|
uint64_t trans_addr = base_addr_ + offset::kTranslateVoice;
|
|
func::__TranslateVoice translate_voice = (func::__TranslateVoice)trans_addr;
|
|
|
|
char temp_msg[0x460] = {0};
|
|
|
|
char* chat_msg = base::utils::WxHeapAlloc<char>(0x460);
|
|
int64_t index = 0;
|
|
int64_t local_id =
|
|
wechat::WeChatDb::GetInstance().GetLocalIdByMsgId(msg_id, index);
|
|
if (local_id <= 0 || index >> 32 == 0) {
|
|
success = -2;
|
|
|
|
return success;
|
|
}
|
|
LARGE_INTEGER l;
|
|
l.HighPart = index >> 32;
|
|
l.LowPart = (DWORD)local_id;
|
|
uint64_t p_chat_msg = new_chat_msg(reinterpret_cast<uint64_t>(chat_msg));
|
|
get_chat_mgr();
|
|
get_by_local_id(l.QuadPart, p_chat_msg);
|
|
uint64_t mgr = get_chat_mgr();
|
|
update(mgr, p_chat_msg, 0);
|
|
|
|
uint64_t voice_mgr = get_voice_mgr();
|
|
uint64_t msg = to_msg(reinterpret_cast<uint64_t>(&temp_msg), p_chat_msg);
|
|
|
|
success = translate_voice(voice_mgr, msg, 0);
|
|
|
|
return success;
|
|
}
|
|
|
|
TODO("GetTranslateVoiceText")
|
|
std::string wechat::WeChatService::GetTranslateVoiceText(uint64_t msg_id) {
|
|
std::string content =
|
|
wechat::WeChatDb::GetInstance().GetChatMsgStrContentByMsgId(msg_id);
|
|
if (content.empty()) {
|
|
return {};
|
|
}
|
|
tinyxml2::XMLDocument doc;
|
|
if (doc.Parse(content.c_str(), content.size()) != 0) {
|
|
SPDLOG_INFO("tinyxml2 parse error");
|
|
return {};
|
|
}
|
|
tinyxml2::XMLElement* msg = doc.FirstChildElement("msg");
|
|
if (msg != nullptr) {
|
|
tinyxml2::XMLElement* voicetrans = msg->FirstChildElement("voicetrans");
|
|
if (voicetrans != nullptr) {
|
|
const char* value = voicetrans->Attribute("transtext", nullptr);
|
|
return value;
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
TODO("OpenUrlByWeChatBrowser")
|
|
int64_t wechat::WeChatService::OpenUrlByWeChatBrowser(const std::wstring& url,
|
|
int flag) {
|
|
int64_t success = -1;
|
|
uint64_t config_addr = base_addr_ + offset::kNewWebViewPageConfig;
|
|
func::__NewWebViewPageConfig config =
|
|
(func::__NewWebViewPageConfig)config_addr;
|
|
|
|
uint64_t free_config_addr = base_addr_ + offset::kFreeWebViewPageConfig;
|
|
func::__FreeWebViewPageConfig free_config =
|
|
(func::__FreeWebViewPageConfig)free_config_addr;
|
|
|
|
uint64_t web_view_mgr_addr = base_addr_ + offset::kGetWebViewMgr;
|
|
func::__GetWebViewMgr web_view_mgr = (func::__GetWebViewMgr)web_view_mgr_addr;
|
|
|
|
uint64_t show_addr = base_addr_ + offset::kShowWebView;
|
|
func::__ShowWebView show_web_view = (func::__ShowWebView)show_addr;
|
|
|
|
uint64_t set_url_addr = base_addr_ + offset::kSetUrl;
|
|
func::__SetUrl set_url = (func::__SetUrl)set_url_addr;
|
|
|
|
int a = flag >> 4;
|
|
int b = flag & 0x1;
|
|
int c = flag & 0x2;
|
|
int d = flag & 0x4;
|
|
int e = flag & 0x8;
|
|
char* web_config = (char*)HeapAlloc(GetProcessHeap(), 0, 0xA20);
|
|
|
|
uint64_t ptr = config(reinterpret_cast<uint64_t>(web_config));
|
|
set_url(ptr + 0x868, reinterpret_cast<uint64_t>(url.c_str()), url.size());
|
|
web_view_mgr();
|
|
success = show_web_view(ptr, a, b, c, d, e);
|
|
free_config(ptr);
|
|
return success;
|
|
}
|
|
|
|
TODO("GetChatRoomMemberNickname")
|
|
std::wstring wechat::WeChatService::GetChatRoomMemberNickname(
|
|
const std::wstring& room_id, const std::wstring& member_id) {
|
|
|
|
return std::wstring();
|
|
}
|
|
|
|
TODO("DelContact")
|
|
int64_t wechat::WeChatService::DelContact(const std::wstring& wxid) {
|
|
int64_t success = -1;
|
|
uint64_t del_contcat_addr = base_addr_ + offset::kDoDelContact;
|
|
func::__DelContact del_contcat = (func::__DelContact)del_contcat_addr;
|
|
|
|
return success;
|
|
}
|
|
|
|
TODO("SearchContact")
|
|
int64_t wechat::WeChatService::SearchContact(
|
|
const std::wstring& keyword, wechat::SearchContactInner& contact) {
|
|
int64_t success = -1;
|
|
prototype::WeChatString key(keyword);
|
|
uint64_t search_mgr_addr = base_addr_ + offset::kGetSearchContactMgr;
|
|
uint64_t search_addr = base_addr_ + offset::kStartSearch;
|
|
|
|
func::__GetSearchContactMgr get_mgr =
|
|
(func::__GetSearchContactMgr)search_mgr_addr;
|
|
func::__StartSearch search = (func::__StartSearch)search_addr;
|
|
uint64_t mgr = get_mgr();
|
|
// success = search(mgr,&key);
|
|
|
|
return success;
|
|
}
|
|
|
|
TODO("AddFriendByWxid")
|
|
int64_t wechat::WeChatService::AddFriendByWxid(const std::wstring& wxid,
|
|
const std::wstring& msg) {
|
|
uint64_t add_friend_addr = base_addr_ + offset::kAddFriend;
|
|
func::__AddFriend add_friend = (func::__AddFriend)add_friend_addr;
|
|
return 0;
|
|
}
|
|
|
|
TODO("VerifyApply")
|
|
int64_t wechat::WeChatService::VerifyApply(const std::wstring& v3,
|
|
const std::wstring& v4,
|
|
int32_t permission) {
|
|
uint64_t verify_addr = base_addr_ + offset::kVerifyApply;
|
|
func::__Verify add_friend = (func::__Verify)verify_addr;
|
|
return 0;
|
|
}
|
|
|
|
TODO("DoConfirmReceipt")
|
|
int64_t wechat::WeChatService::DoConfirmReceipt(
|
|
const std::wstring& wxid, const std::wstring& transcationid,
|
|
const std::wstring& transferid) {
|
|
int success = -1;
|
|
prototype::WeChatString recv_id(wxid);
|
|
prototype::WeChatString transcation_id(transcationid);
|
|
prototype::WeChatString transfer_id(transferid);
|
|
|
|
char pay_info[0x224] = {0};
|
|
uint64_t new_pay_info_addr = base_addr_ + offset::kNewPayInfo;
|
|
uint64_t free_pay_info_addr = base_addr_ + offset::kFreePayInfo;
|
|
uint64_t do_confirm_addr = base_addr_ + offset::kTransferConfirm;
|
|
|
|
func::__NewWCPayInfo new_pay_info = (func::__NewWCPayInfo)new_pay_info_addr;
|
|
func::__FreeWCPayInfo free_pay_info =
|
|
(func::__FreeWCPayInfo)free_pay_info_addr;
|
|
func::__PayTransferConfirm do_confirm =
|
|
(func::__PayTransferConfirm)do_confirm_addr;
|
|
|
|
new_pay_info(reinterpret_cast<uint64_t>(&pay_info));
|
|
memcpy(&pay_info[0x30], &transcation_id, sizeof(transcation_id));
|
|
memcpy(&pay_info[0x58], &transfer_id, sizeof(transfer_id));
|
|
// memcpy(&pay_info[0xA0], &recv_id, sizeof(recv_id));
|
|
success = do_confirm(reinterpret_cast<uint64_t>(&pay_info), reinterpret_cast<uint64_t>(&recv_id));
|
|
|
|
free_pay_info(reinterpret_cast<uint64_t>(&pay_info));
|
|
|
|
return success;
|
|
}
|
|
|
|
TODO("DoRefuseReceipt")
|
|
int64_t wechat::WeChatService::DoRefuseReceipt(
|
|
const std::wstring& wxid, const std::wstring& transcationid,
|
|
const std::wstring& transferid) {
|
|
int success = -1;
|
|
prototype::WeChatString recv_id(wxid);
|
|
prototype::WeChatString transcation_id(transcationid);
|
|
prototype::WeChatString transfer_id(transferid);
|
|
|
|
char pay_info[0x224] = {0};
|
|
uint64_t new_pay_info_addr = base_addr_ + offset::kNewPayInfo;
|
|
uint64_t free_pay_info_addr = base_addr_ + offset::kFreePayInfo;
|
|
uint64_t do_refuse_addr = base_addr_ + offset::kTransferRefuse;
|
|
|
|
func::__NewWCPayInfo new_pay_info = (func::__NewWCPayInfo)new_pay_info_addr;
|
|
func::__FreeWCPayInfo free_pay_info =
|
|
(func::__FreeWCPayInfo)free_pay_info_addr;
|
|
func::__PayTransferRefuse do_refuse =
|
|
(func::__PayTransferRefuse)do_refuse_addr;
|
|
|
|
new_pay_info(reinterpret_cast<uint64_t>(&pay_info));
|
|
memcpy(&pay_info[0x30], &transcation_id, sizeof(transcation_id));
|
|
memcpy(&pay_info[0x58], &transfer_id, sizeof(transfer_id));
|
|
// memcpy(&pay_info[0xA0], &recv_id, sizeof(recv_id));
|
|
success = do_refuse(reinterpret_cast<uint64_t>(&pay_info), reinterpret_cast<uint64_t>(&recv_id));
|
|
|
|
free_pay_info(reinterpret_cast<uint64_t>(&pay_info));
|
|
return success;
|
|
}
|