diff --git a/python/wcferry/client.py b/python/wcferry/client.py
index a53a211..ef3daa8 100644
--- a/python/wcferry/client.py
+++ b/python/wcferry/client.py
@@ -19,7 +19,7 @@ WCF_ROOT = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, WCF_ROOT)
import wcf_pb2 # noqa
-__version__ = "3.7.0.30.23"
+__version__ = "3.7.0.30.24"
def _retry():
@@ -438,6 +438,15 @@ class Wcf():
rsp = self._send_request(req)
return rsp.status
+ def receive_transfer(self, wxid: str, transferid: str) -> int:
+ """接收转账"""
+ req = wcf_pb2.Request()
+ req.func = wcf_pb2.FUNC_RECV_TRANSFER # FUNC_RECV_TRANSFER
+ req.tf.wxid = wxid
+ req.tf.tid = transferid
+ rsp = self._send_request(req)
+ return rsp.status
+
def decrypt_image(self, src: str, dst: str) -> bool:
"""解密图片:
Args:
diff --git a/rpc/proto/wcf.proto b/rpc/proto/wcf.proto
index 4d960a8..15729ea 100644
--- a/rpc/proto/wcf.proto
+++ b/rpc/proto/wcf.proto
@@ -22,6 +22,7 @@ enum Functions {
FUNC_EXEC_DB_QUERY = 0x50;
FUNC_ACCEPT_FRIEND = 0x51;
FUNC_ADD_ROOM_MEMBERS = 0x52;
+ FUNC_RECV_TRANSFER = 0x53;
FUNC_DECRYPT_IMAGE = 0x60;
}
@@ -39,6 +40,7 @@ message Request
AddMembers m = 8;
XmlMsg xml = 9;
DecPath dec = 10;
+ Transfer tf = 11;
}
}
@@ -157,6 +159,12 @@ message UserInfo
message DecPath
{
- string src = 1; // 源路径
- string dst = 2; // 目标路径
+ string src = 1; // 源路径
+ string dst = 2; // 目标路径
+}
+
+message Transfer
+{
+ string wxid = 1; // 转账人
+ string tid = 2; // 转账id transferid
}
diff --git a/spy/Spy.vcxproj b/spy/Spy.vcxproj
index c3d6591..dd1d30c 100644
--- a/spy/Spy.vcxproj
+++ b/spy/Spy.vcxproj
@@ -239,6 +239,7 @@ C:\Tools\nanopb\protoc --nanopb_out=. wcf.proto
+
@@ -262,6 +263,7 @@ C:\Tools\nanopb\protoc --nanopb_out=. wcf.proto
+
diff --git a/spy/Spy.vcxproj.filters b/spy/Spy.vcxproj.filters
index b41235e..2e558b4 100644
--- a/spy/Spy.vcxproj.filters
+++ b/spy/Spy.vcxproj.filters
@@ -87,6 +87,9 @@
头文件
+
+ 头文件
+
@@ -146,6 +149,9 @@
源文件
+
+ 源文件
+
diff --git a/spy/load_calls.cpp b/spy/load_calls.cpp
index 6119de0..b0c0bc5 100644
--- a/spy/load_calls.cpp
+++ b/spy/load_calls.cpp
@@ -22,7 +22,8 @@ WxCalls_t wxCalls = {
Exec, base, start, end, slot, name*/
{ 0x141BDF0, 0x2366934, 0x1428, 0x142C, 0x3C, 0x50 },
{ 0x771980, 0x2AE8D0, 0x1EE40E0 }, // Accept New Friend application
- { 0xE29F0, 0x771980, 0x43D8D0 } // Add chatroom members
+ { 0xE29F0, 0x771980, 0x43D8D0 }, // Add chatroom members
+ { 0x771980, 0xCD2A90 } // Receive transfer
};
int LoadCalls(const wchar_t *version, WxCalls_t *calls)
diff --git a/spy/receive_transfer.cpp b/spy/receive_transfer.cpp
new file mode 100644
index 0000000..80346c2
--- /dev/null
+++ b/spy/receive_transfer.cpp
@@ -0,0 +1,39 @@
+#include "receive_transfer.h"
+#include "load_calls.h"
+#include "log.h"
+#include "util.h"
+
+using namespace std;
+
+extern WxCalls_t g_WxCalls;
+extern DWORD g_WeChatWinDllAddr;
+
+int ReceiveTransfer(string wxid, string transferid)
+{
+ int rv = 0;
+ DWORD recvTransferCall = g_WeChatWinDllAddr + g_WxCalls.tf.call1;
+ DWORD recvTransferCall2 = g_WeChatWinDllAddr + g_WxCalls.tf.call2;
+
+ wstring wsWxid = String2Wstring(wxid);
+ wstring wsTid = String2Wstring(transferid);
+
+ LOG_DEBUG("Receiving transfer, from: {}, transferid: {}", wxid, transferid);
+ __asm {
+ pushad
+ sub esp, 0x30
+ mov ecx, esp
+ lea eax, wsTid
+ push eax
+ call recvTransferCall
+ lea ecx, dword ptr ds:[esp+0x14]
+ lea eax, wsWxid
+ push eax
+ call recvTransferCall
+ call recvTransferCall2
+ add esp, 0x30
+ mov rv, eax
+ popad
+ }
+
+ return rv;
+}
diff --git a/spy/receive_transfer.h b/spy/receive_transfer.h
new file mode 100644
index 0000000..82fd0aa
--- /dev/null
+++ b/spy/receive_transfer.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include
+
+int ReceiveTransfer(std::string wxid, std::string transferid);
diff --git a/spy/rpc_server.cpp b/spy/rpc_server.cpp
index 9183e84..bab87cb 100644
--- a/spy/rpc_server.cpp
+++ b/spy/rpc_server.cpp
@@ -31,6 +31,7 @@
#include "spy_types.h"
#include "user_info.h"
#include "util.h"
+#include "receive_transfer.h"
#define URL_SIZE 20
#define BASE_URL "tcp://0.0.0.0"
@@ -486,6 +487,28 @@ bool func_add_room_members(char *roomid, char *wxids, uint8_t *out, size_t *len)
return true;
}
+bool func_receive_transfer(char *wxid, char *transferid, uint8_t *out, size_t *len)
+{
+ Response rsp = Response_init_default;
+ rsp.func = Functions_FUNC_RECV_TRANSFER;
+ rsp.which_msg = Response_status_tag;
+ rsp.msg.status = 0;
+
+ rsp.msg.status = ReceiveTransfer(wxid, transferid);
+ if (rsp.msg.status != 1) {
+ LOG_ERROR("AddChatroomMember failed: {}", rsp.msg.status);
+ }
+
+ pb_ostream_t stream = pb_ostream_from_buffer(out, *len);
+ if (!pb_encode(&stream, Response_fields, &rsp)) {
+ LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream));
+ return false;
+ }
+ *len = stream.bytes_written;
+
+ return true;
+}
+
bool func_decrypt_image(char *src, char *dst, uint8_t *out, size_t *len)
{
Response rsp = Response_init_default;
@@ -606,6 +629,11 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
ret = func_add_room_members(req.msg.m.roomid, req.msg.m.wxids, out, out_len);
break;
}
+ case Functions_FUNC_RECV_TRANSFER: {
+ LOG_DEBUG("[Functions_FUNC_RECV_TRANSFER]");
+ ret = func_receive_transfer(req.msg.tf.wxid, req.msg.tf.tid, out, out_len);
+ break;
+ }
case Functions_FUNC_DECRYPT_IMAGE: {
LOG_DEBUG("[FUNCTIONS_FUNC_DECRYPT_IMAGE]");
ret = func_decrypt_image(req.msg.dec.src, req.msg.dec.dst, out, out_len);
diff --git a/spy/spy_types.h b/spy/spy_types.h
index c1d0654..e11860e 100644
--- a/spy/spy_types.h
+++ b/spy/spy_types.h
@@ -71,6 +71,11 @@ typedef struct Xml {
DWORD param;
} Xml_t;
+typedef struct TF {
+ DWORD call1;
+ DWORD call2;
+} TF_t;
+
typedef struct WxCalls {
DWORD login; // 登录状态
UserInfoCall_t ui; // 用户信息
@@ -84,6 +89,7 @@ typedef struct WxCalls {
Sql_t sql; // 执行 SQL
NewFriend_t anf; // 通过好友申请
RoomMember_t arm; // 添加群成员
+ TF_t tf; // 接收转账
} WxCalls_t;
typedef struct WxString {