Compare commits

...

13 Commits

Author SHA1 Message Date
hugy
826e504fb3 feat: 获取群成员详情 2023-05-27 11:27:39 +08:00
hugy
80718a2af5 feat: 新增邀请入群 2023-05-27 00:18:11 +08:00
hugy
aaada266df feat: 根据502647092提供的偏移,新增登录二维码 2023-05-25 22:10:03 +08:00
hugy
581aacb8ce feat: 完善3.9.2.26已有的功能 2023-05-25 15:30:27 +08:00
hugy
dccc997067 3.9.2.26部分功能 2023-05-23 12:01:43 +08:00
hugy
0b52a49155 feat: 增加线程池1 2023-05-20 17:12:02 +08:00
hugy
4027c4afe6 feat: 增加线程池 2023-05-20 17:10:14 +08:00
hugy
dcbde9203b feat: 部分偏移更新 2023-05-13 17:25:08 +08:00
hugy
76dc8affe9 chore: spdlog 2023-05-11 10:04:21 +08:00
hugy
fd3e6f4a70 feat: add spdlog 2023-05-11 08:37:35 +08:00
hugy
18e34cd11b feat: 3.9.2.26发送文本,图片,文件 2023-05-11 00:04:46 +08:00
hugy
83d779c072 doc: 23接口更新 2023-05-05 09:40:33 +08:00
hugy
8fa942c741 fix: 通过好友验证需要指定权限 close #105 2023-05-05 09:39:20 +08:00
25 changed files with 3994 additions and 7936 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "spdlog"]
path = spdlog
url = https://github.com/gabime/spdlog

View File

