Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4af7e3f58b | ||
|
|
1638a49dd4 | ||
|
|
41091b1c6f | ||
|
|
19d146db99 | ||
|
|
67949e16fc | ||
|
|
9f7b1dd273 | ||
|
|
4eab2a2414 | ||
|
|
b8dc032525 | ||
|
|
7e89c6ef2d | ||
|
|
82a5ca28db | ||
|
|
861a04e7a0 | ||
|
|
04e7967236 | ||
|
|
822e076a82 | ||
|
|
3ed52a7dbc | ||
|
|
9e5dce93f0 | ||
|
|
db5051ae2f | ||
|
|
c8544a9286 | ||
|
|
3522f9187e | ||
|
|
4e34505cdd | ||
|
|
3d8ed813be | ||
|
|
75d470935d | ||
|
|
7be2903dd2 | ||
|
|
e563710f80 | ||
|
|
915cb1602f | ||
|
|
254a9eeb30 | ||
|
|
a0f83b5a99 | ||
|
|
e7a460ad25 | ||
|
|
ebde430aec | ||
|
|
1216733b82 | ||
|
|
6dca99474b | ||
|
|
d818c826e5 | ||
|
|
b0e73002ff | ||
|
|
a2cfb13217 | ||
|
|
911f87211c | ||
|
|
2f1793b2b1 | ||
|
|
6b36287c4d | ||
|
|
d86d4c0bf6 | ||
|
|
f82f85b2b6 |
+1
-1
@@ -5,7 +5,7 @@ project(wxhelper VERSION 1.0.0)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '0_UNICODE' /D 'UNICODE'")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '_UNICODE' /D 'UNICODE'")
|
||||
|
||||
file(GLOB CPP_FILES ${PROJECT_SOURCE_DIR}/src/*.cc ${PROJECT_SOURCE_DIR}/src/*.cpp)
|
||||
|
||||
|
||||
+142
-5
@@ -19,6 +19,13 @@
|
||||
#include "self_info.h"
|
||||
#include "hook_img.h"
|
||||
#include "ocr.h"
|
||||
#include "pat.h"
|
||||
#include "confirm_receipt.h"
|
||||
#include "sns.h"
|
||||
#include "search_contact.h"
|
||||
#include "download.h"
|
||||
#include "hook_log.h"
|
||||
#include "hook_voice.h"
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
using namespace std;
|
||||
@@ -217,9 +224,8 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
{"account", self_info.account},
|
||||
{"wxid", self_info.wxid},
|
||||
{"mobile", self_info.mobile},
|
||||
{"smallImage", self_info.small_img},
|
||||
{"bigImage", self_info.big_img},
|
||||
{"dataRootPath",self_info.data_root_path},
|
||||
{"headImage", self_info.head_img},
|
||||
{"signature",self_info.signature},
|
||||
{"dataSavePath",self_info.data_save_path},
|
||||
{"currentDataPath",self_info.current_data_path},
|
||||
};
|
||||
@@ -237,6 +243,16 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_MSG_SEND_AT: {
|
||||
wstring chat_room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
|
||||
vector<wstring> wxids = get_http_param_array(hm, j_param, "wxids", is_post);
|
||||
wstring msg = get_http_req_param(hm, j_param, "msg", is_post);
|
||||
vector<wchar_t *> wxid_list;
|
||||
for (unsigned int i = 0; i < wxids.size(); i++){
|
||||
wxid_list.push_back(WS2LW(wxids[i]));
|
||||
}
|
||||
int success = SendAtText(WS2LW(chat_room_id), wxid_list.data(), wxid_list.size(),WS2LW(msg));
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_MSG_SEND_CARD: {
|
||||
@@ -266,7 +282,11 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
}
|
||||
case WECHAT_MSG_START_HOOK: {
|
||||
int port = get_http_req_param_int(hm, j_param, "port", is_post);
|
||||
int success = HookRecvMsg(port);
|
||||
wstring ip = get_http_req_param(hm, j_param, "ip", is_post);
|
||||
string client_ip = Wstring2String(ip);
|
||||
char ip_cstr[16];
|
||||
strcpy_s(ip_cstr,client_ip.c_str());
|
||||
int success = HookRecvMsg(ip_cstr,port);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
@@ -291,9 +311,16 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_MSG_START_VOICE_HOOK: {
|
||||
wstring voice_dir = get_http_req_param(hm, j_param, "voiceDir", is_post);
|
||||
int success = HookVoice(voice_dir);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_MSG_STOP_VOICE_HOOK: {
|
||||
int success = UnHookVoice();
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_GET_LIST: {
|
||||
@@ -314,9 +341,33 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_SEARCH_BY_NET: {
|
||||
wstring keyword = get_http_req_param(hm, j_param, "keyword", is_post);
|
||||
UserInfo *user = nullptr;
|
||||
int success = SearchContactNetScene(WS2LW(keyword), &user);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
if (user) {
|
||||
json info = {
|
||||
{"bigImage", unicode_to_utf8(user->big_image)},
|
||||
{"smallImage", unicode_to_utf8(user->small_image)},
|
||||
{"city", unicode_to_utf8(user->city)},
|
||||
{"nation", unicode_to_utf8(user->nation)},
|
||||
{"nickname", unicode_to_utf8(user->nickname)},
|
||||
{"province", unicode_to_utf8(user->province)},
|
||||
{"sex", user->sex},
|
||||
{"signature", unicode_to_utf8(user->signature)},
|
||||
{"v2", unicode_to_utf8(user->v2)},
|
||||
{"v3", unicode_to_utf8(user->v3)},
|
||||
};
|
||||
ret_data["userInfo"] = info;
|
||||
}
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_ADD_BY_WXID: {
|
||||
wstring user_id = get_http_req_param(hm, j_param, "wxid", is_post);
|
||||
int success = AddFriendByWxid(WS2LW(user_id));
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_ADD_BY_V3: {
|
||||
@@ -348,6 +399,12 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_CHATROOM_GET_MEMBER_NICKNAME: {
|
||||
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
|
||||
wstring member_id = get_http_req_param(hm, j_param, "memberId", is_post);
|
||||
|
||||
wstring nickname = GetChatRoomMemberNickname(WS2LW(room_id),WS2LW(member_id));
|
||||
json ret_data = {{"code", 1}, {"result", "OK"},{"nickname",unicode_to_utf8(WS2LW(nickname))}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CHATROOM_DEL_MEMBER: {
|
||||
@@ -438,9 +495,15 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_LOG_START_HOOK: {
|
||||
int success = HookLog();
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_LOG_STOP_HOOK: {
|
||||
int success = UnHookLog();
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_BROWSER_OPEN_WITH_URL: {
|
||||
@@ -473,6 +536,12 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_GET_TRANSFER: {
|
||||
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
|
||||
wstring transcationid = get_http_req_param(hm, j_param, "transcationId", is_post);
|
||||
wstring transferid = get_http_req_param(hm, j_param, "transferId", is_post);
|
||||
BOOL response = DoConfirmReceipt(WS2LW(wxid), WS2LW(transcationid), WS2LW(transferid));
|
||||
json ret_data = {{"msg", response}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_GET_CONTACT_ALL: {
|
||||
@@ -555,6 +624,57 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_SEND_PAT_MSG:{
|
||||
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
|
||||
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
|
||||
int success = SendPatMsg(WS2LW(room_id),WS2LW(wxid));
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_SET_TOP_MSG:{
|
||||
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
|
||||
ULONG64 msgid = get_http_param_ulong64(hm, j_param, "msgid", is_post);
|
||||
int success = SetTopMsg(WS2LW(wxid),msgid);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_REMOVE_TOP_MSG:{
|
||||
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
|
||||
ULONG64 msgid = get_http_param_ulong64(hm, j_param, "msgid", is_post);
|
||||
int success = RemoveTopMsg(WS2LW(room_id),msgid);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_SNS_GET_FIRST_PAGE:{
|
||||
int success = GetFirstPage();
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_SNS_GET_NEXT_PAGE: {
|
||||
ULONG64 snsid = get_http_param_ulong64(hm, j_param, "snsId", is_post);
|
||||
int success = GetNextPage(snsid);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_NAME:{
|
||||
wstring pri_id = get_http_req_param(hm, j_param, "id", is_post);
|
||||
wstring name =GetContactOrChatRoomNickname(WS2LW(pri_id));
|
||||
json ret_data = {{"code", 1}, {"result", "OK"},{"name",unicode_to_utf8(WS2LW(name))}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_ATTACH_DOWNLOAD:{
|
||||
ULONG64 msg_id = get_http_param_ulong64(hm, j_param, "msgId", is_post);
|
||||
int success = DoDownloadTask(msg_id);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -613,6 +733,23 @@ int http_start(int port) {
|
||||
#endif
|
||||
kHttpRuning = true;
|
||||
kHttpThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)http_server,
|
||||
(LPVOID)port, NULL, 0);
|
||||
(LPVOID)port, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int http_close() {
|
||||
if (!kHttpRuning) {
|
||||
return 1;
|
||||
}
|
||||
kHttpRuning = false;
|
||||
if (kHttpThread) {
|
||||
WaitForSingleObject(kHttpThread, -1);
|
||||
CloseHandle(kHttpThread);
|
||||
kHttpThread = NULL;
|
||||
}
|
||||
UnHookRecvMsg();
|
||||
UnHookImg();
|
||||
UnHookSearchContact();
|
||||
UnHookLog();
|
||||
return 0;
|
||||
}
|
||||
@@ -64,9 +64,17 @@ typedef enum WECHAT_HTTP_APISTag
|
||||
WECHAT_GET_CHATROOM_INFO,
|
||||
WECHAT_GET_IMG_BY_NAME,
|
||||
WECHAT_DO_OCR,
|
||||
WECHAT_SEND_PAT_MSG,
|
||||
WECHAT_SET_TOP_MSG,
|
||||
WECHAT_REMOVE_TOP_MSG,
|
||||
WECHAT_SNS_GET_FIRST_PAGE,
|
||||
WECHAT_SNS_GET_NEXT_PAGE,
|
||||
WECHAT_CONTACT_NAME,
|
||||
WECHAT_ATTACH_DOWNLOAD,
|
||||
} WECHAT_HTTP_APIS,
|
||||
*PWECHAT_HTTP_APIS;
|
||||
|
||||
|
||||
int http_start(int port);
|
||||
extern "C" __declspec(dllexport) int http_start(int port);
|
||||
extern "C" __declspec(dllexport) int http_close();
|
||||
#endif
|
||||
+225
-27
@@ -2,20 +2,31 @@
|
||||
#include "chat_room.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "get_db_handle.h"
|
||||
#include "wechat_data.h"
|
||||
#define WX_CHAT_ROOM_MGR_OFFSET 0x67ee70
|
||||
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xa73a80
|
||||
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xd07010
|
||||
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xd072f0
|
||||
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xa69a50
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x649ac0
|
||||
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xa69560
|
||||
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xa749b0
|
||||
#define WX_INIT_CHAT_ROOM_OFFSET 0xd04d80
|
||||
#define WX_FREE_CHAT_ROOM_OFFSET 0xa7c620
|
||||
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xa6f8f0
|
||||
#include "base64.h"
|
||||
using namespace std;
|
||||
|
||||
#define WX_CHAT_ROOM_MGR_OFFSET 0x72cf60
|
||||
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xb6f260
|
||||
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xe15de0
|
||||
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xe160b0
|
||||
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xb64180
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
|
||||
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xb63c50
|
||||
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xB70260
|
||||
#define WX_INIT_CHAT_ROOM_OFFSET 0xe13b30
|
||||
#define WX_FREE_CHAT_ROOM_OFFSET 0xe13d50
|
||||
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xb6adf0
|
||||
#define WX_NEW_CHAT_MSG_OFFSET 0x70e2a0
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
|
||||
#define WX_TOP_MSG_OFFSET 0xb727e0
|
||||
#define WX_REMOVE_TOP_MSG_OFFSET 0xb725a0
|
||||
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x6f5370
|
||||
#define WX_GET_MEMBER_NICKNAME_OFFSET 0xb703f0
|
||||
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x6f8990
|
||||
#define WX_GET_CONTACT_OFFSET 0xb93b20
|
||||
#define WX_FREE_CONTACT_OFFSET 0xe23690
|
||||
|
||||
int GetChatRoomDetailInfo(wchar_t* chat_room_id, ChatRoomInfoInner& room_info) {
|
||||
int success = 0;
|
||||
@@ -41,21 +52,54 @@ int GetChatRoomDetailInfo(wchar_t* chat_room_id, ChatRoomInfoInner& room_info) {
|
||||
MOV success,EAX
|
||||
POPAD
|
||||
}
|
||||
room_info.chat_room_id.ptr = *(wchar_t**)(chat_room_info + 0x4);
|
||||
room_info.chat_room_id.length = *(DWORD*)(chat_room_info + 0x8);
|
||||
room_info.chat_room_id.max_length = *(DWORD*)(chat_room_info + 0xC);
|
||||
DWORD room_id_len = *(DWORD*)(chat_room_info + 0x8);
|
||||
DWORD room_id_max_len = *(DWORD*)(chat_room_info + 0xC);
|
||||
wchar_t * room_id = new wchar_t[room_id_len + 1];
|
||||
wmemcpy(room_id,*(wchar_t**)(chat_room_info + 0x4),room_id_len + 1);
|
||||
room_info.chat_room_id.ptr = room_id;
|
||||
room_info.chat_room_id.length = room_id_len;
|
||||
room_info.chat_room_id.max_length = room_id_max_len;
|
||||
|
||||
|
||||
room_info.notice.ptr = *(wchar_t**)(chat_room_info + 0x18);
|
||||
room_info.notice.length = *(DWORD*)(chat_room_info + 0x1C);
|
||||
room_info.notice.max_length = *(DWORD*)(chat_room_info + 0x20);
|
||||
DWORD notice_len = *(DWORD*)(chat_room_info + 0x1C);
|
||||
DWORD notice_max_len = *(DWORD*)(chat_room_info + 0x20);
|
||||
wchar_t* notice_ptr = *(wchar_t**)(chat_room_info + 0x18);
|
||||
if(notice_len <= 0){
|
||||
room_info.notice.ptr = nullptr;
|
||||
}else{
|
||||
wchar_t * notice = new wchar_t[notice_len + 1];
|
||||
wmemcpy(notice,notice_ptr,notice_len+1);
|
||||
room_info.notice.ptr = notice;
|
||||
}
|
||||
room_info.notice.length = notice_len;
|
||||
room_info.notice.max_length = notice_max_len;
|
||||
|
||||
room_info.admin.ptr = *(wchar_t**)(chat_room_info + 0x2C);
|
||||
room_info.admin.length = *(DWORD*)(chat_room_info + 0x30);
|
||||
room_info.admin.max_length = *(DWORD*)(chat_room_info + 0x34);
|
||||
DWORD admin_len = *(DWORD*)(chat_room_info + 0x30);
|
||||
DWORD admin_max_len = *(DWORD*)(chat_room_info + 0x34);
|
||||
wchar_t* admin_ptr = *(wchar_t**)(chat_room_info + 0x2C);
|
||||
if(admin_len <= 0){
|
||||
room_info.admin.ptr = nullptr;
|
||||
}else{
|
||||
wchar_t * admin = new wchar_t[admin_len + 1];
|
||||
wmemcpy(admin,admin_ptr,admin_len+1);
|
||||
room_info.admin.ptr = admin;
|
||||
}
|
||||
room_info.admin.length = admin_len;
|
||||
room_info.admin.max_length = admin_max_len;
|
||||
|
||||
DWORD xml_len = *(DWORD*)(chat_room_info + 0x54);
|
||||
DWORD xml_max_len = *(DWORD*)(chat_room_info + 0x58);
|
||||
wchar_t* xml_ptr = *(wchar_t**)(chat_room_info + 0x50);
|
||||
if (xml_len <= 0){
|
||||
room_info.xml.ptr = nullptr;
|
||||
}else{
|
||||
wchar_t * xml = new wchar_t[xml_len + 1];
|
||||
wmemcpy(xml,xml_ptr,xml_len+1);
|
||||
room_info.xml.ptr = xml;
|
||||
}
|
||||
room_info.xml.length = xml_len;
|
||||
room_info.xml.max_length = xml_max_len;
|
||||
|
||||
room_info.xml.ptr = *(wchar_t**)(chat_room_info + 0x50);
|
||||
room_info.xml.length = *(DWORD*)(chat_room_info + 0x54);
|
||||
room_info.xml.max_length = *(DWORD*)(chat_room_info + 0x58);
|
||||
__asm {
|
||||
PUSHAD
|
||||
LEA ECX,chat_room_info
|
||||
@@ -143,8 +187,8 @@ int AddMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids,int len){
|
||||
|
||||
int GetMemberFromChatRoom(wchar_t* chat_room_id,ChatRoomInner & out){
|
||||
int success = 0;
|
||||
WeChatString chat_room(chat_room_id);
|
||||
DWORD chat_room_ptr = (DWORD) &chat_room;
|
||||
WeChatString chat_room(chat_room_id);
|
||||
DWORD chat_room_ptr = (DWORD) &chat_room;
|
||||
char buffer[0x1D4] = {0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_member_addr = base + WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET;
|
||||
@@ -217,4 +261,158 @@ int ModChatRoomMemberNickName(wchar_t* chat_room_id,wchar_t* wxid,wchar_t * nick
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int SetTopMsg(wchar_t* wxid,ULONG64 msg_id){
|
||||
int success = -1;
|
||||
char chat_msg[0x2C4] ={0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
|
||||
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
|
||||
DWORD handle_top_msg_addr = base + WX_TOP_MSG_OFFSET;
|
||||
// DWORD free_addr = base + WX_FREE_CHAT_MSG_OFFSET;
|
||||
DWORD free_addr = base + WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET;
|
||||
vector<string> local_msg = GetChatMsgByMsgId(msg_id);
|
||||
if(local_msg.empty()){
|
||||
return -2;
|
||||
}
|
||||
string type = local_msg[3];
|
||||
string status = local_msg[10];
|
||||
string talker = local_msg[13];
|
||||
string content = local_msg[14];
|
||||
wstring w_talker = String2Wstring(talker);
|
||||
wstring w_content = String2Wstring(content);
|
||||
int msg_type =stoi(type);
|
||||
int msg_status =stoi(status);
|
||||
|
||||
#ifdef _DEBUG
|
||||
wcout << "w_talker:" <<w_talker <<endl;
|
||||
wcout << "w_content:" <<w_content <<endl;
|
||||
#endif
|
||||
WeChatString chat_room(w_talker);
|
||||
WeChatString msg_content(w_content);
|
||||
|
||||
WeChatString user_id(wxid);
|
||||
|
||||
__asm{
|
||||
PUSHAD
|
||||
LEA ECX,chat_msg
|
||||
CALL new_chat_msg_addr
|
||||
POPAD
|
||||
}
|
||||
|
||||
memcpy(&chat_msg[0x30],&msg_id,sizeof(msg_id));
|
||||
memcpy(&chat_msg[0x38],&msg_type,sizeof(msg_type));
|
||||
memcpy(&chat_msg[0x40],&msg_status,sizeof(msg_status));
|
||||
memcpy(&chat_msg[0x48],&chat_room,sizeof(chat_room));
|
||||
|
||||
memcpy(&chat_msg[0x70],&msg_content,sizeof(msg_content));
|
||||
memcpy(&chat_msg[0x174],&user_id,sizeof(user_id));
|
||||
|
||||
|
||||
__asm{
|
||||
PUSHAD
|
||||
CALL get_chat_room_mgr_addr
|
||||
PUSH 0x0
|
||||
LEA EAX,chat_msg
|
||||
PUSH EAX
|
||||
CALL handle_top_msg_addr
|
||||
MOV success,EAX
|
||||
LEA ECX,chat_msg
|
||||
PUSH 0x0
|
||||
CALL free_addr
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int RemoveTopMsg(wchar_t* chat_room_id,ULONG64 msg_id){
|
||||
|
||||
int success = -1;
|
||||
WeChatString chat_room(chat_room_id);
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
|
||||
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
|
||||
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
|
||||
DWORD remove_top_msg_addr = base + WX_REMOVE_TOP_MSG_OFFSET;
|
||||
|
||||
__asm{
|
||||
PUSHAD
|
||||
CALL get_chat_room_mgr_addr
|
||||
MOV EDI,dword ptr [msg_id]
|
||||
LEA EAX,chat_room
|
||||
MOV ESI,dword ptr [msg_id + 0x4]
|
||||
SUB ESP,0x14
|
||||
MOV ECX,ESP
|
||||
PUSH EAX
|
||||
CALL init_chat_msg_addr
|
||||
PUSH ESI
|
||||
PUSH EDI
|
||||
CALL remove_top_msg_addr
|
||||
MOV success,EAX
|
||||
POPAD
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id,wchar_t* wxid){
|
||||
WeChatString chat_room(chat_room_id);
|
||||
WeChatString member_id(wxid);
|
||||
WeChatString nickname(NULL);
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
|
||||
DWORD get_nickname_addr = base + WX_GET_MEMBER_NICKNAME_OFFSET;
|
||||
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
|
||||
DWORD get_contact_addr = base + WX_GET_CONTACT_OFFSET;
|
||||
DWORD free_contact_addr = base + WX_FREE_CONTACT_OFFSET;
|
||||
__asm{
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
CALL get_chat_room_mgr_addr
|
||||
LEA ECX,nickname
|
||||
PUSH ECX
|
||||
LEA ECX,member_id
|
||||
PUSH ECX
|
||||
LEA ECX,chat_room
|
||||
PUSH ECX
|
||||
MOV ECX,EAX
|
||||
CALL get_nickname_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
wstring name = L"";
|
||||
if (nickname.ptr) {
|
||||
name += wstring(nickname.ptr);
|
||||
}else {
|
||||
char buff[0x440] = {0};
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
CALL contact_mgr_addr
|
||||
LEA ECX,buff
|
||||
PUSH ECX
|
||||
LEA ECX,member_id
|
||||
PUSH ECX
|
||||
MOV ECX,EAX
|
||||
CALL get_contact_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
name += READ_WSTRING(buff, 0x6C);
|
||||
|
||||
__asm{
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
LEA ECX,buff
|
||||
CALL free_contact_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@@ -8,4 +8,9 @@ int AddMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids,int len);
|
||||
|
||||
int GetMemberFromChatRoom(wchar_t* chat_room_id,ChatRoomInner & out);
|
||||
int ModChatRoomMemberNickName(wchar_t* chat_room_id,wchar_t* wxid,wchar_t * nick);
|
||||
|
||||
int SetTopMsg(wchar_t* wxid,ULONG64 msg_id);
|
||||
int RemoveTopMsg(wchar_t* chat_room_id,ULONG64 msg_id);
|
||||
|
||||
std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id,wchar_t* wxid);
|
||||
#endif
|
||||
+9
-2
@@ -25,7 +25,7 @@ wstring utf8_to_unicode(const char *buffer) {
|
||||
/// @param wstr unicode
|
||||
/// @return string utf8
|
||||
string unicode_to_utf8(wchar_t *wstr) {
|
||||
int c_size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, FALSE);
|
||||
int c_size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, FALSE);
|
||||
if (c_size > 0) {
|
||||
char *buffer = new char[c_size + 1];
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, buffer, c_size, NULL, FALSE);
|
||||
@@ -126,7 +126,7 @@ string Wstring2String(wstring wstr) {
|
||||
BOOL FindOrCreateDirectoryW(const wchar_t *path) {
|
||||
WIN32_FIND_DATAW fd;
|
||||
HANDLE hFind = ::FindFirstFileW(path, &fd);
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
if (hFind != INVALID_HANDLE_VALUE && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
FindClose(hFind);
|
||||
return true;
|
||||
}
|
||||
@@ -135,4 +135,11 @@ BOOL FindOrCreateDirectoryW(const wchar_t *path) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloseConsole(){
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
FreeConsole();
|
||||
}
|
||||
+8
-8
@@ -1,18 +1,17 @@
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
#include <string>
|
||||
using namespace std;
|
||||
#define READ_WSTRING(addr, offset) ((*(DWORD *)(addr + offset + 0x4) == 0) ? wstring(L"") : wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)))
|
||||
#define READ_WSTRING(addr, offset) ((*(DWORD *)(addr + offset + 0x4) == 0) ? std::wstring(L"") : std::wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)))
|
||||
|
||||
/// @brief utf8 转换成unicode
|
||||
/// @param buffer utf8
|
||||
/// @return unicode
|
||||
wstring utf8_to_unicode(const char *buffer);
|
||||
std::wstring utf8_to_unicode(const char *buffer);
|
||||
|
||||
/// @brief unicode转换utf8
|
||||
/// @param wstr unicode
|
||||
/// @return utf8
|
||||
string unicode_to_utf8(wchar_t *wstr);
|
||||
std::string unicode_to_utf8(wchar_t *wstr);
|
||||
|
||||
/// @brief 获取WeChatWin.dll基址
|
||||
/// @return 基址
|
||||
@@ -35,7 +34,7 @@ void UnHookAnyAddress(DWORD hook_addr, char *origin);
|
||||
/// @brief get timeW
|
||||
/// @param timestamp timestamp
|
||||
/// @return str
|
||||
wstring GetTimeW(long long timestamp);
|
||||
std::wstring GetTimeW(long long timestamp);
|
||||
/// @brief unicode trans utf8
|
||||
/// @param str unicode str
|
||||
/// @return utf8 str
|
||||
@@ -43,20 +42,21 @@ std::string UnicodeToUtf8(const wchar_t *str);
|
||||
/// @brief string convert wstring
|
||||
/// @param str
|
||||
/// @return
|
||||
wstring String2Wstring(string str);
|
||||
std::wstring String2Wstring(std::string str);
|
||||
/// @brief wstring convert string
|
||||
/// @param str
|
||||
/// @return
|
||||
string Wstring2String(wstring wstr);
|
||||
std::string Wstring2String(std::wstring wstr);
|
||||
|
||||
/// @brief create dir
|
||||
/// @param path
|
||||
/// @return
|
||||
BOOL FindOrCreateDirectoryW(const wchar_t *path);
|
||||
|
||||
void CloseConsole();
|
||||
|
||||
template <typename T1, typename T2>
|
||||
vector<T1> split(T1 str, T2 letter) {
|
||||
std::vector<T1> split(T1 str, T2 letter) {
|
||||
vector<T1> arr;
|
||||
size_t pos;
|
||||
while ((pos = str.find_first_of(letter)) != T1::npos) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "pch.h"
|
||||
#include "confirm_receipt.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_NEW_WCPAYINFO_OFFSET 0x756340
|
||||
#define WX_FREE_WCPAYINFO_OFFSET 0x73c170
|
||||
#define WX_CONFIRM_RECEIPT_OFFSET 0x15287a0
|
||||
|
||||
int DoConfirmReceipt(wchar_t *wxid, wchar_t *transcationid,
|
||||
wchar_t *transferid) {
|
||||
int success = -1;
|
||||
WeChatString recv_id(wxid);
|
||||
WeChatString transcation_id(transcationid);
|
||||
WeChatString transfer_id(transferid);
|
||||
char pay_info[0x134] = {0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD new_pay_info_addr = base + WX_NEW_WCPAYINFO_OFFSET;
|
||||
DWORD free_pay_info_addr = base + WX_FREE_WCPAYINFO_OFFSET;
|
||||
DWORD do_confirm_addr = base + WX_CONFIRM_RECEIPT_OFFSET;
|
||||
__asm {
|
||||
PUSHAD
|
||||
LEA ECX,pay_info
|
||||
CALL new_pay_info_addr
|
||||
MOV dword ptr [pay_info + 0x4], 0x1
|
||||
MOV dword ptr [pay_info + 0x4C], 0x1
|
||||
POPAD
|
||||
}
|
||||
memcpy(&pay_info[0x1c], &transcation_id, sizeof(transcation_id));
|
||||
memcpy(&pay_info[0x38], &transfer_id, sizeof(transfer_id));
|
||||
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSH 0x1
|
||||
SUB ESP,0x8
|
||||
LEA EDX,recv_id
|
||||
LEA ECX,pay_info
|
||||
CALL do_confirm_addr
|
||||
MOV success,EAX
|
||||
ADD ESP,0xC
|
||||
PUSH 0x0
|
||||
LEA ECX,pay_info
|
||||
CALL free_pay_info_addr
|
||||
POPAD
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef CONFIRM_RECEIPT_H
|
||||
#define CONFIRM_RECEIPT_H
|
||||
|
||||
int DoConfirmReceipt(wchar_t* wxid,wchar_t *transcationid, wchar_t *transferid);
|
||||
|
||||
#endif
|
||||
+114
-24
@@ -3,12 +3,18 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
using namespace std;
|
||||
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x6f8990
|
||||
#define WX_CONTACT_GET_LIST_OFFSET 0xb97550
|
||||
#define WX_CONTACT_DEL_OFFSET 0xb9b3b0
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
|
||||
#define WX_SYNC_MGR_OFFSET 0xa87fd0
|
||||
#define WX_SET_VALUE_OFFSET 0x1f80900
|
||||
#define WX_DO_DEL_CONTACT_OFFSET 0xca6480
|
||||
#define WX_FREE_CONTACT_OFFSET 0xe23690
|
||||
#define WX_GET_CONTACT_OFFSET 0xb93b20
|
||||
#define WX_DO_VERIFY_USER_OFFSET 0xB91160
|
||||
|
||||
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x64dc30
|
||||
#define WX_CONTACT_GET_LIST_OFFSET 0xa9b000
|
||||
#define WX_CONTACT_DEL_OFFSET 0xa9ef40
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
|
||||
#define WX_DB_QUERY_OFFSET 0xa9ec40
|
||||
int GetAllContact(vector<Contact> &vec) {
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_instance = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
|
||||
@@ -66,37 +72,121 @@ int GetAllContact(vector<Contact> &vec) {
|
||||
}
|
||||
return success;
|
||||
}
|
||||
// todo
|
||||
// note maybe not delete
|
||||
int DelContact(wchar_t *wxid) {
|
||||
int success = 0;
|
||||
int success = -1;
|
||||
WeChatString user_id(wxid);
|
||||
DWORD id_ptr = (DWORD) &user_id;
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_instance_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
|
||||
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
|
||||
DWORD del_addr = base + WX_CONTACT_DEL_OFFSET;
|
||||
DWORD db_op_addr = base + WX_DB_QUERY_OFFSET;
|
||||
DWORD sync_mgr_addr = base + WX_SYNC_MGR_OFFSET;
|
||||
DWORD set_id_addr = base + WX_SET_VALUE_OFFSET;
|
||||
DWORD del_contact_addr = base + WX_DO_DEL_CONTACT_OFFSET;
|
||||
int len = user_id.length;
|
||||
|
||||
string id_cstr = unicode_to_utf8(wxid);
|
||||
char id_[0x20]={0};
|
||||
memcpy(id_,id_cstr.c_str(),id_cstr.size()+1);
|
||||
char buff[0x10]={0};
|
||||
__asm{
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
CALL get_instance_addr
|
||||
MOV ECX,dword ptr[id_ptr]
|
||||
PUSH ECX
|
||||
CALL sync_mgr_addr
|
||||
MOV ECX,EAX
|
||||
MOV ESI,EAX
|
||||
CALL db_op_addr
|
||||
SUB ESP,0x14
|
||||
MOV EAX,dword ptr[id_ptr]
|
||||
MOV ECX,ESP
|
||||
PUSH EAX
|
||||
CALL init_chat_msg_addr
|
||||
MOV ECX,ESI
|
||||
CALL del_addr
|
||||
MOV success,EAX
|
||||
LEA EAX,buff
|
||||
MOV [ECX + 4],EAX
|
||||
LEA EAX,id_
|
||||
Mov dword ptr[buff +0x4],EAX
|
||||
CALL del_contact_addr
|
||||
MOV success,EAX
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
std::wstring GetContactOrChatRoomNickname(wchar_t *id) {
|
||||
int success = -1;
|
||||
char buff[0x440] = {0};
|
||||
WeChatString pri(id);
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
|
||||
DWORD get_contact_addr = base + WX_GET_CONTACT_OFFSET;
|
||||
DWORD free_contact_addr = base + WX_FREE_CONTACT_OFFSET;
|
||||
wstring name = L"";
|
||||
__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
|
||||
}
|
||||
name += READ_WSTRING(buff, 0x6C);
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
LEA ECX,buff
|
||||
CALL free_contact_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
int AddFriendByWxid(wchar_t *wxid){
|
||||
int success = -1;
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
|
||||
DWORD set_group_addr = base + 0x746E20;
|
||||
DWORD fn2_addr = base + 0x285D968;
|
||||
DWORD fn3_addr = base + 0x6F6050;
|
||||
DWORD fn4_addr = base + 0xED3BE0;
|
||||
DWORD do_verify_user_addr = base + WX_DO_VERIFY_USER_OFFSET;
|
||||
|
||||
DWORD instance =0;
|
||||
WeChatString chat_room(NULL);
|
||||
WeChatString user_id(wxid);
|
||||
__asm{
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
CALL contact_mgr_addr
|
||||
SUB ESP,0x18
|
||||
MOV dword ptr [instance],EAX
|
||||
MOV ECX,ESP
|
||||
PUSH ECX
|
||||
LEA ECX,chat_room
|
||||
CALL set_group_addr
|
||||
MOV EAX,fn2_addr
|
||||
SUB ESP,0x18
|
||||
MOV ECX,ESP
|
||||
PUSH EAX
|
||||
CALL fn3_addr
|
||||
PUSH 0x0
|
||||
PUSH 0XE
|
||||
SUB ESP,0x14
|
||||
MOV ESI,ESP
|
||||
MOV dword ptr [ESI],0x0
|
||||
MOV dword ptr [ESI+0x4],0x0
|
||||
MOV dword ptr [ESI+0x8],0x0
|
||||
MOV dword ptr [ESI+0xC],0x0
|
||||
MOV dword ptr [ESI+0x10],0x0
|
||||
PUSH 0x1
|
||||
SUB ESP,0x14
|
||||
MOV ECX,ESP
|
||||
LEA EAX,user_id
|
||||
PUSH EAX
|
||||
CALL fn4_addr
|
||||
MOV ECX,dword ptr [instance]
|
||||
CALL do_verify_user_addr
|
||||
MOV success,EAX
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
+5
-1
@@ -3,9 +3,13 @@
|
||||
#include <vector>
|
||||
#include "wechat_data.h"
|
||||
|
||||
int GetAllContact(vector<Contact> &vec);
|
||||
int GetAllContact(std::vector<Contact> &vec);
|
||||
|
||||
|
||||
|
||||
int DelContact(wchar_t* wxid);
|
||||
|
||||
std::wstring GetContactOrChatRoomNickname(wchar_t* id);
|
||||
|
||||
int AddFriendByWxid(wchar_t *wxid);
|
||||
#endif
|
||||
+9
-4
@@ -4,7 +4,7 @@
|
||||
#include "base64.h"
|
||||
#include "common.h"
|
||||
#include "new_sqlite3.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// @brief free data
|
||||
void FreeResult(vector<vector<SqlResult>> &data) {
|
||||
@@ -15,11 +15,11 @@ void FreeResult(vector<vector<SqlResult>> &data) {
|
||||
for (unsigned j = 0; j < data[i].size(); j++) {
|
||||
SqlResult *sr = (SqlResult *)&data[i][j];
|
||||
if (sr->column_name) {
|
||||
delete sr->column_name;
|
||||
delete[] sr->column_name;
|
||||
sr->column_name = NULL;
|
||||
}
|
||||
if (sr->content) {
|
||||
delete sr->content;
|
||||
delete[] sr->content;
|
||||
sr->content = NULL;
|
||||
}
|
||||
}
|
||||
@@ -97,10 +97,15 @@ int Select(DWORD db_hanle, const char *sql,
|
||||
if (status == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(data.size() == 0){
|
||||
return 1;
|
||||
}
|
||||
vector<string> index;
|
||||
for (size_t i = 0; i < data[0].size(); i++)
|
||||
for (size_t i = 0; i < data[0].size(); i++){
|
||||
index.push_back(data[0][i].column_name);
|
||||
}
|
||||
query_result.push_back(index);
|
||||
|
||||
for (auto it : data) {
|
||||
vector<string> item;
|
||||
for (size_t i = 0; i < it.size(); i++) {
|
||||
|
||||
+1
-2
@@ -2,7 +2,6 @@
|
||||
#define DB_OPERATION_H_
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
struct SqlResult {
|
||||
char *column_name;
|
||||
DWORD column_name_len;
|
||||
@@ -18,6 +17,6 @@ struct SqlResult {
|
||||
/// @return
|
||||
int ExecuteSQL(DWORD db, const char *sql, DWORD callback, void *data);
|
||||
|
||||
int Select(DWORD db_hanle, const char *sql,vector<vector<string>> &query_result);
|
||||
int Select(DWORD db_hanle, const char *sql,std::vector<std::vector<std::string>> &query_result);
|
||||
|
||||
#endif
|
||||
+3
-1
@@ -6,7 +6,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved) {
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH: {
|
||||
http_start(19088);
|
||||
// http_start(19088);
|
||||
break;
|
||||
}
|
||||
case DLL_THREAD_ATTACH: {
|
||||
@@ -16,6 +16,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH: {
|
||||
CloseConsole();
|
||||
http_close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
#include "pch.h"
|
||||
#include "download.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "get_db_handle.h"
|
||||
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_NEW_CHAT_MSG_OFFSET 0x70e2a0
|
||||
#define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x7ae310
|
||||
#define WX_PUSH_ATTACH_TASK_OFFSET 0x7c94a0
|
||||
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x6f5370
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
|
||||
#define WX_CHAT_MGR_OFFSET 0x732660
|
||||
#define WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET 0xb54950
|
||||
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc11140
|
||||
#define WX_APP_MSG_INFO_OFFSET 0x7571d0
|
||||
#define WX_GET_APP_MSG_XML_OFFSET 0xddef80
|
||||
#define WX_FREE_APP_MSG_INFO_OFFSET 0x73d820
|
||||
#define WX_PUSH_THUMB_TASK_OFFSET 0x7c93a0
|
||||
#define WX_VIDEO_MGR_OFFSET 0x7c7300
|
||||
#define WX_DOWNLOAD_VIDEO_IMG_OFFSET 0xcc6d80
|
||||
|
||||
using namespace std;
|
||||
|
||||
int DoDownloadTask(ULONG64 msg_id) {
|
||||
int success = -1;
|
||||
int db_index = 0;
|
||||
int local_id = GetLocalIdByMsgId(msg_id, db_index);
|
||||
if (local_id < 1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
char chat_msg[0x2C4] = {0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
|
||||
DWORD get_chat_mgr_addr = base + WX_CHAT_MGR_OFFSET;
|
||||
DWORD pre_download_mgr_addr = base + WX_GET_PRE_DOWNLOAD_MGR_OFFSET;
|
||||
DWORD push_attach_task_addr = base + WX_PUSH_ATTACH_TASK_OFFSET;
|
||||
DWORD free_addr = base + WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET;
|
||||
DWORD get_by_local_Id_addr = base + WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET;
|
||||
DWORD get_current_data_path_addr = base + WX_GET_CURRENT_DATA_PATH_OFFSET;
|
||||
DWORD free_app_msg_info_addr = base + WX_FREE_APP_MSG_INFO_OFFSET;
|
||||
DWORD push_thumb_task_addr = base + WX_PUSH_THUMB_TASK_OFFSET;
|
||||
DWORD video_mgr_addr = base + WX_VIDEO_MGR_OFFSET;
|
||||
DWORD download_video_image_addr = base + WX_VIDEO_MGR_OFFSET;
|
||||
|
||||
WeChatString current_data_path;
|
||||
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
LEA ECX,current_data_path
|
||||
CALL get_current_data_path_addr
|
||||
|
||||
LEA ECX,chat_msg
|
||||
CALL new_chat_msg_addr
|
||||
|
||||
CALL get_chat_mgr_addr
|
||||
PUSH dword ptr [db_index]
|
||||
LEA ECX,chat_msg
|
||||
PUSH dword ptr [local_id]
|
||||
CALL get_by_local_Id_addr
|
||||
ADD ESP,0x8
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
wstring save_path = L"";
|
||||
wstring thumb_path = L"";
|
||||
if (current_data_path.length > 0) {
|
||||
save_path += current_data_path.ptr;
|
||||
save_path += L"wxhelper";
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FindOrCreateDirectoryW(save_path.c_str())) {
|
||||
return -3;
|
||||
}
|
||||
DWORD type = *(DWORD *)(chat_msg + 0x38);
|
||||
wchar_t *content = *(wchar_t **)(chat_msg + 0x70);
|
||||
|
||||
switch (type) {
|
||||
case 0x3: {
|
||||
save_path += L"\\image";
|
||||
if (!FindOrCreateDirectoryW(save_path.c_str())) {
|
||||
return -3;
|
||||
}
|
||||
save_path = save_path +L"\\"+ to_wstring(msg_id) + L".png";
|
||||
break;
|
||||
}
|
||||
case 0x3E:
|
||||
case 0x2B: {
|
||||
save_path += L"\\video";
|
||||
if (!FindOrCreateDirectoryW(save_path.c_str())) {
|
||||
return -3;
|
||||
}
|
||||
thumb_path = save_path + L"\\"+ to_wstring(msg_id) + L".jpg";
|
||||
save_path = save_path + L"\\"+ to_wstring(msg_id) + L".mp4";
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x31: {
|
||||
save_path += L"\\file";
|
||||
wcout << save_path << endl;
|
||||
if (!FindOrCreateDirectoryW(save_path.c_str())) {
|
||||
return -3;
|
||||
}
|
||||
char xml_app_msg[0xC80] = {0};
|
||||
DWORD new_app_msg_addr = base + WX_APP_MSG_INFO_OFFSET;
|
||||
DWORD get_xml_addr = base + WX_GET_APP_MSG_XML_OFFSET;
|
||||
WeChatString w_content(content);
|
||||
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
LEA ECX,xml_app_msg
|
||||
CALL new_app_msg_addr
|
||||
PUSH 0x1
|
||||
LEA EAX,w_content
|
||||
PUSH EAX
|
||||
LEA ECX,xml_app_msg
|
||||
CALL get_xml_addr
|
||||
MOV success,EAX
|
||||
LEA ECX,xml_app_msg
|
||||
CALL free_app_msg_info_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
if (success != 1) {
|
||||
return -4;
|
||||
}
|
||||
WeChatString *file_name = (WeChatString *)((DWORD)xml_app_msg + 0x44);
|
||||
save_path = save_path +L"\\" + to_wstring(msg_id) + L"_" +
|
||||
wstring(file_name->ptr, file_name->length);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
WeChatString w_save_path(save_path);
|
||||
WeChatString w_thumb_path(thumb_path);
|
||||
int temp =1;
|
||||
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[0x290], &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 {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
CALL pre_download_mgr_addr
|
||||
PUSH 0x1
|
||||
PUSH 0x0
|
||||
LEA ECX,chat_msg
|
||||
PUSH ECX
|
||||
MOV ECX,EAX
|
||||
CALL push_attach_task_addr
|
||||
MOV success,EAX
|
||||
LEA ECX,chat_msg
|
||||
PUSH 0x0
|
||||
CALL free_addr
|
||||
POPFD
|
||||
POPAD
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#ifndef DOWNLOAD_H_
|
||||
#define DOWNLOAD_H_
|
||||
|
||||
int DoDownloadTask(ULONG64 msg_id);
|
||||
#endif
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
#include "common.h"
|
||||
#include "get_db_handle.h"
|
||||
#include "wechat_data.h"
|
||||
#define WX_FORWARD_MSG_OFFSET 0xb6a4e0
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
|
||||
#define WX_FORWARD_MSG_OFFSET 0xc715f0
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
|
||||
|
||||
int ForwardMsg(wchar_t *wxid, unsigned long long msgid) {
|
||||
int success = 0;
|
||||
|
||||
+25
-6
@@ -5,7 +5,7 @@
|
||||
#include "new_sqlite3.h"
|
||||
#include "pch.h"
|
||||
#include "wechat_data.h"
|
||||
#define CONTACT_G_PINSTANCE 0x2c42e78
|
||||
#define CONTACT_G_PINSTANCE_OFFSET 0x2e2d628
|
||||
#define DB_MICRO_MSG_OFFSET 0x68
|
||||
#define DB_CHAT_MSG_OFFSET 0x1C0
|
||||
#define DB_MISC_OFFSET 0x3D8
|
||||
@@ -15,10 +15,10 @@
|
||||
#define DB_FUNCTION_MSG_OFFSET 0x11B0
|
||||
#define DB_NAME_OFFSET 0x14
|
||||
|
||||
#define PUBLIC_MSG_MGR_OFFSET 0x2c7ec88
|
||||
#define MULTI_DB_MSG_MGR_OFFSET 0x2c807d0
|
||||
#define FAVORITE_STORAGE_MGR_OFFSET 0x2c801f8
|
||||
#define FTS_FAVORITE_MGR_OFFSET 0x2c439b8
|
||||
#define PUBLIC_MSG_MGR_OFFSET 0x2e6ce20
|
||||
#define MULTI_DB_MSG_MGR_OFFSET 0x2e6ec84
|
||||
#define FAVORITE_STORAGE_MGR_OFFSET 0x2e6e630
|
||||
#define FTS_FAVORITE_MGR_OFFSET 0x2e2e168
|
||||
|
||||
using namespace std;
|
||||
map<wstring, DatabaseInfo> dbmap;
|
||||
@@ -64,7 +64,7 @@ std::vector<void *> GetDbHandles() {
|
||||
dbs.clear();
|
||||
dbmap.clear();
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD p_contact_addr = *(DWORD *)(base + CONTACT_G_PINSTANCE);
|
||||
DWORD p_contact_addr = *(DWORD *)(base + CONTACT_G_PINSTANCE_OFFSET);
|
||||
DWORD micro_msg_db_addr = *(DWORD *)(p_contact_addr + DB_MICRO_MSG_OFFSET);
|
||||
DWORD chat_msg_db_addr = *(DWORD *)(p_contact_addr + DB_CHAT_MSG_OFFSET);
|
||||
DWORD misc_db_addr = *(DWORD *)(p_contact_addr + DB_MISC_OFFSET);
|
||||
@@ -296,4 +296,23 @@ unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex) {
|
||||
return stoi(result[1][0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
vector<string> GetChatMsgByMsgId(ULONG64 msgid){
|
||||
char sql[260] = {0};
|
||||
sprintf_s(sql, "select localId,TalkerId,MsgSvrID,Type,SubType,IsSender,CreateTime,Sequence,StatusEx,FlagEx,Status,MsgServerSeq,MsgSequence,StrTalker,StrContent,BytesExtra from MSG where MsgSvrID=%llu;", msgid);
|
||||
wchar_t dbname[20] = {0};
|
||||
for (int i = 0;; i++) {
|
||||
swprintf_s(dbname, L"MSG%d.db", i);
|
||||
DWORD handle = GetDbHandleByDbName(dbname);
|
||||
if (handle == 0) return {};
|
||||
vector<vector<string>> result;
|
||||
int ret = Select(handle, (const char *)sql, result);
|
||||
#ifdef _DEBUG
|
||||
cout <<" size =" <<result.size()<<endl;
|
||||
#endif
|
||||
if (result.size() == 0) continue;
|
||||
return result[1];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -2,8 +2,10 @@
|
||||
#define GET_DB_HANDLE_H_
|
||||
#include "windows.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
std::vector<void *> GetDbHandles();
|
||||
DWORD GetDbHandleByDbName(wchar_t *dbname);
|
||||
unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex);
|
||||
std::vector<std::string> GetChatMsgByMsgId(ULONG64 msgid);
|
||||
#endif
|
||||
+4
-4
@@ -2,13 +2,13 @@
|
||||
#include "hook_img.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// #define WX_HOOK_IMG_OFFSET 0xd7eaa5
|
||||
// #define WX_HOOK_IMG_NEXT_OFFSET 0xda56e0
|
||||
#define WX_HOOK_IMG_OFFSET 0xc672cc
|
||||
#define WX_HOOK_IMG_NEXT_OFFSET 0xd82370
|
||||
#define WX_SELF_ID_OFFSET 0x2C42A38
|
||||
#define WX_HOOK_IMG_OFFSET 0xd723dc
|
||||
#define WX_HOOK_IMG_NEXT_OFFSET 0xe91d90
|
||||
#define WX_SELF_ID_OFFSET 0x2E2CD3C
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#define JPEG0 0xFF
|
||||
|
||||
+1
-2
@@ -1,9 +1,8 @@
|
||||
#ifndef HOOK_IMG_H_
|
||||
#define HOOK_IMG_H_
|
||||
#include "windows.h"
|
||||
using namespace std;
|
||||
|
||||
int HookImg(wstring save_path);
|
||||
int HookImg(std::wstring save_path);
|
||||
int UnHookImg();
|
||||
|
||||
int GetImgByName(wchar_t* file_path,wchar_t* save_dir);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "pch.h"
|
||||
#include "hook_log.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define WX_HOOK_LOG_OFFSET 0xed1675
|
||||
#define WX_HOOK_LOG_NEXT_OFFSET 0x2344832
|
||||
|
||||
static int kLogHooked = FALSE;
|
||||
static DWORD kWeChatWinBase = GetWeChatWinBase();
|
||||
static char kOriginLogAsmCode[5] = {0};
|
||||
|
||||
static DWORD kHookLogAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
|
||||
static DWORD kHookLogNextAddress = kWeChatWinBase + WX_HOOK_LOG_NEXT_OFFSET;
|
||||
static DWORD kHookLogJmpBackAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET + 0x5;
|
||||
|
||||
void log_print(DWORD addr) {
|
||||
if (!addr) {
|
||||
return;
|
||||
}
|
||||
DWORD dwId = 0;
|
||||
char *msg = (char *)addr;
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, msg, -1, 0, 0);
|
||||
wchar_t *w_msg = new wchar_t[size + 1];
|
||||
memset(w_msg, 0, (size + 1) * 2);
|
||||
MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, size);
|
||||
size = WideCharToMultiByte(CP_ACP, 0, w_msg, -1, 0, 0, 0, 0);
|
||||
char *ansi_message = new char[size + 1];
|
||||
memset(ansi_message, 0, size + 1);
|
||||
WideCharToMultiByte(CP_ACP, 0, w_msg, -1, ansi_message, size, 0, 0);
|
||||
delete[] w_msg;
|
||||
w_msg = NULL;
|
||||
cout << ansi_message;
|
||||
delete[] ansi_message;
|
||||
ansi_message = NULL;
|
||||
}
|
||||
|
||||
_declspec(naked) void handle_log() {
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
PUSH EAX
|
||||
CALL log_print
|
||||
ADD ESP, 0x4
|
||||
POPFD
|
||||
POPAD
|
||||
CALL kHookLogNextAddress
|
||||
JMP kHookLogJmpBackAddress
|
||||
}
|
||||
}
|
||||
|
||||
int HookLog() {
|
||||
kWeChatWinBase = GetWeChatWinBase();
|
||||
if (!kWeChatWinBase) {
|
||||
return -1;
|
||||
}
|
||||
if (kLogHooked) {
|
||||
return 2;
|
||||
}
|
||||
kHookLogAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
|
||||
kHookLogNextAddress = kWeChatWinBase + WX_HOOK_LOG_NEXT_OFFSET;
|
||||
kHookLogJmpBackAddress = kHookLogAddress + 0x5;
|
||||
HookAnyAddress(kHookLogAddress, (LPVOID)handle_log, kOriginLogAsmCode);
|
||||
kLogHooked = TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UnHookLog() {
|
||||
if (!kLogHooked) {
|
||||
return 1;
|
||||
}
|
||||
DWORD hook_img_addr = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
|
||||
UnHookAnyAddress(hook_img_addr, kOriginLogAsmCode);
|
||||
kLogHooked = FALSE;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef HOOK_LOG_H_
|
||||
#define HOOK_LOG_H_
|
||||
#include "windows.h"
|
||||
|
||||
int HookLog();
|
||||
int UnHookLog();
|
||||
|
||||
#endif
|
||||
+89
-8
@@ -10,8 +10,10 @@
|
||||
using namespace nlohmann;
|
||||
|
||||
using namespace std;
|
||||
#define WX_RECV_MSG_HOOK_OFFSET 0xb97126
|
||||
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x6fc850
|
||||
#define WX_RECV_MSG_HOOK_OFFSET 0xca0284
|
||||
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x7d5030
|
||||
#define WX_SNS_HOOK_OFFSET 0x143ef09
|
||||
#define WX_SNS_HOOK_NEXT_OFFSET 0x143f1b0
|
||||
|
||||
// SyncMgr::addMsgListToDB
|
||||
// #define WX_RECV_MSG_HOOK_OFFSET 0xB9C919
|
||||
@@ -20,6 +22,7 @@ using namespace std;
|
||||
#define CLIENT_IP "127.0.0.1"
|
||||
static int kServerPort = 0;
|
||||
static int kMessageHooked = FALSE;
|
||||
static char kServerIp[16]= "127.0.0.1";
|
||||
static DWORD kWeChatWinBase = GetWeChatWinBase();
|
||||
|
||||
static char kOriginReceMsgAsmCode[5] = {0};
|
||||
@@ -28,6 +31,13 @@ static DWORD kReceMsgJmpBackAddress =
|
||||
static DWORD kReceMsgNextAddress =
|
||||
kWeChatWinBase + WX_RECV_MSG_HOOK_NEXT_OFFSET;
|
||||
|
||||
|
||||
static char kOriginSnsMsgAsmCode[5] = {0};
|
||||
static DWORD kSnsMsgJmpBackAddress =
|
||||
kWeChatWinBase + WX_SNS_HOOK_OFFSET + 0x5;
|
||||
static DWORD kSnsMsgNextAddress =
|
||||
kWeChatWinBase + WX_SNS_HOOK_NEXT_OFFSET;
|
||||
|
||||
struct InnerMessageStruct {
|
||||
char *buffer;
|
||||
int length;
|
||||
@@ -59,10 +69,12 @@ BOOL SendBySocket(const char *buffer, size_t len) {
|
||||
memset(&client_addr, 0, sizeof(client_addr));
|
||||
client_addr.sin_family = AF_INET;
|
||||
client_addr.sin_port = htons((u_short)kServerPort);
|
||||
InetPtonA(AF_INET, CLIENT_IP, &client_addr.sin_addr.s_addr);
|
||||
InetPtonA(AF_INET, kServerIp, &client_addr.sin_addr.s_addr);
|
||||
if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr),
|
||||
sizeof(sockaddr)) < 0) {
|
||||
#ifdef _DEBUG
|
||||
cout << "kServerIp:" << kServerIp <<endl;
|
||||
cout << "port:" << kServerPort <<endl;
|
||||
cout << "connect error,"
|
||||
<< " errno:" << errno << endl;
|
||||
#endif
|
||||
@@ -109,7 +121,7 @@ void SendSocketMessage(InnerMessageStruct *msg) {
|
||||
}
|
||||
/// @brief msg handle
|
||||
/// @param msg_addr msg address in memory
|
||||
void OnRecvMsg(DWORD msg_addr) {
|
||||
void __cdecl OnRecvMsg(DWORD msg_addr) {
|
||||
json j_msg;
|
||||
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
|
||||
j_msg["msgId"] = msgid;
|
||||
@@ -135,9 +147,6 @@ void OnRecvMsg(DWORD msg_addr) {
|
||||
if (content_len > 0) {
|
||||
j_msg["content"] =
|
||||
unicode_to_utf8((wchar_t *)READ_WSTRING(msg_addr, 0x70).c_str());
|
||||
#ifdef _DEBUG
|
||||
printf("%s", j_msg["content"].get<std::string>().c_str());
|
||||
#endif
|
||||
}
|
||||
int sign_len = *(DWORD *)(msg_addr + 0x18C);
|
||||
if (sign_len > 0) {
|
||||
@@ -172,6 +181,50 @@ void OnRecvMsg(DWORD msg_addr) {
|
||||
CloseHandle(thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void __cdecl OnSnsTimeLineMsg(DWORD msg_addr) {
|
||||
json j_sns;
|
||||
DWORD begin_addr = *(DWORD *)(msg_addr + 0x20);
|
||||
DWORD end_addr = *(DWORD *)(msg_addr + 0x24);
|
||||
#ifdef _DEBUG
|
||||
cout << "begin" <<begin_addr<<endl;
|
||||
cout << "end" <<end_addr<<endl;
|
||||
#endif
|
||||
if (begin_addr == 0) {
|
||||
j_sns = {{"data", json::array()}};
|
||||
} else {
|
||||
while (begin_addr < end_addr) {
|
||||
json j_item;
|
||||
j_item["snsId"] = *(unsigned long long *)(begin_addr);
|
||||
j_item["createTime"] = *(DWORD *)(begin_addr + 0x2C);
|
||||
|
||||
j_item["senderId"] =
|
||||
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x18).c_str());
|
||||
|
||||
j_item["content"] =
|
||||
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x3c).c_str());
|
||||
|
||||
j_item["xml"] =
|
||||
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x384).c_str());
|
||||
|
||||
j_sns["data"].push_back(j_item);
|
||||
begin_addr += 0xB48;
|
||||
}
|
||||
}
|
||||
string jstr = j_sns.dump() + '\n';
|
||||
InnerMessageStruct *inner_msg = new InnerMessageStruct;
|
||||
inner_msg->buffer = new char[jstr.size() + 1];
|
||||
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
|
||||
inner_msg->length = jstr.size();
|
||||
HANDLE thread = CreateThread(
|
||||
NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, inner_msg, NULL, 0);
|
||||
if (thread) {
|
||||
CloseHandle(thread);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief hook implement
|
||||
_declspec(naked) void handle_sync_msg() {
|
||||
__asm {
|
||||
@@ -187,11 +240,29 @@ _declspec(naked) void handle_sync_msg() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief hook sns msg implement
|
||||
_declspec(naked) void handle_sns_msg() {
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
PUSH [ESP + 0x24]
|
||||
CALL OnSnsTimeLineMsg
|
||||
ADD ESP, 0x4
|
||||
POPFD
|
||||
POPAD
|
||||
CALL kSnsMsgNextAddress
|
||||
JMP kSnsMsgJmpBackAddress
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief hook any address address+0x5
|
||||
/// @param port 端口
|
||||
/// @return 成功返回1,已经hook返回2,失败返回-1
|
||||
int HookRecvMsg(int port) {
|
||||
int HookRecvMsg(char* client_ip,int port) {
|
||||
kServerPort = port;
|
||||
strcpy_s(kServerIp,client_ip);
|
||||
kWeChatWinBase = GetWeChatWinBase();
|
||||
if (!kWeChatWinBase) {
|
||||
return -1;
|
||||
@@ -206,6 +277,14 @@ int HookRecvMsg(int port) {
|
||||
kReceMsgJmpBackAddress = hook_recv_msg_addr + 0x5;
|
||||
HookAnyAddress(hook_recv_msg_addr, (LPVOID)handle_sync_msg,
|
||||
kOriginReceMsgAsmCode);
|
||||
|
||||
DWORD hook_sns_msg_addr = kWeChatWinBase + WX_SNS_HOOK_OFFSET;
|
||||
kSnsMsgNextAddress = kWeChatWinBase + WX_SNS_HOOK_NEXT_OFFSET;
|
||||
kSnsMsgJmpBackAddress = hook_sns_msg_addr + 0x5;
|
||||
HookAnyAddress(hook_sns_msg_addr, (LPVOID)handle_sns_msg,
|
||||
kOriginSnsMsgAsmCode);
|
||||
|
||||
|
||||
kMessageHooked = TRUE;
|
||||
return 1;
|
||||
}
|
||||
@@ -214,7 +293,9 @@ int UnHookRecvMsg() {
|
||||
kServerPort = 0;
|
||||
if (!kMessageHooked) return 2;
|
||||
DWORD hook_recv_msg_addr = kWeChatWinBase + WX_RECV_MSG_HOOK_OFFSET;
|
||||
DWORD hook_sns_addr = kWeChatWinBase + WX_SNS_HOOK_OFFSET;
|
||||
UnHookAnyAddress(hook_recv_msg_addr, kOriginReceMsgAsmCode);
|
||||
UnHookAnyAddress(hook_sns_addr, kOriginSnsMsgAsmCode);
|
||||
kMessageHooked = FALSE;
|
||||
return 1;
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/// @brief hook any address address+0x5
|
||||
/// @param port 端口
|
||||
/// @return 成功返回1,已经hook返回2
|
||||
int HookRecvMsg(int port);
|
||||
int HookRecvMsg(char* client_ip,int port);
|
||||
|
||||
int UnHookRecvMsg();
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "pch.h"
|
||||
#include "hook_voice.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define WX_HOOK_VOICE_OFFSET 0xccd561
|
||||
#define WX_HOOK_VOICE_NEXT_OFFSET 0x1f74560
|
||||
#define WX_SELF_ID_OFFSET 0x2E2CD3C
|
||||
|
||||
static wstring kVoiceStorePath = L"";
|
||||
static int kVoiceHooked = FALSE;
|
||||
static DWORD kWeChatWinBase = GetWeChatWinBase();
|
||||
static char kOriginVoiceAsmCode[5] = {0};
|
||||
|
||||
static DWORD kHookVoiceNextAddress = kWeChatWinBase + WX_HOOK_VOICE_NEXT_OFFSET;
|
||||
static DWORD kHookVoiceJmpBackAddress =
|
||||
kWeChatWinBase + WX_HOOK_VOICE_OFFSET + 0x5;
|
||||
|
||||
void OnHookVoice(DWORD buff,int len , DWORD msg_addr) {
|
||||
DWORD wxid_addr = GetWeChatWinBase() + WX_SELF_ID_OFFSET;
|
||||
string wxid = string(*(char **)wxid_addr, *(DWORD *)(wxid_addr + 0x10));
|
||||
wstring self_id = utf8_to_unicode(wxid.c_str());
|
||||
wstring save_path = kVoiceStorePath + self_id;
|
||||
if (!FindOrCreateDirectoryW(save_path.c_str())) {
|
||||
return;
|
||||
}
|
||||
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
|
||||
save_path = save_path + L"\\" + to_wstring(msgid) + L".amr";
|
||||
HANDLE file_handle = CreateFileW(save_path.c_str(), GENERIC_ALL, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
DWORD bytes_write = 0;
|
||||
WriteFile(file_handle, (LPCVOID)buff, len, &bytes_write, 0);
|
||||
CloseHandle(file_handle);
|
||||
}
|
||||
|
||||
/// @brief hook voice implement
|
||||
_declspec(naked) void handle_voice() {
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
PUSH EDI
|
||||
PUSH EDX
|
||||
PUSH EAX
|
||||
CALL OnHookVoice
|
||||
ADD ESP, 0xC
|
||||
POPFD
|
||||
POPAD
|
||||
CALL kHookVoiceNextAddress
|
||||
JMP kHookVoiceJmpBackAddress
|
||||
}
|
||||
}
|
||||
|
||||
int HookVoice(std::wstring save_path) {
|
||||
kWeChatWinBase = GetWeChatWinBase();
|
||||
if (!kWeChatWinBase) {
|
||||
return -1;
|
||||
}
|
||||
if (kVoiceHooked) {
|
||||
return 2;
|
||||
}
|
||||
kVoiceStorePath = save_path;
|
||||
if (kVoiceStorePath.back() != '\\') {
|
||||
kVoiceStorePath += L"\\";
|
||||
}
|
||||
wstring createpath = kVoiceStorePath.substr(0, kVoiceStorePath.length() - 1);
|
||||
if (!FindOrCreateDirectoryW(createpath.c_str())) {
|
||||
return -2;
|
||||
}
|
||||
DWORD hook_voice_addr = kWeChatWinBase + WX_HOOK_VOICE_OFFSET;
|
||||
kHookVoiceNextAddress = kWeChatWinBase + WX_HOOK_VOICE_NEXT_OFFSET;
|
||||
static DWORD kHookVoiceJmpBackAddress = hook_voice_addr + 0x5;
|
||||
HookAnyAddress(hook_voice_addr, (LPVOID)handle_voice, kOriginVoiceAsmCode);
|
||||
kVoiceHooked = TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UnHookVoice() {
|
||||
if (!kVoiceHooked) return 1;
|
||||
DWORD hook_voice_addr = kWeChatWinBase + WX_HOOK_VOICE_OFFSET;
|
||||
UnHookAnyAddress(hook_voice_addr, kOriginVoiceAsmCode);
|
||||
kVoiceHooked = FALSE;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef HOOK_VOICE_H_
|
||||
#define HOOK_VOICE_H_
|
||||
#include <string>
|
||||
|
||||
int HookVoice(std::wstring save_path);
|
||||
|
||||
int UnHookVoice();
|
||||
#endif
|
||||
+18
-18
@@ -135,24 +135,24 @@
|
||||
#define SQLITE_NULL 5
|
||||
#define SQLITE_TEXT 3
|
||||
|
||||
#define SQLITE3_EXEC_OFFSET 0x1ba9de0
|
||||
#define SQLITE3_BACKUP_INIT_OFFSET 0x1b6f760
|
||||
#define SQLITE3_PREPARE_OFFSET 0x1bb0730
|
||||
#define SQLITE3_OPEN_OFFSET 0x1bde730
|
||||
#define SQLITE3_BACKUP_STEP_OFFSET 0x1b6fb60
|
||||
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1b702a0
|
||||
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1b702b0
|
||||
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1b701a0
|
||||
#define SQLITE3_SLEEP_OFFSET 0x1bdef70
|
||||
#define SQLITE3_ERRCODE_OFFSET 0x1bdd3d0
|
||||
#define SQLITE3_CLOSE_OFFSET 0x1bdbb20
|
||||
#define SQLITE3_STEP_OFFSET 0x1b785d0
|
||||
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1b78ae0
|
||||
#define SQLITE3_COLUMN_NAME_OFFSET 0x1b793d0
|
||||
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1b79270
|
||||
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1b78b20
|
||||
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1b78c00
|
||||
#define SQLITE3_FINALIZE_OFFSET 0x1b775a0
|
||||
#define SQLITE3_EXEC_OFFSET 0x1d5cf70
|
||||
#define SQLITE3_BACKUP_INIT_OFFSET 0x1d228d0
|
||||
#define SQLITE3_PREPARE_OFFSET 0x1d638c0
|
||||
#define SQLITE3_OPEN_OFFSET 0x1d918b0
|
||||
#define SQLITE3_BACKUP_STEP_OFFSET 0x1d22ce0
|
||||
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1d23420
|
||||
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1d23430
|
||||
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1d23320
|
||||
#define SQLITE3_SLEEP_OFFSET 0x1d920f0
|
||||
#define SQLITE3_ERRCODE_OFFSET 0x1d90550
|
||||
#define SQLITE3_CLOSE_OFFSET 0x1d8ecd0
|
||||
#define SQLITE3_STEP_OFFSET 0x1d2b750
|
||||
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1d2bc60
|
||||
#define SQLITE3_COLUMN_NAME_OFFSET 0x1d2c550
|
||||
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1d2c3f0
|
||||
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1d2bca0
|
||||
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1d2bd80
|
||||
#define SQLITE3_FINALIZE_OFFSET 0x1d2a720
|
||||
|
||||
typedef int (*Sqlite3_callback)(void*, int, char**, char**);
|
||||
|
||||
|
||||
+8
-5
@@ -4,10 +4,10 @@
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_INIT_OBJ_OFFSET 0x6cbab0
|
||||
#define WX_OCR_MANAGER_OFFSET 0x6cff00
|
||||
#define WX_DO_OCR_TASK_OFFSET 0x11e3210
|
||||
|
||||
#define WX_INIT_OBJ_OFFSET 0x7a98f0
|
||||
#define WX_OCR_MANAGER_OFFSET 0x7ae470
|
||||
#define WX_DO_OCR_TASK_OFFSET 0x13230c0
|
||||
using namespace std;
|
||||
int DoOCRTask(wchar_t *img_path, std::string &result) {
|
||||
int success = -1;
|
||||
WeChatString path(img_path);
|
||||
@@ -17,6 +17,7 @@ int DoOCRTask(wchar_t *img_path, std::string &result) {
|
||||
DWORD ocr_manager_addr = base + WX_OCR_MANAGER_OFFSET;
|
||||
DWORD do_ocr_task_addr = base + WX_DO_OCR_TASK_OFFSET;
|
||||
DWORD init_addr = base + WX_INIT_OBJ_OFFSET;
|
||||
DWORD flag = 0;
|
||||
__asm {
|
||||
PUSHAD
|
||||
PUSHFD
|
||||
@@ -25,9 +26,11 @@ int DoOCRTask(wchar_t *img_path, std::string &result) {
|
||||
CALL ocr_manager_addr
|
||||
LEA ECX,null_obj
|
||||
PUSH ECX
|
||||
LEA ECX,flag
|
||||
PUSH ECX
|
||||
LEA ECX,ocr_result
|
||||
PUSH ECX
|
||||
PUSH ECX
|
||||
PUSH 0x0
|
||||
LEA ECX,path
|
||||
PUSH ECX
|
||||
MOV ECX,EAX
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#include "pch.h"
|
||||
#include "pat.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_PAT_MGR_OFFSET 0x8d0c00
|
||||
#define WX_SEND_PAT_MSG_OFFSET 0x1369850
|
||||
#define WX_RET_OFFSET 0x1C94D34
|
||||
|
||||
int SendPatMsg(wchar_t* chat_room_id, wchar_t* wxid) {
|
||||
int success = -1;
|
||||
WeChatString chat_room(chat_room_id);
|
||||
WeChatString self_wxid(wxid);
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD get_pat_mgr_addr = base + WX_PAT_MGR_OFFSET;
|
||||
DWORD send_pat_msg_addr = base + WX_SEND_PAT_MSG_OFFSET;
|
||||
DWORD ret_addr = base + WX_RET_OFFSET;
|
||||
__asm {
|
||||
PUSHAD
|
||||
CALL get_pat_mgr_addr
|
||||
PUSH ret_addr
|
||||
PUSH 0x0
|
||||
PUSH EAX
|
||||
LEA ECX,chat_room
|
||||
LEA EDX,self_wxid
|
||||
CALL send_pat_msg_addr
|
||||
ADD ESP,0xc
|
||||
MOVZX EAX,AL
|
||||
MOV success,EAX
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef PAT_H_
|
||||
#define PAT_H_
|
||||
int SendPatMsg(wchar_t* chat_room_id,wchar_t* wxid);
|
||||
#endif
|
||||
@@ -0,0 +1,275 @@
|
||||
#include "pch.h"
|
||||
#include "search_contact.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT 0xd94d1e
|
||||
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT 0xed13a0
|
||||
#define WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT 0xa2a260
|
||||
#define WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT 0xa2a4c0
|
||||
|
||||
|
||||
#define WX_SEARCH_CONTACT_OFFSeT 0xc5bb00
|
||||
#define WX_SEARCH_CONTACT_MGR_OFFSeT 0xa0d550
|
||||
|
||||
|
||||
|
||||
static BOOL kSearchContactHooked = false;
|
||||
static char kHookSearchContactErrcodeOldAsm[5] = {0};
|
||||
static char kHookUserInfoOldAsm[5] = {0};
|
||||
static DWORD kWeChatWinBase = GetWeChatWinBase();
|
||||
|
||||
static DWORD kHookSearchContactErrcodeNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
|
||||
static DWORD kHookSearchContactErrcodeAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
|
||||
static DWORD kHookSearchContactErrcodeJmpBackAddr =
|
||||
kHookSearchContactErrcodeAddr + 0x5;
|
||||
|
||||
static DWORD kHookUserInfoNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
|
||||
static DWORD kHookUserInfoAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
|
||||
static DWORD kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
|
||||
|
||||
static UserInfo userinfo;
|
||||
|
||||
void SetErrorCode(int code) { userinfo.error_code = code; }
|
||||
|
||||
void SetUserInfoDetail(DWORD address) {
|
||||
DWORD length = *(DWORD *)(address + 0x8);
|
||||
userinfo.keyword = new wchar_t[length + 1];
|
||||
userinfo.keyword_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.keyword, (wchar_t *)(*(DWORD *)(address + 0x4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.keyword, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x1C);
|
||||
userinfo.v3 = new wchar_t[length + 1];
|
||||
userinfo.v3_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.v3, (wchar_t *)(*(DWORD *)(address + 0x18)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.v3, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x30);
|
||||
userinfo.big_image = new wchar_t[length + 1];
|
||||
userinfo.big_image_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.big_image, (wchar_t *)(*(DWORD *)(address + 0x2C)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.big_image, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0xC8);
|
||||
userinfo.nickname = new wchar_t[length + 1];
|
||||
userinfo.nickname_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.nickname, (wchar_t *)(*(DWORD *)(address + 0xC4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.nickname, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x108);
|
||||
userinfo.v2 = new wchar_t[length + 1];
|
||||
userinfo.v2_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.v2, (wchar_t *)(*(DWORD *)(address + 0x104)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.v2, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x16C);
|
||||
userinfo.small_image = new wchar_t[length + 1];
|
||||
userinfo.small_image_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.small_image, (wchar_t *)(*(DWORD *)(address + 0x168)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.small_image, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x1F8);
|
||||
userinfo.signature = new wchar_t[length + 1];
|
||||
userinfo.signature_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.signature, (wchar_t *)(*(DWORD *)(address + 0x1F4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.signature, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x20C);
|
||||
userinfo.nation = new wchar_t[length + 1];
|
||||
userinfo.nation_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.nation, (wchar_t *)(*(DWORD *)(address + 0x208)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.nation, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x220);
|
||||
userinfo.province = new wchar_t[length + 1];
|
||||
userinfo.province_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.province, (wchar_t *)(*(DWORD *)(address + 0x21C)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.province, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x234);
|
||||
userinfo.city = new wchar_t[length + 1];
|
||||
userinfo.city_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.city, (wchar_t *)(*(DWORD *)(address + 0x230)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.city, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
userinfo.sex = *(DWORD *)(address + 0x1BC);
|
||||
userinfo.over = true;
|
||||
}
|
||||
|
||||
static void DeleteUserInfoCache() {
|
||||
if (userinfo.keyword) {
|
||||
delete userinfo.keyword;
|
||||
}
|
||||
if (userinfo.v2) {
|
||||
delete userinfo.v2;
|
||||
}
|
||||
if (userinfo.v3) {
|
||||
delete userinfo.v3;
|
||||
}
|
||||
if (userinfo.nickname) {
|
||||
delete userinfo.nickname;
|
||||
}
|
||||
if (userinfo.nation) {
|
||||
delete userinfo.nation;
|
||||
}
|
||||
if (userinfo.province) {
|
||||
delete userinfo.province;
|
||||
}
|
||||
if (userinfo.city) {
|
||||
delete userinfo.city;
|
||||
}
|
||||
if (userinfo.signature) {
|
||||
delete userinfo.signature;
|
||||
}
|
||||
if (userinfo.small_image) {
|
||||
delete userinfo.small_image;
|
||||
}
|
||||
if (userinfo.big_image) {
|
||||
delete userinfo.big_image;
|
||||
}
|
||||
ZeroMemory(&userinfo, sizeof(UserInfo));
|
||||
userinfo.error_code = 1;
|
||||
}
|
||||
|
||||
__declspec(naked) void HandleErrorCode() {
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
push edi;
|
||||
call SetErrorCode;
|
||||
add esp, 0x4;
|
||||
popfd;
|
||||
popad;
|
||||
call kHookSearchContactErrcodeNextAddr;
|
||||
jmp kHookSearchContactErrcodeJmpBackAddr;
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void HandleUserInfoDetail() {
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
push dword ptr [ebp + 0x14];
|
||||
call SetUserInfoDetail;
|
||||
add esp, 0x4;
|
||||
popfd;
|
||||
popad;
|
||||
call kHookUserInfoNextAddr;
|
||||
jmp kHookUserInfoJmpBackAddr;
|
||||
}
|
||||
}
|
||||
|
||||
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user) {
|
||||
int success = -1;
|
||||
HookSearchContact();
|
||||
DeleteUserInfoCache();
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD search_contact_mgr_addr = base + WX_SEARCH_CONTACT_MGR_OFFSeT;
|
||||
DWORD search_contact_addr = base + WX_SEARCH_CONTACT_OFFSeT;
|
||||
WeChatString key(keyword);
|
||||
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
call search_contact_mgr_addr;
|
||||
lea ebx, key;
|
||||
push ebx;
|
||||
mov ecx, eax;
|
||||
call search_contact_addr;
|
||||
popfd;
|
||||
popad;
|
||||
}
|
||||
success = 1;
|
||||
while (userinfo.error_code == 1 && kSearchContactHooked) {
|
||||
Sleep(20);
|
||||
}
|
||||
if (userinfo.error_code == 0) {
|
||||
while (userinfo.over == false && kSearchContactHooked) {
|
||||
Sleep(20);
|
||||
}
|
||||
}
|
||||
*user= &userinfo;
|
||||
return success;
|
||||
}
|
||||
|
||||
int HookSearchContact() {
|
||||
kWeChatWinBase = GetWeChatWinBase();
|
||||
if (!kWeChatWinBase) {
|
||||
return -1;
|
||||
}
|
||||
if (kSearchContactHooked) {
|
||||
return 2;
|
||||
}
|
||||
kHookSearchContactErrcodeNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
|
||||
kHookSearchContactErrcodeAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
|
||||
kHookSearchContactErrcodeJmpBackAddr = kHookSearchContactErrcodeAddr + 0x5;
|
||||
|
||||
kHookUserInfoNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
|
||||
kHookUserInfoAddr = kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
|
||||
kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
|
||||
HookAnyAddress(kHookSearchContactErrcodeAddr,
|
||||
(LPVOID)HandleErrorCode,
|
||||
kHookSearchContactErrcodeOldAsm);
|
||||
HookAnyAddress(kHookUserInfoAddr, (LPVOID)HandleUserInfoDetail, kHookUserInfoOldAsm);
|
||||
kSearchContactHooked = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UnHookSearchContact() {
|
||||
if (!kSearchContactHooked) return 2;
|
||||
UnHookAnyAddress(kHookSearchContactErrcodeAddr,
|
||||
kHookSearchContactErrcodeOldAsm);
|
||||
UnHookAnyAddress(kHookUserInfoAddr, kHookUserInfoOldAsm);
|
||||
kSearchContactHooked = false;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SEARCH_CONTACT_H_
|
||||
#define SEARCH_CONTACT_H_
|
||||
#include "wechat_data.h"
|
||||
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user);
|
||||
|
||||
int HookSearchContact();
|
||||
int UnHookSearchContact();
|
||||
#endif
|
||||
+183
-121
@@ -4,151 +4,213 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "wechat_data.h"
|
||||
using namespace std;
|
||||
|
||||
#define WX_SELF_NAME_OFFSET 0x2C426E8
|
||||
#define WX_SELF_MOBILE_OFFSET 0x2C42658
|
||||
#define WX_SELF_CITY_OFFSET 0x2C426B8
|
||||
#define WX_SELF_PROVINCE_OFFSET 0x2C426A0
|
||||
#define WX_SELF_COUNTRY_OFFSET 0x2C42688
|
||||
#define WX_SELF_ACCOUNT_OFFSET 0x2C42640
|
||||
#define WX_SELF_ID_OFFSET 0x2C42A38
|
||||
#define WX_SELF_SMALL_IMG_OFFSET 0x2C4289C
|
||||
#define WX_SELF_BIG_IMG_OFFSET 0x2C428B4
|
||||
#define WX_LOGIN_STATUS_OFFSET 0x2c42a10
|
||||
#define WX_APP_DATA_ROOT_PATH_OFFSET 0x2c84ae0
|
||||
#define WX_APP_DATA_SAVE_PATH_OFFSET 0x2c65728
|
||||
#define WX_CURRENT_DATA_PATH_OFFSET 0x2c636fc
|
||||
|
||||
#define WX_LOGOUT_OFFSET 0xccc320
|
||||
#define WX_ACCOUT_SERVICE_OFFSET 0x65bcc0
|
||||
#define WX_SELF_NAME_OFFSET 0x2E2CE48
|
||||
#define WX_SELF_MOBILE_OFFSET 0x2E2CDB8
|
||||
#define WX_SELF_CITY_OFFSET 0x2E2CE18
|
||||
#define WX_SELF_PROVINCE_OFFSET 0x2E2CE00
|
||||
#define WX_SELF_COUNTRY_OFFSET 0x2E2CDE8
|
||||
#define WX_SELF_ACCOUNT_OFFSET 0x2e2d1d0
|
||||
#define WX_SELF_ID_OFFSET 0x2E2CD3C
|
||||
#define WX_SELF_SMALL_IMG_OFFSET 0x2E2D014
|
||||
#define WX_SELF_BIG_IMG_OFFSET 0x2E2CFFC
|
||||
#define WX_LOGIN_STATUS_OFFSET 0x2E2D1C0
|
||||
#define WX_APP_DATA_ROOT_PATH_OFFSET 0x2E73010
|
||||
#define WX_APP_DATA_SAVE_PATH_OFFSET 0x2E52DB0
|
||||
#define WX_CURRENT_DATA_PATH_OFFSET 0x2E4F290
|
||||
|
||||
#define WX_LOGOUT_OFFSET 0xdd5c90
|
||||
#define WX_ACCOUNT_SERVICE_OFFSET 0x707960
|
||||
#define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xeb4b00
|
||||
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc11140
|
||||
int GetSelfInfo(SelfInfoInner &out) {
|
||||
DWORD base = GetWeChatWinBase();
|
||||
#ifdef _DEBUG
|
||||
cout << "mobile:" << (char *)(base + WX_SELF_MOBILE_OFFSET) << endl;
|
||||
cout << "name:" << (char *)(base + WX_SELF_NAME_OFFSET) << endl;
|
||||
cout << "city:" << (char *)(base + WX_SELF_CITY_OFFSET) << endl;
|
||||
cout << "city:" << (char *)(base + WX_SELF_CITY_OFFSET) << endl;
|
||||
cout << "province:" << (char *)(base + WX_SELF_PROVINCE_OFFSET) << endl;
|
||||
cout << "country:" << (char *)(base + WX_SELF_COUNTRY_OFFSET) << endl;
|
||||
cout << "account:" << (char *)(base + WX_SELF_ACCOUNT_OFFSET) << endl;
|
||||
cout << "wxid:" << (char *)(base + WX_SELF_ID_OFFSET) << endl;
|
||||
cout << "small_img:" << (char *)(base + WX_SELF_SMALL_IMG_OFFSET) << endl;
|
||||
cout << "big_img:" << (char *)(base + WX_SELF_BIG_IMG_OFFSET) << endl;
|
||||
#endif
|
||||
if (*(DWORD *)(base + WX_SELF_NAME_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_NAME_OFFSET + 0x10) == 0) {
|
||||
out.name = string();
|
||||
} else {
|
||||
out.name = string((char *)(base + WX_SELF_NAME_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_NAME_OFFSET + 0x10));
|
||||
DWORD accout_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
|
||||
DWORD get_app_save_addr = base + WX_GET_APP_DATA_SAVE_PATH_OFFSET;
|
||||
DWORD get_current_data_path_addr = base + WX_GET_CURRENT_DATA_PATH_OFFSET;
|
||||
DWORD service_addr = NULL;
|
||||
__asm {
|
||||
PUSHAD
|
||||
CALL accout_service_addr
|
||||
MOV service_addr,EAX
|
||||
POPAD
|
||||
}
|
||||
if (*(DWORD *)(base + WX_SELF_MOBILE_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_MOBILE_OFFSET + 0x10) == 0) {
|
||||
out.mobile = string();
|
||||
} else {
|
||||
out.mobile = string((char *)(base + WX_SELF_MOBILE_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_MOBILE_OFFSET + 0x10));
|
||||
if (service_addr) {
|
||||
if (*(DWORD *)(service_addr + 0x44) == 0 ||
|
||||
*(DWORD *)(service_addr + 0x44 + 0x10) == 0) {
|
||||
out.wxid = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0x44 + 0x14) == 0xF) {
|
||||
out.wxid = string((char *)(service_addr + 0x44),
|
||||
*(DWORD *)(service_addr + 0x44 + 0x10));
|
||||
} else {
|
||||
out.wxid = string(*(char **)(service_addr + 0x44),
|
||||
*(DWORD *)(service_addr + 0x44 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0xA8) == 0 ||
|
||||
*(DWORD *)(service_addr + 0xA8 + 0x10) == 0) {
|
||||
out.account = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0xA8 + 0x14) == 0xF) {
|
||||
out.account = string((char *)(service_addr + 0xA8),
|
||||
*(DWORD *)(service_addr + 0xA8 + 0x10));
|
||||
} else {
|
||||
out.account = string(*(char **)(service_addr + 0xA8),
|
||||
*(DWORD *)(service_addr + 0xA8 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0xC0) == 0 ||
|
||||
*(DWORD *)(service_addr + 0xC0 + 0x10) == 0) {
|
||||
out.mobile = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0xC0 + 0x14) == 0xF) {
|
||||
out.mobile = string((char *)(service_addr + 0xC0),
|
||||
*(DWORD *)(service_addr + 0xC0 + 0x10));
|
||||
} else {
|
||||
out.mobile = string(*(char **)(service_addr + 0xC0),
|
||||
*(DWORD *)(service_addr + 0xC0 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0xD8) == 0 ||
|
||||
*(DWORD *)(service_addr + 0xD8 + 0x10) == 0) {
|
||||
out.signature = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0xD8 + 0x14) == 0xF) {
|
||||
out.signature = string((char *)(service_addr + 0xD8),
|
||||
*(DWORD *)(service_addr + 0xD8 + 0x10));
|
||||
} else {
|
||||
out.signature = string(*(char **)(service_addr + 0xD8),
|
||||
*(DWORD *)(service_addr + 0xD8 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0xF0) == 0 ||
|
||||
*(DWORD *)(service_addr + 0xF0 + 0x10) == 0) {
|
||||
out.country = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0xF0 + 0x14) == 0xF) {
|
||||
out.country = string((char *)(service_addr + 0xF0),
|
||||
*(DWORD *)(service_addr + 0xF0 + 0x10));
|
||||
} else {
|
||||
out.country = string(*(char **)(service_addr + 0xF0),
|
||||
*(DWORD *)(service_addr + 0xF0 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0x108) == 0 ||
|
||||
*(DWORD *)(service_addr + 0x108 + 0x10) == 0) {
|
||||
out.province = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0x108 + 0x14) == 0xF) {
|
||||
out.province = string((char *)(service_addr + 0x108),
|
||||
*(DWORD *)(service_addr + 0x108 + 0x10));
|
||||
} else {
|
||||
out.province = string(*(char **)(service_addr + 0x108),
|
||||
*(DWORD *)(service_addr + 0x108 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0x120) == 0 ||
|
||||
*(DWORD *)(service_addr + 0x120 + 0x10) == 0) {
|
||||
out.city = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0x120 + 0x14) == 0xF) {
|
||||
out.city = string((char *)(service_addr + 0x120),
|
||||
*(DWORD *)(service_addr + 0x120 + 0x10));
|
||||
} else {
|
||||
out.city = string(*(char **)(service_addr + 0x120),
|
||||
*(DWORD *)(service_addr + 0x120 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0x150) == 0 ||
|
||||
*(DWORD *)(service_addr + 0x150 + 0x10) == 0) {
|
||||
out.name = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0x150 + 0x14) == 0xF) {
|
||||
out.name = string((char *)(service_addr + 0x150),
|
||||
*(DWORD *)(service_addr + 0x150 + 0x10));
|
||||
} else {
|
||||
out.name = string(*(char **)(service_addr + 0x150),
|
||||
*(DWORD *)(service_addr + 0x150 + 0x10));
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(service_addr + 0x304) == 0 ||
|
||||
*(DWORD *)(service_addr + 0x304 + 0x10) == 0) {
|
||||
out.head_img = string();
|
||||
} else {
|
||||
if (*(DWORD *)(service_addr + 0x304 + 0x14) == 0xF) {
|
||||
out.head_img = string((char *)(service_addr + 0x304),
|
||||
*(DWORD *)(service_addr + 0x304 + 0x10));
|
||||
} else {
|
||||
out.head_img = string(*(char **)(service_addr + 0x304),
|
||||
*(DWORD *)(service_addr + 0x304 + 0x10));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_CITY_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_CITY_OFFSET + 0x10) == 0) {
|
||||
out.city = string();
|
||||
} else {
|
||||
out.city = string((char *)(base + WX_SELF_CITY_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_CITY_OFFSET + 0x10));
|
||||
WeChatString data_save_path;
|
||||
WeChatString current_data_path;
|
||||
|
||||
__asm {
|
||||
PUSHAD
|
||||
LEA ECX,data_save_path
|
||||
CALL get_app_save_addr
|
||||
LEA ECX,current_data_path
|
||||
CALL get_current_data_path_addr
|
||||
POPAD
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET + 0x10) == 0) {
|
||||
out.province = string();
|
||||
} else {
|
||||
out.province = string((char *)(base + WX_SELF_PROVINCE_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET + 0x10));
|
||||
if (data_save_path.ptr) {
|
||||
out.data_save_path =
|
||||
Wstring2String(wstring(data_save_path.ptr, data_save_path.length));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET + 0x10) == 0) {
|
||||
out.country = string();
|
||||
} else {
|
||||
out.country = string((char *)(base + WX_SELF_COUNTRY_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET + 0x10));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET + 0x10) == 0) {
|
||||
out.account = string();
|
||||
} else {
|
||||
out.account = string(*(char **)(base + WX_SELF_ACCOUNT_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET + 0x10));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_ID_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_ID_OFFSET + 0x10) == 0) {
|
||||
out.wxid = string();
|
||||
} else {
|
||||
out.wxid = string(*(char **)(base + WX_SELF_ID_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_ID_OFFSET + 0x10));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET + 0x10) == 0) {
|
||||
out.small_img = string();
|
||||
} else {
|
||||
out.small_img = string(*(char **)(base + WX_SELF_SMALL_IMG_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET + 0x10));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET + 0x10) == 0) {
|
||||
out.big_img = string();
|
||||
} else {
|
||||
out.big_img = string(*(char **)(base + WX_SELF_BIG_IMG_OFFSET),
|
||||
*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET + 0x10));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET + 0x4) == 0) {
|
||||
out.data_root_path = string();
|
||||
} else {
|
||||
out.data_root_path = Wstring2String(wstring(*(wchar_t **)(base + WX_APP_DATA_ROOT_PATH_OFFSET),
|
||||
*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET + 0x4)));
|
||||
}
|
||||
|
||||
if (*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET + 0x4) == 0) {
|
||||
else {
|
||||
out.data_save_path = string();
|
||||
} else {
|
||||
out.data_save_path = Wstring2String(wstring(*(wchar_t **)(base + WX_APP_DATA_SAVE_PATH_OFFSET),
|
||||
*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET + 0x4)));
|
||||
}
|
||||
if (*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET) == 0 ||
|
||||
*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET + 0x4) == 0) {
|
||||
out.current_data_path = string();
|
||||
} else {
|
||||
out.current_data_path = Wstring2String(wstring(*(wchar_t **)(base + WX_CURRENT_DATA_PATH_OFFSET),
|
||||
*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET + 0x4)));
|
||||
}
|
||||
|
||||
if (current_data_path.ptr) {
|
||||
out.current_data_path = Wstring2String(
|
||||
wstring(current_data_path.ptr, current_data_path.length));
|
||||
} else {
|
||||
out.current_data_path = string();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int CheckLogin(){
|
||||
int CheckLogin() {
|
||||
DWORD base = GetWeChatWinBase();
|
||||
return *(DWORD*) (base + WX_LOGIN_STATUS_OFFSET);
|
||||
DWORD accout_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
|
||||
DWORD service_addr = NULL;
|
||||
__asm {
|
||||
PUSHAD
|
||||
CALL accout_service_addr
|
||||
MOV service_addr,EAX
|
||||
POPAD
|
||||
}
|
||||
if (service_addr) {
|
||||
return *(DWORD *)(service_addr + 0x4C8);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Logout(){
|
||||
int Logout() {
|
||||
int success = 0;
|
||||
if(!CheckLogin()){
|
||||
if (!CheckLogin()) {
|
||||
return success;
|
||||
}
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD account_service_addr = base + WX_ACCOUT_SERVICE_OFFSET;
|
||||
DWORD account_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
|
||||
DWORD logout_addr = base + WX_LOGOUT_OFFSET;
|
||||
__asm{
|
||||
__asm {
|
||||
PUSHAD
|
||||
CALL account_service_addr
|
||||
PUSH 0x0
|
||||
|
||||
+5
-5
@@ -3,16 +3,16 @@
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_APP_MSG_MGR_OFFSET 0x65df50
|
||||
#define WX_SEND_FILE_OFFSET 0xa10190
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x649ac0
|
||||
#define WX_APP_MSG_MGR_OFFSET 0x709bb0
|
||||
#define WX_SEND_FILE_OFFSET 0xb06240
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
|
||||
|
||||
int SendFile(wchar_t *wxid, wchar_t *file_path){
|
||||
int success = 0;
|
||||
WeChatString to_user(wxid);
|
||||
WeChatString path(file_path);
|
||||
char chat_msg[0x2A8] = {0};
|
||||
char chat_msg[0x2C4] = {0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD app_msg_mgr_addr = base + WX_APP_MSG_MGR_OFFSET;
|
||||
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
|
||||
|
||||
+5
-5
@@ -3,17 +3,17 @@
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_SEND_IMAGE_OFFSET 0xb6a3f0
|
||||
#define WX_SEND_MESSAGE_MGR_OFFSET 0x65b2a0
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x649ac0
|
||||
#define WX_SEND_IMAGE_OFFSET 0xc71500
|
||||
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
|
||||
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
|
||||
|
||||
int SendImage(wchar_t *wxid, wchar_t *image_path){
|
||||
|
||||
int success = 0;
|
||||
WeChatString to_user(wxid);
|
||||
WeChatString path(image_path);
|
||||
char chat_msg[0x2A8] ={0};
|
||||
char chat_msg[0x2C4] ={0};
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD send_message_mgr_addr = base + WX_SEND_MESSAGE_MGR_OFFSET;
|
||||
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
|
||||
|
||||
+84
-11
@@ -4,41 +4,114 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
#include "contact.h"
|
||||
|
||||
#define WX_SEND_TEXT_OFFSET 0xb6a930
|
||||
#define WX_SEND_TEXT_OFFSET 0xc71a60
|
||||
|
||||
#define WX_SEND_MESSAGE_MGR_OFFSET 0x65b2a0
|
||||
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
|
||||
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x649ac0
|
||||
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
|
||||
using namespace std;
|
||||
/// @brief 发生文本消息
|
||||
/// @param wxid wxid
|
||||
/// @param msg 文本消息
|
||||
/// @return 成功返回1
|
||||
int SendText(wchar_t* wxid, wchar_t* msg) {
|
||||
int SendText(wchar_t* wxid, wchar_t* msg) {
|
||||
int success = 0;
|
||||
WeChatString to_user(wxid);
|
||||
WeChatString text_msg(msg);
|
||||
wchar_t **msg_pptr = &text_msg.ptr;
|
||||
char chat_msg[0x2A8] ={0};
|
||||
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD send_message_mgr_addr = base + WX_SEND_MESSAGE_MGR_OFFSET;
|
||||
DWORD send_text_msg_addr = base + WX_SEND_TEXT_OFFSET;
|
||||
DWORD free_msg_addr = base + WX_FREE_CHAT_MSG_OFFSET;
|
||||
DWORD free_chat_msg_addr = base + WX_FREE_CHAT_MSG_OFFSET;
|
||||
char chat_msg[0x2C4] ={0};
|
||||
__asm{
|
||||
PUSHAD
|
||||
CALL send_message_mgr_addr
|
||||
PUSH 0x0
|
||||
PUSH 0x0
|
||||
PUSH 0x0
|
||||
PUSH 0x1
|
||||
PUSH 0x0
|
||||
MOV EDI,msg_pptr
|
||||
PUSH EDI
|
||||
MOV EAX,msg_pptr
|
||||
PUSH EAX
|
||||
LEA EDX,to_user
|
||||
LEA ECX,chat_msg
|
||||
CALL send_text_msg_addr
|
||||
ADD ESP,0x14
|
||||
CALL send_text_msg_addr
|
||||
MOV success,EAX
|
||||
ADD ESP,0x18
|
||||
LEA ECX,chat_msg
|
||||
CALL free_chat_msg_addr
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SendAtText(wchar_t* chat_room_id,wchar_t** wxids,int len,wchar_t* msg){
|
||||
int success = -1;
|
||||
WeChatString * at_users = new WeChatString[len+1];
|
||||
wstring at_msg = L"";
|
||||
int number =0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
wstring nickname;
|
||||
if (!lstrcmpiW((wchar_t *)wxids[i], (wchar_t *)L"notify@all")) {
|
||||
nickname = L"ËùÓÐÈË";
|
||||
} else {
|
||||
nickname = GetContactOrChatRoomNickname(wxids[i]);
|
||||
}
|
||||
if (nickname.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WeChatString temp = {0};
|
||||
temp.ptr = (wchar_t *)wxids[i];
|
||||
temp.length = wcslen((wchar_t *)wxids[i]);
|
||||
temp.max_length = wcslen((wchar_t *)wxids[i]) * 2;
|
||||
memcpy(&at_users[number], &temp, sizeof(WeChatString));
|
||||
at_msg = at_msg + L"@" + nickname + L" ";
|
||||
number++;
|
||||
}
|
||||
if (number < 1){
|
||||
return success;
|
||||
}
|
||||
wstring origin(msg);
|
||||
at_msg += origin;
|
||||
AtInner at_list = {0};
|
||||
at_list.start = (DWORD)at_users;
|
||||
at_list.finsh = (DWORD)&at_users[number];
|
||||
at_list.end = (DWORD)&at_users[number];
|
||||
WeChatString to_user(chat_room_id);
|
||||
WeChatString text_msg((wchar_t *)at_msg.c_str());
|
||||
wchar_t **msg_pptr = &text_msg.ptr;
|
||||
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD send_message_mgr_addr = base + WX_SEND_MESSAGE_MGR_OFFSET;
|
||||
DWORD send_text_msg_addr = base + WX_SEND_TEXT_OFFSET;
|
||||
DWORD free_chat_msg_addr = base + WX_FREE_CHAT_MSG_OFFSET;
|
||||
char chat_msg[0x2C4] ={0};
|
||||
|
||||
__asm{
|
||||
PUSHAD
|
||||
CALL send_message_mgr_addr
|
||||
PUSH 0x0
|
||||
PUSH 0x0
|
||||
PUSH 0x0
|
||||
PUSH 0x1
|
||||
LEA EAX,at_list
|
||||
PUSH EAX
|
||||
MOV EAX,msg_pptr
|
||||
PUSH EAX
|
||||
LEA EDX,to_user
|
||||
LEA ECX,chat_msg
|
||||
CALL free_msg_addr
|
||||
CALL send_text_msg_addr
|
||||
MOV success,EAX
|
||||
ADD ESP,0x18
|
||||
LEA ECX,chat_msg
|
||||
CALL free_chat_msg_addr
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
#define SEND_TEXT_H_
|
||||
|
||||
int SendText(wchar_t* wxid, wchar_t* msg);
|
||||
|
||||
int SendAtText(wchar_t* chat_room_id,wchar_t** wxids,int len,wchar_t* msg);
|
||||
#endif
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#include "pch.h"
|
||||
#include "sns.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "wechat_data.h"
|
||||
using namespace std;
|
||||
#define WX_SNS_DATA_MGR_OFFSET 0xbc4100
|
||||
#define WX_SNS_GET_FIRST_PAGE_OFFSET 0x1427be0
|
||||
#define WX_SNS_GET_NEXT_PAGE_OFFSET 0x1427c80
|
||||
|
||||
int GetFirstPage() {
|
||||
int success = -1;
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD sns_data_mgr_addr = base + WX_SNS_DATA_MGR_OFFSET;
|
||||
DWORD get_first_page_addr = base + WX_SNS_GET_FIRST_PAGE_OFFSET;
|
||||
|
||||
char buff[0xB44] = {};
|
||||
__asm {
|
||||
PUSHAD
|
||||
CALL sns_data_mgr_addr
|
||||
PUSH 0x1
|
||||
LEA ECX,buff
|
||||
PUSH ECX
|
||||
MOV ECX,EAX
|
||||
CALL get_first_page_addr
|
||||
MOV success,EAX
|
||||
POPAD
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int GetNextPage(ULONG64 sns_id) {
|
||||
int success = -1;
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD sns_data_mgr_addr = base + WX_SNS_DATA_MGR_OFFSET;
|
||||
DWORD get_next_page_addr = base + WX_SNS_GET_NEXT_PAGE_OFFSET;
|
||||
VectorInner temp = {};
|
||||
__asm{
|
||||
PUSHAD
|
||||
CALL sns_data_mgr_addr
|
||||
LEA ECX,temp
|
||||
PUSH ECX
|
||||
MOV EBX,dword ptr [sns_id + 0x4]
|
||||
PUSH EBX
|
||||
MOV EDI,dword ptr [sns_id ]
|
||||
PUSH EDI
|
||||
MOV ECX,EAX
|
||||
CALL get_next_page_addr
|
||||
MOV success,EAX
|
||||
POPAD
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef SNS_H_
|
||||
#define SNS_H_
|
||||
|
||||
int GetFirstPage();
|
||||
int GetNextPage(ULONG64 sns_id);
|
||||
#endif
|
||||
+211
-15
@@ -4,7 +4,6 @@
|
||||
// #include <windows.h>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
struct WeChatString {
|
||||
wchar_t *ptr;
|
||||
DWORD length;
|
||||
@@ -13,7 +12,7 @@ struct WeChatString {
|
||||
DWORD c_len = 0;
|
||||
WeChatString() { WeChatString(NULL); }
|
||||
|
||||
WeChatString(wstring &s) {
|
||||
WeChatString(std::wstring &s) {
|
||||
ptr = (wchar_t *)(s.c_str());
|
||||
length = s.length();
|
||||
max_length = s.length() * 2;
|
||||
@@ -51,7 +50,7 @@ struct DatabaseInfo {
|
||||
DWORD handle = 0;
|
||||
wchar_t *db_name = NULL;
|
||||
DWORD db_name_len = 0;
|
||||
vector<TableInfo> tables;
|
||||
std::vector<TableInfo> tables;
|
||||
DWORD count = 0;
|
||||
DWORD extrainfo = 0;
|
||||
};
|
||||
@@ -101,6 +100,25 @@ struct ChatRoomInfoInner {
|
||||
WeChatString notice;
|
||||
WeChatString admin;
|
||||
WeChatString xml;
|
||||
|
||||
~ChatRoomInfoInner(){
|
||||
if(chat_room_id.ptr){
|
||||
delete []chat_room_id.ptr;
|
||||
chat_room_id.ptr = nullptr;
|
||||
}
|
||||
if(notice.ptr){
|
||||
delete []notice.ptr;
|
||||
notice.ptr = nullptr;
|
||||
}
|
||||
if(admin.ptr){
|
||||
delete []admin.ptr;
|
||||
admin.ptr = nullptr;
|
||||
}
|
||||
if(xml.ptr){
|
||||
delete []xml.ptr;
|
||||
xml.ptr = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct VectorInner {
|
||||
@@ -124,17 +142,195 @@ struct ChatRoomInner{
|
||||
};
|
||||
|
||||
struct SelfInfoInner{
|
||||
string name;
|
||||
string city;
|
||||
string province;
|
||||
string country;
|
||||
string account;
|
||||
string wxid;
|
||||
string mobile;
|
||||
string small_img;
|
||||
string big_img;
|
||||
string data_root_path;
|
||||
string data_save_path;
|
||||
string current_data_path;
|
||||
std::string name;
|
||||
std::string city;
|
||||
std::string province;
|
||||
std::string country;
|
||||
std::string account;
|
||||
std::string wxid;
|
||||
std::string mobile;
|
||||
std::string head_img;
|
||||
std::string data_save_path;
|
||||
std::string signature;
|
||||
std::string current_data_path;
|
||||
};
|
||||
|
||||
struct UserInfo {
|
||||
int error_code;
|
||||
wchar_t *keyword;
|
||||
int keyword_len;
|
||||
wchar_t *v3;
|
||||
int v3_len;
|
||||
wchar_t *nickname;
|
||||
int nickname_len;
|
||||
wchar_t *signature;
|
||||
int signature_len;
|
||||
wchar_t *v2;
|
||||
int v2_len;
|
||||
wchar_t *nation;
|
||||
int nation_len;
|
||||
wchar_t *province;
|
||||
int province_len;
|
||||
wchar_t *city;
|
||||
int city_len;
|
||||
wchar_t *big_image;
|
||||
int big_image_len;
|
||||
wchar_t *small_image;
|
||||
int small_image_len;
|
||||
DWORD sex;
|
||||
BOOL over;
|
||||
};
|
||||
|
||||
struct AtInner{
|
||||
DWORD start;
|
||||
DWORD finsh;
|
||||
DWORD end;
|
||||
};
|
||||
|
||||
struct ChatMsg {
|
||||
DWORD **field0_0x0;
|
||||
DWORD field1_0x4;
|
||||
ULONG64 sequence;
|
||||
DWORD field3_0x10;
|
||||
DWORD field4_0x14;
|
||||
ULONG64 msgSequence;
|
||||
DWORD localId;
|
||||
DWORD field7_0x24;
|
||||
DWORD field8_0x28;
|
||||
DWORD field9_0x2c;
|
||||
ULONG64 msgId;
|
||||
DWORD type;
|
||||
DWORD isSendMsg;
|
||||
DWORD msgStatus;
|
||||
DWORD timestamp;
|
||||
WeChatString talker;
|
||||
DWORD field16_0x5c;
|
||||
DWORD field17_0x60;
|
||||
DWORD field18_0x64;
|
||||
DWORD field19_0x68;
|
||||
DWORD field20_0x6c;
|
||||
WeChatString content;
|
||||
DWORD field22_0x84;
|
||||
DWORD field23_0x88;
|
||||
DWORD field24_0x8c;
|
||||
DWORD field25_0x90;
|
||||
DWORD field26_0x94;
|
||||
DWORD field27_0x98;
|
||||
DWORD field28_0x9c;
|
||||
DWORD field29_0xa0;
|
||||
DWORD field30_0xa4;
|
||||
DWORD field31_0xa8;
|
||||
DWORD field32_0xac;
|
||||
DWORD field33_0xb0;
|
||||
DWORD field34_0xb4;
|
||||
DWORD field35_0xb8;
|
||||
DWORD field36_0xbc;
|
||||
DWORD field37_0xc0;
|
||||
DWORD field38_0xc4;
|
||||
DWORD field39_0xc8;
|
||||
DWORD field40_0xcc;
|
||||
DWORD field41_0xd0;
|
||||
DWORD field42_0xd4;
|
||||
DWORD field43_0xd8;
|
||||
DWORD field44_0xdc;
|
||||
DWORD field45_0xe0;
|
||||
DWORD field46_0xe4;
|
||||
DWORD field47_0xe8;
|
||||
DWORD field48_0xec;
|
||||
DWORD field49_0xf0;
|
||||
DWORD field50_0xf4;
|
||||
DWORD field51_0xf8;
|
||||
DWORD field52_0xfc;
|
||||
DWORD field53_0x100;
|
||||
DWORD field54_0x104;
|
||||
DWORD field55_0x108;
|
||||
DWORD field56_0x10c;
|
||||
DWORD field57_0x110;
|
||||
DWORD field58_0x114;
|
||||
DWORD field59_0x118;
|
||||
DWORD field60_0x11c;
|
||||
DWORD field61_0x120;
|
||||
DWORD field62_0x124;
|
||||
DWORD field63_0x128;
|
||||
DWORD field64_0x12c;
|
||||
DWORD field65_0x130;
|
||||
DWORD field66_0x134;
|
||||
DWORD field67_0x138;
|
||||
DWORD field68_0x13c;
|
||||
DWORD field69_0x140;
|
||||
DWORD field70_0x144;
|
||||
DWORD field71_0x148;
|
||||
DWORD field72_0x14c;
|
||||
DWORD field73_0x150;
|
||||
DWORD field74_0x154;
|
||||
DWORD field75_0x158;
|
||||
DWORD field76_0x15c;
|
||||
DWORD field77_0x160;
|
||||
DWORD field78_0x164;
|
||||
DWORD field79_0x168;
|
||||
DWORD field80_0x16c;
|
||||
DWORD field81_0x170;
|
||||
WeChatString fromGroup;
|
||||
WeChatString sign;
|
||||
WeChatString thumbPath;
|
||||
WeChatString path;
|
||||
DWORD field86_0x1c4;
|
||||
DWORD field87_0x1c8;
|
||||
DWORD field88_0x1cc;
|
||||
DWORD field89_0x1d0;
|
||||
DWORD field90_0x1d4;
|
||||
DWORD field91_0x1d8;
|
||||
DWORD field92_0x1dc;
|
||||
DWORD field93_0x1e0;
|
||||
DWORD field94_0x1e4;
|
||||
DWORD field95_0x1e8;
|
||||
DWORD field96_0x1ec;
|
||||
WeChatString signature;
|
||||
DWORD field98_0x204;
|
||||
DWORD field99_0x208;
|
||||
DWORD field100_0x20c;
|
||||
DWORD field101_0x210;
|
||||
DWORD field102_0x214;
|
||||
DWORD field103_0x218;
|
||||
DWORD field104_0x21c;
|
||||
DWORD field105_0x220;
|
||||
DWORD field106_0x224;
|
||||
DWORD field107_0x228;
|
||||
DWORD field108_0x22c;
|
||||
DWORD field109_0x230;
|
||||
DWORD field110_0x234;
|
||||
DWORD field111_0x238;
|
||||
DWORD field112_0x23c;
|
||||
DWORD field113_0x240;
|
||||
DWORD field114_0x244;
|
||||
DWORD field115_0x248;
|
||||
DWORD field116_0x24c;
|
||||
DWORD field117_0x250;
|
||||
DWORD field118_0x254;
|
||||
DWORD field119_0x258;
|
||||
DWORD field120_0x25c;
|
||||
DWORD field121_0x260;
|
||||
DWORD field122_0x264;
|
||||
DWORD field123_0x268;
|
||||
DWORD field124_0x26c;
|
||||
DWORD field125_0x270;
|
||||
DWORD field126_0x274;
|
||||
DWORD field127_0x278;
|
||||
DWORD field128_0x27c;
|
||||
DWORD field129_0x280;
|
||||
DWORD field130_0x284;
|
||||
DWORD field131_0x288;
|
||||
DWORD field132_0x28c;
|
||||
DWORD field133_0x290;
|
||||
DWORD field134_0x294;
|
||||
DWORD field135_0x298;
|
||||
DWORD field136_0x29c;
|
||||
DWORD field137_0x2a0;
|
||||
DWORD field138_0x2a4;
|
||||
DWORD field139_0x2a8;
|
||||
DWORD field140_0x2ac;
|
||||
DWORD field141_0x2b0;
|
||||
int field142_0x2b4;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user