Merge pull request #151 from lich0821/3.9.10.19

3.9.10.19
This commit is contained in:
Changhua 2024-04-29 21:28:02 +08:00 committed by GitHub
commit 4c079db075
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 436 additions and 651 deletions

220
README.MD
View File

@ -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>
|![碲矿](assets/TEQuant.jpg)|![赞赏](assets/QR.jpeg)| |![碲矿](assets/TEQuant.jpg)|![赞赏](assets/QR.jpeg)|
|:-:|:-:| |:-:|:-:|
|后台回复 `WCF` 加群交流|如果你觉得有用| |后台回复 `WCF` 加群交流|如果你觉得有用|
## 快速开始
### Python
[![PyPi](https://img.shields.io/pypi/v/wcferry.svg)](https://pypi.python.org/pypi/wcferry) [![Downloads](https://static.pepy.tech/badge/wcferry)](https://pypi.python.org/pypi/wcferry) [![Documentation Status](https://readthedocs.org/projects/wechatferry/badge/?version=latest)](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,15 @@ 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 integrate install vcpkg integrate install
``` ```
@ -139,27 +62,39 @@ vcpkg integrate install
</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 进程
``` ```
## 项目结构 ## 项目结构
```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 # 二维码,测试用图
@ -169,7 +104,7 @@ WeChatFerry
│   ├── gohttp # HTTP 客户端 │   ├── gohttp # HTTP 客户端
│   ├── http # HTTP 客户端 │   ├── http # HTTP 客户端
│   ├── java # Java 客户端 │   ├── java # Java 客户端
│   ├── node # Node.js 客户端 │   ├── node # Node.js 客户端
│   ├── pyauto # 群友封装的客户端 │   ├── pyauto # 群友封装的客户端
│   ├── python # Python 客户端 │   ├── python # Python 客户端
│   └── rust # Rust 客户端 │   └── rust # Rust 客户端
@ -177,47 +112,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 +130,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 +160,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 +201,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 +209,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.222023.04.09 ### v3.7.0.30.222023.04.09
将监听端口调整为可配置。 将监听端口调整为可配置。
### v3.7.0.30.212023.03.15 ### v3.7.0.30.212023.03.15
* 发送表情 * 发送表情
### v3.7.0.30.202023.03.12 ### v3.7.0.30.202023.03.12
修复 wxid 获取问题。 修复 wxid 获取问题。
### v3.7.0.30.192023.03.06 ### v3.7.0.30.192023.03.06
修复重复消息问题。 修复重复消息问题。
### v3.7.0.30.182023.03.05 ### v3.7.0.30.182023.03.05
修复添加好友问题。 修复添加好友问题。
### v3.7.0.30.172023.03.05 ### v3.7.0.30.172023.03.05
修复获取登录账号 wxid 问题。 修复获取登录账号 wxid 问题。
### v3.7.0.30.162023.03.04 ### v3.7.0.30.162023.03.04
将错误码改成错误消息,方便调试。 将错误码改成错误消息,方便调试。
### v3.7.0.30.152023.03.01 ### v3.7.0.30.152023.03.01
* 发送 xml * 发送 xml
### v3.7.0.30.142023.02.28 ### v3.7.0.30.142023.02.28
* 添加群成员 * 添加群成员
### v3.7.0.30.132023.02.27 ### v3.7.0.30.132023.02.27
去除 gRPC 框架,自定义更轻量的 RPC 轮子 `nnprc`。 去除 gRPC 框架,自定义更轻量的 RPC 轮子 `nnprc`。
### v3.7.0.30.122023.01.20 ### v3.7.0.30.122023.01.20
* 更新 Python 客户端 * 更新 Python 客户端
* 修改监听地址为 `0.0.0.0:10086` * 修改监听地址为 `0.0.0.0:10086`
* 增加 `Launcher`,直接注入 `spy` * 增加 `Launcher`,直接注入 `spy`
### v3.7.0.30.112022.10.19 ### v3.7.0.30.112022.10.19
更新 Python 客户端。 更新 Python 客户端。
### v3.7.0.30-gRPC-22022.10.18 ### v3.7.0.30-gRPC-22022.10.18
增加 Java 客户端。 增加 Java 客户端。
### v3.7.0.30-gRPC-12022.10.16 ### v3.7.0.30-gRPC-12022.10.16
将 RPC 框架切换为 gRPC 将 RPC 框架切换为 gRPC
### v3.7.0.30-82022.09.25 ### v3.7.0.30-82022.09.25
* 获取登录账号微信 ID * 获取登录账号微信 ID
### v3.7.0.30-72022.09.24 ### v3.7.0.30-72022.09.24
修复群聊有系统消息时会崩溃 bug。后续考虑把消息来源交还给客户端自己区别。 修复群聊有系统消息时会崩溃 bug。后续考虑把消息来源交还给客户端自己区别。
### v3.7.0.30-62022.08.21 ### v3.7.0.30-62022.08.21
* 通过好友验证 * 通过好友验证
### v3.7.0.30-52022.08.20 ### v3.7.0.30-52022.08.20
* 执行 SQL 语句 * 执行 SQL 语句
### v3.7.0.30-42022.08.20 ### v3.7.0.30-42022.08.20
修复群消息 @人 功能。有几点注意事项: 修复群消息 @人 功能。有几点注意事项:
1. `vAtWxids` 是要 `@` 的 `wxid` 清单,以 `,` 分隔。 1. `vAtWxids` 是要 `@` 的 `wxid` 清单,以 `,` 分隔。
2. 只有群主才能 `@所有人`,非群主硬发 `@所有人` 会导致消息发不出去;`@所有人` 对应 `vAtWxids` 为 `"notify@all"`。 2. 只有群主才能 `@所有人`,非群主硬发 `@所有人` 会导致消息发不出去;`@所有人` 对应 `vAtWxids` 为 `"notify@all"`。
3. 消息体里 `@` 的数量必须与 `vAtWxids` 里的数量一致,否则消息能发出但 `@` 功能失效。 3. 消息体里 `@` 的数量必须与 `vAtWxids` 里的数量一致,否则消息能发出但 `@` 功能失效。
### v3.7.0.30-32022.08.20 ### v3.7.0.30-32022.08.20
修复可重入 bug。 修复可重入 bug。
### v3.7.0.30-22022.08.14 ### v3.7.0.30-22022.08.14
优化 Hook 和 Inject 代码,实现可重入。 优化 Hook 和 Inject 代码,实现可重入。
### v3.7.0.30-12022.08.12 ### v3.7.0.30-12022.08.12
适配微信 `3.7.0.30`。 适配微信 `3.7.0.30`。
### v3.7.0.29-32022.08.7 ### v3.7.0.29-32022.08.7
* 查询数据库,获取库、表。 * 查询数据库,获取库、表。
### v3.7.0.29-22022.08.7 ### v3.7.0.29-22022.08.7
优化 RPC。 优化 RPC。
### v3.7.0.29-12022.08.7 ### v3.7.0.29-12022.08.7
适配微信 `3.7.0.29`。 适配微信 `3.7.0.29`。
### v3.3.0.115-32021.08.28 ### v3.3.0.115-32021.08.28
适配微信 `3.3.0.115`,新增功能: 适配微信 `3.3.0.115`,新增功能:
* 获取所有联系人 * 获取所有联系人
### v3.3.0.115-22021.08.22 ### v3.3.0.115-22021.08.22
适配微信 `3.3.0.115`,新增功能: 适配微信 `3.3.0.115`,新增功能:
* 发送图片消息 * 发送图片消息
### v3.3.0.115-12021.08.22 ### v3.3.0.115-12021.08.22
适配微信 `3.3.0.115`。 适配微信 `3.3.0.115`。
### v3.0.0.57-12021.02.12 ### v3.0.0.57-12021.02.12
适配微信 `3.0.0.57`,支持功能: 适配微信 `3.0.0.57`,支持功能:
* 登录状态判断 * 登录状态判断
* 接收文本消息 * 接收文本消息

View File

@ -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

View File

@ -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) {

View File

@ -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);
@ -163,9 +163,9 @@ int GetWeChatVersion(wchar_t *version)
return ret; return ret;
} }
DWORD GetWeChatPid() UINT64 GetWeChatPid()
{ {
DWORD pid = 0; UINT64 pid = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) }; PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
while (Process32Next(hSnapshot, &pe32)) { while (Process32Next(hSnapshot, &pe32)) {
@ -179,7 +179,7 @@ DWORD GetWeChatPid()
return pid; return pid;
} }
int OpenWeChat(DWORD *pid) int OpenWeChat(UINT64 *pid)
{ {
*pid = GetWeChatPid(); *pid = GetWeChatPid();
if (*pid) { if (*pid) {
@ -208,9 +208,9 @@ int OpenWeChat(DWORD *pid)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size)
{ {
DWORD strLength = GET_DWORD(address + 4); size_t strLength = GET_UINT64(address + 4);
if (strLength == 0) { if (strLength == 0) {
return 0; return 0;
} else if (strLength > buffer_size) { } else if (strLength > buffer_size) {
@ -222,27 +222,27 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
return strLength; return strLength;
} }
string GetStringByAddress(DWORD address) string GetStringByAddress(UINT64 address)
{ {
DWORD strLength = GET_DWORD(address + 4); UINT64 strLength = GET_UINT64(address + 4);
return Wstring2String(wstring(GET_WSTRING(address), strLength)); return Wstring2String(wstring(GET_WSTRING(address), strLength));
} }
string GetStringByStrAddr(DWORD addr) string GetStringByStrAddr(UINT64 addr)
{ {
DWORD strLength = GET_DWORD(addr + 4); UINT64 strLength = GET_UINT64(addr + 4);
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); UINT64 strLength = GET_UINT64(addr + 4);
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 address)
{ {
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)address, data, 4, 0)) {
@ -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;

35
WeChatFerry/com/util.h Normal file
View File

@ -0,0 +1,35 @@
#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_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;
UINT64 GetWeChatPid();
int OpenWeChat(UINT64 *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, ...);

View File

@ -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" />

View File

@ -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">

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;

View File

@ -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" />

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -3,9 +3,10 @@
#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 { 0x2FFD484, 0x2FFD590, 0x2FFD500, 0x30238CC }, // User Info: wxid, nickname, mobile, home
{ 0x768140, 0xCE6C80, 0x756960 }, // Send Message { 0x768140, 0xCE6C80, 0x756960 }, // Send Message
/* Receive Message: /* Receive Message:

View File

@ -19,7 +19,7 @@ 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; static DWORD reg_buffer = 0;
static DWORD recvMsgHookAddr = 0; static DWORD recvMsgHookAddr = 0;
@ -31,7 +31,7 @@ static DWORD recvPyqHookAddr = 0;
static DWORD recvPyqCallAddr = 0; static DWORD recvPyqCallAddr = 0;
static DWORD recvPyqJumpBackAddr = 0; static DWORD recvPyqJumpBackAddr = 0;
static CHAR recvPyqBackupCode[5] = { 0 }; static CHAR recvPyqBackupCode[5] = { 0 };
#if 0
MsgTypes_t GetMsgTypes() MsgTypes_t GetMsgTypes()
{ {
const MsgTypes_t m = { const MsgTypes_t m = {
@ -259,3 +259,4 @@ void UnListenPyq()
UnHookAddress(recvPyqHookAddr, recvPyqBackupCode); UnHookAddress(recvPyqHookAddr, recvPyqBackupCode);
gIsListeningPyq = false; gIsListeningPyq = false;
} }
#endif

View File

@ -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

View File

@ -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;
@ -70,7 +68,7 @@ bool func_is_login(uint8_t *out, size_t *len)
return true; return true;
} }
#if 0
bool func_get_self_wxid(uint8_t *out, size_t *len) bool func_get_self_wxid(uint8_t *out, size_t *len)
{ {
Response rsp = Response_init_default; Response rsp = Response_init_default;
@ -837,7 +835,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,11 +848,13 @@ 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);
break; break;
} }
#if 0
case Functions_FUNC_GET_SELF_WXID: { case Functions_FUNC_GET_SELF_WXID: {
ret = func_get_self_wxid(out, out_len); ret = func_get_self_wxid(out, out_len);
break; break;
@ -977,11 +977,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 +1067,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.");

View File

@ -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.

View File

@ -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();
}

View File

@ -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"

View File

@ -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;
} }

View File

@ -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 + 0x14);
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 + 0x14);
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

View File

@ -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, ...);

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -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)