@ -1,9 +1,12 @@
cmake_minimum_required(VERSION 3.0.0) cmake_minimum_required(VERSION 3.0.0)
# include(ExternalProject)
project(wxhelper VERSION 1.0.0) project(wxhelper VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '_UNICODE' /D 'UNICODE' ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '_UNICODE' /D 'UNICODE' ")
@ -11,15 +14,17 @@ file(GLOB CPP_FILES ${PROJECT_SOURCE_DIR}/src/*.cc ${PROJECT_SOURCE_DIR}/src/*
include_directories(${VCPKG_INSTALLED_DIR}/x86-windows/include) include_directories(${VCPKG_INSTALLED_DIR}/x86-windows/include ${PROJECT_SOURCE_DIR}/spdlog/include)
# add_subdirectory(3rd)
add_subdirectory(spdlog)
# add_subdirectory(source) # add_subdirectory(source)
find_package(nlohmann_json CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED)
find_package(unofficial-mongoose CONFIG REQUIRED) find_package(unofficial-mongoose CONFIG REQUIRED)
# find_package(spdlog CONFIG REQUIRED) # find_package(spdlog CONFIG REQUIRED)
# find_package(minhook CONFIG REQUIRED)
add_library(wxhelper SHARED ${CPP_FILES} ) add_library(wxhelper SHARED ${CPP_FILES} )
@ -29,7 +34,8 @@ add_library(wxhelper SHARED ${CPP_FILES} )
target_link_libraries(wxhelper PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(wxhelper PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(wxhelper PRIVATE unofficial::mongoose::mongoose) target_link_libraries(wxhelper PRIVATE unofficial::mongoose::mongoose)
# target_link_libraries(wxhelper PRIVATE spdlog::spdlog spdlog::spdlog_header_only) target_link_libraries(wxhelper PRIVATE spdlog::spdlog spdlog::spdlog_header_only)
# target_link_libraries(wxhelper PRIVATE minhook::minhook) # target_link_libraries(wxhelper PRIVATE minhook::minhook)
SET_TARGET_PROPERTIES(wxhelper PROPERTIES LINKER_LANGUAGE C SET_TARGET_PROPERTIES(wxhelper PROPERTIES LINKER_LANGUAGE C

1630
doc/3.9.2.23.md Normal file

File diff suppressed because it is too large Load Diff

1746
doc/3.9.2.26.md Normal file

File diff suppressed because it is too large Load Diff

1
spdlog Submodule

@ -0,0 +1 @@
Subproject commit ad0e89cbfb4d0c1ce4d097e134eb7be67baebb36

View File

@ -1,22 +1,16 @@
#include "pch.h" #include "pch.h"
#include "account_mgr.h" #include "account_mgr.h"
#include "easylogging++.h"
#include "wechat_function.h" #include "wechat_function.h"
using namespace std; using namespace std;
namespace wxhelper { namespace wxhelper {
AccountMgr::AccountMgr(DWORD base):BaseMgr(base){ AccountMgr::AccountMgr(DWORD base) : BaseMgr(base) {}
AccountMgr::~AccountMgr() {}
}
AccountMgr::~AccountMgr(){
}
int AccountMgr::GetSelfInfo(SelfInfoInner &out) { int AccountMgr::GetSelfInfo(SelfInfoInner &out) {
DWORD accout_service_addr = base_addr_ + WX_ACCOUNT_SERVICE_OFFSET; DWORD accout_service_addr = base_addr_ + WX_ACCOUNT_SERVICE_OFFSET;
DWORD get_app_save_addr = base_addr_ + WX_GET_APP_DATA_SAVE_PATH_OFFSET; DWORD get_app_save_addr = base_addr_ + WX_GET_APP_DATA_SAVE_PATH_OFFSET;
DWORD get_current_data_path_addr = base_addr_ + WX_GET_CURRENT_DATA_PATH_OFFSET; DWORD get_current_data_path_addr =
base_addr_ + WX_GET_CURRENT_DATA_PATH_OFFSET;
DWORD service_addr = NULL; DWORD service_addr = NULL;
__asm { __asm {
PUSHAD PUSHAD
@ -129,16 +123,16 @@ int AccountMgr::GetSelfInfo(SelfInfoInner &out) {
} }
} }
if (*(DWORD *)(service_addr + 0x304) == 0 || if (*(DWORD *)(service_addr + 0x31C) == 0 ||
*(DWORD *)(service_addr + 0x304 + 0x10) == 0) { *(DWORD *)(service_addr + 0x31C + 0x10) == 0) {
out.head_img = string(); out.head_img = string();
} else { } else {
if (*(DWORD *)(service_addr + 0x304 + 0x14) == 0xF) { if (*(DWORD *)(service_addr + 0x31C + 0x14) == 0xF) {
out.head_img = string((char *)(service_addr + 0x304), out.head_img = string((char *)(service_addr + 0x31C),
*(DWORD *)(service_addr + 0x304 + 0x10)); *(DWORD *)(service_addr + 0x31C + 0x10));
} else { } else {
out.head_img = string(*(char **)(service_addr + 0x304), out.head_img = string(*(char **)(service_addr + 0x31C),
*(DWORD *)(service_addr + 0x304 + 0x10)); *(DWORD *)(service_addr + 0x31C + 0x10));
} }
} }
@ -216,4 +210,35 @@ int AccountMgr::Logout() {
return success; return success;
} }
/// @brief 根据 502647092 提供的偏移 获取二维码url
/// @return
std::string AccountMgr::GetQRCodeUrl() {
DWORD qr_code_login_addr = base_addr_ + WX_QR_CODE_LOGIN_MGR_OFFSET ;
DWORD get_qr_code_img_addr = base_addr_ + WX_GET_QR_CODE_IMAGE_OFFSET ;
DWORD temp;
__asm {
PUSHAD
PUSHFD
CALL qr_code_login_addr
MOV temp,EAX
POPFD
POPAD
}
std::string pre("https://weixin.qq.com/x/");
DWORD ptr = temp + 0x8;
DWORD len = *(DWORD*)(ptr+0x10);
if (*(DWORD *)(ptr) == 0) {
return std::string();
} else {
if( *(DWORD*) (temp+0x1c) > 0xf){
std::string suff(*(char **)ptr,len);
return pre + suff;
}else{
std::string suff((char *)ptr,len);
return pre + suff;
}
}
}
} // namespace wxhelper } // namespace wxhelper

View File

@ -13,6 +13,8 @@ namespace wxhelper{
int CheckLogin(); int CheckLogin();
int Logout(); int Logout();
std::string GetQRCodeUrl();
}; };
} }

View File

@ -71,6 +71,9 @@ typedef enum HTTP_API_ROUTE {
WECHAT_CONTACT_NAME, WECHAT_CONTACT_NAME,
WECHAT_ATTACH_DOWNLOAD, WECHAT_ATTACH_DOWNLOAD,
WECHAT_GET_VOICE, WECHAT_GET_VOICE,
WECHAT_GET_QRCODE,
WECHAT_INVITE_MEMBERS,
WECHAT_GET_MEMBER_PROFILE,
} WECHAT_HTTP_APIS, } WECHAT_HTTP_APIS,
*PWECHAT_HTTP_APIS; *PWECHAT_HTTP_APIS;

View File

@ -108,6 +108,7 @@ int ChatRoomMgr::DelMemberFromChatRoom(wchar_t* chat_room_id, wchar_t** wxids,
DWORD init_chat_msg_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET; DWORD init_chat_msg_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET;
__asm { __asm {
PUSHAD PUSHAD
PUSHFD
CALL get_chat_room_mgr_addr CALL get_chat_room_mgr_addr
SUB ESP,0x14 SUB ESP,0x14
MOV ESI,EAX MOV ESI,EAX
@ -120,6 +121,7 @@ int ChatRoomMgr::DelMemberFromChatRoom(wchar_t* chat_room_id, wchar_t** wxids,
PUSH EAX PUSH EAX
CALL del_member_addr CALL del_member_addr
MOV success,EAX MOV success,EAX
POPFD
POPAD POPAD
} }
return success; return success;
@ -372,4 +374,65 @@ std::wstring ChatRoomMgr::GetChatRoomMemberNickname(wchar_t* chat_room_id,
} }
return name; return name;
} }
int ChatRoomMgr::InviteMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids, int len) {
int success = -1;
WeChatString chat_room(chat_room_id);
vector<WeChatString> members;
VectorInner* list = (VectorInner*)&members;
DWORD members_ptr = (DWORD)&list->start;
for (int i = 0; i < len; i++) {
WeChatString pwxid(wxids[i]);
members.push_back(pwxid);
}
DWORD get_chat_room_mgr_addr = base_addr_ + WX_CHAT_ROOM_MGR_OFFSET;
DWORD add_member_addr = base_addr_ + WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET;
DWORD init_chat_msg_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET;
DWORD get_share_record_mgr_addr = base_addr_ + WX_SHARE_RECORD_MGR_OFFSET;
DWORD fn1 = base_addr_ + 0x7fa730;
DWORD fn2 = base_addr_ + 0x78d9a0;
DWORD fn3 = base_addr_ + 0x7fb6e0;
DWORD fn4 = base_addr_ + 0x755af0;
DWORD invite_addr = base_addr_ + 0xbd28a0;
DWORD sys_addr = (DWORD)GetModuleHandleA("win32u.dll") + 0x116C;
DWORD addr[2] = {sys_addr,0};
__asm {
PUSHAD
PUSHFD
CALL get_share_record_mgr_addr
LEA ECX,addr
PUSH ECX
MOV ECX,EAX
CALL fn1
CALL get_chat_room_mgr_addr
SUB ESP,0x8
LEA EAX,addr
MOV ECX,ESP
PUSH EAX
CALL fn2
SUB ESP,0x14
MOV ECX,ESP
LEA EAX,chat_room
PUSH EAX
CALL init_chat_msg_addr
MOV EAX,dword ptr[members_ptr]
PUSH EAX
CALL invite_addr
CALL get_share_record_mgr_addr
PUSH 0x0
PUSH 0x1
MOV ECX,EAX
CALL fn3
LEA ECX,addr
CALL fn4
POPFD
POPAD
}
success = 1;
return success;
}
} // namespace wxhelper } // namespace wxhelper

View File

@ -23,6 +23,8 @@ class ChatRoomMgr:public BaseMgr {
std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id, std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id,
wchar_t* wxid); wchar_t* wxid);
int InviteMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids,
int len);
}; };
} // namespace wxhelper } // namespace wxhelper
#endif #endif

View File

@ -126,7 +126,7 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
DWORD verify_msg_addr = base_addr_ + WX_VERIFY_MSG_OFFSET; DWORD verify_msg_addr = base_addr_ + WX_VERIFY_MSG_OFFSET;
DWORD set_value_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET; DWORD set_value_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET;
DWORD do_verify_user_addr = base_addr_ + WX_DO_VERIFY_USER_OFFSET; DWORD do_verify_user_addr = base_addr_ + WX_DO_VERIFY_USER_OFFSET;
DWORD fn1_addr = base_addr_ + 0x758720; DWORD fn1_addr = base_addr_ + 0x7591b0;
WeChatString user_id(wxid); WeChatString user_id(wxid);
WeChatString w_msg(msg); WeChatString w_msg(msg);
DWORD instance =0; DWORD instance =0;
@ -175,7 +175,7 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
return success; return success;
} }
int ContactMgr::VerifyApply(wchar_t *v3, wchar_t *v4){ int ContactMgr::VerifyApply(wchar_t *v3, wchar_t *v4,int permission){
int success = -1; int success = -1;
DWORD set_value_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET; DWORD set_value_addr = base_addr_ + WX_INIT_CHAT_MSG_OFFSET;
DWORD verify_addr = base_addr_ + WX_VERIFY_OK_OFFSET; DWORD verify_addr = base_addr_ + WX_VERIFY_OK_OFFSET;
@ -186,12 +186,13 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
WeChatString v3_str(v3); WeChatString v3_str(v3);
char helper_obj[0x40] = {0}; char helper_obj[0x40] = {0};
char nullbuffer[0x3CC] = {0}; char nullbuffer[0x3CC] = {0};
int flag = permission < 0 ? 0:permission;
__asm { __asm {
PUSHAD PUSHAD
PUSHFD PUSHFD
LEA ECX,helper_obj LEA ECX,helper_obj
CALL new_helper_addr CALL new_helper_addr
MOV ESI,0x0 MOV ESI,flag
MOV EDI,0x6 MOV EDI,0x6
PUSH ESI PUSH ESI
PUSH EDI PUSH EDI
@ -216,4 +217,42 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
} }
return success; return success;
} }
int ContactMgr::GetContactByWxid(wchar_t *wxid,ContactProfile& profile){
int success = -1;
char buff[0x440] = {0};
WeChatString pri(wxid);
DWORD contact_mgr_addr = base_addr_ + WX_CONTACT_MGR_OFFSET;
DWORD get_contact_addr = base_addr_ + WX_GET_CONTACT_OFFSET;
DWORD free_contact_addr = base_addr_ + WX_FREE_CONTACT_OFFSET;
__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
}
success = 0;
profile.wxid = READ_WSTRING(buff, 0x10);
profile.account = READ_WSTRING(buff, 0x24);
profile.v3 = READ_WSTRING(buff, 0x38);
profile.nickname = READ_WSTRING(buff, 0x6C);
profile.head_image = READ_WSTRING(buff, 0x110);
__asm {
PUSHAD
PUSHFD
LEA ECX,buff
CALL free_contact_addr
POPFD
POPAD
}
success = 1;
return success;
}
} // namespace wxhelper } // namespace wxhelper

View File

@ -14,7 +14,8 @@ class ContactMgr : public BaseMgr {
int DelContact(wchar_t* wxid); int DelContact(wchar_t* wxid);
std::wstring GetContactOrChatRoomNickname(wchar_t* id); std::wstring GetContactOrChatRoomNickname(wchar_t* id);
int AddFriendByWxid(wchar_t* wxid,wchar_t* msg); int AddFriendByWxid(wchar_t* wxid,wchar_t* msg);
int VerifyApply(wchar_t *v3, wchar_t *v4); int VerifyApply(wchar_t *v3, wchar_t *v4,int permission);
int GetContactByWxid(wchar_t* wxid,ContactProfile& profile);
}; };
} // namespace wxhelper } // namespace wxhelper

View File

@ -2,8 +2,6 @@
#include "db.h" #include "db.h"
#include "base64.h" #include "base64.h"
#include "easylogging++.h"
#include "wechat_function.h" #include "wechat_function.h"
#include "utils.h" #include "utils.h"
using namespace std; using namespace std;
@ -462,9 +460,9 @@ std::vector<void *> DB::GetDbHandles() {
dbs_.push_back(db_end); dbs_.push_back(db_end);
#ifdef _DEBUG #ifdef _DEBUG
for (unsigned int i = 0; i < dbs_.size() - 1; i++) { for (unsigned int i = 0; i < dbs_.size() - 1; i++) {
LOG(INFO) << "dbname =" << dbs_[i].db_name; // LOG(INFO) << "dbname =" << dbs_[i].db_name;
LOG(INFO) << "handle =" << dbs_[i].handle; // LOG(INFO) << "handle =" << dbs_[i].handle;
LOG(INFO) << "table_count =" << dbs_[i].tables.size(); // LOG(INFO) << "table_count =" << dbs_[i].tables.size();
} }
#endif #endif
vector<void *> ret_array; vector<void *> ret_array;
@ -492,7 +490,7 @@ unsigned int DB::GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex) {
swprintf_s(dbname, L"MSG%d.db", i); swprintf_s(dbname, L"MSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname); DWORD handle = GetDbHandleByDbName(dbname);
if (handle == 0) { if (handle == 0) {
LOG(INFO) << "MSG db handle is null"; SPDLOG_INFO("MSG db handle is null");
return 0; return 0;
} }
vector<vector<string>> result; vector<vector<string>> result;
@ -517,7 +515,7 @@ vector<string> DB::GetChatMsgByMsgId(ULONG64 msgid) {
swprintf_s(dbname, L"MSG%d.db", i); swprintf_s(dbname, L"MSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname); DWORD handle = GetDbHandleByDbName(dbname);
if (handle == 0) { if (handle == 0) {
LOG(INFO) << "MSG db handle is null"; // LOG(INFO) << "MSG db handle is null";
return {}; return {};
} }
vector<vector<string>> result; vector<vector<string>> result;
@ -536,7 +534,7 @@ std::string DB::GetVoiceBuffByMsgId(ULONG64 msgid) {
swprintf_s(dbname, L"MediaMSG%d.db", i); swprintf_s(dbname, L"MediaMSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname); DWORD handle = GetDbHandleByDbName(dbname);
if (handle == 0) { if (handle == 0) {
LOG(INFO) << "Media db handle is null"; // LOG(INFO) << "Media db handle is null";
return ""; return "";
} }
vector<vector<string>> result; vector<vector<string>> result;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
#include "pch.h" #include "pch.h"
#include "global_context.h" #include "global_context.h"
#include "http_server.h" #include "http_server.h"
#include "easylogging++.h"
#include "hooks.h" #include "hooks.h"
#include "thread_pool.h"
namespace wxhelper { namespace wxhelper {
@ -28,6 +28,7 @@ void GlobalContext::initialize(HMODULE module) {
account_mgr.emplace(AccountMgr{base}); account_mgr.emplace(AccountMgr{base});
chat_room_mgr.emplace(ChatRoomMgr{base}); chat_room_mgr.emplace(ChatRoomMgr{base});
sns_mgr.emplace(SNSMgr{base}); sns_mgr.emplace(SNSMgr{base});
ThreadPool::GetInstance().Create(1,512);
} }
void GlobalContext::finally() { void GlobalContext::finally() {

View File

@ -1,10 +1,9 @@
#include <Ws2tcpip.h> #include "pch.h"
#include <Ws2tcpip.h>
#include <winsock2.h> #include <winsock2.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "thread_pool.h"
#include "easylogging++.h"
#include "pch.h"
#include "wechat_function.h" #include "wechat_function.h"
using namespace nlohmann; using namespace nlohmann;
using namespace std; using namespace std;
@ -57,12 +56,12 @@ void SendSocketMessage(InnerMessageStruct *msg) {
string jstr = j_msg.dump() + "\n"; string jstr = j_msg.dump() + "\n";
if (server_port_ == 0) { if (server_port_ == 0) {
LOG(INFO) << "http server port error :" << server_port_; SPDLOG_ERROR("http server port error :{}",server_port_);
return; return;
} }
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket < 0) { if (client_socket < 0) {
LOG(INFO) << "socket init fail"; SPDLOG_ERROR("socket init fail");
return; return;
} }
BOOL status = false; BOOL status = false;
@ -73,13 +72,13 @@ void SendSocketMessage(InnerMessageStruct *msg) {
InetPtonA(AF_INET, server_ip_, &client_addr.sin_addr.s_addr); InetPtonA(AF_INET, server_ip_, &client_addr.sin_addr.s_addr);
if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr), if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr),
sizeof(sockaddr)) < 0) { sizeof(sockaddr)) < 0) {
LOG(INFO) << "socket connect fail"; SPDLOG_ERROR("socket connect fail");
return; return;
} }
char recv_buf[1024] = {0}; char recv_buf[1024] = {0};
int ret = send(client_socket, jstr.c_str(), jstr.size(), 0); int ret = send(client_socket, jstr.c_str(), jstr.size(), 0);
if (ret == -1 || ret == 0) { if (ret == -1 || ret == 0) {
LOG(INFO) << "socket send fail ,ret:" << ret; SPDLOG_ERROR("socket send fail ,ret::{}",ret);
closesocket(client_socket); closesocket(client_socket);
return; return;
} }
@ -87,10 +86,83 @@ void SendSocketMessage(InnerMessageStruct *msg) {
ret = recv(client_socket, recv_buf, sizeof(recv_buf), 0); ret = recv(client_socket, recv_buf, sizeof(recv_buf), 0);
closesocket(client_socket); closesocket(client_socket);
if (ret == -1 || ret == 0) { if (ret == -1 || ret == 0) {
LOG(INFO) << "socket recv fail ,ret:" << ret; SPDLOG_ERROR("socket recv fail ,ret:{}",ret);
return;
} }
} }
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
InnerMessageStruct *msg = (InnerMessageStruct *)context;
if (msg == NULL) {
SPDLOG_INFO("add work:msg is null");
return;
}
unique_ptr<InnerMessageStruct> sms(msg);
json j_msg =
json::parse(msg->buffer, msg->buffer + msg->length, nullptr, false);
if (j_msg.is_discarded() == true) {
return;
}
string jstr = j_msg.dump() + "\n";
if (server_port_ == 0) {
SPDLOG_ERROR("http server port error :{}", server_port_);
return;
}
WSADATA was_data = {0};
int ret = WSAStartup(MAKEWORD(2, 2), &was_data);
if (ret != 0) {
SPDLOG_ERROR("WSAStartup failed:{}", ret);
return;
}
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket < 0) {
SPDLOG_ERROR("socket init fail");
return;
}
BOOL status = false;
sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons((u_short)server_port_);
InetPtonA(AF_INET, server_ip_, &client_addr.sin_addr.s_addr);
if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr),
sizeof(sockaddr)) < 0) {
SPDLOG_ERROR("socket connect fail");
closesocket(client_socket);
WSACleanup();
return ;
}
char recv_buf[1024] = {0};
ret = send(client_socket, jstr.c_str(), jstr.size(), 0);
if (ret == -1 || ret == 0) {
SPDLOG_ERROR("socket send fail ,ret:{}", ret);
closesocket(client_socket);
WSACleanup();
return;
}
ret = shutdown(client_socket, SD_SEND);
if (ret == SOCKET_ERROR) {
SPDLOG_ERROR("shutdown failed with erro:{}", ret);
closesocket(client_socket);
WSACleanup();
return ;
}
memset(recv_buf, 0, sizeof(recv_buf));
ret = recv(client_socket, recv_buf, sizeof(recv_buf), 0);
closesocket(client_socket);
if (ret == -1 || ret == 0) {
SPDLOG_ERROR("socket recv fail ,ret:{}", ret);
WSACleanup();
return;
}
WSACleanup();
return;
}
void __cdecl OnRecvMsg(DWORD msg_addr) { void __cdecl OnRecvMsg(DWORD msg_addr) {
json j_msg; json j_msg;
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30); unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
@ -138,13 +210,17 @@ void __cdecl OnRecvMsg(DWORD msg_addr) {
inner_msg->buffer = new char[jstr.size() + 1]; inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1); memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size(); inner_msg->length = jstr.size();
HANDLE thread = CreateThread( bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback,inner_msg);
NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, inner_msg, NULL, 0); SPDLOG_INFO("add work:{}",add);
if (thread) { // HANDLE thread = CreateThread(
CloseHandle(thread); // NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, inner_msg, NULL, 0);
} // if (thread) {
// CloseHandle(thread);
// }
} }
/// @brief hook msg implement /// @brief hook msg implement
_declspec(naked) void HandleSyncMsg() { _declspec(naked) void HandleSyncMsg() {
__asm { __asm {
@ -214,38 +290,35 @@ int HookRecvMsg(char *client_ip, int port) {
strcpy_s(server_ip_, client_ip); strcpy_s(server_ip_, client_ip);
DWORD base = Utils::GetWeChatWinBase(); DWORD base = Utils::GetWeChatWinBase();
if (!base) { if (!base) {
SPDLOG_INFO("base addr is null");
return -1; return -1;
} }
if (msg_hook_flag_) { if (msg_hook_flag_) {
SPDLOG_INFO("recv msg hook already called");
return 2; return 2;
} }
DWORD hook_recv_msg_addr = base + WX_RECV_MSG_HOOK_OFFSET; DWORD hook_recv_msg_addr = base + WX_RECV_MSG_HOOK_OFFSET;
msg_next_addr_ = base + WX_RECV_MSG_HOOK_NEXT_OFFSET; msg_next_addr_ = base + WX_RECV_MSG_HOOK_NEXT_OFFSET;
msg_back_addr_ = hook_recv_msg_addr + 0x5; msg_back_addr_ = hook_recv_msg_addr + 0x5;
LOG(INFO) << "base" << base;
LOG(INFO) << "msg_next_addr_" << msg_next_addr_;
LOG(INFO) << "msg_back_addr_" << msg_back_addr_;
Utils::HookAnyAddress(hook_recv_msg_addr, (LPVOID)HandleSyncMsg, Utils::HookAnyAddress(hook_recv_msg_addr, (LPVOID)HandleSyncMsg,
msg_asm_code_); msg_asm_code_);
DWORD hook_sns_msg_addr = base + WX_SNS_HOOK_OFFSET; DWORD hook_sns_msg_addr = base + WX_SNS_HOOK_OFFSET;
sns_next_addr_ = base + WX_SNS_HOOK_NEXT_OFFSET; sns_next_addr_ = base + WX_SNS_HOOK_NEXT_OFFSET;
sns_back_addr_ = hook_sns_msg_addr + 0x5; sns_back_addr_ = hook_sns_msg_addr + 0x5;
LOG(INFO) << "base" << base;
LOG(INFO) << "sns_next_addr_" << sns_next_addr_;
LOG(INFO) << "sns_back_addr_" << sns_back_addr_;
Utils::HookAnyAddress(hook_sns_msg_addr, (LPVOID)HandleSNSMsg, sns_asm_code_); Utils::HookAnyAddress(hook_sns_msg_addr, (LPVOID)HandleSNSMsg, sns_asm_code_);
msg_hook_flag_ = true; msg_hook_flag_ = true;
SPDLOG_INFO("hook recv msg success");
return 1; return 1;
} }
int UnHookRecvMsg() { int UnHookRecvMsg() {
server_port_ = 0; server_port_ = 0;
if (!msg_hook_flag_) { if (!msg_hook_flag_) {
LOG(INFO) << "this port already hooked"; SPDLOG_INFO("recv msg hook already called");
return 2; return 2;
} }
DWORD base = Utils::GetWeChatWinBase(); DWORD base = Utils::GetWeChatWinBase();
@ -271,9 +344,9 @@ void PrintLog(DWORD addr) {
char *ansi_message = new char[size + 1]; char *ansi_message = new char[size + 1];
memset(ansi_message, 0, size + 1); memset(ansi_message, 0, size + 1);
WideCharToMultiByte(CP_ACP, 0, w_msg, -1, ansi_message, size, 0, 0); WideCharToMultiByte(CP_ACP, 0, w_msg, -1, ansi_message, size, 0, 0);
spdlog::info("wechat log:{}", ansi_message);
delete[] w_msg; delete[] w_msg;
w_msg = NULL; w_msg = NULL;
LOG(INFO) << ansi_message;
delete[] ansi_message; delete[] ansi_message;
ansi_message = NULL; ansi_message = NULL;
} }
@ -321,7 +394,7 @@ int UnHookLog() {
void SetErrorCode(int code) { userinfo.error_code = code; } void SetErrorCode(int code) { userinfo.error_code = code; }
void SetUserInfoDetail(DWORD address) { void SetUserInfoDetail(DWORD address) {
LOG(INFO) << "hook userinfo addr" <<&userinfo; SPDLOG_INFO("hook userinfo addr = {}",address);
DWORD length = *(DWORD *)(address + 0x8); DWORD length = *(DWORD *)(address + 0x8);
userinfo.keyword = new wchar_t[length + 1]; userinfo.keyword = new wchar_t[length + 1];
userinfo.keyword_len = length; userinfo.keyword_len = length;
@ -352,6 +425,36 @@ void SetUserInfoDetail(DWORD address) {
ZeroMemory(userinfo.big_image, (length + 1) * sizeof(wchar_t)); ZeroMemory(userinfo.big_image, (length + 1) * sizeof(wchar_t));
} }
length = *(DWORD *)(address + 0x6C);
userinfo.V3 = new wchar_t[length + 1];
userinfo.V3_len = length;
if (length) {
memcpy(userinfo.V3, (wchar_t *)(*(DWORD *)(address + 0x68)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.V3, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x80);
userinfo.account = new wchar_t[length + 1];
userinfo.account_len = length;
if (length) {
memcpy(userinfo.account, (wchar_t *)(*(DWORD *)(address + 0x7C)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.account, (length + 1) * sizeof(wchar_t));
}
// length = *(DWORD *)(address + 0x94);
// userinfo.friend_name = new wchar_t[length + 1];
// userinfo.friend_name_len = length;
// if (length) {
// memcpy(userinfo.friend_name, (wchar_t *)(*(DWORD *)(address + 0x90)),
// (length + 1) * sizeof(wchar_t));
// } else {
// ZeroMemory(userinfo.friend_name, (length + 1) * sizeof(wchar_t));
// }
length = *(DWORD *)(address + 0xC8); length = *(DWORD *)(address + 0xC8);
userinfo.nickname = new wchar_t[length + 1]; userinfo.nickname = new wchar_t[length + 1];
userinfo.nickname_len = length; userinfo.nickname_len = length;
@ -362,15 +465,28 @@ void SetUserInfoDetail(DWORD address) {
ZeroMemory(userinfo.nickname, (length + 1) * sizeof(wchar_t)); ZeroMemory(userinfo.nickname, (length + 1) * sizeof(wchar_t));
} }
length = *(DWORD *)(address + 0x108); // the results of calling and UI operations are different
userinfo.v2 = new wchar_t[length + 1]; //
userinfo.v2_len = length; // length = *(DWORD *)(address + 0x108);
if (length) { // userinfo.v2 = new wchar_t[length + 1];
memcpy(userinfo.v2, (wchar_t *)(*(DWORD *)(address + 0x104)), // userinfo.v2_len = length;
(length + 1) * sizeof(wchar_t)); // if (length) {
} else { // memcpy(userinfo.v2, (wchar_t *)(*(DWORD *)(address + 0x104)),
ZeroMemory(userinfo.v2, (length + 1) * sizeof(wchar_t)); // (length + 1) * sizeof(wchar_t));
} // } else {
// ZeroMemory(userinfo.v2, (length + 1) * sizeof(wchar_t));
// }
// length = *(DWORD *)(address + 0x11C);
// userinfo.py = new wchar_t[length + 1];
// userinfo.py_len = length;
// if (length) {
// memcpy(userinfo.py, (wchar_t *)(*(DWORD *)(address + 0x118)),
// (length + 1) * sizeof(wchar_t));
// } else {
// ZeroMemory(userinfo.py, (length + 1) * sizeof(wchar_t));
// }
length = *(DWORD *)(address + 0x16C); length = *(DWORD *)(address + 0x16C);
userinfo.small_image = new wchar_t[length + 1]; userinfo.small_image = new wchar_t[length + 1];
@ -436,9 +552,21 @@ void DeleteUserInfoCache() {
if (userinfo.v3) { if (userinfo.v3) {
delete userinfo.v3; delete userinfo.v3;
} }
if (userinfo.V3) {
delete userinfo.V3;
}
if (userinfo.account) {
delete userinfo.account;
}
if (userinfo.friend_name) {
delete userinfo.friend_name;
}
if (userinfo.nickname) { if (userinfo.nickname) {
delete userinfo.nickname; delete userinfo.nickname;
} }
if (userinfo.py) {
delete userinfo.py;
}
if (userinfo.nation) { if (userinfo.nation) {
delete userinfo.nation; delete userinfo.nation;
} }
@ -497,11 +625,11 @@ int HookSearchContact() {
if (search_contact_flag_) { if (search_contact_flag_) {
return 2; return 2;
} }
DWORD hook_error_code_addr = base + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSET; // DWORD hook_error_code_addr = base + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSET;
error_code_next_addr_ = base + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSET; // error_code_next_addr_ = base + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSET;
error_code_back_addr_ = hook_error_code_addr + 0x5; // error_code_back_addr_ = hook_error_code_addr + 0x5;
Utils::HookAnyAddress(hook_error_code_addr, (LPVOID)HandleErrorCode, // Utils::HookAnyAddress(hook_error_code_addr, (LPVOID)HandleErrorCode,
error_code_asm_code_); // error_code_asm_code_);
DWORD hook_user_info_addr = base + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSET; DWORD hook_user_info_addr = base + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSET;
user_info_next_addr_ = base + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSET; user_info_next_addr_ = base + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSET;

View File

@ -9,7 +9,6 @@
#include "chat_room_mgr.h" #include "chat_room_mgr.h"
#include "contact_mgr.h" #include "contact_mgr.h"
#include "db.h" #include "db.h"
#include "easylogging++.h"
#include "hooks.h" #include "hooks.h"
#include "misc_mgr.h" #include "misc_mgr.h"
#include "send_message_mgr.h" #include "send_message_mgr.h"
@ -71,9 +70,9 @@ string Dispatch(struct mg_connection *c, struct mg_http_message *hm) {
if (mg_vcasecmp(&hm->method, "POST") == 0) { if (mg_vcasecmp(&hm->method, "POST") == 0) {
is_post = 1; is_post = 1;
} }
el::Logger *defaultLogger = el::Loggers::getLogger("default"); // el::Logger *defaultLogger = el::Loggers::getLogger("default");
defaultLogger->info("method: %v body: %v", hm->method.ptr, hm->body.ptr); // defaultLogger->info("method: %v body: %v", hm->method.ptr, hm->body.ptr);
LOG_IF(is_post != 1, INFO) << "request method is not post"; // LOG_IF(is_post != 1, INFO) << "request method is not post";
if (is_post == 0) { if (is_post == 0) {
json ret_data = {{"result", "ERROR"}, {"msg", "not support method"}}; json ret_data = {{"result", "ERROR"}, {"msg", "not support method"}};
@ -227,8 +226,12 @@ string Dispatch(struct mg_connection *c, struct mg_http_message *hm) {
{"province", Utils::WCharToUTF8(user->province)}, {"province", Utils::WCharToUTF8(user->province)},
{"sex", user->sex}, {"sex", user->sex},
{"signature", Utils::WCharToUTF8(user->signature)}, {"signature", Utils::WCharToUTF8(user->signature)},
{"v2", Utils::WCharToUTF8(user->v2)}, // {"v2", Utils::WCharToUTF8(user->v2)},
{"v3", Utils::WCharToUTF8(user->v3)}, {"v3", Utils::WCharToUTF8(user->v3)},
{"V3", Utils::WCharToUTF8(user->V3)},
{"account", Utils::WCharToUTF8(user->account)},
// {"friendName", Utils::WCharToUTF8(user->friend_name)},
// {"py", Utils::WCharToUTF8(user->py)},
}; };
ret_data["userInfo"] = info; ret_data["userInfo"] = info;
} }
@ -252,7 +255,8 @@ string Dispatch(struct mg_connection *c, struct mg_http_message *hm) {
case WECHAT_CONTACT_VERIFY_APPLY: { case WECHAT_CONTACT_VERIFY_APPLY: {
wstring v3 = GetWStringParam(j_param, "v3"); wstring v3 = GetWStringParam(j_param, "v3");
wstring v4 = GetWStringParam(j_param, "v4"); wstring v4 = GetWStringParam(j_param, "v4");
int success = g_context.contact_mgr->VerifyApply(WS2LPWS(v3),WS2LPWS(v4)); int permission = GetIntParam(j_param, "permission");
int success = g_context.contact_mgr->VerifyApply(WS2LPWS(v3),WS2LPWS(v4),permission);
json ret_data = {{"code", success}, {"result", "OK"}}; json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump(); ret = ret_data.dump();
break; break;
@ -568,7 +572,51 @@ string Dispatch(struct mg_connection *c, struct mg_http_message *hm) {
ret = ret_data.dump(); ret = ret_data.dump();
break; break;
} }
case WECHAT_GET_QRCODE: {
string url = g_context.account_mgr->GetQRCodeUrl();
json ret_data = {{"code", 1}, {"result", "OK"},{"qrCodeUrl",url}};
ret = ret_data.dump();
break;
}
case WECHAT_INVITE_MEMBERS: {
wstring room_id = GetWStringParam(j_param, "chatRoomId");
vector<wstring> wxids = getArrayParam(j_param, "memberIds");
vector<wchar_t *> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++) {
wxid_list.push_back(WS2LPWS(wxids[i]));
}
int success = g_context.chat_room_mgr->InviteMemberToChatRoom(
WS2LPWS(room_id), wxid_list.data(), wxid_list.size());
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_GET_MEMBER_PROFILE: {
wstring pri_id = GetWStringParam(j_param, "wxid");
ContactProfile profile;
int success =
g_context.contact_mgr->GetContactByWxid(WS2LPWS(pri_id),profile);
if(success==1){
json ret_data = {
{"code", success},
{"result", "OK"},
{"account", Utils::WstringToUTF8(profile.account)},
{"headImage", Utils::WstringToUTF8(profile.head_image)},
{"nickname", Utils::WstringToUTF8(profile.nickname)},
{"v3", Utils::WstringToUTF8(profile.v3)},
{"wxid", Utils::WstringToUTF8(profile.wxid)},
};
ret = ret_data.dump();
} else {
json ret_data = {{"result", "ok"}, {"code", success}};
ret = ret_data.dump();
}
break;
}
default: default:
json ret_data = {{"result", "ERROR"}, {"msg", "not support api"}};
ret = ret_data.dump();
break; break;
} }

View File

@ -1,37 +1,20 @@
#include "log.h" #include "pch.h"
#include "log.h"
#include "easylogging++.h" #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
INITIALIZE_EASYLOGGINGPP
namespace wxhelper { namespace wxhelper {
Log::Log(/* args */) {} Log::Log(/* args */) {}
Log::~Log() {} Log::~Log() {
}
void Log::Initialize() { void Log::Initialize() {
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 23, 59);
el::Configurations conf; logger->flush_on(spdlog::level::err);
// 启用日志 spdlog::set_default_logger(logger);
conf.setGlobally(el::ConfigurationType::Enabled, "true"); spdlog::flush_every(std::chrono::seconds(3));
// 设置日志文件目录以及文件名 spdlog::set_level(spdlog::level::debug);
conf.setGlobally(el::ConfigurationType::Filename, spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
"log\\log_%datetime{%Y%M%d %H%m%s}.log");
// 设置日志文件最大文件大小
conf.setGlobally(el::ConfigurationType::MaxLogFileSize, "20971520");
// 是否写入文件
conf.setGlobally(el::ConfigurationType::ToFile, "true");
// 是否输出控制台
conf.setGlobally(el::ConfigurationType::ToStandardOutput, "true");
// 设置日志输出格式
conf.setGlobally(el::ConfigurationType::Format,
"[%datetime] [%thread] [%loc] [%level] : %msg");
// 设置日志文件写入周期如下每100条刷新到输出流中
#ifdef _DEBUG
conf.setGlobally(el::ConfigurationType::LogFlushThreshold, "1");
#else
conf.setGlobally(el::ConfigurationType::LogFlushThreshold, "100");
#endif
// 设置配置文件
el::Loggers::reconfigureAllLoggers(conf);
} }
} // namespace wxhelper } // namespace wxhelper

