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 {