Merge branch 'lich0821:master' into master

This commit is contained in:
chandler 2025-03-25 20:47:08 +08:00 committed by GitHub
commit 40fff7552f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 74 additions and 35 deletions

View File

@ -32,6 +32,7 @@
* 发送图片消息 * 发送图片消息
* 发送文件消息 * 发送文件消息
* 发送卡片消息 * 发送卡片消息
* 发送 XML
* 发送 GIF 消息 * 发送 GIF 消息
* 拍一拍群友 * 拍一拍群友
* 转发消息 * 转发消息
@ -41,6 +42,7 @@
* 获取朋友圈消息 * 获取朋友圈消息
* 下载图片、视频、文件 * 下载图片、视频、文件
* 解密图片 * 解密图片
* 通过好友申请
* 添加群成员 * 添加群成员
* 删除群成员 * 删除群成员
* 邀请群成员 * 邀请群成员
@ -205,9 +207,9 @@ WeChatFerry
## 版本更新 ## 版本更新
### v39.4.2 ### v39.4.4
* 修复附件下载类型错误 * 实现通发送 XML 功能
<details><summary>点击查看更多</summary> <details><summary>点击查看更多</summary>
@ -219,6 +221,14 @@ WeChatFerry
* `y` 是 `WeChatFerry` 的版本,从 0 开始 * `y` 是 `WeChatFerry` 的版本,从 0 开始
* `z` 是各客户端的版本,从 0 开始 * `z` 是各客户端的版本,从 0 开始
### v39.4.3
* 实现通过好友申请功能。
### v39.4.2
* 修复附件下载类型错误。
### v39.4.1 ### v39.4.1
* 修复乱码问题。 * 修复乱码问题。

View File

@ -25,7 +25,7 @@ type "DISCLAIMER.md" > temp_disclaimer.txt
:: 使用 PowerShell 显示弹窗 :: 使用 PowerShell 显示弹窗
powershell -NoProfile -Command ^ powershell -NoProfile -Command ^
"$text = Get-Content -Raw -Path 'temp_disclaimer.txt';" ^ "$text = [System.IO.File]::ReadAllText('temp_disclaimer.txt', [System.Text.Encoding]::UTF8);" ^
"Add-Type -AssemblyName PresentationFramework;" ^ "Add-Type -AssemblyName PresentationFramework;" ^
"$result = [System.Windows.MessageBox]::Show($text, '免责声明', 'OKCancel', 'Warning');" ^ "$result = [System.Windows.MessageBox]::Show($text, '免责声明', 'OKCancel', 'Warning');" ^
"if ($result -ne 'OK') { exit 1 }" "if ($result -ne 'OK') { exit 1 }"

View File

@ -17,6 +17,8 @@ namespace OsCon = Offsets::Contact;
using get_contact_mgr_t = QWORD (*)(); using get_contact_mgr_t = QWORD (*)();
using get_contact_list_t = QWORD (*)(QWORD, QWORD); using get_contact_list_t = QWORD (*)(QWORD, QWORD);
using func_verify_new_t = QWORD (*)(QWORD, WxString *);
using func_verify_ok_t = QWORD (*)(QWORD, WxString *, QWORD *, QWORD, QWORD, QWORD *, WxString *, QWORD *, WxString *);
#define FEAT_LEN 5 #define FEAT_LEN 5
static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 }; static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 };
@ -90,8 +92,30 @@ vector<RpcContact_t> get_contacts()
int accept_new_friend(const std::string &v3, const std::string &v4, int scene) int accept_new_friend(const std::string &v3, const std::string &v4, int scene)
{ {
LOG_ERROR("技术太菜,实现不了。"); // TODO: 处理来源、备注、标签等
return -1; // 成功返回 1 auto func_new = Spy::getFunction<func_verify_new_t>(OsCon::VERIFY_NEW);
auto func_verify = Spy::getFunction<func_verify_ok_t>(OsCon::VERIFY_OK);
QWORD helper = util::get_qword(Spy::WeChatDll.load() + OsCon::ADD_FRIEND_HELPER);
QWORD fvdf = util::get_qword(Spy::WeChatDll.load() + OsCon::FVDF);
QWORD mgr = util::get_qword(Spy::WeChatDll.load() + OsCon::VERIFY_MGR);
QWORD a8 = util::get_qword(Spy::WeChatDll.load() + OsCon::VERIFY_A8);
auto pV3 = util::CreateWxString(v3);
auto pV4 = util::CreateWxString(v4);
QWORD v4Array[4] = { 0 };
QWORD p_v4Buff = func_new(reinterpret_cast<QWORD>(&v4Array), pV4);
char buff[0x100] = { 0 };
memcpy(buff, &helper, sizeof(&helper));
QWORD a1 = reinterpret_cast<QWORD>(&buff);
QWORD ret = func_verify(a1, pV3, &fvdf, 0x3A08A4, p_v4Buff, &mgr, pV4, &a8, pV4);
util::FreeWxString(pV3);
util::FreeWxString(pV4);
return static_cast<int>(ret); // 成功返回 1
} }
RpcContact_t get_contact_by_wxid(const string &wxid) RpcContact_t get_contact_by_wxid(const string &wxid)

