commit
1ae4c4b30c
233
README.MD
233
README.MD
@ -1,7 +1,8 @@
|
|||||||
# WeChatFerry
|
# WeChatFerry
|
||||||
|
|
||||||
一个玩微信的工具。更多介绍见:[WeChatFerry: 一个玩微信的工具](https://mp.weixin.qq.com/s/CGLfSaNDy8MyuyPWGjGJ7w)。
|
一个玩微信的工具。更多介绍见:[WeChatFerry: 一个玩微信的工具](https://mp.weixin.qq.com/s/CGLfSaNDy8MyuyPWGjGJ7w)。
|
||||||
|
|
||||||
<details><summary><font color="#FF0000" size="5">免责声明【必读】</font></summary>
|
<details><summary><font color="red" size="12">免责声明【必读】</font></summary>
|
||||||
|
|
||||||
本工具仅供学习和技术研究使用,不得用于任何商业或非法行为,否则后果自负。
|
本工具仅供学习和技术研究使用,不得用于任何商业或非法行为,否则后果自负。
|
||||||
|
|
||||||
@ -15,101 +16,22 @@
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|[📖 Python 文档](https://wechatferry.readthedocs.io/)|[📺 Python 视频教程](https://mp.weixin.qq.com/s/APdjGyZ2hllXxyG_sNCfXQ)|[🙋 FAQ](https://mp.weixin.qq.com/s/WOw26mKJG8Nq55cT6iG-yA)|
|
|
||||||
|:-:|:-:|:-:|
|
|
||||||
|
|
||||||
👉 [WeChatRobot🤖](https://github.com/lich0821/WeChatRobot),一个基于 WeChatFerry 的 Python 机器人框架。
|
|
||||||
|
|
||||||
<details><summary>点击查看功能清单</summary>
|
|
||||||
|
|
||||||
* 检查登录状态
|
|
||||||
* 获取登录账号的 wxid
|
|
||||||
* 获取消息类型
|
|
||||||
* 获取所有联系人
|
|
||||||
* 获取所有好友
|
|
||||||
* 获取数据库
|
|
||||||
* 获取某数据库下的表
|
|
||||||
* 获取用户信息
|
|
||||||
* 发送文本消息(可 @)
|
|
||||||
* 发送图片
|
|
||||||
* 发送文件
|
|
||||||
* 允许接收消息
|
|
||||||
* 停止接收消息
|
|
||||||
* 执行 SQL 查询
|
|
||||||
* 接受好友申请
|
|
||||||
* 添加群成员
|
|
||||||
* 删除群成员
|
|
||||||
* 解密图片
|
|
||||||
* 获取朋友圈消息
|
|
||||||
* 保存图片
|
|
||||||
* 保存语音
|
|
||||||
* 发送卡片消息
|
|
||||||
* 拍一拍群友
|
|
||||||
* 邀请群成员
|
|
||||||
* 图片 OCR
|
|
||||||
* 转发消息
|
|
||||||
* 撤回消息
|
|
||||||
* 获取登录二维码
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details><summary>点击查看支持的客户端</summary>
|
|
||||||
|
|
||||||
* Go
|
|
||||||
* HTTP (Go, Rust)
|
|
||||||
* Java
|
|
||||||
* Node.js
|
|
||||||
* Python
|
|
||||||
* Rust
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|||
|
|||
|
||||||
|:-:|:-:|
|
|:-:|:-:|
|
||||||
|后台回复 `WCF` 加群交流|如果你觉得有用|
|
|后台回复 `WCF` 加群交流|如果你觉得有用|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
### Python
|
|
||||||
[](https://pypi.python.org/pypi/wcferry) [](https://pypi.python.org/pypi/wcferry) [](https://wechatferry.readthedocs.io/zh/latest/?badge=latest)
|
|
||||||
|
|
||||||
* 安装
|
|
||||||
```sh
|
|
||||||
pip install --upgrade wcferry
|
|
||||||
```
|
|
||||||
|
|
||||||
* 参考框架:[🤖WeChatRobot](https://github.com/lich0821/WeChatRobot)
|
|
||||||
|
|
||||||
### HTTP
|
|
||||||
#### [wcfrust](https://github.com/lich0821/wcf-client-rust)(基于 Rust)
|
|
||||||
开箱即用:[快速开始](https://github.com/lich0821/wcf-client-rust?tab=readme-ov-file#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)。
|
|
||||||
|
|
||||||
#### GoHttp(基于 Go)
|
|
||||||
参考 [GoHttp README.MD](clients/gohttp/README.md)
|
|
||||||
|
|
||||||
#### ~~wcfhttp(基于 Python)~~
|
|
||||||
❗ **wcfhttp 不再维护,有需要可以使用 [WcfRust](https://github.com/lich0821/wcf-client-rust) 或者 [GoHttp](clients/gohttp/README.md)。**
|
|
||||||
|
|
||||||
其余客户端,可下载 [最新发布的版本](https://github.com/lich0821/WeChatFerry/releases/latest),根据技术栈,选择客户端,将相应 `dll` 和 `exe` 文件放到对应位置。
|
|
||||||
|
|
||||||
### Go
|
|
||||||
参考 [Go README.MD](clients/go/README.md)
|
|
||||||
|
|
||||||
### Java
|
|
||||||
参考 [Java README.MD](clients/java/README.MD)
|
|
||||||
|
|
||||||
### Node.js
|
|
||||||
参考 [Node.js README.MD](https://github.com/stkevintan/node-wcferry/blob/main/README.md)
|
|
||||||
|
|
||||||
### Rust
|
|
||||||
参考 [Rust README.MD](clients/rust/README.MD)
|
|
||||||
|
|
||||||
## 一起开发
|
## 一起开发
|
||||||
|
|
||||||
> 🚫 非开发用户不需要往下看。
|
> 🚫 非开发用户不需要往下看。
|
||||||
|
|
||||||
### 安装开发环境
|
### 安装开发环境
|
||||||
|
|
||||||
<details><summary>点击查看</summary>
|
<details><summary>点击查看</summary>
|
||||||
|
|
||||||
#### 安装 vcpkg
|
#### 安装 vcpkg
|
||||||
|
|
||||||
* 安装,参考[Vcpkg: 总览](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md)。
|
* 安装,参考[Vcpkg: 总览](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md)。
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd C:\Tools
|
cd C:\Tools
|
||||||
git clone https://github.com/microsoft/vcpkg
|
git clone https://github.com/microsoft/vcpkg
|
||||||
@ -117,14 +39,16 @@ git clone https://github.com/microsoft/vcpkg
|
|||||||
```
|
```
|
||||||
|
|
||||||
* 添加全局配置:
|
* 添加全局配置:
|
||||||
环境变量增加 `vcpkg` 所在路径(本文为:`C:\Tools\vcpkg`)。
|
环境变量增加 `vcpkg` 所在路径(本项目为:`C:\Tools\vcpkg`)。
|
||||||
|
|
||||||
#### 安装相关组件
|
#### 安装相关组件
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
vcpkg install protobuf[zlib]:x86-windows-static
|
vcpkg install protobuf[zlib]:x64-windows-static
|
||||||
vcpkg install spdlog:x86-windows-static
|
vcpkg install spdlog:x64-windows-static
|
||||||
vcpkg install nng:x86-windows-static
|
vcpkg install nng:x64-windows-static
|
||||||
vcpkg install magic-enum:x86-windows-static
|
vcpkg install magic-enum:x64-windows-static
|
||||||
|
vcpkg install minhook:x64-windows-static
|
||||||
vcpkg integrate install
|
vcpkg integrate install
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -134,32 +58,56 @@ vcpkg integrate install
|
|||||||
|
|
||||||
#### 安装 Python3
|
#### 安装 Python3
|
||||||
|
|
||||||
通过微软商店或者 python.org 自行下载均可,注意配置好环境变量,确保 `python3` 在命令行下可用
|
通过微软商店或者 python.org 自行下载均可,注意配置好环境变量,确保 `python3` 在命令行下可用。
|
||||||
|
|
||||||
|
安装依赖:
|
||||||
|
```sh
|
||||||
|
pip install grpcio-tools==1.48.2
|
||||||
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 编译
|
### 编译
|
||||||
使用 VS2019 打开工程,编译即可。
|
|
||||||
|
使用 VS2019 打开工程,编译即可。编译成功后,在 `WeChatFerry\WeChatFerry\Out` 目录中会看到相应的 DLL 文件。
|
||||||
|
|
||||||
**注**:如果遇到执行 `protoc` 时的 9009 错误,检查是否是 python3 环境有问题,或者 protoc 命令的环境变量配置不正确。
|
**注**:如果遇到执行 `protoc` 时的 9009 错误,检查是否是 python3 环境有问题,或者 protoc 命令的环境变量配置不正确。
|
||||||
|
|
||||||
### 运行
|
### 运行
|
||||||
运行 `wcf.exe` 启动
|
```py
|
||||||
```sh
|
import ctypes
|
||||||
wcf.exe --help
|
# 加载 sdk.dll (需要绝对路径)
|
||||||
|
sdk = ctypes.cdll.LoadLibrary("C:/Projs/WeChatFerry/WeChatFerry/Out/sdk.dll")
|
||||||
|
|
||||||
|
# 初始化
|
||||||
|
sdk.WxInitSDK(False, 10086)
|
||||||
|
|
||||||
|
# 退出 SDK
|
||||||
|
sdk.WxDestroySDK()
|
||||||
|
|
||||||
|
# 注意关闭 Python 进程
|
||||||
|
```
|
||||||
|
|
||||||
|
### 调试日志
|
||||||
|
```c
|
||||||
|
DbgMsg("ListenMessage"); // 封装的 OutputDebugString
|
||||||
|
OutputDebugString(L"ListenMessage\n");
|
||||||
|
MessageBox(NULL, L"ListenMessage", L"ListenMessage", 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
WeChatFerry
|
WeChatFerry
|
||||||
├── LICENSE # LICENSE
|
├── LICENSE # LICENSE
|
||||||
├── README.MD # 说明
|
├── README.MD # 说明
|
||||||
├── WeChatFerry
|
├── WeChatFerry
|
||||||
│ ├── WeChatFerry.sln # VS2019 工程文件
|
│ ├── WeChatFerry.sln # VS2019 工程文件
|
||||||
|
│ ├── com # 公共模块
|
||||||
│ ├── rpc # RPC 模块
|
│ ├── rpc # RPC 模块
|
||||||
│ ├── sdk # 注入及启动模块
|
│ ├── sdk # 注入及启动模块
|
||||||
│ ├── spy # 核心功能实现模块
|
│ ├── smc # Silk-Mp3 转换模块
|
||||||
│ └── wcf # 命令行版启动器
|
│ └── spy # 核心功能实现模块
|
||||||
├── assets
|
├── assets
|
||||||
│ ├── QR.jpeg # 二维码,测试用图
|
│ ├── QR.jpeg # 二维码,测试用图
|
||||||
│ ├── TEQuant.jpg # 二维码,测试用图
|
│ ├── TEQuant.jpg # 二维码,测试用图
|
||||||
@ -177,47 +125,13 @@ WeChatFerry
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<details><summary>点击查看</summary>
|
|
||||||
|
|
||||||
### go
|
|
||||||
Go 客户端。
|
|
||||||
|
|
||||||
### gohttp
|
|
||||||
HTTP 客户端,二进制发布无依赖
|
|
||||||
|
|
||||||
### http
|
|
||||||
HTTP 客户端。
|
|
||||||
|
|
||||||
### node
|
|
||||||
Node.js 客户端.
|
|
||||||
|
|
||||||
### java
|
|
||||||
Java 客户端。
|
|
||||||
|
|
||||||
### python
|
|
||||||
Python 客户端。
|
|
||||||
|
|
||||||
### rpc
|
|
||||||
RPC 的通信部分和序列化 / 反序列化部分。
|
|
||||||
|
|
||||||
### rust
|
|
||||||
Rust 客户端。
|
|
||||||
|
|
||||||
### sdk
|
|
||||||
负责将 `spy` 注入微信进程,并启动 RPC 服务。
|
|
||||||
|
|
||||||
### spy
|
|
||||||
间谍模块,注入到微信中,通过 RPC 做消息转发工作。
|
|
||||||
|
|
||||||
### wcf
|
|
||||||
命令行版启动器,调用 `sdk` 将 `spy` 注入微信。其他客户端可通过 RPC 连接到 `spy` 进行消息传递。默认监听的地址为 `tcp://0.0.0.0:10086` 和 `tcp://0.0.0.0:10087`。一般情况不需要显式运行,各客户端自动调用。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 版本更新
|
## 版本更新
|
||||||
|
|
||||||
### v39.0.14 (2024.02.18)
|
### v39.1.0 (2024.04.19)
|
||||||
* 修复获取登录二维码问题
|
|
||||||
|
* 适配 x64 环境
|
||||||
|
* 重构项目
|
||||||
|
* 开始适配 `3.9.10.19`
|
||||||
|
|
||||||
<details><summary>点击查看更多</summary>
|
<details><summary>点击查看更多</summary>
|
||||||
|
|
||||||
@ -229,21 +143,29 @@ Rust 客户端。
|
|||||||
* `y` 是 `WeChatFerry` 的版本,从 0 开始
|
* `y` 是 `WeChatFerry` 的版本,从 0 开始
|
||||||
* `z` 是各客户端的版本,从 0 开始
|
* `z` 是各客户端的版本,从 0 开始
|
||||||
|
|
||||||
|
### v39.0.14 (2024.02.18)
|
||||||
|
|
||||||
|
* 修复获取登录二维码问题
|
||||||
|
|
||||||
### v39.0.13 (2024.02.14)
|
### v39.0.13 (2024.02.14)
|
||||||
|
|
||||||
* 修复若干问题
|
* 修复若干问题
|
||||||
* 撤回消息
|
* 撤回消息
|
||||||
* 获取登录二维码
|
* 获取登录二维码
|
||||||
|
|
||||||
### v39.0.12 (2023.12.20)
|
### v39.0.12 (2023.12.20)
|
||||||
|
|
||||||
* 修复一个问题
|
* 修复一个问题
|
||||||
* 消息转发
|
* 消息转发
|
||||||
|
|
||||||
### v39.0.11 (2023.12.16)
|
### v39.0.11 (2023.12.16)
|
||||||
|
|
||||||
* 修复 PB 消息类型(可能会导致非 Python 客户端崩溃)
|
* 修复 PB 消息类型(可能会导致非 Python 客户端崩溃)
|
||||||
* 修复日志错误
|
* 修复日志错误
|
||||||
* 移除非必要依赖
|
* 移除非必要依赖
|
||||||
|
|
||||||
### v39.0.10 (2023.12.08)
|
### v39.0.10 (2023.12.08)
|
||||||
|
|
||||||
* 代码优化
|
* 代码优化
|
||||||
* 发送卡片消息
|
* 发送卡片消息
|
||||||
* 拍一拍群友
|
* 拍一拍群友
|
||||||
@ -251,30 +173,39 @@ Rust 客户端。
|
|||||||
* 图片 OCR
|
* 图片 OCR
|
||||||
|
|
||||||
### v39.0.7 (2023.12.03)
|
### v39.0.7 (2023.12.03)
|
||||||
|
|
||||||
* 保存语音
|
* 保存语音
|
||||||
|
|
||||||
### v39.0.6 (2023.11.26)
|
### v39.0.6 (2023.11.26)
|
||||||
|
|
||||||
* 修复下载图片退出问题
|
* 修复下载图片退出问题
|
||||||
|
|
||||||
### v39.0.5 (2023.11.22)
|
### v39.0.5 (2023.11.22)
|
||||||
|
|
||||||
* 修复收到某些文件崩溃问题
|
* 修复收到某些文件崩溃问题
|
||||||
|
|
||||||
### v39.0.4 (2023.11.21)
|
### v39.0.4 (2023.11.21)
|
||||||
|
|
||||||
* 下载图片、文件和视频
|
* 下载图片、文件和视频
|
||||||
|
|
||||||
### v39.0.3 (2023.09.28)
|
### v39.0.3 (2023.09.28)
|
||||||
|
|
||||||
* 修复登录账号昵称超长报错问题
|
* 修复登录账号昵称超长报错问题
|
||||||
|
|
||||||
### v39.0.2 (2023.07.16)
|
### v39.0.2 (2023.07.16)
|
||||||
|
|
||||||
* 修复朋友圈消息 `is_group` 为 `True` 问题
|
* 修复朋友圈消息 `is_group` 为 `True` 问题
|
||||||
|
|
||||||
### v39.0.1 (2023.07.16)
|
### v39.0.1 (2023.07.16)
|
||||||
|
|
||||||
* 获取朋友圈消息
|
* 获取朋友圈消息
|
||||||
|
|
||||||
### v39.0.0 (2023.07.14)
|
### v39.0.0 (2023.07.14)
|
||||||
|
|
||||||
升级到 `3.9.2.23`。
|
升级到 `3.9.2.23`。
|
||||||
|
|
||||||
### v37.1.25 (2023.05.07)
|
### v37.1.25 (2023.05.07)
|
||||||
|
|
||||||
更新版本编码。
|
更新版本编码。
|
||||||
|
|
||||||
根据新版本编码规则:
|
根据新版本编码规则:
|
||||||
@ -283,6 +214,7 @@ Rust 客户端。
|
|||||||
* HTTP 客户端 `wcfhttp` 的 `v3.7.0.30.25` 应该调整为 `v37.1.25.0`
|
* HTTP 客户端 `wcfhttp` 的 `v3.7.0.30.25` 应该调整为 `v37.1.25.0`
|
||||||
|
|
||||||
### v3.7.0.30.25 (2023.05.05)
|
### v3.7.0.30.25 (2023.05.05)
|
||||||
|
|
||||||
* 修复群消息判断错误
|
* 修复群消息判断错误
|
||||||
* 修复名片添加好友问题
|
* 修复名片添加好友问题
|
||||||
* 修复获取数据库多余字符问题
|
* 修复获取数据库多余字符问题
|
||||||
@ -290,105 +222,136 @@ Rust 客户端。
|
|||||||
* Python 客户端发送图片支持网络路径
|
* Python 客户端发送图片支持网络路径
|
||||||
|
|
||||||
### v3.7.0.30.24 (2023.04.19)
|
### v3.7.0.30.24 (2023.04.19)
|
||||||
|
|
||||||
实现了一个功能。
|
实现了一个功能。
|
||||||
|
|
||||||
### v3.7.0.30.23 (2023.04.13)
|
### v3.7.0.30.23 (2023.04.13)
|
||||||
|
|
||||||
* 解密图片
|
* 解密图片
|
||||||
* 获取登录账号信息
|
* 获取登录账号信息
|
||||||
* 获取联系人备注
|
* 获取联系人备注
|
||||||
|
|
||||||
### v3.7.0.30.22(2023.04.09)
|
### v3.7.0.30.22(2023.04.09)
|
||||||
|
|
||||||
将监听端口调整为可配置。
|
将监听端口调整为可配置。
|
||||||
|
|
||||||
### v3.7.0.30.21(2023.03.15)
|
### v3.7.0.30.21(2023.03.15)
|
||||||
|
|
||||||
* 发送表情
|
* 发送表情
|
||||||
|
|
||||||
### v3.7.0.30.20(2023.03.12)
|
### v3.7.0.30.20(2023.03.12)
|
||||||
|
|
||||||
修复 wxid 获取问题。
|
修复 wxid 获取问题。
|
||||||
|
|
||||||
### v3.7.0.30.19(2023.03.06)
|
### v3.7.0.30.19(2023.03.06)
|
||||||
|
|
||||||
修复重复消息问题。
|
修复重复消息问题。
|
||||||
|
|
||||||
### v3.7.0.30.18(2023.03.05)
|
### v3.7.0.30.18(2023.03.05)
|
||||||
|
|
||||||
修复添加好友问题。
|
修复添加好友问题。
|
||||||
|
|
||||||
### v3.7.0.30.17(2023.03.05)
|
### v3.7.0.30.17(2023.03.05)
|
||||||
|
|
||||||
修复获取登录账号 wxid 问题。
|
修复获取登录账号 wxid 问题。
|
||||||
|
|
||||||
### v3.7.0.30.16(2023.03.04)
|
### v3.7.0.30.16(2023.03.04)
|
||||||
|
|
||||||
将错误码改成错误消息,方便调试。
|
将错误码改成错误消息,方便调试。
|
||||||
|
|
||||||
### v3.7.0.30.15(2023.03.01)
|
### v3.7.0.30.15(2023.03.01)
|
||||||
|
|
||||||
* 发送 xml
|
* 发送 xml
|
||||||
|
|
||||||
### v3.7.0.30.14(2023.02.28)
|
### v3.7.0.30.14(2023.02.28)
|
||||||
|
|
||||||
* 添加群成员
|
* 添加群成员
|
||||||
|
|
||||||
### v3.7.0.30.13(2023.02.27)
|
### v3.7.0.30.13(2023.02.27)
|
||||||
|
|
||||||
去除 gRPC 框架,自定义更轻量的 RPC 轮子 `nnprc`。
|
去除 gRPC 框架,自定义更轻量的 RPC 轮子 `nnprc`。
|
||||||
|
|
||||||
### v3.7.0.30.12(2023.01.20)
|
### v3.7.0.30.12(2023.01.20)
|
||||||
|
|
||||||
* 更新 Python 客户端
|
* 更新 Python 客户端
|
||||||
* 修改监听地址为 `0.0.0.0:10086`
|
* 修改监听地址为 `0.0.0.0:10086`
|
||||||
* 增加 `Launcher`,直接注入 `spy`
|
* 增加 `Launcher`,直接注入 `spy`
|
||||||
|
|
||||||
### v3.7.0.30.11(2022.10.19)
|
### v3.7.0.30.11(2022.10.19)
|
||||||
|
|
||||||
更新 Python 客户端。
|
更新 Python 客户端。
|
||||||
|
|
||||||
### v3.7.0.30-gRPC-2(2022.10.18)
|
### v3.7.0.30-gRPC-2(2022.10.18)
|
||||||
|
|
||||||
增加 Java 客户端。
|
增加 Java 客户端。
|
||||||
|
|
||||||
### v3.7.0.30-gRPC-1(2022.10.16)
|
### v3.7.0.30-gRPC-1(2022.10.16)
|
||||||
|
|
||||||
将 RPC 框架切换为 gRPC!
|
将 RPC 框架切换为 gRPC!
|
||||||
|
|
||||||
### v3.7.0.30-8(2022.09.25)
|
### v3.7.0.30-8(2022.09.25)
|
||||||
|
|
||||||
* 获取登录账号微信 ID
|
* 获取登录账号微信 ID
|
||||||
|
|
||||||
### v3.7.0.30-7(2022.09.24)
|
### v3.7.0.30-7(2022.09.24)
|
||||||
|
|
||||||
修复群聊有系统消息时会崩溃 bug。后续考虑把消息来源交还给客户端自己区别。
|
修复群聊有系统消息时会崩溃 bug。后续考虑把消息来源交还给客户端自己区别。
|
||||||
|
|
||||||
### v3.7.0.30-6(2022.08.21)
|
### v3.7.0.30-6(2022.08.21)
|
||||||
|
|
||||||
* 通过好友验证
|
* 通过好友验证
|
||||||
|
|
||||||
### v3.7.0.30-5(2022.08.20)
|
### v3.7.0.30-5(2022.08.20)
|
||||||
|
|
||||||
* 执行 SQL 语句
|
* 执行 SQL 语句
|
||||||
|
|
||||||
### v3.7.0.30-4(2022.08.20)
|
### v3.7.0.30-4(2022.08.20)
|
||||||
|
|
||||||
修复群消息 @人 功能。有几点注意事项:
|
修复群消息 @人 功能。有几点注意事项:
|
||||||
1. `vAtWxids` 是要 `@` 的 `wxid` 清单,以 `,` 分隔。
|
1. `vAtWxids` 是要 `@` 的 `wxid` 清单,以 `,` 分隔。
|
||||||
2. 只有群主才能 `@所有人`,非群主硬发 `@所有人` 会导致消息发不出去;`@所有人` 对应 `vAtWxids` 为 `"notify@all"`。
|
2. 只有群主才能 `@所有人`,非群主硬发 `@所有人` 会导致消息发不出去;`@所有人` 对应 `vAtWxids` 为 `"notify@all"`。
|
||||||
3. 消息体里 `@` 的数量必须与 `vAtWxids` 里的数量一致,否则消息能发出但 `@` 功能失效。
|
3. 消息体里 `@` 的数量必须与 `vAtWxids` 里的数量一致,否则消息能发出但 `@` 功能失效。
|
||||||
|
|
||||||
### v3.7.0.30-3(2022.08.20)
|
### v3.7.0.30-3(2022.08.20)
|
||||||
|
|
||||||
修复可重入 bug。
|
修复可重入 bug。
|
||||||
|
|
||||||
### v3.7.0.30-2(2022.08.14)
|
### v3.7.0.30-2(2022.08.14)
|
||||||
|
|
||||||
优化 Hook 和 Inject 代码,实现可重入。
|
优化 Hook 和 Inject 代码,实现可重入。
|
||||||
|
|
||||||
### v3.7.0.30-1(2022.08.12)
|
### v3.7.0.30-1(2022.08.12)
|
||||||
|
|
||||||
适配微信 `3.7.0.30`。
|
适配微信 `3.7.0.30`。
|
||||||
|
|
||||||
### v3.7.0.29-3(2022.08.7)
|
### v3.7.0.29-3(2022.08.7)
|
||||||
|
|
||||||
* 查询数据库,获取库、表。
|
* 查询数据库,获取库、表。
|
||||||
|
|
||||||
### v3.7.0.29-2(2022.08.7)
|
### v3.7.0.29-2(2022.08.7)
|
||||||
|
|
||||||
优化 RPC。
|
优化 RPC。
|
||||||
|
|
||||||
### v3.7.0.29-1(2022.08.7)
|
### v3.7.0.29-1(2022.08.7)
|
||||||
|
|
||||||
适配微信 `3.7.0.29`。
|
适配微信 `3.7.0.29`。
|
||||||
|
|
||||||
### v3.3.0.115-3(2021.08.28)
|
### v3.3.0.115-3(2021.08.28)
|
||||||
|
|
||||||
适配微信 `3.3.0.115`,新增功能:
|
适配微信 `3.3.0.115`,新增功能:
|
||||||
* 获取所有联系人
|
* 获取所有联系人
|
||||||
|
|
||||||
### v3.3.0.115-2(2021.08.22)
|
### v3.3.0.115-2(2021.08.22)
|
||||||
|
|
||||||
适配微信 `3.3.0.115`,新增功能:
|
适配微信 `3.3.0.115`,新增功能:
|
||||||
* 发送图片消息
|
* 发送图片消息
|
||||||
|
|
||||||
### v3.3.0.115-1(2021.08.22)
|
### v3.3.0.115-1(2021.08.22)
|
||||||
|
|
||||||
适配微信 `3.3.0.115`。
|
适配微信 `3.3.0.115`。
|
||||||
|
|
||||||
### v3.0.0.57-1(2021.02.12)
|
### v3.0.0.57-1(2021.02.12)
|
||||||
|
|
||||||
适配微信 `3.0.0.57`,支持功能:
|
适配微信 `3.0.0.57`,支持功能:
|
||||||
* 登录状态判断
|
* 登录状态判断
|
||||||
* 接收文本消息
|
* 接收文本消息
|
||||||
|
@ -10,27 +10,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk", "sdk\sdk.vcxproj", "{
|
|||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA} = {4DE80B82-5F6A-4C4C-9D16-1574308110FA}
|
{4DE80B82-5F6A-4C4C-9D16-1574308110FA} = {4DE80B82-5F6A-4C4C-9D16-1574308110FA}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wcf", "wcf\wcf.vcxproj", "{02747CE0-AD9F-4812-B019-FCF9867F7514}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA} = {4DE80B82-5F6A-4C4C-9D16-1574308110FA}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x86 = Debug|x86
|
Debug|x64 = Debug|x64
|
||||||
Release|x86 = Release|x86
|
Release|x64 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x86.ActiveCfg = Debug|Win32
|
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x86.Build.0 = Debug|Win32
|
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x64.Build.0 = Debug|x64
|
||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x86.ActiveCfg = Release|Win32
|
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x86.Build.0 = Release|Win32
|
{4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x64.Build.0 = Release|x64
|
||||||
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Debug|x86.ActiveCfg = Release|Win32
|
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x86.ActiveCfg = Release|Win32
|
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.ActiveCfg = Release|x64
|
||||||
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x86.Build.0 = Release|Win32
|
{ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.Build.0 = Release|x64
|
||||||
{02747CE0-AD9F-4812-B019-FCF9867F7514}.Debug|x86.ActiveCfg = Release|Win32
|
|
||||||
{02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -40,7 +40,7 @@ static char buf[BUF_SIZE] = { 0 };
|
|||||||
|
|
||||||
void log_buffer(uint8_t *buffer, size_t len)
|
void log_buffer(uint8_t *buffer, size_t len)
|
||||||
{
|
{
|
||||||
size_t j = sprintf_s(buf, BUF_SIZE, "BUF@%08X[%ld]: ", (uint32_t)buffer, len);
|
size_t j = sprintf_s(buf, BUF_SIZE, "BUF@%p[%zd]: ", buffer, len);
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
j += sprintf_s(buf + j, BUF_SIZE, "%02X ", buffer[i]);
|
j += sprintf_s(buf + j, BUF_SIZE, "%02X ", buffer[i]);
|
||||||
if (j > BUF_SIZE - 3) {
|
if (j > BUF_SIZE - 3) {
|
@ -133,12 +133,12 @@ static bool GetFileVersion(const wchar_t *filePath, wchar_t *version)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD verMS = pVerInfo->dwFileVersionMS;
|
UINT64 verMS = pVerInfo->dwFileVersionMS;
|
||||||
DWORD verLS = pVerInfo->dwFileVersionLS;
|
UINT64 verLS = pVerInfo->dwFileVersionLS;
|
||||||
DWORD major = HIWORD(verMS);
|
UINT64 major = HIWORD(verMS);
|
||||||
DWORD minor = LOWORD(verMS);
|
UINT64 minor = LOWORD(verMS);
|
||||||
DWORD build = HIWORD(verLS);
|
UINT64 build = HIWORD(verLS);
|
||||||
DWORD revision = LOWORD(verLS);
|
UINT64 revision = LOWORD(verLS);
|
||||||
delete[] pData;
|
delete[] pData;
|
||||||
|
|
||||||
StringCbPrintf(version, 0x20, TEXT("%d.%d.%d.%d"), major, minor, build, revision);
|
StringCbPrintf(version, 0x20, TEXT("%d.%d.%d.%d"), major, minor, build, revision);
|
||||||
@ -208,44 +208,44 @@ int OpenWeChat(DWORD *pid)
|
|||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
size_t GetWstringByAddress(UINT64 addr, wchar_t *buffer, UINT64 buffer_size)
|
||||||
{
|
{
|
||||||
DWORD strLength = GET_DWORD(address + 4);
|
size_t strLength = GET_DWORD(addr + 8);
|
||||||
if (strLength == 0) {
|
if (strLength == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (strLength > buffer_size) {
|
} else if (strLength > buffer_size) {
|
||||||
strLength = buffer_size - 1;
|
strLength = buffer_size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(address), strLength + 1);
|
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(addr), strLength + 1);
|
||||||
|
|
||||||
return strLength;
|
return strLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByAddress(DWORD address)
|
string GetStringByAddress(UINT64 addr)
|
||||||
{
|
{
|
||||||
DWORD strLength = GET_DWORD(address + 4);
|
size_t strLength = GET_DWORD(addr + 8);
|
||||||
return Wstring2String(wstring(GET_WSTRING(address), strLength));
|
return Wstring2String(wstring(GET_WSTRING(addr), strLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByStrAddr(DWORD addr)
|
string GetStringByStrAddr(UINT64 addr)
|
||||||
{
|
{
|
||||||
DWORD strLength = GET_DWORD(addr + 4);
|
size_t strLength = GET_DWORD(addr + 8);
|
||||||
return strLength ? string(GET_STRING(addr), strLength) : string();
|
return strLength ? string(GET_STRING(addr), strLength) : string();
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByWstrAddr(DWORD addr)
|
string GetStringByWstrAddr(UINT64 addr)
|
||||||
{
|
{
|
||||||
DWORD strLength = GET_DWORD(addr + 4);
|
size_t strLength = GET_DWORD(addr + 8);
|
||||||
return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string();
|
return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string();
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
|
UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 addr)
|
||||||
{
|
{
|
||||||
DWORD value = 0;
|
UINT32 value = 0;
|
||||||
|
|
||||||
unsigned char data[4] = { 0 };
|
unsigned char data[4] = { 0 };
|
||||||
if (ReadProcessMemory(hProcess, (LPVOID)address, data, 4, 0)) {
|
if (ReadProcessMemory(hProcess, (LPVOID)addr, data, 4, 0)) {
|
||||||
value = data[0] & 0xFF;
|
value = data[0] & 0xFF;
|
||||||
value |= ((data[1] << 8) & 0xFF00);
|
value |= ((data[1] << 8) & 0xFF00);
|
||||||
value |= ((data[2] << 16) & 0xFF0000);
|
value |= ((data[2] << 16) & 0xFF0000);
|
||||||
@ -255,12 +255,12 @@ DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address)
|
wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address)
|
||||||
{
|
{
|
||||||
wstring value = L"";
|
wstring value = L"";
|
||||||
|
|
||||||
DWORD strAddress = GetMemoryIntByAddress(hProcess, address);
|
UINT64 strAddress = GetMemoryIntByAddress(hProcess, address);
|
||||||
DWORD strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
UINT64 strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
||||||
if (strLen > 500)
|
if (strLen > 500)
|
||||||
return value;
|
return value;
|
||||||
|
|
36
WeChatFerry/com/util.h
Normal file
36
WeChatFerry/com/util.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define WECHAREXE L"WeChat.exe"
|
||||||
|
#define WECHATWINDLL L"WeChatWin.dll"
|
||||||
|
#define WCFSDKDLL L"sdk.dll"
|
||||||
|
#define WCFSPYDLL L"spy.dll"
|
||||||
|
#define WCFSPYDLL_DEBUG L"spy_debug.dll"
|
||||||
|
|
||||||
|
#define GET_UINT64(addr) ((UINT64) * (UINT64 *)(addr))
|
||||||
|
#define GET_DWORD(addr) ((DWORD) * (UINT64 *)(addr))
|
||||||
|
#define GET_QWORD(addr) ((UINT64) * (UINT64 *)(addr))
|
||||||
|
#define GET_STRING(addr) ((CHAR *)(*(UINT64 *)(addr)))
|
||||||
|
#define GET_WSTRING(addr) ((WCHAR *)(*(UINT64 *)(addr)))
|
||||||
|
#define GET_STRING_FROM_P(addr) ((CHAR *)(addr))
|
||||||
|
#define GET_WSTRING_FROM_P(addr) ((WCHAR *)(addr))
|
||||||
|
|
||||||
|
typedef struct PortPath {
|
||||||
|
int port;
|
||||||
|
char path[MAX_PATH];
|
||||||
|
} PortPath_t;
|
||||||
|
|
||||||
|
DWORD GetWeChatPid();
|
||||||
|
int OpenWeChat(DWORD *pid);
|
||||||
|
int GetWeChatVersion(wchar_t *version);
|
||||||
|
size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size);
|
||||||
|
UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 address);
|
||||||
|
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address);
|
||||||
|
std::wstring String2Wstring(std::string s);
|
||||||
|
std::string Wstring2String(std::wstring ws);
|
||||||
|
std::string GB2312ToUtf8(const char *gb2312);
|
||||||
|
std::string GetStringByAddress(UINT64 address);
|
||||||
|
std::string GetStringByStrAddr(UINT64 addr);
|
||||||
|
std::string GetStringByWstrAddr(UINT64 addr);
|
||||||
|
void DbgMsg(const char *zcFormat, ...);
|
@ -86,6 +86,10 @@
|
|||||||
<VcpkgUseStatic>true</VcpkgUseStatic>
|
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||||
<VcpkgTriplet>x86-windows-static</VcpkgTriplet>
|
<VcpkgTriplet>x86-windows-static</VcpkgTriplet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||||
|
<VcpkgTriplet>x64-windows-static</VcpkgTriplet>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
@ -154,30 +158,43 @@
|
|||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>
|
||||||
|
</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)com;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include</AdditionalIncludeDirectories>
|
||||||
|
<PrecompiledHeaderOutputFile />
|
||||||
|
<SupportJustMyCode>true</SupportJustMyCode>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy files</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\spy\log.h" />
|
<ClInclude Include="..\com\log.h" />
|
||||||
<ClInclude Include="..\spy\util.h" />
|
<ClInclude Include="..\com\util.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="injector.h" />
|
<ClInclude Include="injector.h" />
|
||||||
<ClInclude Include="sdk.h" />
|
<ClInclude Include="sdk.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\spy\log.cpp" />
|
<ClCompile Include="..\com\log.cpp" />
|
||||||
<ClCompile Include="..\spy\util.cpp" />
|
<ClCompile Include="..\com\util.cpp" />
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
<ClCompile Include="injector.cpp" />
|
<ClCompile Include="injector.cpp" />
|
||||||
<ClCompile Include="sdk.cpp" />
|
<ClCompile Include="sdk.cpp" />
|
||||||
|
@ -21,32 +21,32 @@
|
|||||||
<ClInclude Include="sdk.h">
|
<ClInclude Include="sdk.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\spy\util.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\spy\log.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="injector.h">
|
<ClInclude Include="injector.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\com\log.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\com\util.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\spy\log.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\spy\util.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="sdk.cpp">
|
<ClCompile Include="sdk.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="injector.cpp">
|
<ClCompile Include="injector.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\com\log.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\com\util.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="sdk.def">
|
<None Include="sdk.def">
|
||||||
|
@ -1,26 +1,44 @@
|
|||||||
#include "injector.h"
|
#include "framework.h"
|
||||||
|
#include "psapi.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
#include "injector.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static void ShowErrorMessage(DWORD dwError, HANDLE hProcess)
|
using namespace std;
|
||||||
|
|
||||||
|
HMODULE GetTargetModuleBase(HANDLE process, string dll)
|
||||||
{
|
{
|
||||||
BOOL bIsWow64 = FALSE;
|
DWORD cbNeeded;
|
||||||
WCHAR szErrorMessage[256] = { 0 };
|
HMODULE moduleHandleList[512];
|
||||||
LPFN_ISWOW64PROCESS fnIsWow64Process
|
BOOL ret = EnumProcessModulesEx(process, moduleHandleList, sizeof(moduleHandleList), &cbNeeded, LIST_MODULES_64BIT);
|
||||||
= (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
if (!ret) {
|
||||||
if (fnIsWow64Process != NULL && fnIsWow64Process(hProcess, &bIsWow64)) {
|
MessageBox(NULL, L"获取模块失败", L"GetTargetModuleBase", 0);
|
||||||
if (bIsWow64) {
|
return NULL;
|
||||||
wsprintf(szErrorMessage, L"LoadLibrary 调用失败,请检查应用版本/位数。错误码: %lu", dwError);
|
}
|
||||||
|
|
||||||
|
if (cbNeeded > sizeof(moduleHandleList)) {
|
||||||
|
MessageBox(NULL, L"模块数量过多", L"GetTargetModuleBase", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DWORD processCount = cbNeeded / sizeof(HMODULE);
|
||||||
|
|
||||||
|
char moduleName[32];
|
||||||
|
for (DWORD i = 0; i < processCount; i++) {
|
||||||
|
GetModuleBaseNameA(process, moduleHandleList[i], moduleName, 32);
|
||||||
|
if (!strncmp(dll.c_str(), moduleName, dll.size())) {
|
||||||
|
return moduleHandleList[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wsprintf(szErrorMessage, L"LoadLibrary 调用失败。错误码: %lu", dwError);
|
return NULL;
|
||||||
MessageBox(NULL, szErrorMessage, L"InjectDll", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
||||||
{
|
{
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
// 1. 打开目标进程
|
// 1. 打开目标进程
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
if (hProcess == NULL) {
|
if (hProcess == NULL) {
|
||||||
@ -39,18 +57,31 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
|||||||
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL);
|
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL);
|
||||||
|
|
||||||
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
|
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
|
||||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, 0, NULL);
|
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
|
||||||
|
if (k32 == NULL) {
|
||||||
|
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FARPROC libAddr = GetProcAddress(k32, "LoadLibraryW");
|
||||||
|
if (!libAddr) {
|
||||||
|
MessageBox(NULL, L"获取 LoadLibrary 失败", L"InjectDll", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, pRemoteAddress, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (hThread == NULL) {
|
||||||
ShowErrorMessage(GetLastError(), hProcess);
|
|
||||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
|
MessageBox(NULL, L"CreateRemoteThread 失败", L"InjectDll", 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(hThread, -1);
|
WaitForSingleObject(hThread, -1);
|
||||||
GetExitCodeThread(hThread, (LPDWORD)injectedBase);
|
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
|
|
||||||
|
*injectedBase = GetTargetModuleBase(hProcess, filesystem::path(Wstring2String(dllPath)).filename().string());
|
||||||
|
|
||||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
// CloseHandle(hProcess); // Close when exit
|
// CloseHandle(hProcess); // Close when exit
|
||||||
|
|
||||||
@ -62,7 +93,18 @@ bool EjectDll(HANDLE process, HMODULE dllBase)
|
|||||||
HANDLE hThread = NULL;
|
HANDLE hThread = NULL;
|
||||||
|
|
||||||
// 使目标进程调用 FreeLibrary,卸载 DLL
|
// 使目标进程调用 FreeLibrary,卸载 DLL
|
||||||
hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dllBase, 0, NULL);
|
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
|
||||||
|
if (k32 == NULL) {
|
||||||
|
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread");
|
||||||
|
if (!libAddr) {
|
||||||
|
MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, (LPVOID)dllBase, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (hThread == NULL) {
|
||||||
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
|
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
|
||||||
return false;
|
return false;
|
||||||
@ -74,29 +116,33 @@ bool EjectDll(HANDLE process, HMODULE dllBase)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *GetFuncAddr(LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName)
|
static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName)
|
||||||
{
|
{
|
||||||
HMODULE hLoaded = LoadLibrary(dllPath);
|
HMODULE dll = LoadLibrary(dllPath);
|
||||||
if (hLoaded == NULL) {
|
if (dll == NULL) {
|
||||||
return NULL;
|
MessageBox(NULL, L"获取 DLL 失败", L"GetFuncOffset", 0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *absAddr = GetProcAddress(hLoaded, funcName);
|
LPVOID absAddr = GetProcAddress(dll, funcName);
|
||||||
DWORD offset = (DWORD)absAddr - (DWORD)hLoaded;
|
UINT64 offset = (UINT64)absAddr - (UINT64)dll;
|
||||||
|
FreeLibrary(dll);
|
||||||
|
|
||||||
FreeLibrary(hLoaded);
|
return offset;
|
||||||
|
|
||||||
return (void *)((DWORD)dllBase + offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, DWORD *ret)
|
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPDWORD ret)
|
||||||
{
|
{
|
||||||
void *pFunc = GetFuncAddr(dllPath, dllBase, funcName);
|
UINT64 offset = GetFuncOffset(dllPath, funcName);
|
||||||
if (pFunc == NULL) {
|
if (offset == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
|
||||||
|
if (pFunc <= (UINT64)dllBase) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, parameter, 0, NULL);
|
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (hThread == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -110,10 +156,14 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
||||||
DWORD *ret)
|
LPDWORD ret)
|
||||||
{
|
{
|
||||||
void *pFunc = GetFuncAddr(dllPath, dllBase, funcName);
|
UINT64 offset = GetFuncOffset(dllPath, funcName);
|
||||||
if (pFunc == NULL) {
|
if (offset == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
|
||||||
|
if (pFunc <= (UINT64)dllBase) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
|
|
||||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase);
|
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase);
|
||||||
bool EjectDll(HANDLE process, HMODULE dllBase);
|
bool EjectDll(HANDLE process, HMODULE dllBase);
|
||||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, DWORD *ret);
|
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, DWORD *ret);
|
||||||
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
||||||
DWORD *ret);
|
DWORD *ret);
|
||||||
|
@ -8,25 +8,23 @@
|
|||||||
#include "sdk.h"
|
#include "sdk.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define WCF_LOCK ".wcf.lock"
|
static BOOL injected = false;
|
||||||
|
|
||||||
static bool debugMode = false;
|
|
||||||
static HANDLE wcProcess = NULL;
|
static HANDLE wcProcess = NULL;
|
||||||
static HMODULE spyBase = NULL;
|
static HMODULE spyBase = NULL;
|
||||||
static WCHAR spyDllPath[MAX_PATH] = { 0 };
|
static WCHAR spyDllPath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
static int GetDllPath(bool debug, wchar_t *dllPath)
|
static int GetDllPath(bool debug, wchar_t *dllPath)
|
||||||
{
|
{
|
||||||
GetModuleFileName(GetModuleHandle(WECHATSDKDLL), spyDllPath, MAX_PATH);
|
GetModuleFileName(GetModuleHandle(WCFSDKDLL), dllPath, MAX_PATH);
|
||||||
PathRemoveFileSpec(spyDllPath);
|
PathRemoveFileSpec(dllPath);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
PathAppend(spyDllPath, WECHATINJECTDLL_DEBUG);
|
PathAppend(dllPath, WCFSPYDLL_DEBUG);
|
||||||
} else {
|
} else {
|
||||||
PathAppend(spyDllPath, WECHATINJECTDLL);
|
PathAppend(dllPath, WCFSPYDLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PathFileExists(spyDllPath)) {
|
if (!PathFileExists(dllPath)) {
|
||||||
MessageBox(NULL, spyDllPath, L"文件不存在", 0);
|
MessageBox(NULL, dllPath, L"文件不存在", 0);
|
||||||
return ERROR_FILE_NOT_FOUND;
|
return ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,60 +63,22 @@ int WxInitSDK(bool debug, int port)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WCF
|
injected = true;
|
||||||
FILE *fd = fopen(WCF_LOCK, "wb");
|
|
||||||
if (fd == NULL) {
|
|
||||||
MessageBox(NULL, L"无法打开lock文件", L"WxInitSDK", 0);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
fwrite((uint8_t *)&debug, sizeof(debug), 1, fd);
|
|
||||||
fwrite((uint8_t *)&spyBase, sizeof(spyBase), 1, fd);
|
|
||||||
fclose(fd);
|
|
||||||
#endif
|
|
||||||
debugMode = debug;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WxDestroySDK()
|
int WxDestroySDK()
|
||||||
{
|
{
|
||||||
int status = 0;
|
if (!injected) {
|
||||||
#ifdef WCF
|
|
||||||
bool debug;
|
|
||||||
DWORD pid = GetWeChatPid();
|
|
||||||
if (pid == 0) {
|
|
||||||
MessageBox(NULL, L"微信未运行", L"WxDestroySDK", 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
wcProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
|
||||||
if (wcProcess == NULL) {
|
|
||||||
MessageBox(NULL, L"微信未运行", L"WxDestroySDK", 0);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *fd = fopen(WCF_LOCK, "rb");
|
if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) {
|
||||||
if (fd == NULL) {
|
|
||||||
MessageBox(NULL, L"无法打开lock文件", L"WxDestroySDK", 0);
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
fread((uint8_t *)&debug, sizeof(debug), 1, fd);
|
|
||||||
fread((uint8_t *)&spyBase, sizeof(spyBase), 1, fd);
|
|
||||||
fclose(fd);
|
|
||||||
status = GetDllPath(debug, spyDllPath);
|
|
||||||
#else
|
|
||||||
status = GetDllPath(debugMode, spyDllPath);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL, NULL)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EjectDll(wcProcess, spyBase)) {
|
if (!EjectDll(wcProcess, spyBase)) {
|
||||||
return -1; // TODO: Unify error codes
|
return -3; // TODO: Unify error codes
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetName>$(ProjectName)_debug</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
@ -94,6 +95,12 @@
|
|||||||
<VcpkgUseStatic>true</VcpkgUseStatic>
|
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||||
<VcpkgConfiguration>Release</VcpkgConfiguration>
|
<VcpkgConfiguration>Release</VcpkgConfiguration>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
@ -191,10 +198,20 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_DEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;ENABLE_DEBUG_LOG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>
|
||||||
|
</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)com;$(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include</AdditionalIncludeDirectories>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<OmitFramePointers>false</OmitFramePointers>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile />
|
||||||
|
<DisableSpecificWarnings>4251;4731;4819</DisableSpecificWarnings>
|
||||||
|
<AdditionalOptions>/EHa %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@ -202,7 +219,28 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<ModuleDefinitionFile>spy.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>spy.def</ModuleDefinitionFile>
|
||||||
<AdditionalOptions> /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions> /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)smc;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;Codec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Command>cd $(SolutionDir)rpc\proto
|
||||||
|
$(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Message>Generating PB files</Message>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>if not exist $(SolutionDir)Out md $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).exp $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).lib $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).pdb $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy spy.dll</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -210,21 +248,48 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>
|
||||||
|
</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)com;$(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include</AdditionalIncludeDirectories>
|
||||||
|
<OmitFramePointers>false</OmitFramePointers>
|
||||||
|
<PrecompiledHeaderOutputFile />
|
||||||
|
<DisableSpecificWarnings>4251;4731;4819</DisableSpecificWarnings>
|
||||||
|
<AdditionalOptions>/EHa %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<ModuleDefinitionFile>spy.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>spy.def</ModuleDefinitionFile>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)smc;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;Codec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalOptions> /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
|
<PreBuildEvent>
|
||||||
|
<Message>Generating PB files</Message>
|
||||||
|
<Command>cd $(SolutionDir)rpc\proto
|
||||||
|
$(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
||||||
|
</PreBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy spy.dll</Message>
|
||||||
|
<Command>if not exist $(SolutionDir)Out md $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).exp $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).lib $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetName).pdb $(SolutionDir)Out
|
||||||
|
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\com\log.h" />
|
||||||
|
<ClInclude Include="..\com\util.h" />
|
||||||
<ClInclude Include="..\rpc\nanopb\pb.h" />
|
<ClInclude Include="..\rpc\nanopb\pb.h" />
|
||||||
<ClInclude Include="..\rpc\nanopb\pb_common.h" />
|
<ClInclude Include="..\rpc\nanopb\pb_common.h" />
|
||||||
<ClInclude Include="..\rpc\nanopb\pb_decode.h" />
|
<ClInclude Include="..\rpc\nanopb\pb_decode.h" />
|
||||||
@ -239,7 +304,6 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="contact_mgmt.h" />
|
<ClInclude Include="contact_mgmt.h" />
|
||||||
<ClInclude Include="load_calls.h" />
|
<ClInclude Include="load_calls.h" />
|
||||||
<ClInclude Include="log.h" />
|
|
||||||
<ClInclude Include="receive_msg.h" />
|
<ClInclude Include="receive_msg.h" />
|
||||||
<ClInclude Include="receive_transfer.h" />
|
<ClInclude Include="receive_transfer.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
@ -249,9 +313,10 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<ClInclude Include="spy_types.h" />
|
<ClInclude Include="spy_types.h" />
|
||||||
<ClInclude Include="sqlite3.h" />
|
<ClInclude Include="sqlite3.h" />
|
||||||
<ClInclude Include="user_info.h" />
|
<ClInclude Include="user_info.h" />
|
||||||
<ClInclude Include="util.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\com\log.cpp" />
|
||||||
|
<ClCompile Include="..\com\util.cpp" />
|
||||||
<ClCompile Include="..\rpc\nanopb\pb_common.c" />
|
<ClCompile Include="..\rpc\nanopb\pb_common.c" />
|
||||||
<ClCompile Include="..\rpc\nanopb\pb_decode.c" />
|
<ClCompile Include="..\rpc\nanopb\pb_decode.c" />
|
||||||
<ClCompile Include="..\rpc\nanopb\pb_encode.c" />
|
<ClCompile Include="..\rpc\nanopb\pb_encode.c" />
|
||||||
@ -263,14 +328,12 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto</Command>
|
|||||||
<ClCompile Include="exec_sql.cpp" />
|
<ClCompile Include="exec_sql.cpp" />
|
||||||
<ClCompile Include="contact_mgmt.cpp" />
|
<ClCompile Include="contact_mgmt.cpp" />
|
||||||
<ClCompile Include="load_calls.cpp" />
|
<ClCompile Include="load_calls.cpp" />
|
||||||
<ClCompile Include="log.cpp" />
|
|
||||||
<ClCompile Include="receive_msg.cpp" />
|
<ClCompile Include="receive_msg.cpp" />
|
||||||
<ClCompile Include="receive_transfer.cpp" />
|
<ClCompile Include="receive_transfer.cpp" />
|
||||||
<ClCompile Include="rpc_server.cpp" />
|
<ClCompile Include="rpc_server.cpp" />
|
||||||
<ClCompile Include="send_msg.cpp" />
|
<ClCompile Include="send_msg.cpp" />
|
||||||
<ClCompile Include="spy.cpp" />
|
<ClCompile Include="spy.cpp" />
|
||||||
<ClCompile Include="user_info.cpp" />
|
<ClCompile Include="user_info.cpp" />
|
||||||
<ClCompile Include="util.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\rpc\proto\wcf.proto" />
|
<None Include="..\rpc\proto\wcf.proto" />
|
||||||
|
@ -24,9 +24,6 @@
|
|||||||
<ClInclude Include="rpc_server.h">
|
<ClInclude Include="rpc_server.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="log.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="exec_sql.h">
|
<ClInclude Include="exec_sql.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -48,9 +45,6 @@
|
|||||||
<ClInclude Include="spy_types.h">
|
<ClInclude Include="spy_types.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="util.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\rpc\nanopb\pb.h">
|
<ClInclude Include="..\rpc\nanopb\pb.h">
|
||||||
<Filter>nnrpc</Filter>
|
<Filter>nnrpc</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -93,6 +87,12 @@
|
|||||||
<ClInclude Include="..\smc\codec.h">
|
<ClInclude Include="..\smc\codec.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\com\log.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\com\util.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
@ -101,9 +101,6 @@
|
|||||||
<ClCompile Include="rpc_server.cpp">
|
<ClCompile Include="rpc_server.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="log.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="exec_sql.cpp">
|
<ClCompile Include="exec_sql.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -122,9 +119,6 @@
|
|||||||
<ClCompile Include="spy.cpp">
|
<ClCompile Include="spy.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="util.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\rpc\nanopb\pb_common.c">
|
<ClCompile Include="..\rpc\nanopb\pb_common.c">
|
||||||
<Filter>nnrpc</Filter>
|
<Filter>nnrpc</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -152,6 +146,12 @@
|
|||||||
<ClCompile Include="receive_transfer.cpp">
|
<ClCompile Include="receive_transfer.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\com\log.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\com\util.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="spy.def">
|
<None Include="spy.def">
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
#if 0
|
||||||
int AddChatroomMember(string roomid, string wxids)
|
int AddChatroomMember(string roomid, string wxids)
|
||||||
{
|
{
|
||||||
if (roomid.empty() || wxids.empty()) {
|
if (roomid.empty() || wxids.empty()) {
|
||||||
@ -178,3 +178,4 @@ int InviteChatroomMember(string roomid, string wxids)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
#if 0
|
||||||
#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 };
|
||||||
static const uint8_t FEAT_PROVINCE[FEAT_LEN] = { 0xE2, 0xEA, 0xA8, 0xD1, 0x18 };
|
static const uint8_t FEAT_PROVINCE[FEAT_LEN] = { 0xE2, 0xEA, 0xA8, 0xD1, 0x18 };
|
||||||
@ -183,3 +183,4 @@ RpcContact_t GetContactByWxid(string wxid)
|
|||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
#define OFFSET_DB_NAME 0x14
|
#define OFFSET_DB_NAME 0x14
|
||||||
#define OFFSET_DB_MSG_MGR 0x30403B8
|
#define OFFSET_DB_MSG_MGR 0x30403B8
|
||||||
|
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
|
||||||
typedef map<string, DWORD> dbMap_t;
|
typedef map<string, DWORD> dbMap_t;
|
||||||
static dbMap_t dbMap;
|
static dbMap_t dbMap;
|
||||||
|
#if 0
|
||||||
static void GetDbHandle(DWORD base, DWORD offset)
|
static void GetDbHandle(DWORD base, DWORD offset)
|
||||||
{
|
{
|
||||||
wchar_t *wsp;
|
wchar_t *wsp;
|
||||||
@ -225,3 +225,4 @@ vector<uint8_t> GetAudioData(uint64_t id)
|
|||||||
|
|
||||||
return vector<uint8_t>();
|
return vector<uint8_t>();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -23,8 +23,11 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
extern bool gIsListeningPyq;
|
extern bool gIsListeningPyq;
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
|
||||||
|
int IsLogin(void) { return (int)GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.login); }
|
||||||
|
|
||||||
|
#if 0
|
||||||
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
||||||
{
|
{
|
||||||
// PNG?
|
// PNG?
|
||||||
@ -443,3 +446,4 @@ string GetLoginUrl()
|
|||||||
}
|
}
|
||||||
return "http://weixin.qq.com/x/" + string(url);
|
return "http://weixin.qq.com/x/" + string(url);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
int IsLogin(void);
|
||||||
std::string GetAudio(uint64_t id, std::string dir);
|
std::string GetAudio(uint64_t id, std::string dir);
|
||||||
std::string DecryptImage(std::string src, std::string dst);
|
std::string DecryptImage(std::string src, std::string dst);
|
||||||
int RefreshPyq(uint64_t id);
|
int RefreshPyq(uint64_t id);
|
||||||
|
@ -3,14 +3,15 @@
|
|||||||
|
|
||||||
#include "load_calls.h"
|
#include "load_calls.h"
|
||||||
|
|
||||||
#define SUPPORT_VERSION L"3.9.2.23"
|
#define SUPPORT_VERSION L"3.9.10.19"
|
||||||
|
|
||||||
WxCalls_t wxCalls = {
|
WxCalls_t wxCalls = {
|
||||||
0x2FFD638, // Login Status
|
0x5AB9184, // Login Status
|
||||||
{ 0x2FFD484, 0x2FFD590, 0x2FFD500, 0x30238CC }, // User Info: wxid, nickname, mobile, home
|
{ 0x5AB8FC8, 0x5AB90A8, 0x5AB8FE8, 0x5A7F170 }, // User Info: wxid, nickname, mobile, home
|
||||||
{ 0x768140, 0xCE6C80, 0x756960 }, // Send Message
|
{ 0x768140, 0xCE6C80, 0x756960 }, // Send Message
|
||||||
/* Receive Message:
|
/* Receive Message:
|
||||||
Hook, call, msgId, type, isSelf, ts, roomId, content, wxid, sign, thumb, extra, msgXml */
|
Hook, call, msgId, type, isSelf, ts, roomId, content, wxid, sign, thumb, extra, msgXml */
|
||||||
{ 0xD19A0B, 0x756960, 0x30, 0x38, 0x3C, 0x44, 0x48, 0x70, 0x180, 0x194, 0x1A8, 0x1BC, 0x1FC },
|
{ 0x00, 0x2206570, 0x30, 0x38, 0x3C, 0x44, 0x48, 0x88, 0x240, 0x260, 0x280, 0x2A0, 0x308 },
|
||||||
{ 0x768140, 0XF59E40, 0XCE6640, 0x756960 }, // Send Image Message
|
{ 0x768140, 0XF59E40, 0XCE6640, 0x756960 }, // Send Image Message
|
||||||
{ 0x76AE20, 0xF59E40, 0xB6D1F0, 0x756960 }, // Send File Message
|
{ 0x76AE20, 0xF59E40, 0xB6D1F0, 0x756960 }, // Send File Message
|
||||||
{ 0xB8A70, 0x3ED5E0, 0x107F00, 0x3ED7B0, 0x2386FE4 }, // Send xml Message
|
{ 0xB8A70, 0x3ED5E0, 0x107F00, 0x3ED7B0, 0x2386FE4 }, // Send xml Message
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma execution_character_set("utf-8")
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#include "MinHook.h"
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -19,18 +20,11 @@ extern queue<WxMsg_t> gMsgQueue;
|
|||||||
|
|
||||||
// Defined in spy.cpp
|
// Defined in spy.cpp
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
|
||||||
static DWORD reg_buffer = 0;
|
typedef UINT64 (*funcRecvMsg_t)(UINT64, UINT64);
|
||||||
static DWORD recvMsgHookAddr = 0;
|
static funcRecvMsg_t funcRecvMsg = nullptr;
|
||||||
static DWORD recvMsgCallAddr = 0;
|
static funcRecvMsg_t realRecvMsg = nullptr;
|
||||||
static DWORD recvMsgJumpBackAddr = 0;
|
|
||||||
static CHAR recvMsgBackupCode[5] = { 0 };
|
|
||||||
|
|
||||||
static DWORD recvPyqHookAddr = 0;
|
|
||||||
static DWORD recvPyqCallAddr = 0;
|
|
||||||
static DWORD recvPyqJumpBackAddr = 0;
|
|
||||||
static CHAR recvPyqBackupCode[5] = { 0 };
|
|
||||||
|
|
||||||
MsgTypes_t GetMsgTypes()
|
MsgTypes_t GetMsgTypes()
|
||||||
{
|
{
|
||||||
@ -73,6 +67,130 @@ MsgTypes_t GetMsgTypes()
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT64 DispatchMsg(UINT64 arg1, UINT64 arg2)
|
||||||
|
{
|
||||||
|
WxMsg_t wxMsg = { 0 };
|
||||||
|
try {
|
||||||
|
wxMsg.id = GET_QWORD(arg2 + g_WxCalls.recvMsg.msgId);
|
||||||
|
wxMsg.type = GET_DWORD(arg2 + g_WxCalls.recvMsg.type);
|
||||||
|
wxMsg.is_self = GET_DWORD(arg2 + g_WxCalls.recvMsg.isSelf);
|
||||||
|
wxMsg.ts = GET_DWORD(arg2 + g_WxCalls.recvMsg.ts);
|
||||||
|
wxMsg.content = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.content);
|
||||||
|
wxMsg.sign = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.sign);
|
||||||
|
wxMsg.xml = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.msgXml);
|
||||||
|
|
||||||
|
string roomid = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.roomId);
|
||||||
|
if (roomid.find("@chatroom") != string::npos) { // 群 ID 的格式为 xxxxxxxxxxx@chatroom
|
||||||
|
wxMsg.is_group = true;
|
||||||
|
wxMsg.roomid = roomid;
|
||||||
|
if (wxMsg.is_self) {
|
||||||
|
wxMsg.sender = GetSelfWxid();
|
||||||
|
} else {
|
||||||
|
wxMsg.sender = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.wxid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wxMsg.is_group = false;
|
||||||
|
if (wxMsg.is_self) {
|
||||||
|
wxMsg.sender = GetSelfWxid();
|
||||||
|
} else {
|
||||||
|
wxMsg.sender = roomid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxMsg.thumb = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.thumb);
|
||||||
|
if (!wxMsg.thumb.empty()) {
|
||||||
|
wxMsg.thumb = GetHomePath() + wxMsg.thumb;
|
||||||
|
replace(wxMsg.thumb.begin(), wxMsg.thumb.end(), '\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
wxMsg.extra = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.extra);
|
||||||
|
if (!wxMsg.extra.empty()) {
|
||||||
|
wxMsg.extra = GetHomePath() + wxMsg.extra;
|
||||||
|
replace(wxMsg.extra.begin(), wxMsg.extra.end(), '\\', '/');
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LOG_ERROR(GB2312ToUtf8(e.what()));
|
||||||
|
} catch (...) {
|
||||||
|
LOG_ERROR("Unknow exception.");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock(gMutex);
|
||||||
|
gMsgQueue.push(wxMsg); // 推送到队列
|
||||||
|
}
|
||||||
|
|
||||||
|
gCV.notify_all(); // 通知各方消息就绪
|
||||||
|
return realRecvMsg(arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListenMessage()
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_UNKNOWN;
|
||||||
|
if (gIsListening || (g_WeChatWinDllAddr == 0)) {
|
||||||
|
LOG_WARN("gIsListening || (g_WeChatWinDllAddr == 0)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call);
|
||||||
|
|
||||||
|
status = MH_Initialize();
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast<LPVOID *>(&realRecvMsg));
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_CreateHook failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_EnableHook(funcRecvMsg);
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_EnableHook failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gIsListening = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnListenMessage()
|
||||||
|
{
|
||||||
|
MH_STATUS status = MH_UNKNOWN;
|
||||||
|
if (!gIsListening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_DisableHook(funcRecvMsg);
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_DisableHook failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_Uninitialize();
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gIsListening = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListenPyq() { }
|
||||||
|
|
||||||
|
void UnListenPyq() { }
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// static DWORD reg_buffer = 0;
|
||||||
|
// static DWORD recvMsgHookAddr = 0;
|
||||||
|
// static DWORD recvMsgCallAddr = 0;
|
||||||
|
// static DWORD recvMsgJumpBackAddr = 0;
|
||||||
|
// static CHAR recvMsgBackupCode[5] = { 0 };
|
||||||
|
|
||||||
|
// static DWORD recvPyqHookAddr = 0;
|
||||||
|
// static DWORD recvPyqCallAddr = 0;
|
||||||
|
// static DWORD recvPyqJumpBackAddr = 0;
|
||||||
|
// static CHAR recvPyqBackupCode[5] = { 0 };
|
||||||
|
|
||||||
void HookAddress(DWORD hookAddr, LPVOID funcAddr, CHAR recvMsgBackupCode[5])
|
void HookAddress(DWORD hookAddr, LPVOID funcAddr, CHAR recvMsgBackupCode[5])
|
||||||
{
|
{
|
||||||
// 组装跳转数据
|
// 组装跳转数据
|
||||||
@ -259,3 +377,4 @@ void UnListenPyq()
|
|||||||
UnHookAddress(recvPyqHookAddr, recvPyqBackupCode);
|
UnHookAddress(recvPyqHookAddr, recvPyqBackupCode);
|
||||||
gIsListeningPyq = false;
|
gIsListeningPyq = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
#if 0
|
||||||
int ReceiveTransfer(string wxid, string transferid, string transactionid)
|
int ReceiveTransfer(string wxid, string transferid, string transactionid)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
@ -53,3 +53,4 @@ int ReceiveTransfer(string wxid, string transferid, string transactionid)
|
|||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -40,8 +40,6 @@
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
extern int IsLogin(void); // Defined in spy.cpp
|
|
||||||
|
|
||||||
bool gIsListening = false;
|
bool gIsListening = false;
|
||||||
bool gIsListeningPyq = false;
|
bool gIsListeningPyq = false;
|
||||||
mutex gMutex;
|
mutex gMutex;
|
||||||
@ -90,6 +88,28 @@ bool func_get_self_wxid(uint8_t *out, size_t *len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool func_get_user_info(uint8_t *out, size_t *len)
|
||||||
|
{
|
||||||
|
Response rsp = Response_init_default;
|
||||||
|
rsp.func = Functions_FUNC_GET_USER_INFO;
|
||||||
|
rsp.which_msg = Response_ui_tag;
|
||||||
|
|
||||||
|
UserInfo_t ui = GetUserInfo();
|
||||||
|
rsp.msg.ui.wxid = (char *)ui.wxid.c_str();
|
||||||
|
rsp.msg.ui.name = (char *)ui.name.c_str();
|
||||||
|
rsp.msg.ui.mobile = (char *)ui.mobile.c_str();
|
||||||
|
rsp.msg.ui.home = (char *)ui.home.c_str();
|
||||||
|
|
||||||
|
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_get_msg_types(uint8_t *out, size_t *len)
|
bool func_get_msg_types(uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
Response rsp = Response_init_default;
|
Response rsp = Response_init_default;
|
||||||
@ -109,7 +129,7 @@ bool func_get_msg_types(uint8_t *out, size_t *len)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
bool func_get_contacts(uint8_t *out, size_t *len)
|
bool func_get_contacts(uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
Response rsp = Response_init_default;
|
Response rsp = Response_init_default;
|
||||||
@ -170,28 +190,6 @@ bool func_get_db_tables(char *db, uint8_t *out, size_t *len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool func_get_user_info(uint8_t *out, size_t *len)
|
|
||||||
{
|
|
||||||
Response rsp = Response_init_default;
|
|
||||||
rsp.func = Functions_FUNC_GET_USER_INFO;
|
|
||||||
rsp.which_msg = Response_ui_tag;
|
|
||||||
|
|
||||||
UserInfo_t ui = GetUserInfo();
|
|
||||||
rsp.msg.ui.wxid = (char *)ui.wxid.c_str();
|
|
||||||
rsp.msg.ui.name = (char *)ui.name.c_str();
|
|
||||||
rsp.msg.ui.mobile = (char *)ui.mobile.c_str();
|
|
||||||
rsp.msg.ui.home = (char *)ui.home.c_str();
|
|
||||||
|
|
||||||
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_get_audio_msg(uint64_t id, char *dir, uint8_t *out, size_t *len)
|
bool func_get_audio_msg(uint64_t id, char *dir, uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
Response rsp = Response_init_default;
|
Response rsp = Response_init_default;
|
||||||
@ -428,7 +426,7 @@ bool func_forward_msg(uint64_t id, char *receiver, uint8_t *out, size_t *len)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
static void PushMessage()
|
static void PushMessage()
|
||||||
{
|
{
|
||||||
static uint8_t buffer[G_BUF_SIZE] = { 0 };
|
static uint8_t buffer[G_BUF_SIZE] = { 0 };
|
||||||
@ -545,6 +543,7 @@ bool func_disable_recv_txt(uint8_t *out, size_t *len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool func_exec_db_query(char *db, char *sql, uint8_t *out, size_t *len)
|
bool func_exec_db_query(char *db, char *sql, uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
Response rsp = Response_init_default;
|
Response rsp = Response_init_default;
|
||||||
@ -837,7 +836,7 @@ bool func_invite_room_members(char *roomid, char *wxids, uint8_t *out, size_t *l
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
|
static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
@ -850,6 +849,7 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("{:#04x}[{}] length: {}", (uint8_t)req.func, magic_enum::enum_name(req.func), in_len);
|
LOG_DEBUG("{:#04x}[{}] length: {}", (uint8_t)req.func, magic_enum::enum_name(req.func), in_len);
|
||||||
|
|
||||||
switch (req.func) {
|
switch (req.func) {
|
||||||
case Functions_FUNC_IS_LOGIN: {
|
case Functions_FUNC_IS_LOGIN: {
|
||||||
ret = func_is_login(out, out_len);
|
ret = func_is_login(out, out_len);
|
||||||
@ -859,10 +859,15 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_get_self_wxid(out, out_len);
|
ret = func_get_self_wxid(out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Functions_FUNC_GET_USER_INFO: {
|
||||||
|
ret = func_get_user_info(out, out_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Functions_FUNC_GET_MSG_TYPES: {
|
case Functions_FUNC_GET_MSG_TYPES: {
|
||||||
ret = func_get_msg_types(out, out_len);
|
ret = func_get_msg_types(out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
case Functions_FUNC_GET_CONTACTS: {
|
case Functions_FUNC_GET_CONTACTS: {
|
||||||
ret = func_get_contacts(out, out_len);
|
ret = func_get_contacts(out, out_len);
|
||||||
break;
|
break;
|
||||||
@ -875,10 +880,6 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_get_db_tables(req.msg.str, out, out_len);
|
ret = func_get_db_tables(req.msg.str, out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Functions_FUNC_GET_USER_INFO: {
|
|
||||||
ret = func_get_user_info(out, out_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Functions_FUNC_GET_AUDIO_MSG: {
|
case Functions_FUNC_GET_AUDIO_MSG: {
|
||||||
ret = func_get_audio_msg(req.msg.am.id, req.msg.am.dir, out, out_len);
|
ret = func_get_audio_msg(req.msg.am.id, req.msg.am.dir, out, out_len);
|
||||||
break;
|
break;
|
||||||
@ -907,7 +908,6 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_forward_msg(req.msg.fm.id, req.msg.fm.receiver, out, out_len);
|
ret = func_forward_msg(req.msg.fm.id, req.msg.fm.receiver, out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
case Functions_FUNC_SEND_XML: {
|
case Functions_FUNC_SEND_XML: {
|
||||||
ret = func_send_xml(req.msg.xml, out, out_len);
|
ret = func_send_xml(req.msg.xml, out, out_len);
|
||||||
break;
|
break;
|
||||||
@ -925,6 +925,7 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_disable_recv_txt(out, out_len);
|
ret = func_disable_recv_txt(out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
case Functions_FUNC_EXEC_DB_QUERY: {
|
case Functions_FUNC_EXEC_DB_QUERY: {
|
||||||
ret = func_exec_db_query(req.msg.query.db, req.msg.query.sql, out, out_len);
|
ret = func_exec_db_query(req.msg.query.db, req.msg.query.sql, out, out_len);
|
||||||
break;
|
break;
|
||||||
@ -977,11 +978,13 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_invite_room_members(req.msg.m.roomid, req.msg.m.wxids, out, out_len);
|
ret = func_invite_room_members(req.msg.m.roomid, req.msg.m.wxids, out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
default: {
|
default: {
|
||||||
LOG_ERROR("[UNKNOW FUNCTION]");
|
LOG_ERROR("[UNKNOW FUNCTION]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pb_release(Request_fields, &req);
|
pb_release(Request_fields, &req);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1065,7 +1068,7 @@ int RpcStopServer()
|
|||||||
if (lIsRunning) {
|
if (lIsRunning) {
|
||||||
nng_close(cmdSock);
|
nng_close(cmdSock);
|
||||||
nng_close(msgSock);
|
nng_close(msgSock);
|
||||||
UnListenMessage();
|
// UnListenMessage();
|
||||||
lIsRunning = false;
|
lIsRunning = false;
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
LOG_INFO("Server stoped.");
|
LOG_INFO("Server stoped.");
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
extern HANDLE g_hEvent;
|
extern HANDLE g_hEvent;
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
extern string GetSelfWxid(); // Defined in spy.cpp
|
extern string GetSelfWxid(); // Defined in spy.cpp
|
||||||
|
#if 0
|
||||||
void SendTextMessage(string wxid, string msg, string atWxids)
|
void SendTextMessage(string wxid, string msg, string atWxids)
|
||||||
{
|
{
|
||||||
int success = 0;
|
int success = 0;
|
||||||
@ -438,3 +438,4 @@ int ForwardMessage(uint64_t msgid, string receiver)
|
|||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Binary file not shown.
@ -7,19 +7,18 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
WxCalls_t g_WxCalls = { 0 };
|
WxCalls_t g_WxCalls = { 0 };
|
||||||
DWORD g_WeChatWinDllAddr = 0;
|
UINT64 g_WeChatWinDllAddr = 0;
|
||||||
|
|
||||||
void InitSpy(LPVOID args)
|
void InitSpy(LPVOID args)
|
||||||
{
|
{
|
||||||
|
|
||||||
wchar_t version[16] = { 0 };
|
wchar_t version[16] = { 0 };
|
||||||
PortPath_t *pp = (PortPath_t *)args;
|
PortPath_t *pp = (PortPath_t *)args;
|
||||||
int port = pp->port;
|
|
||||||
std::string path(pp->path);
|
|
||||||
|
|
||||||
InitLogger(path);
|
InitLogger(pp->path);
|
||||||
g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址
|
g_WeChatWinDllAddr = (UINT64)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址
|
||||||
if (g_WeChatWinDllAddr == 0) {
|
if (g_WeChatWinDllAddr == 0) {
|
||||||
LOG_ERROR("获取wechatWin.dll模块地址失败");
|
LOG_ERROR("获取 wechatWin.dll 模块地址失败");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,16 +26,18 @@ void InitSpy(LPVOID args)
|
|||||||
LOG_ERROR("获取微信版本失败");
|
LOG_ERROR("获取微信版本失败");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("WeChat version: {}", Wstring2String(version).c_str());
|
LOG_INFO("WeChat version: {}", Wstring2String(version).c_str());
|
||||||
if (LoadCalls(version, &g_WxCalls) != 0) { // 加载微信版本对应的Call地址
|
if (LoadCalls(version, &g_WxCalls) != 0) { // 加载微信版本对应的Call地址
|
||||||
LOG_ERROR("不支持当前版本");
|
LOG_ERROR("不支持当前版本");
|
||||||
MessageBox(NULL, L"不支持当前版本", L"错误", 0);
|
MessageBox(NULL, L"不支持当前版本", L"错误", 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcStartServer(port);
|
RpcStartServer(pp->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanupSpy() { RpcStopServer(); }
|
void CleanupSpy()
|
||||||
|
{
|
||||||
int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); }
|
LOG_DEBUG("CleanupSpy");
|
||||||
|
RpcStopServer();
|
||||||
|
}
|
||||||
|
@ -51,8 +51,8 @@ END
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 39,0,13,0
|
FILEVERSION 39,1,0,0
|
||||||
PRODUCTVERSION 3,9,2,23
|
PRODUCTVERSION 3,9,10,19
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -69,12 +69,12 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "WeChatFerry"
|
VALUE "CompanyName", "WeChatFerry"
|
||||||
VALUE "FileDescription", "WeChatFerry"
|
VALUE "FileDescription", "WeChatFerry"
|
||||||
VALUE "FileVersion", "39.0.13.0"
|
VALUE "FileVersion", "39.1.0.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"
|
||||||
VALUE "ProductName", "WeChatFerry"
|
VALUE "ProductName", "WeChatFerry"
|
||||||
VALUE "ProductVersion", "3.9.2.23"
|
VALUE "ProductVersion", "3.9.10.19"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -206,8 +206,8 @@ struct WxString {
|
|||||||
WxString(std::wstring &ws)
|
WxString(std::wstring &ws)
|
||||||
{
|
{
|
||||||
wptr = ws.c_str();
|
wptr = ws.c_str();
|
||||||
size = ws.size();
|
size = (DWORD)ws.size();
|
||||||
capacity = ws.capacity();
|
capacity = (DWORD)ws.capacity();
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
clen = 0;
|
clen = 0;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#include "user_info.h"
|
#include "user_info.h"
|
||||||
#include "load_calls.h"
|
#include "load_calls.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern DWORD g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
|
|
||||||
static char home[MAX_PATH] = { 0 };
|
static char home[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
@ -20,9 +20,9 @@ string GetHomePath()
|
|||||||
|
|
||||||
string GetSelfWxid()
|
string GetSelfWxid()
|
||||||
{
|
{
|
||||||
DWORD wxidType = 0;
|
UINT64 wxidType = 0;
|
||||||
try {
|
try {
|
||||||
wxidType = GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x14);
|
wxidType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x18);
|
||||||
if (wxidType == 0xF) {
|
if (wxidType == 0xF) {
|
||||||
return GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.wxid);
|
return GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.wxid);
|
||||||
} else {
|
} else {
|
||||||
@ -41,7 +41,7 @@ UserInfo_t GetUserInfo()
|
|||||||
|
|
||||||
ui.wxid = GetSelfWxid();
|
ui.wxid = GetSelfWxid();
|
||||||
|
|
||||||
DWORD nameType = GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x14);
|
UINT64 nameType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x18);
|
||||||
if (nameType == 0xF) {
|
if (nameType == 0xF) {
|
||||||
ui.name = GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.nickName);
|
ui.name = GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.nickName);
|
||||||
} else { // 0x1F
|
} else { // 0x1F
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define WECHAREXE L"WeChat.exe"
|
|
||||||
#define WECHATWINDLL L"WeChatWin.dll"
|
|
||||||
#define WECHATSDKDLL L"sdk.dll"
|
|
||||||
#define WECHATINJECTDLL L"spy.dll"
|
|
||||||
#define WECHATINJECTDLL_DEBUG L"spy_debug.dll"
|
|
||||||
|
|
||||||
#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr))
|
|
||||||
#define GET_QWORD(addr) ((uint64_t) * (uint64_t *)(addr))
|
|
||||||
#define GET_STRING(addr) ((CHAR *)(*(DWORD *)(addr)))
|
|
||||||
#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr)))
|
|
||||||
#define GET_STRING_FROM_P(addr) ((CHAR *)(addr))
|
|
||||||
#define GET_WSTRING_FROM_P(addr) ((WCHAR *)(addr))
|
|
||||||
|
|
||||||
typedef struct PortPath {
|
|
||||||
int port;
|
|
||||||
char path[MAX_PATH];
|
|
||||||
} PortPath_t;
|
|
||||||
|
|
||||||
DWORD GetWeChatPid();
|
|
||||||
int OpenWeChat(DWORD *pid);
|
|
||||||
int GetWeChatVersion(wchar_t *version);
|
|
||||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size);
|
|
||||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address);
|
|
||||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
|
||||||
std::wstring String2Wstring(std::string s);
|
|
||||||
std::string Wstring2String(std::wstring ws);
|
|
||||||
std::string GB2312ToUtf8(const char *gb2312);
|
|
||||||
std::string GetStringByAddress(DWORD address);
|
|
||||||
std::string GetStringByStrAddr(DWORD addr);
|
|
||||||
std::string GetStringByWstrAddr(DWORD addr);
|
|
||||||
void DbgMsg(const char *zcFormat, ...);
|
|
@ -1,34 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "sdk.h"
|
|
||||||
|
|
||||||
void help()
|
|
||||||
{
|
|
||||||
printf("\nUsage: \n启动: wcf.exe start port [debug]\n关闭: wcf.exe stop\nport: 命令端口, 消息端口为命令端口+1\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
bool debug = false;
|
|
||||||
|
|
||||||
if ((argc < 2) || (argc > 4)) {
|
|
||||||
help();
|
|
||||||
} else if (argc == 4) {
|
|
||||||
debug = (strcmp(argv[3], "debug") == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "start") == 0) {
|
|
||||||
int port = strtol(argv[2], NULL, 10);
|
|
||||||
|
|
||||||
ret = WxInitSDK(debug, port);
|
|
||||||
} else if (strcmp(argv[1], "stop") == 0) {
|
|
||||||
ret = WxDestroySDK();
|
|
||||||
} else {
|
|
||||||
help();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,173 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<ProjectGuid>{02747ce0-ad9f-4812-b019-fcf9867f7514}</ProjectGuid>
|
|
||||||
<RootNamespace>wcf</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<VcpkgUseStatic>true</VcpkgUseStatic>
|
|
||||||
<VcpkgTriplet>x86-windows-static</VcpkgTriplet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WCF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)sdk;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x86-windows-static\include</AdditionalIncludeDirectories>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
|
||||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out
|
|
||||||
xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Message>Copy files</Message>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="..\sdk\framework.h" />
|
|
||||||
<ClInclude Include="..\sdk\injector.h" />
|
|
||||||
<ClInclude Include="..\sdk\sdk.h" />
|
|
||||||
<ClInclude Include="..\spy\log.h" />
|
|
||||||
<ClInclude Include="..\spy\util.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\sdk\injector.cpp" />
|
|
||||||
<ClCompile Include="..\sdk\sdk.cpp" />
|
|
||||||
<ClCompile Include="..\spy\log.cpp" />
|
|
||||||
<ClCompile Include="..\spy\util.cpp" />
|
|
||||||
<ClCompile Include="main.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="源文件">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="头文件">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="资源文件">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="..\sdk\framework.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\sdk\injector.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\spy\log.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\sdk\sdk.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\spy\util.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\sdk\injector.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\spy\log.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\sdk\sdk.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\spy\util.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="main.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup />
|
|
||||||
</Project>
|
|
18
clients/python/wcferry/client.py
vendored
18
clients/python/wcferry/client.py
vendored
@ -1,10 +1,11 @@
|
|||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__version__ = "39.0.14.1"
|
__version__ = "39.1.0.0"
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
import base64
|
import base64
|
||||||
|
import ctypes
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
@ -72,11 +73,12 @@ class Wcf():
|
|||||||
self.LOG.info(f"wcferry version: {__version__}")
|
self.LOG.info(f"wcferry version: {__version__}")
|
||||||
self.port = port
|
self.port = port
|
||||||
self.host = host
|
self.host = host
|
||||||
|
self.sdk = None
|
||||||
if host is None:
|
if host is None:
|
||||||
self._local_mode = True
|
self._local_mode = True
|
||||||
self.host = "127.0.0.1"
|
self.host = "127.0.0.1"
|
||||||
cmd = fr'"{self._wcf_root}\wcf.exe" start {self.port} {"debug" if debug else ""}'
|
self.sdk = ctypes.cdll.LoadLibrary(f"{self._wcf_root}/sdk.dll")
|
||||||
if os.system(cmd) != 0:
|
if self.sdk.WxInitSDK(debug, port) != 0:
|
||||||
self.LOG.error("初始化失败!")
|
self.LOG.error("初始化失败!")
|
||||||
os._exit(-1)
|
os._exit(-1)
|
||||||
|
|
||||||
@ -121,11 +123,9 @@ class Wcf():
|
|||||||
self.disable_recv_msg()
|
self.disable_recv_msg()
|
||||||
self.cmd_socket.close()
|
self.cmd_socket.close()
|
||||||
|
|
||||||
if self._local_mode:
|
if self._local_mode and self.sdk and self.sdk.WxDestroySDK() != 0:
|
||||||
cmd = fr'"{self._wcf_root}\wcf.exe" stop'
|
self.LOG.error("退出失败!")
|
||||||
if os.system(cmd) != 0:
|
|
||||||
self.LOG.error("退出失败!")
|
|
||||||
return
|
|
||||||
self._is_running = False
|
self._is_running = False
|
||||||
|
|
||||||
def keep_running(self):
|
def keep_running(self):
|
||||||
@ -658,7 +658,7 @@ class Wcf():
|
|||||||
if (cnt["wxid"].endswith("@chatroom") or # 群聊
|
if (cnt["wxid"].endswith("@chatroom") or # 群聊
|
||||||
cnt["wxid"].startswith("gh_") or # 公众号
|
cnt["wxid"].startswith("gh_") or # 公众号
|
||||||
cnt["wxid"] in not_friends.keys() # 其他杂号
|
cnt["wxid"] in not_friends.keys() # 其他杂号
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
friends.append(cnt)
|
friends.append(cnt)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user