View File

@ -5,7 +5,6 @@
#include "base64.h" #include "base64.h"
#include "db.h" #include "db.h"
#include "hooks.h" #include "hooks.h"
#include "easylogging++.h"
#define BUFSIZE 1024 #define BUFSIZE 1024
#define JPEG0 0xFF #define JPEG0 0xFF
@ -154,8 +153,8 @@ int MiscMgr::DoDownloadTask(ULONG64 msg_id) {
DWORD get_current_data_path_addr = base_addr_ + WX_GET_CURRENT_DATA_PATH_OFFSET; DWORD get_current_data_path_addr = base_addr_ + WX_GET_CURRENT_DATA_PATH_OFFSET;
DWORD free_app_msg_info_addr = base_addr_ + WX_FREE_APP_MSG_INFO_OFFSET; DWORD free_app_msg_info_addr = base_addr_ + WX_FREE_APP_MSG_INFO_OFFSET;
DWORD push_thumb_task_addr = base_addr_ + WX_PUSH_THUMB_TASK_OFFSET; DWORD push_thumb_task_addr = base_addr_ + WX_PUSH_THUMB_TASK_OFFSET;
DWORD video_mgr_addr = base_addr_ + WX_VIDEO_MGR_OFFSET;
DWORD download_video_image_addr = base_addr_ + WX_VIDEO_MGR_OFFSET;
WeChatString current_data_path; WeChatString current_data_path;
@ -256,22 +255,6 @@ int MiscMgr::DoDownloadTask(ULONG64 msg_id) {
memcpy(&chat_msg[0x19C], &w_thumb_path, sizeof(w_thumb_path)); memcpy(&chat_msg[0x19C], &w_thumb_path, sizeof(w_thumb_path));
memcpy(&chat_msg[0x1B0], &w_save_path, sizeof(w_save_path)); memcpy(&chat_msg[0x1B0], &w_save_path, sizeof(w_save_path));
memcpy(&chat_msg[0x29C], &temp, sizeof(temp)); memcpy(&chat_msg[0x29C], &temp, sizeof(temp));
// note the image has been downloaded and will not be downloaded again
// use low-level method
// this function does not work, need to modify chatmsg.
// if (type == 0x3E || type == 0x2B){
// __asm{
// PUSHAD
// PUSHFD
// CALL video_mgr_addr
// LEA ECX,chat_msg
// PUSH ECX
// MOV ECX,EAX
// CALL download_video_image_addr
// POPFD
// POPAD
// }
// }
__asm { __asm {
PUSHAD PUSHAD
@ -402,8 +385,8 @@ int MiscMgr::GetImgByName(wchar_t* file_path,wchar_t* save_dir) {
int MiscMgr::SearchContactNetScene(wchar_t *keyword,UserInfo ** user) { int MiscMgr::SearchContactNetScene(wchar_t *keyword,UserInfo ** user) {
int success = -1; int success = -1;
hooks::HookSearchContact();
hooks::DeleteUserInfoCache(); hooks::DeleteUserInfoCache();
hooks::HookSearchContact();
DWORD search_contact_mgr_addr = base_addr_ + WX_SEARCH_CONTACT_MGR_OFFSET; DWORD search_contact_mgr_addr = base_addr_ + WX_SEARCH_CONTACT_MGR_OFFSET;
DWORD search_contact_addr = base_addr_ + WX_SEARCH_CONTACT_OFFSET; DWORD search_contact_addr = base_addr_ + WX_SEARCH_CONTACT_OFFSET;
WeChatString key(keyword); WeChatString key(keyword);
@ -420,16 +403,15 @@ int MiscMgr::SearchContactNetScene(wchar_t *keyword,UserInfo ** user) {
popad; popad;
} }
success = 1; success = 1;
while (hooks::userinfo.error_code == 1 && hooks::user_info_flag_) { // while (hooks::userinfo.error_code == 1 && hooks::user_info_flag_) {
Sleep(20); // Sleep(20);
} // }
if (hooks::userinfo.error_code == 0) { // if (hooks::userinfo.error_code == 0) {
while (hooks::userinfo.over == false && hooks::user_info_flag_) { while (hooks::userinfo.over == false && hooks::user_info_flag_) {
Sleep(20); Sleep(2);
}
} }
// }
*user= &hooks::userinfo; *user= &hooks::userinfo;
LOG(INFO)<<"user:" <<user;
return success; return success;
} }

View File

@ -16,6 +16,11 @@
#include <fcntl.h> #include <fcntl.h>
#include "Windows.h" #include "Windows.h"
#include "utils.h" #include "utils.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#endif // PCH_H #endif // PCH_H

View File

@ -1,12 +1,9 @@
#include "pch.h" #include "pch.h"
#include "send_message_mgr.h" #include "send_message_mgr.h"
#include "easylogging++.h"
#include "wechat_function.h" #include "wechat_function.h"
#include "db.h" #include "db.h"
#include "contact_mgr.h" #include "contact_mgr.h"
#include "spdlog/spdlog.h"
namespace wxhelper { namespace wxhelper {
SendMessageMgr::SendMessageMgr(DWORD base):BaseMgr(base) {} SendMessageMgr::SendMessageMgr(DWORD base):BaseMgr(base) {}
SendMessageMgr::~SendMessageMgr() {} SendMessageMgr::~SendMessageMgr() {}
@ -21,6 +18,7 @@ int SendMessageMgr::SendText(wchar_t* wxid, wchar_t* msg) {
char chat_msg[0x2D8] = {0}; char chat_msg[0x2D8] = {0};
__asm { __asm {
PUSHAD PUSHAD
PUSHFD
CALL send_message_mgr_addr CALL send_message_mgr_addr
PUSH 0x0 PUSH 0x0
PUSH 0x0 PUSH 0x0
@ -36,9 +34,11 @@ int SendMessageMgr::SendText(wchar_t* wxid, wchar_t* msg) {
ADD ESP,0x18 ADD ESP,0x18
LEA ECX,chat_msg LEA ECX,chat_msg
CALL free_chat_msg_addr CALL free_chat_msg_addr
POPFD
POPAD POPAD
} }
LOG_IF((success == -1), ERROR) << "SendText fail"; SPDLOG_INFO("SendText code = {}",success);
SPDLOG_INFO("global log with source info");
return success; return success;
} }
int SendMessageMgr::SendAtText(wchar_t* chat_room_id, wchar_t** wxids, int len, int SendMessageMgr::SendAtText(wchar_t* chat_room_id, wchar_t** wxids, int len,
@ -86,6 +86,7 @@ int SendMessageMgr::SendAtText(wchar_t* chat_room_id, wchar_t** wxids, int len,
char chat_msg[0x2D8] = {0}; char chat_msg[0x2D8] = {0};
__asm{ __asm{
PUSHAD PUSHAD
PUSHFD
CALL send_message_mgr_addr CALL send_message_mgr_addr
PUSH 0x0 PUSH 0x0
PUSH 0x0 PUSH 0x0
@ -102,9 +103,10 @@ int SendMessageMgr::SendAtText(wchar_t* chat_room_id, wchar_t** wxids, int len,
ADD ESP,0x18 ADD ESP,0x18
LEA ECX,chat_msg LEA ECX,chat_msg
CALL free_chat_msg_addr CALL free_chat_msg_addr
POPFD
POPAD POPAD
} }
LOG_IF((success == -1), ERROR) << "SendText fail"; SPDLOG_INFO("SendText code = {}",success);
return success; return success;
} }
int SendMessageMgr::SendImage(wchar_t* wxid, wchar_t* image_path) { int SendMessageMgr::SendImage(wchar_t* wxid, wchar_t* image_path) {
@ -120,6 +122,7 @@ int SendMessageMgr::SendImage(wchar_t* wxid, wchar_t* image_path) {
WeChatString null_obj = {0}; WeChatString null_obj = {0};
__asm { __asm {
PUSHAD PUSHAD
PUSHFD
CALL send_message_mgr_addr CALL send_message_mgr_addr
SUB ESP,0x14 SUB ESP,0x14
MOV temp,EAX MOV temp,EAX
@ -138,9 +141,10 @@ int SendMessageMgr::SendImage(wchar_t* wxid, wchar_t* image_path) {
MOV success,EAX MOV success,EAX
LEA ECX,chat_msg LEA ECX,chat_msg
CALL free_msg_addr CALL free_msg_addr
POPFD
POPAD POPAD
} }
LOG_IF((success == -1), ERROR) << "SendImage fail"; SPDLOG_INFO("SendImage code = {}",success);
return success; return success;
} }
int SendMessageMgr::SendFile(wchar_t* wxid, wchar_t* file_path) { int SendMessageMgr::SendFile(wchar_t* wxid, wchar_t* file_path) {
@ -194,10 +198,10 @@ int SendMessageMgr::SendFile(wchar_t* wxid, wchar_t* file_path) {
POPFD POPFD
POPAD POPAD
} }
SPDLOG_INFO("SendFile code = {}",success);
if (success == 0x31) { if (success == 0x31) {
return 1; return 1;
} }
LOG_IF((success == -1), ERROR) << "SendFile fail";
return success; return success;
} }

41
src/thread_pool.cc Normal file
View File

@ -0,0 +1,41 @@

#include "pch.h"
#include "thread_pool.h"
#include "Windows.h"
namespace wxhelper {
ThreadPool::~ThreadPool() {
CloseThreadpoolCleanupGroupMembers(cleanup_group_, true, NULL);
CloseThreadpoolCleanupGroup(cleanup_group_);
CloseThreadpool(pool_);
}
bool ThreadPool::Create(unsigned long min, unsigned long max) {
InitializeThreadpoolEnvironment(&env_);
pool_ = CreateThreadpool(NULL);
if (NULL == pool_) {
return false;
}
SetThreadpoolThreadMaximum(pool_, max);
BOOL ret = SetThreadpoolThreadMinimum(pool_, min);
if (FALSE == ret) {
return false;
}
cleanup_group_ = CreateThreadpoolCleanupGroup();
if (NULL == cleanup_group_) {
return false;
}
SetThreadpoolCallbackPool(&env_, pool_);
SetThreadpoolCallbackCleanupGroup(&env_, cleanup_group_, NULL);
return true;
}
bool ThreadPool::AddWork(PTP_WORK_CALLBACK callback,PVOID opt) {
PTP_WORK work = CreateThreadpoolWork(callback, opt, &env_);
if (NULL == work) {
return false;
}
SubmitThreadpoolWork(work);
return true;
}
} // namespace wxhelper

26
src/thread_pool.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef WXHELPER_THREAD_POOL_H_
#define WXHELPER_THREAD_POOL_H_
#include "Windows.h"
#include "singleton.h"
namespace wxhelper {
class ThreadPool :public Singleton<ThreadPool>{
public:
~ThreadPool();
bool Create(unsigned long min = 1, unsigned long max = 4);
bool AddWork(PTP_WORK_CALLBACK callback,PVOID opt);
private:
void operator=(const ThreadPool&) = delete;
void operator=(ThreadPool&&) = delete;
PTP_POOL pool_;
PTP_CLEANUP_GROUP cleanup_group_;
TP_CALLBACK_ENVIRON env_;
};
} // namespace wxhelper
#endif

View File

@ -4,97 +4,97 @@
#include <string> #include <string>
// snsDataMgr // snsDataMgr
#define WX_SNS_DATA_MGR_OFFSET 0xc39680 #define WX_SNS_DATA_MGR_OFFSET 0xc3a500
// chatRoomMgr // chatRoomMgr
#define WX_CHAT_ROOM_MGR_OFFSET 0x78cf20 #define WX_CHAT_ROOM_MGR_OFFSET 0x78d9d0
// contactMgr // contactMgr
#define WX_CONTACT_MGR_OFFSET 0x75a4a0 #define WX_CONTACT_MGR_OFFSET 0x75af30
// syncMgr // syncMgr
#define WX_SYNC_MGR_OFFSET 0xa87fd0 #define WX_SYNC_MGR_OFFSET 0xa87fd0
// preDownloadMgr // preDownloadMgr
#define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x80f110 #define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x80fe50
// chatMgr // chatMgr
#define WX_CHAT_MGR_OFFSET 0x792700 #define WX_CHAT_MGR_OFFSET 0x7931b0
// videoMgr // videoMgr
#define WX_VIDEO_MGR_OFFSET 0x829820 #define WX_VIDEO_MGR_OFFSET 0x82a560
// patMgr // patMgr
#define WX_PAT_MGR_OFFSET 0x931730 #define WX_PAT_MGR_OFFSET 0x932470
// searchContactMgr // searchContactMgr
#define WX_SEARCH_CONTACT_MGR_OFFSET 0xa6cb00 #define WX_SEARCH_CONTACT_MGR_OFFSET 0xa6d860
// appMsgMgr // appMsgMgr
#define WX_APP_MSG_MGR_OFFSET 0x76ae20 #define WX_APP_MSG_MGR_OFFSET 0x76b8c0
// sendMessageMgr // sendMessageMgr
#define WX_SEND_MESSAGE_MGR_OFFSET 0x768140 #define WX_SEND_MESSAGE_MGR_OFFSET 0x768be0
// shareRecordMgr
#define WX_SHARE_RECORD_MGR_OFFSET 0x78d5f0
// setChatMsgValue // setChatMsgValue
#define WX_INIT_CHAT_MSG_OFFSET 0xf59e40 #define WX_INIT_CHAT_MSG_OFFSET 0xf5b3f0
// chatMsg // chatMsg
#define WX_NEW_CHAT_MSG_OFFSET 0x76f010 #define WX_NEW_CHAT_MSG_OFFSET 0x76fab0
#define WX_FREE_CHAT_MSG_OFFSET 0x756960 #define WX_FREE_CHAT_MSG_OFFSET 0x7573f0
#define WX_FREE_CHAT_MSG_2_OFFSET 0x6f4ea0 // #define WX_FREE_CHAT_MSG_2_OFFSET 0x6f4ea0
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x756e30 #define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x7578c0
//sns //sns
#define WX_SNS_GET_FIRST_PAGE_OFFSET 0x14e2140 #define WX_SNS_GET_FIRST_PAGE_OFFSET 0x14e36e0
#define WX_SNS_GET_NEXT_PAGE_OFFSET 0x14e21e0 #define WX_SNS_GET_NEXT_PAGE_OFFSET 0x14e3780
//chat room //chat room
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xbde090 #define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xbdef30
// chatRoomInfo // chatRoomInfo
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xe99c40 #define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xe9abd0
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xe99f40 #define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xe9aed0
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xbd22a0 #define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xbd3140
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xbd1dc0 #define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xbd2c60
// chatRoom // chatRoom
#define WX_INIT_CHAT_ROOM_OFFSET 0xe97890 #define WX_INIT_CHAT_ROOM_OFFSET 0xe98820
#define WX_FREE_CHAT_ROOM_OFFSET 0xe97ab0 #define WX_FREE_CHAT_ROOM_OFFSET 0xe98a40
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xbdf260 #define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xbe0100
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xbd9680 #define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xbda520
#define WX_TOP_MSG_OFFSET 0xbe1840 #define WX_TOP_MSG_OFFSET 0xbe26e0
#define WX_REMOVE_TOP_MSG_OFFSET 0xbe1620 #define WX_REMOVE_TOP_MSG_OFFSET 0xbe24c0
#define WX_GET_MEMBER_NICKNAME_OFFSET 0xbdf3f0 #define WX_GET_MEMBER_NICKNAME_OFFSET 0xbe0290
#define WX_FREE_CONTACT_OFFSET 0xea7880 #define WX_FREE_CONTACT_OFFSET 0xea8800
// wcpayinfo // wcpayinfo
#define WX_NEW_WCPAYINFO_OFFSET 0x7b2e60 #define WX_NEW_WCPAYINFO_OFFSET 0x7b3900
#define WX_FREE_WCPAYINFO_OFFSET 0x79c250 #define WX_FREE_WCPAYINFO_OFFSET 0x79cd00
#define WX_CONFIRM_RECEIPT_OFFSET 0x15e2c20 #define WX_CONFIRM_RECEIPT_OFFSET 0x15e41d0
//contact //contact
#define WX_CONTACT_GET_LIST_OFFSET 0xc089f0 #define WX_CONTACT_GET_LIST_OFFSET 0xc09890
#define WX_CONTACT_DEL_OFFSET 0xb9b3b0 #define WX_CONTACT_DEL_OFFSET 0xb9b3b0
#define WX_SET_VALUE_OFFSET 0x1f80900 #define WX_SET_VALUE_OFFSET 0x1f80900
#define WX_DO_DEL_CONTACT_OFFSET 0xca6480 #define WX_DO_DEL_CONTACT_OFFSET 0xca6480
#define WX_GET_CONTACT_OFFSET 0xc04e00 #define WX_GET_CONTACT_OFFSET 0xc05ca0
#define WX_DO_VERIFY_USER_OFFSET 0xc02100 #define WX_DO_VERIFY_USER_OFFSET 0xc02f90
#define WX_VERIFY_MSG_OFFSET 0xf59d40 #define WX_VERIFY_MSG_OFFSET 0xf5b2f0
#define WX_VERIFY_OK_OFFSET 0xa18bd0 #define WX_VERIFY_OK_OFFSET 0xa19940
#define WX_NEW_ADD_FRIEND_HELPER_OFFSET 0xa17d50 #define WX_NEW_ADD_FRIEND_HELPER_OFFSET 0xa18ac0
#define WX_FREE_ADD_FRIEND_HELPER_OFFSET 0xa17e70 #define WX_FREE_ADD_FRIEND_HELPER_OFFSET 0xa18be0
// pushAttachTask // pushAttachTask
#define WX_PUSH_ATTACH_TASK_OFFSET 0x82bb40 #define WX_PUSH_ATTACH_TASK_OFFSET 0x82c880
#define WX_FREE_CHAT_MSG_OFFSET 0x756960 #define WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET 0xbc11d0
#define WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET 0xbc0370
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc872c0
#define WX_APP_MSG_INFO_OFFSET 0x7b3d20 #define WX_APP_MSG_INFO_OFFSET 0x7b3d20
#define WX_GET_APP_MSG_XML_OFFSET 0xe628a0 #define WX_GET_APP_MSG_XML_OFFSET 0xe628a0
#define WX_FREE_APP_MSG_INFO_OFFSET 0x79d900 #define WX_FREE_APP_MSG_INFO_OFFSET 0x79e3b0
#define WX_PUSH_THUMB_TASK_OFFSET 0x82ba40 #define WX_PUSH_THUMB_TASK_OFFSET 0x82c780
#define WX_DOWNLOAD_VIDEO_IMG_OFFSET 0xd46c30 #define WX_DOWNLOAD_VIDEO_IMG_OFFSET 0xd46c30
@ -102,45 +102,46 @@
// pat // pat
#define WX_SEND_PAT_MSG_OFFSET 0x1421940 #define WX_SEND_PAT_MSG_OFFSET 0x1422f30
#define WX_RET_OFFSET 0x1D58751 #define WX_RET_OFFSET 0x1D59DB1
//search hook //search hook
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSET 0xe17054 #define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSET 0xe17ed4
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSET 0xf57a20 #define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSET 0xf58fd0
#define WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSET 0xa8ceb0 #define WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSET 0xa8dc00
#define WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSET 0xa8d100 #define WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSET 0xa8de50
#define WX_SEARCH_CONTACT_OFFSET 0xcd1510 #define WX_SEARCH_CONTACT_OFFSET 0xcd2370
//login //login
#define WX_LOGOUT_OFFSET 0xe58870 #define WX_LOGOUT_OFFSET 0xe596d0
#define WX_ACCOUNT_SERVICE_OFFSET 0x768c80 #define WX_ACCOUNT_SERVICE_OFFSET 0x769720
#define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xf3a610 #define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xf3bbd0
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc872c0 #define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc88120
#define WX_QR_CODE_LOGIN_MGR_OFFSET 0xaeab70
#define WX_GET_QR_CODE_IMAGE_OFFSET 0xcdb560
//forward //forward
#define WX_FORWARD_MSG_OFFSET 0xce6730 #define WX_FORWARD_MSG_OFFSET 0xce75a0
// send file // send file
#define WX_SEND_FILE_OFFSET 0xb6d1f0 #define WX_SEND_FILE_OFFSET 0xb6dfd0
// send image // send image
#define WX_SEND_IMAGE_OFFSET 0xce6640 #define WX_SEND_IMAGE_OFFSET 0xce74b0
// send text // send text
#define WX_SEND_TEXT_OFFSET 0xce6c80 #define WX_SEND_TEXT_OFFSET 0xce7af0
//ocr //ocr
#define WX_INIT_OBJ_OFFSET 0x80a800 #define WX_INIT_OBJ_OFFSET 0x80b540
#define WX_OCR_MANAGER_OFFSET 0x80f270 #define WX_OCR_MANAGER_OFFSET 0x80ffc0
#define WX_DO_OCR_TASK_OFFSET 0x13da3e0 #define WX_DO_OCR_TASK_OFFSET 0x13db9a0
//storage //storage
#define CONTACT_G_PINSTANCE_OFFSET 0x2ffddc8 #define CONTACT_G_PINSTANCE_OFFSET 0x2fffe08
#define DB_MICRO_MSG_OFFSET 0x68 #define DB_MICRO_MSG_OFFSET 0x68
#define DB_CHAT_MSG_OFFSET 0x1C0 #define DB_CHAT_MSG_OFFSET 0x1C0
#define DB_MISC_OFFSET 0x3D8 #define DB_MISC_OFFSET 0x3D8
@ -153,10 +154,10 @@
#define STORAGE_START_OFFSET 0x13f8 #define STORAGE_START_OFFSET 0x13f8
#define STORAGE_END_OFFSET 0x13fc #define STORAGE_END_OFFSET 0x13fc
#define PUBLIC_MSG_MGR_OFFSET 0x303df74 #define PUBLIC_MSG_MGR_OFFSET 0x30400a4
#define MULTI_DB_MSG_MGR_OFFSET 0x30403b8 #define MULTI_DB_MSG_MGR_OFFSET 0x30424dc
#define FAVORITE_STORAGE_MGR_OFFSET 0x303fd40 #define FAVORITE_STORAGE_MGR_OFFSET 0x3041e70
#define FTS_FAVORITE_MGR_OFFSET 0x2ffe908 #define FTS_FAVORITE_MGR_OFFSET 0x3000948
#define OP_LOG_STORAGE_VFTABLE 0x2AD3A20 #define OP_LOG_STORAGE_VFTABLE 0x2AD3A20
#define CHAT_MSG_STORAGE_VFTABLE 0x2AC10F0 #define CHAT_MSG_STORAGE_VFTABLE 0x2AC10F0
@ -196,15 +197,15 @@
// hook log // hook log
#define WX_HOOK_LOG_OFFSET 0xf57d67 #define WX_HOOK_LOG_OFFSET 0xf59317
#define WX_HOOK_LOG_NEXT_OFFSET 0x240ea71 #define WX_HOOK_LOG_NEXT_OFFSET 0x24102b4
// hook msg // hook msg
#define WX_RECV_MSG_HOOK_OFFSET 0xd19a0b #define WX_RECV_MSG_HOOK_OFFSET 0xd1a89b
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x756960 #define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x7573f0
#define WX_SNS_HOOK_OFFSET 0x14f9e15 #define WX_SNS_HOOK_OFFSET 0x14fb3b5
#define WX_SNS_HOOK_NEXT_OFFSET 0x14fa0a0 #define WX_SNS_HOOK_NEXT_OFFSET 0x14fb640
// hook voice // hook voice
@ -350,24 +351,24 @@
#define SQLITE_NULL 5 #define SQLITE_NULL 5
#define SQLITE_TEXT 3 #define SQLITE_TEXT 3
#define SQLITE3_EXEC_OFFSET 0x1e24f70 #define SQLITE3_EXEC_OFFSET 0x1e26770
#define SQLITE3_BACKUP_INIT_OFFSET 0x1dea900 #define SQLITE3_BACKUP_INIT_OFFSET 0x1dec100
#define SQLITE3_PREPARE_OFFSET 0x1e2b8c0 #define SQLITE3_PREPARE_OFFSET 0x1E2D0C0
#define SQLITE3_OPEN_OFFSET 0x1e598b0 #define SQLITE3_OPEN_OFFSET 0x1e5b090
#define SQLITE3_BACKUP_STEP_OFFSET 0x1dead00 #define SQLITE3_BACKUP_STEP_OFFSET 0x1DEC500
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1deb440 #define SQLITE3_BACKUP_REMAINING_OFFSET 0x1DECC40
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1deb450 #define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1DECC50
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1deb340 #define SQLITE3_BACKUP_FINISH_OFFSET 0x1DECB40
#define SQLITE3_SLEEP_OFFSET 0x1e5a0f0 #define SQLITE3_SLEEP_OFFSET 0x1e5b8d0
#define SQLITE3_ERRCODE_OFFSET 0x1e58550 #define SQLITE3_ERRCODE_OFFSET 0x1e59d30
#define SQLITE3_CLOSE_OFFSET 0x1e56cd0 #define SQLITE3_CLOSE_OFFSET 0x1e584b0
#define SQLITE3_STEP_OFFSET 0x1df3770 #define SQLITE3_STEP_OFFSET 0x1df4f70
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1df3c80 #define SQLITE3_COLUMN_COUNT_OFFSET 0x1df5480
#define SQLITE3_COLUMN_NAME_OFFSET 0x1df4570 #define SQLITE3_COLUMN_NAME_OFFSET 0x1df5d70
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1df4410 #define SQLITE3_COLUMN_TYPE_OFFSET 0x1df5c10
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1df3cc0 #define SQLITE3_COLUMN_BLOB_OFFSET 0x1df54c0
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1df3da0 #define SQLITE3_COLUMN_BYTES_OFFSET 0x1df55a0
#define SQLITE3_FINALIZE_OFFSET 0x1df2740 #define SQLITE3_FINALIZE_OFFSET 0x1df3f40
typedef int (*Sqlite3_callback)(void*, int, char**, char**); typedef int (*Sqlite3_callback)(void*, int, char**, char**);
@ -578,12 +579,20 @@ struct UserInfo {
int keyword_len; int keyword_len;
wchar_t *v3; wchar_t *v3;
int v3_len; int v3_len;
wchar_t *V3;
int V3_len;
wchar_t *account;
int account_len;
wchar_t *friend_name;
int friend_name_len;
wchar_t *nickname; wchar_t *nickname;
int nickname_len; int nickname_len;
wchar_t *signature; wchar_t *signature;
int signature_len; int signature_len;
wchar_t *v2; wchar_t *v2;
int v2_len; int v2_len;
wchar_t *py;
int py_len;
wchar_t *nation; wchar_t *nation;
int nation_len; int nation_len;
wchar_t *province; wchar_t *province;
@ -769,4 +778,12 @@ struct Unkown{
DWORD field5= 0; DWORD field5= 0;
DWORD field6= 0; DWORD field6= 0;
}; };
struct ContactProfile{
std::wstring wxid;
std::wstring account;
std::wstring v3;
std::wstring nickname;
std::wstring head_image;
};
#endif #endif