View File

@ -126,30 +126,26 @@ void Sender::send_file(const std::string &wxid, const std::string &path)
void Sender::send_xml(const std::string &receiver, const std::string &xml, const std::string &path, uint64_t type) void Sender::send_xml(const std::string &receiver, const std::string &xml, const std::string &path, uint64_t type)
{ {
#if 0 char buff1[0x500] = { 0 };
std::unique_ptr<char[]> buff(new char[0x500]()); char buff2[0x500] = { 0 };
std::unique_ptr<char[]> buff2(new char[0x500]()); char buff3[0x1C] = { 0 };
char nullBuf[0x1C] = { 0 };
func_new_chat_msg(reinterpret_cast<QWORD>(buff.get())); auto pBuff1 = func_new_chat_msg(reinterpret_cast<QWORD>(buff1));
func_new_chat_msg(reinterpret_cast<QWORD>(buff2.get())); auto pBuff2 = func_new_chat_msg(reinterpret_cast<QWORD>(buff2));
auto pBuff3 = reinterpret_cast<QWORD>(&buff3);
QWORD sbuf[4] = { 0, 0, 0, 0 }; QWORD array[4] = { 0 };
QWORD sign = func_xml_buf_sign(reinterpret_cast<QWORD>(buff2.get()), reinterpret_cast<QWORD>(sbuf), 0x1);
auto wxReceiver = new_wx_string(receiver); auto sign = func_xml_buf_sign(pBuff2, reinterpret_cast<QWORD>(&array), 0x1);
auto wxXml = new_wx_string(xml);
auto wxPath = new_wx_string(path);
auto wxSender = new_wx_string(account::get_self_wxid());
func_send_xml(reinterpret_cast<QWORD>(buff.get()), reinterpret_cast<QWORD>(wxSender.get()), util::WxStringHolder<std::string> to(receiver);
reinterpret_cast<QWORD>(wxReceiver.get()), reinterpret_cast<QWORD>(wxXml.get()), util::WxStringHolder<std::string> body(xml);
reinterpret_cast<QWORD>(wxPath.get()), reinterpret_cast<QWORD>(nullBuf), type, 0x4, sign, util::WxStringHolder<std::string> thumb(path);
reinterpret_cast<QWORD>(buff2.get())); util::WxStringHolder<std::string> from(account::get_self_wxid());
func_free_chat_msg(reinterpret_cast<QWORD>(buff.get())); func_send_xml(pBuff1, &from.wx, &to.wx, &body.wx, &thumb.wx, pBuff3, type, 0x4, sign, pBuff2);
func_free_chat_msg(reinterpret_cast<QWORD>(buff2.get())); func_free_chat_msg(pBuff1);
#endif func_free_chat_msg(pBuff2);
} }
void Sender::send_emotion(const std::string &wxid, const std::string &path) void Sender::send_emotion(const std::string &wxid, const std::string &path)

View File

@ -56,7 +56,8 @@ private:
using GetEmotionMgr_t = QWORD (*)(); using GetEmotionMgr_t = QWORD (*)();
using SendEmotion_t = QWORD (*)(QWORD, WxString *, QWORD *, WxString *, QWORD, QWORD *, QWORD, QWORD *); using SendEmotion_t = QWORD (*)(QWORD, WxString *, QWORD *, WxString *, QWORD, QWORD *, QWORD, QWORD *);
using XmlBufSign_t = QWORD (*)(QWORD, QWORD, QWORD); using XmlBufSign_t = QWORD (*)(QWORD, QWORD, QWORD);
using SendXml_t = QWORD (*)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD); using SendXml_t
= QWORD (*)(QWORD, WxString *, WxString *, WxString *, WxString *, QWORD, QWORD, QWORD, QWORD, QWORD);
New_t func_new_chat_msg; New_t func_new_chat_msg;
Free_t func_free_chat_msg; Free_t func_free_chat_msg;

View File

