Compare commits

..
Author SHA1 Message Date
hugy 6436ce072a fix: 返回值修改 2023-08-08 20:46:08 +08:00
hugy 58caad4f34 doc: client 2023-08-08 17:44:49 +08:00
hugy bdf91943f3 feat: 发送@消息 2023-08-08 17:41:30 +08:00
hugy 129bb55c36 feat:收藏 2023-08-05 10:52:28 +08:00
hugy e9a6e0da57 feat: sns 2023-08-04 16:40:10 +08:00
hugy 9b4d326d63 doc:更新文档 2023-07-31 16:18:05 +08:00
hugy 64ba6007a8 feat:退群和转发 2023-07-31 16:11:47 +08:00
9 changed files with 908 additions and 16 deletions
+372
View File
@@ -993,4 +993,376 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
"data": null,
"msg": "success"
}
```
#### 20.退群**
###### 接口功能
> 退群
###### 接口地址
> [/api/quitChatRoom](/api/quitChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId|string|群id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"123456@chatroom"
}
```
响应:
``` javascript
{
"code": 119536579329,
"data": null,
"msg": "success"
}
```
#### 21.转发消息**
###### 接口功能
> 转发消息
###### 接口地址
> [/api/forwardMsg](/api/forwardMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|接收人id|
|msgId|string|消息id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxid":"filehelper",
"msgId":"1233312233123"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 22.朋友圈首页**
###### 接口功能
> 朋友圈首页,前置条件需先调用hook消息接口成功,具体内容会在hook消息里返回,格式如下:
``` javascript
{
"data":[
{
"content": "",
"createTime': 1691125287,
"senderId': "",
"snsId': 123,
"xml':""
}
]
}
```
###### 接口地址
> [/api/getSNSFirstPage](/api/getSNSFirstPage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 23.朋友圈下一页**
###### 接口功能
> 朋友圈下一页
###### 接口地址
> [/api/getSNSNextPage](/api/getSNSNextPage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|snsId|number|snsId|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"snsid":123
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 24.收藏消息**
###### 接口功能
> 收藏消息
###### 接口地址
> [/api/addFavFromMsg](/api/addFavFromMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|msgId|number|消息id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"msgId":123
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 24.收藏图片**
###### 接口功能
> 收藏图片
###### 接口地址
> [/api/addFavFromImage](/api/addFavFromImage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|wxid|
|imagePath|string|图片地址|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_12333",
"imagePath":"C:\\test\\test.png"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 25.发送@消息**
###### 接口功能
> 发送@消息
###### 接口地址
> [/api/sendAtText](/api/sendAtText)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxids|string|wxid字符串,多个用,分隔,发送所有人传值"notify@all"|
|chatRoomId|string|群id|
|msg|string|消息内容|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxids":"notify@all",
"chatRoomId":"123@chatroom",
"msg":"你们好啊"
}
```
响应:
``` javascript
{
"code": 67316444768,
"data": null,
"msg": "success"
}
```
#### 26.获取群成员信息**
###### 接口功能
> 获取群成员基础信息
###### 接口地址
> [/api/getContactProfile](/api/getContactProfile)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|wxid|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
|  account|string|账号|
|  headImage|string|头像|
|  nickname|string|昵称|
|  v3|string|v3|
|  wxid|string|wxid|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_123"
}
```
响应:
``` javascript
{
"code": 1,
"data": {
"account": "account",
"headImage": "https://wx.qlogo.cn/mmhead/ver_1/0",
"nickname": "test",
"v3": "wxid_123",
"wxid": "wxid_123"
},
"msg": "success"
}
```
+121
View File
@@ -274,6 +274,127 @@ def createChatRoom():
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def quitChatRoom():
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
url = "127.0.0.1:19088/api/quitChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def forwardMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = "127.0.0.1:19088/api/forwardMsg"
payload = json.dumps({
"wxid": "filehelper",
"msgId": "12331"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSFirstPage():
url = "127.0.0.1:19088/api/getSNSFirstPage"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSNextPage():
print("modify snsId ")
raise RuntimeError("modify snsId then deleted me")
url = "127.0.0.1:19088/api/getSNSNextPage"
payload = json.dumps({
"snsId": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = "127.0.0.1:19088/api/addFavFromMsg"
payload = json.dumps({
"msgId": "1222222"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromImage():
print("modify wxid imagePath ")
raise RuntimeError("modify wxid imagePath then deleted me")
url = "127.0.0.1:19088/api/addFavFromImage"
payload = json.dumps({
"wxid": "",
"imagePath": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getContactProfile():
print("modify wxid ")
raise RuntimeError("modify wxid then deleted me")
url = "127.0.0.1:19088/api/getContactProfile"
payload = json.dumps({
"wxid": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendAtText():
print("modify wxids chatRoomId")
raise RuntimeError("modify wxids chatRoomId then deleted me")
url = "127.0.0.1:19088/api/sendAtText"
payload = json.dumps({
"wxids": "notify@all",
"chatRoomId": "123@chatroom",
"msg": "你好啊"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
if __name__ == '__main__':
checkLogin()
+3 -1
View File
@@ -17,7 +17,9 @@ GlobalContext::~GlobalContext() {
void GlobalContext::initialize(HMODULE module) {
state =GlobalContextState::INITIALIZING;
module_ = module;
// Utils::Hide(module);
#ifndef _DEBUG
Utils::Hide(module);
#endif
UINT64 base = Utils::GetWeChatWinBase();
config.emplace();
config->Initialize();
-7
View File
@@ -24,13 +24,6 @@ class GlobalContext : public Singleton<GlobalContext> {
std::unique_ptr<HttpServer> http_server;
std::unique_ptr<Manager> mgr;
// std::optional<ContactMgr> contact_mgr;
// std::optional<MiscMgr> misc_mgr;
// std::optional<SendMessageMgr> send_mgr;
// std::optional<AccountMgr> account_mgr;
// std::optional<ChatRoomMgr> chat_room_mgr;
// std::optional<SNSMgr> sns_mgr;
GlobalContextState state = GlobalContextState::NOT_INITIALIZED;
private:
+50 -4
View File
@@ -18,6 +18,8 @@ static char kServerIp[16] = "127.0.0.1";
static bool kEnableHttp = false;
static bool kLogHookFlag = false;
static bool kSnsFinishHookFlag = false;
static UINT64 (*R_DoAddMsg)(UINT64, UINT64, UINT64) = (UINT64(*)(
@@ -29,6 +31,10 @@ static UINT64 (*R_Log)(UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64,
UINT64, UINT64, UINT64,
UINT64))(Utils::GetWeChatWinBase() + offset::kHookLog);
static UINT64 (*R_OnSnsTimeLineSceneFinish)(UINT64, UINT64, UINT64) =
(UINT64(*)(UINT64, UINT64, UINT64))(Utils::GetWeChatWinBase() +
offset::kOnSnsTimeLineSceneFinish);
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
@@ -167,6 +173,39 @@ if(p== 0 || p == 1){
return p;
}
void HandleSNSMsg(INT64 param1, INT64 param2, INT64 param3) {
nlohmann::json j_sns;
INT64 begin_addr = *(INT64 *)(param2 + 0x30);
INT64 end_addr = *(INT64 *)(param2 + 0x38);
if (begin_addr == 0) {
j_sns = {{"data", nlohmann::json::array()}};
} else {
while (begin_addr < end_addr) {
nlohmann::json j_item;
j_item["snsId"] = *(UINT64 *)(begin_addr);
j_item["createTime"] = *(DWORD *)(begin_addr + 0x38);
j_item["senderId"] = Utils::ReadWstringThenConvert(begin_addr + 0x18);
j_item["content"] = Utils::ReadWstringThenConvert(begin_addr + 0x48);
j_item["xml"] = Utils::ReadWstringThenConvert(begin_addr + 0x580);
j_sns["data"].push_back(j_item);
begin_addr += 0x11E0;
}
}
std::string jstr = j_sns.dump() + '\n';
common::InnerMessageStruct *inner_msg = new common::InnerMessageStruct;
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
if (kEnableHttp) {
bool add = ThreadPool::GetInstance().AddWork(SendHttpMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add http msg work:{}", add);
} else {
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add msg work:{}", add);
}
R_OnSnsTimeLineSceneFinish(param1, param2, param3);
}
int HookSyncMsg(std::string client_ip, int port, std::string url,
uint64_t timeout, bool enable) {
if (kMsgHookFlag) {
@@ -189,15 +228,23 @@ int HookSyncMsg(std::string client_ip, int port, std::string url,
return -1;
}
DetourRestoreAfterWith();
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourAttach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kMsgHookFlag = true;
}
SPDLOG_INFO("hook sync {}",ret);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)R_OnSnsTimeLineSceneFinish, &HandleSNSMsg);
ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kSnsFinishHookFlag = true;
}
SPDLOG_INFO("hook sns {}",ret);
return ret;
}
@@ -212,7 +259,6 @@ int UnHookSyncMsg() {
UINT64 base = Utils::GetWeChatWinBase();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourDetach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
@@ -235,7 +281,7 @@ int UnHookSyncMsg() {
return -1;
}
DetourRestoreAfterWith();
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kHookLog;
+97 -4
View File
@@ -6,6 +6,8 @@
#include "hooks.h"
#include "db.h"
#define STR2ULL(str) (wxhelper::Utils::IsDigit(str) ? stoull(str) : 0)
#define STR2LL(str) (wxhelper::Utils::IsDigit(str) ? stoll(str) : 0)
#define STR2I(str) (wxhelper::Utils::IsDigit(str) ? stoi(str) : 0)
namespace common = wxhelper::common;
@@ -30,6 +32,16 @@ INT64 GetINT64Param(nlohmann::json data, std::string key) {
return result;
}
INT64 GetUINT64Param(nlohmann::json data, std::string key) {
UINT64 result;
try {
result = data[key].get<UINT64>();
} catch (nlohmann::json::exception) {
result = STR2ULL(data[key].get<std::string>());
}
return result;
}
std::string GetStringParam(nlohmann::json data, std::string key) {
return data[key].get<std::string>();
}
@@ -183,7 +195,7 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
timeout = GetIntParam(j_param, "timeout");
}
INT64 success =
wxhelper::hooks::HookSyncMsg(ip, port, url, timeout, false);
wxhelper::hooks::HookSyncMsg(ip, port, url, timeout, enable);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
@@ -406,12 +418,93 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else {
} else if (mg_http_match_uri(hm, "/api/quitChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->QuitChatRoom(room_id);
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
}
} else if (mg_http_match_uri(hm, "/api/forwardMsg")) {
INT64 msg_id = GetINT64Param(j_param, "msgId");
std::wstring wxid = GetWStringParam(j_param, "wxid");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ForwardMsg(msg_id,wxid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSFirstPage")) {
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSFirstPage();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSNextPage")) {
UINT64 snsid = GetUINT64Param(j_param, "snsId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSNextPage(snsid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromMsg")) {
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->AddFavFromMsg(msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromImage")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring image_path = GetWStringParam(j_param, "imagePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->AddFavFromImage(
wxid, image_path);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendAtText")) {
std::wstring chat_room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "wxids");
std::wstring msg = GetWStringParam(j_param, "msg");
std::vector<std::wstring> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++) {
wxid_list.push_back(wxids[i]);
}
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendAtText(
chat_room_id, wxid_list, msg);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getContactProfile")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
common::ContactProfileInner profile;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetContactByWxid(
wxid, profile);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
if (success == 1) {
nlohmann::json contact_profile = {
{"account", profile.account}, {"headImage", profile.head_image},
{"nickname", profile.nickname}, {"v3", profile.v3},
{"wxid", profile.wxid},
};
ret_data["data"] = contact_profile;
}
ret = ret_data.dump();
return ret;
} else {
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
ret = ret_data.dump();
return ret;
}
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "unreachable code."}};
ret = ret_data.dump();
+210
View File
@@ -573,4 +573,214 @@ INT64 Manager::CreateChatRoom(const std::vector<std::wstring>& wxids){
success = create_chat_room(mgr, head, end);
return success;
}
INT64 Manager::QuitChatRoom(const std::wstring &room_id) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 quit_chat_room_addr = base_addr_ + offset::kQuitChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__QuitChatRoom quit_chat_room =
(func::__QuitChatRoom)quit_chat_room_addr;
UINT64 mgr = get_chat_room_mgr();
prototype::WeChatString chat_room_id(room_id);
success = quit_chat_room(mgr, reinterpret_cast<UINT64>(&chat_room_id), 0);
return success;
}
INT64 Manager::ForwardMsg(UINT64 msg_id, const std::wstring &wxid) {
INT64 success = -1;
UINT64 forward_addr = base_addr_ + offset::kForwardMsg;
func::__ForwardMsg forward_msg = (func::__ForwardMsg)forward_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
prototype::WeChatString *recv = BuildWechatString(wxid);
success = forward_msg(reinterpret_cast<UINT64>(recv), l.QuadPart, 0x4, 0x0);
return success;
}
INT64 Manager::GetSNSFirstPage() {
INT64 success = -1;
UINT64 sns_data_mgr_addr = base_addr_ + offset::kSNSDataMgr;
UINT64 sns_first_page_addr = base_addr_ + offset::kSNSGetFirstPage;
func::__GetSNSDataMgr sns_data_mgr = (func::__GetSNSDataMgr)sns_data_mgr_addr;
func::__GetSNSFirstPage sns_first_page =
(func::__GetSNSFirstPage)sns_first_page_addr;
UINT64 mgr = sns_data_mgr();
INT64 buff[16] = {0};
success = sns_first_page(mgr, reinterpret_cast<UINT64>(&buff), 1);
return success;
}
INT64 Manager::GetSNSNextPage(UINT64 sns_id) {
INT64 success = -1;
UINT64 time_line_mgr_addr = base_addr_ + offset::kSNSTimeLineMgr;
UINT64 sns_next_page_addr = base_addr_ + offset::kSNSGetNextPageScene;
func::__GetSnsTimeLineMgr time_line_mgr =
(func::__GetSnsTimeLineMgr)time_line_mgr_addr;
func::__GetSNSNextPageScene sns_next_page =
(func::__GetSNSNextPageScene)sns_next_page_addr;
UINT64 mgr = time_line_mgr();
success = sns_next_page(mgr, sns_id);
return success;
}
INT64 Manager::AddFavFromMsg(UINT64 msg_id) {
INT64 success = -1;
UINT64 get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
UINT64 get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
UINT64 add_fav_addr = base_addr_ + offset::kAddFavFromMsg;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
func::__GetMgrByPrefixLocalId get_by_local_id = (func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
UINT64 new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
func::__AddFavFromMsg add_fav = (func::__AddFavFromMsg)add_fav_addr;
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
func::__GetFavoriteMgr get_favorite_mgr = (func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
char chat_msg[0x460]= {0};
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 p_chat_msg = new_chat_msg(reinterpret_cast<UINT64>(&chat_msg));
get_chat_mgr();
get_by_local_id(l.QuadPart,p_chat_msg);
UINT64 mgr = get_favorite_mgr();
success = add_fav(mgr,p_chat_msg);
free_chat_msg(p_chat_msg);
return success;
}
INT64 Manager::AddFavFromImage(const std::wstring &wxid,
const std::wstring &image_path) {
INT64 success = -1;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 add_fav_from_image_addr = base_addr_ + offset::kAddFavFromImage;
prototype::WeChatString *send_id = BuildWechatString(wxid);
prototype::WeChatString *path = BuildWechatString(image_path);
func::__GetFavoriteMgr get_favorite_mgr =
(func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__AddFavFromImage add_fav_from_image =
(func::__AddFavFromImage)add_fav_from_image_addr;
UINT64 mgr = get_favorite_mgr();
success = add_fav_from_image(mgr, reinterpret_cast<UINT64>(path),
reinterpret_cast<UINT64>(send_id));
return success;
}
INT64 Manager::SendAtText(const std::wstring &room_id,
const std::vector<std::wstring> &wxids,
const std::wstring &msg) {
INT64 success = -1;
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
std::wstring at_msg = L"";
int number = 0;
for (unsigned int i = 0; i < wxids.size(); i++) {
std::wstring nickname;
std::wstring at_all = L"notify@all";
if (at_all.compare(wxids[i]) == 0 ) {
nickname = L"所有人";
} else {
nickname = GetContactOrChatRoomNickname(wxids[i]);
}
if (nickname.length() == 0) {
continue;
}
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
at_msg = at_msg + L"@" + nickname + L" ";
number++;
}
if (number < 1) {
return success;
}
at_msg += msg;
INT64 head = (INT64)&list->start;
prototype::WeChatString to_user(room_id);
prototype::WeChatString text_msg(at_msg);
UINT64 send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
UINT64 send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
char chat_msg[0x460] = {0};
func::__GetSendMessageMgr mgr;
mgr = (func::__GetSendMessageMgr)send_message_mgr_addr;
func::__SendTextMsg send;
send = (func::__SendTextMsg)send_text_msg_addr;
func::__FreeChatMsg free;
free = (func::__FreeChatMsg)free_chat_msg_addr;
mgr();
success = send(reinterpret_cast<UINT64>(&chat_msg),
reinterpret_cast<UINT64>(&to_user),
reinterpret_cast<UINT64>(&text_msg), head, 1, 1, 0, 0);
free(reinterpret_cast<UINT64>(&chat_msg));
return success;
}
std::wstring Manager::GetContactOrChatRoomNickname(const std::wstring &wxid) {
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
INT64 success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
if (success == 1) {
std::wstring nickname = Utils::ReadWstring(contact + 0xA0);
free_contact(contact);
return nickname;
} else {
free_contact(contact);
return L"";
}
}
INT64 Manager::GetContactByWxid(const std::wstring &wxid,
common::ContactProfileInner &profile) {
INT64 success = -1;
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
profile.wxid = Utils::ReadWstringThenConvert(contact + 0x10);
profile.account = Utils::ReadWstringThenConvert(contact + 0x30);
profile.v3 = Utils::ReadWstringThenConvert(contact + 0x50);
profile.nickname = Utils::ReadWstringThenConvert(contact + 0xA0);
profile.head_image = Utils::ReadWstringThenConvert(contact + 0x188);
free_contact(contact);
return success;
}
} // namespace wxhelper
+13
View File
@@ -30,6 +30,19 @@ class Manager {
INT64 InviteMemberToChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& wxids);
INT64 CreateChatRoom(const std::vector<std::wstring>& wxids);
INT64 QuitChatRoom(const std::wstring& room_id);
INT64 ForwardMsg(UINT64 msg_id, const std::wstring& wxid);
INT64 GetSNSFirstPage();
INT64 GetSNSNextPage(UINT64 sns_id);
INT64 AddFavFromMsg(UINT64 msg_id);
INT64 AddFavFromImage(const std::wstring& wxid,
const std::wstring& image_path);
INT64 SendAtText(const std::wstring& room_id,
const std::vector<std::wstring>& wxids,
const std::wstring& msg);
std::wstring GetContactOrChatRoomNickname(const std::wstring& wxid);
INT64 GetContactByWxid(const std::wstring& wxid,
common::ContactProfileInner& profile);
private:
UINT64 base_addr_;
+42
View File
@@ -198,6 +198,16 @@ struct ChatRoomMemberInner {
member("") {}
};
struct ContactProfileInner {
std::string wxid;
std::string account;
std::string v3;
std::string nickname;
std::string head_image;
ContactProfileInner()
: wxid(""), account(""), v3(""), nickname(""), head_image("") {}
};
} // namespace common
namespace V3_9_5_81 {
namespace function {
@@ -238,6 +248,22 @@ typedef UINT64 (*__RemoveTopMsg)(UINT64,UINT64,UINT64);
typedef UINT64 (*__InviteMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__CreateChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__QuitChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__ForwardMsg)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSFirstPage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSNextPageScene)(UINT64,UINT64);
typedef UINT64 (*__GetSNSDataMgr)();
typedef UINT64 (*__GetSnsTimeLineMgr)();
typedef UINT64 (*__GetMgrByPrefixLocalId)(UINT64,UINT64);
typedef UINT64 (*__AddFavFromMsg)(UINT64,UINT64);
typedef UINT64 (*__GetChatMgr)();
typedef UINT64 (*__GetFavoriteMgr)();
typedef UINT64 (*__AddFavFromImage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetContact)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewContact)(UINT64);
typedef UINT64 (*__FreeContact)(UINT64);
} // namespace function
@@ -342,6 +368,22 @@ const UINT64 kInviteMember = 0xe63650;
const UINT64 kHookLog = 0x1304e60;
const UINT64 kCreateChatRoom = 0xe63340;
const UINT64 kQuitChatRoom = 0xe6e3b0;
const UINT64 kForwardMsg = 0xfcd0f0;
const UINT64 kOnSnsTimeLineSceneFinish = 0x1a73150;
const UINT64 kSNSGetFirstPage = 0x1a51dd0;
const UINT64 kSNSGetNextPageScene = 0x1a77240;
const UINT64 kSNSDataMgr = 0xeebda0;
const UINT64 kSNSTimeLineMgr = 0x19e83a0;
const UINT64 kGetMgrByPrefixLocalId = 0xe4add0;
const UINT64 kAddFavFromMsg = 0x1601520;
const UINT64 kGetChatMgr = 0x8f0400;
const UINT64 kGetFavoriteMgr = 0x8c69b0;
const UINT64 kAddFavFromImage = 0x160b920;
const UINT64 kGetContact = 0xEA5F90;
const UINT64 kNewContact = 0x1212e40;
const UINT64 kFreeContact = 0x12134e0;
} // namespace offset
} // namespace V3_9_5_81