@ -35,6 +35,13 @@ namespace Contact
constexpr uint64_t NAME = 0xA0; constexpr uint64_t NAME = 0xA0;
constexpr uint64_t GENDER = 0x0E; constexpr uint64_t GENDER = 0x0E;
constexpr uint64_t STEP = 0x6A8; constexpr uint64_t STEP = 0x6A8;
constexpr uint64_t VERIFY_NEW = 0x2621B00;
constexpr uint64_t VERIFY_OK = 0x1F421E0;
constexpr uint64_t VERIFY_MGR = 0x4F022A8;
constexpr uint64_t VERIFY_A8 = 0x2621B91;
constexpr uint64_t ADD_FRIEND_HELPER = 0x4EE4A20;
constexpr uint64_t FVDF = 0x4F02768; // FriendVeriyDialogFragment
} }
namespace Db namespace Db
@ -112,8 +119,8 @@ namespace Message
constexpr uint64_t IMAGE = 0x22BF430; constexpr uint64_t IMAGE = 0x22BF430;
constexpr uint64_t APP_MGR = 0x1B5C2F0; constexpr uint64_t APP_MGR = 0x1B5C2F0;
constexpr uint64_t FILE = 0x20D30E0; constexpr uint64_t FILE = 0x20D30E0;
constexpr uint64_t XML = 0x0; constexpr uint64_t XML = 0x20D2210;
constexpr uint64_t XML_BUF_SIGN = 0x0; constexpr uint64_t XML_BUF_SIGN = 0x24F95C0;
constexpr uint64_t EMOTION_MGR = 0x1BD2310; constexpr uint64_t EMOTION_MGR = 0x1BD2310;
constexpr uint64_t EMOTION = 0x21B8100; constexpr uint64_t EMOTION = 0x21B8100;

View File

@ -51,7 +51,7 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 39,4,2,0 FILEVERSION 39,4,4,0
PRODUCTVERSION 3,9,12,17 PRODUCTVERSION 3,9,12,17
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
@ -69,7 +69,7 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "WeChatFerry" VALUE "CompanyName", "WeChatFerry"
VALUE "FileDescription", "WeChatFerry" VALUE "FileDescription", "WeChatFerry"
VALUE "FileVersion", "39.4.2.0" VALUE "FileVersion", "39.4.4.0"
VALUE "InternalName", "spy.dll" VALUE "InternalName", "spy.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "spy.dll" VALUE "OriginalFilename", "spy.dll"

View File

@ -44,8 +44,8 @@ python -m grpc_tools.protoc --python_out=. --proto_path=../../../WeChatFerry/rpc
## 版本更新 ## 版本更新
### v39.4.2.1 ### v39.4.4.0
* 实现视频下载方法 * 实现发送 XML 功能
<details><summary>点击查看更多</summary> <details><summary>点击查看更多</summary>
@ -59,6 +59,7 @@ python -m grpc_tools.protoc --python_out=. --proto_path=../../../WeChatFerry/rpc
功能: 功能:
* 获取登录二维码
* 查询登录状态 * 查询登录状态
* 获取登录账号信息 * 获取登录账号信息
* 获取消息类型 * 获取消息类型
@ -70,6 +71,7 @@ python -m grpc_tools.protoc --python_out=. --proto_path=../../../WeChatFerry/rpc
* 发送图片消息 * 发送图片消息
* 发送文件消息 * 发送文件消息
* 发送卡片消息 * 发送卡片消息
* 发送 XML
* 发送 GIF 消息 * 发送 GIF 消息
* 拍一拍群友 * 拍一拍群友
* 转发消息 * 转发消息
@ -77,8 +79,9 @@ python -m grpc_tools.protoc --python_out=. --proto_path=../../../WeChatFerry/rpc
* 关闭接收消息 * 关闭接收消息
* 查询数据库 * 查询数据库
* 获取朋友圈消息 * 获取朋友圈消息
* 下载图片 * 下载图片、视频、文件
* 解密图片 * 解密图片
* 通过好友申请
* 添加群成员 * 添加群成员
* 删除群成员 * 删除群成员
* 邀请群成员 * 邀请群成员

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__version__ = "39.4.2.2" __version__ = "39.4.4.0"
import atexit import atexit
import base64 import base64
@ -409,7 +409,6 @@ class Wcf():
Returns: Returns:
int: 0 为成功其他失败 int: 0 为成功其他失败
""" """
raise Exception("Not implemented, yet")
req = wcf_pb2.Request() req = wcf_pb2.Request()
req.func = wcf_pb2.FUNC_SEND_XML # FUNC_SEND_XML req.func = wcf_pb2.FUNC_SEND_XML # FUNC_SEND_XML
req.xml.receiver = receiver req.xml.receiver = receiver
@ -647,7 +646,6 @@ class Wcf():
Returns: Returns:
int: 1 为成功其他失败 int: 1 为成功其他失败
""" """
raise Exception("Not implemented, yet")
req = wcf_pb2.Request() req = wcf_pb2.Request()
req.func = wcf_pb2.FUNC_ACCEPT_FRIEND # FUNC_ACCEPT_FRIEND req.func = wcf_pb2.FUNC_ACCEPT_FRIEND # FUNC_ACCEPT_FRIEND
req.v.v3 = v3 req.v.v3 = v3