Compare commits

...
35 Commits
Author SHA1 Message Date
hugy 822e076a82 更新文档 2023-02-17 14:49:58 +08:00
hugy 3ed52a7dbc 新增搜索微信 2023-02-17 14:47:06 +08:00
hugy 9e5dce93f0 新增搜索微信 2023-02-17 14:46:49 +08:00
hugy db5051ae2f 新增添加好友 2023-02-17 08:44:51 +08:00
hugy c8544a9286 更新文档 2023-02-13 13:33:15 +08:00
hugy 3522f9187e 修改宏定义笔误 2023-02-13 11:44:45 +08:00
hugy 4e34505cdd 修改文档 2023-02-13 11:37:34 +08:00
hugy 3d8ed813be 新增查询昵称 2023-02-13 11:30:33 +08:00
hugy 75d470935d 已有的功能全部更新到3.9.0.28版本 2023-02-11 16:26:05 +08:00
hugy 7be2903dd2 3.9.0.28版本数据库和群相关功能 2023-02-10 15:52:55 +08:00
hugy e563710f80 3.9.0.28版本 2023-02-09 15:47:55 +08:00
hugy 915cb1602f 文档修改 2023-02-08 13:43:57 +08:00
hugy 254a9eeb30 朋友圈消息hook和朋友圈消息获取 2023-02-08 13:35:04 +08:00
hugy a0f83b5a99 转账收款 2023-02-07 08:36:13 +08:00
hugy e7a460ad25 新增确认收款 close #12 2023-02-06 17:56:37 +08:00
hugy ebde430aec 修复一些内存泄漏 2023-02-06 11:21:13 +08:00
hugy 1216733b82 完善接口文档 close #10 2023-02-04 16:42:57 +08:00
hugy 6dca99474b 修改转发消息接口文档 2023-02-04 16:28:34 +08:00
hugy d818c826e5 使用微信内部函数释放内存 2023-02-04 15:07:01 +08:00
hugy b0e73002ff 新增群消息置顶,修改问题 close #9 2023-02-04 12:04:28 +08:00
hugy a2cfb13217 修改hook消息接口问题 2023-02-01 17:05:12 +08:00
hugy 911f87211c 修改hook消息接口 close #5 2023-02-01 17:01:53 +08:00
hugy 2f1793b2b1 拍一拍实现 2023-02-01 11:57:32 +08:00
hugy 6b36287c4d 修改文档 2023-02-01 10:39:41 +08:00
hugy d86d4c0bf6 新增拍一拍 2023-02-01 10:36:32 +08:00
hugy f82f85b2b6 修改文档错误描述 2023-01-31 16:50:18 +08:00
hugy c508ae30f8 新增修改群昵称 2023-01-31 16:10:58 +08:00
hugy c05e9ce303 3.8.1.26 release dll 2023-01-29 14:23:15 +08:00
hugy 4758fbf005 3.8.1.26 release dll 2023-01-29 14:15:12 +08:00
hugy 088a7d28cb 修改cmake变量,构建更通用 2023-01-04 09:55:45 +08:00
Gy Hu a9b01eebe1 修改更新内容 2023-01-02 11:46:58 +08:00
Gy Hu 8b68a347a0 退出微信登录 2023-01-02 11:45:04 +08:00
Gy Hu fd66a641f6 新增ocr 2022-12-29 14:58:41 +08:00
Gy Hu ab3780c413 注入dll 2022-12-26 16:53:26 +08:00
Gy Hu e62a37b354 支持3.8.1.26版本 2022-12-26 16:44:14 +08:00
40 changed files with 2102 additions and 216 deletions
+3
View File
@@ -30,3 +30,6 @@
#*.exe
*.out
*.app
/out
CMakePresets.json
.vscode
+2 -2
View File
@@ -5,13 +5,13 @@ project(wxhelper VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '0_UNICODE' /D 'UNICODE'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '_UNICODE' /D 'UNICODE'")
file(GLOB CPP_FILES ${PROJECT_SOURCE_DIR}/src/*.cc ${PROJECT_SOURCE_DIR}/src/*.cpp)
include_directories(c:/soft/vcpkg/installed/x86-windows/include)
include_directories(${VCPKG_INSTALLED_DIR}/x86-windows/include)
# add_subdirectory(3rd)
+790 -46
View File
@@ -1,33 +1,146 @@
# wxhelper
wechat hook .
wechat hook 。PC端微信逆向学习。支持3.8.0.41,3.8.1.26,3.9.0.28版本。
#### 免责声明:
本仓库发布的内容,仅用于学习研究,请勿用于非法用途和商业用途!如因此产生任何法律纠纷,均与作者无关!
#### 项目说明:
本项目是个人学习学习逆向的项目,主要参考https://github.com/ttttupup/ComWeChatRobot,在此基础上实现了wechat 3.8.0.41的版本的部分内容。
本项目是个人学习学习逆向的项目,主要参考 https://github.com/ljc545w/ComWeChatRobot ,在此基础上实现了微信的的其它版本的部分内容。
#### 使用说明:
支持的版本3.8.0.41,目前是最新版本。
src:主要的dll代码
tool:简单的注入工具,一个是控制台,一个是图形界面。
python: 简单的服务器,用以接收消息内容。
release:编译好的dll。
支持的版本3.8.0.41,3.8.1.26, 3.9.0.28。
src:主要的dll代码
tool:简单的注入工具,一个是控制台,一个是图形界面。
python: 简单的服务器,用以接收hook的消息内容。
0.首先安装对应的微信版本,主分支是3.8.0.41版本,分支对应相应的微信版本号.
1.通过cmake构建成功后,将wxhelper.dll注入到微信,本地启动tcp server,监听19088端口。
2.通过http协议与dll通信,方便客户端操作。
3.接口的url为http://127.0.0.1:19088,注入成功后,直接进行调用即可。
4.特别注意数据库查询接口需要先调用获取到句柄之后,才能进行查询。
5.相关功能只在win11环境下进行简单测试,其他环境无法保证。
6.注意个别接口在3.8.0.41版本没有实现,具体参考源码。
7.对应分支接口文档都是支持指定版本的,其他版本不支持,请特别注意版本。
8.相应分支的文档对应相应版本,带有删除线的接口表示该版本的暂未实现,其他版本有实现。后续会继续实现。
1.通过cmake构建成功后,将wxhelper.dll注入到微信,本地启动tcp server,监听19088端口。
2.通过http协议与dll通信,方便客户端操作。
3.接口的url为http://127.0.0.1:19088,注入成功后,直接进行调用即可。
4.特别注意数据库查询接口需要先调用获取到句柄之后,才能进行查询。
5.相关功能只在win11环境下进行简单测试,其他环境无法保证。
#### 编译环境
Visual Studio 2022(x86)
Visual Studio code
cmake
vcpkg
Visual Studio 2022(x86)
Visual Studio code
cmake
vcpkg
#### 构建步骤
以下是在vscode中操作,vs中的操作类似。
1.安装vcpkg,cmake,vscode
2.安装相应的库,如果安装的版本不同,则根据vcpkg安装成功后提示的find_package修改CMakeLists.txt内容即可。或者自己编译。
```
vcpkg install mongoose
vcpkg install nlohmann-json
```
3.vscode 配置CMakePresets.json,主要设置CMAKE_C_COMPILER 和CMAKE_CXX_COMPILER 为cl.exe.参考如下
```
{
"name": "x86-release",
"displayName": "x86-release",
"description": "Sets Ninja generator, build and install directory",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"architecture":{
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
"CMAKE_TOOLCHAIN_FILE": {
"value": "C:/soft/vcpkg/scripts/buildsystems/vcpkg.cmake",
"type": "FILEPATH"
}
},
"environment": {
}
}
```
4.vscode中右键configure all projects,在Terminal中点击Run Task,如没有先配置build任务,然后运行即可
5.命令行注入工具,注入命令
``` javascript
//-i 注入程序名 -p 注入dll路径
// -u 卸载程序名 -d 卸载dll名称
//注入
ConsoleInject.exe -i demo.exe -p E:\testInject.dll
//卸载
ConsoleInject.exe -u demo.exe -d testInject.dll
```
#### 更新说明
2022-12-26 : 增加3.8.1.26版本支持。
2022-12-29 : 新增提取文字功能。
2023-01-02 : 退出微信登录。
2023-01-31 : 新增修改群昵称(仅支持3.8.1.26)。
2023-02-01 : 新增拍一拍(仅支持3.8.1.26)。
2023-02-04 : 新增群消息置顶和取消置顶。
2023-02-06 : 新增确认收款。
2023-02-08 : 新增朋友圈消息。
2023-02-09 : 新增3.9.0.28版本基础功能。
2023-02-13 : 新增查询联系人昵称功能。
2023-02-17 : 新增通过wxid添加好友和查找微信。
#### 功能预览:
0.检查是否登录
1.获取登录微信信息
2.发送文本
5.发送图片
6.发送文件
9.hook消息
10.取消hook消息
11.hook图片
12.取消hook图片
17.删除好友
19.通过手机或qq查找微信
20.通过wxid添加好友
25.获取群成员
26.获取群成员昵称
27.删除群成员
28.增加群成员
31.修改群昵称
32.获取数据库句柄
34.查询数据库
40.转发消息
44.退出登录
45.确认收款
46.联系人列表
47.获取群详情
48.获取解密图片
49.图片提取文字ocr
50.拍一拍
51.群消息置顶消息
52.群消息取消置顶
53.朋友圈首页
54.朋友圈下一页
55.获取联系人或者群名称
### 接口文档:
#### 0.检查微信登录**
###### 接口功能
> 检查微信是否登录
@@ -51,7 +164,6 @@ vcpkg
|data|string|响应内容|
###### 接口示例
地址:https://www.bincoding.cn/test
入参:
``` javascript
```
@@ -98,7 +210,6 @@ vcpkg
|wxid|string|wxid|
###### 接口示例
地址:https://www.bincoding.cn/test
入参:
``` javascript
```
@@ -123,7 +234,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|msg|true |string|消息文本内容|
###### 返回字段
@@ -134,7 +245,7 @@ vcpkg
###### 接口示例
地址:https://www.bincoding.cn/test
入参:
``` javascript
{
@@ -162,7 +273,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|imagePath|true |string|图片路径|
###### 返回字段
@@ -200,7 +311,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|filePath|true |string|文件路径|
###### 返回字段
@@ -237,8 +348,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|port |ture |string| 本地服务端端口,用来接收消息内容 |
|port |true |string| 本地服务端端口,用来接收消息内容 |
|ip |true |string| 服务端ip地址,用来接收消息内容,可以是任意ip,即tcp客户端连接的服务端的ip (3.8.1.26版本)|
###### 返回字段
|返回字段|字段类型|说明 |
@@ -252,6 +363,7 @@ vcpkg
``` javascript
{
"port": "19099"
"ip":"127.0.0.1"
}
```
响应:
@@ -260,6 +372,38 @@ vcpkg
```
#### 10.取消hook消息**
###### 接口功能
> 取消hook消息
###### 接口地址
> [/api/?type=10](/api/?type=10)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 11.hook图片**
###### 接口功能
@@ -274,7 +418,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imgDir |ture |string| 图片保存的目录 |
|imgDir |true |string| 图片保存的目录 |
###### 返回字段
@@ -297,13 +441,12 @@ vcpkg
```
#### 17.删除好友**
#### 12.取消hook图片**
###### 接口功能
> 删除好友
> 取消hook图片
###### 接口地址
> [/api/?type=17](/api/?type=17)
> [/api/?type=12](/api/?type=12)
###### HTTP请求方式
> POST JSON
@@ -311,7 +454,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 好友wxid |
###### 返回字段
@@ -324,15 +467,144 @@ vcpkg
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_o"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 17.删除好友**
###### 接口功能
> 删除好友,该接口不够完善,删除后,只会在通讯录里删除,如果点击聊天记录,又会重新加回来,删除的不彻底。
###### 接口地址
> [/api/?type=17](/api/?type=17)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |true |string| 好友wxid |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_o"
}
```
响应:
``` javascript
{"code":0,"result":"OK"}
```
#### 19.通过手机或qq查找微信**
###### 接口功能
> 通过手机或qq查找微信
###### 接口地址
> [/api/?type=19](/api/?type=19)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|keyword |true |string| 手机或qq |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
|userInfo|object|用户信息|
|  bigImage|string|大头像|
|  smallImage|string|小头像|
|  city|string|城市|
|  nation|string|民族|
|  nickname|string|昵称|
|  province|string|省|
|  sex|number|性别|
|  signature|string|签名|
|  v2|string|v2|
|  v3|string|v3|
###### 接口示例
入参:
``` javascript
{
"keyword":"131111111"
}
```
响应:
``` javascript
{
"code": 1,
"result": "OK",
"userInfo": {
"bigImage": "http://wx.qlogo.cn/mmhead/ver_1/7NIHQAyXeaAPa7Vd7p122mKxgETJwoAiaERdk1sSyOyfnLLQOfElw4G9I32QkZzh7bGfZr2lg0OIQE1Az3cUwtWaLUM79Q/0",
"city": "",
"nation": "",
"nickname": "昵称",
"province": "",
"sex": 0,
"signature": "",
"smallImage": "http://wx.qlogo.cn/mmhead/ver_1/7NIHQAyXeaAPa7Vd7p4KR3vxiasmKxgETJwoAiaER23QE6G5mLBcdBQkZzh7bGfZr2lg0OIQE1Az3cUwtWaLUM79Q/132",
"v2": "wxid_12333",
"v3": "v3_020b3826fd0301000000000098ca23832239a3dba12f95f6b60a0536a1adb6b40fc4086288f46c0b89e6c4eb70c34f118c7b4b6a6845144843b088f0077e406507f821068571289b36c4158a8ac47ec41ae47bee65e9@stranger"
}
}
```
#### 20.通过wxid添加好友**
###### 接口功能
> 添加好友
###### 接口地址
> [/api/?type=20](/api/?type=20)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |true |string| 好友wxid |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_o1112222"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 25.获取群成员**
@@ -348,7 +620,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|chatRoomId |true |string| 群id |
###### 返回字段
@@ -375,6 +647,43 @@ vcpkg
```
#### 26.获取群成员昵称**
###### 接口功能
> 获取群成员群内昵称
###### 接口地址
> [/api/?type=26](/api/?type=26)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|memberId |true |string| 群成员id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
|nickname|string|昵称|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"123@chatroom",
"memberId":"wxid_123"
}
```
响应:
``` javascript
{"code":1,"nickname":"昵称","result":"OK"}
```
#### 27.删除群成员**
###### 接口功能
@@ -389,8 +698,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|memberIds |ture |string| 成员id,以,分割 |
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,以,分割 |
###### 返回字段
@@ -428,8 +737,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|memberIds |ture |string| 成员id,以,分割 |
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,以,分割 |
###### 返回字段
@@ -453,6 +762,43 @@ vcpkg
```
#### 31.修改自身群昵称**
###### 接口功能
> 修改群名片
###### 接口地址
> [/api/?type=31](/api/?type=31)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|wxid |true |string| 自己的id,只能修改自己的群名片 |
|nickName |true |string| 修改的昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"34932563384@chatroom",
"wxid":"wxid_272211111121112",
"nickName":"昵称test"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
@@ -528,8 +874,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|dbHandle |ture |int| 句柄 |
|sql |ture |string| sql语句 |
|dbHandle |true |int| 句柄 |
|sql |true |string| sql语句 |
###### 返回字段
@@ -555,6 +901,119 @@ vcpkg
```
#### 40.转发消息**
###### 接口功能
> 直接转发消息
###### 接口地址
> [/api/?type=40](/api/?type=40)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |true |string| 消息接收人wxid |
|msgid |true |number| 消息id,hook消息接口中返回的消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,非0成功|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"wxid": "filehelper",
"msgid":7215505498606506901
}
```
响应:
``` javascript
{"code":4344,"result":"OK"}
```
#### 44.退出登录**
###### 接口功能
> 退出登录微信,相当于直接退出微信,跟手动退出比,少了重新打开登录的一步,dll注入后也会随微信关闭而关闭。调用后不能再继续操作dll。
###### 接口地址
> [/api/?type=44](/api/?type=44)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,非0成功|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":4344,"result":"OK"}
```
#### 45.确认收款**
###### 接口功能
> 收到转账消息后,自动收款确认。type=49 即是转账消息。
###### 接口地址
> [/api/?type=45](/api/?type=45)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|转账人微信id,从hook的消息中获取|
|transcationId|string|从hook的消息中获取对应的字段内容。|
|transferId|string|从hook的消息中获取对应的字段内容。|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_agz5q76f11112",
"transcationId":"10000500012302060002831233124719620",
"transferId":"10000500012023020619112332136412"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 46.联系人列表**
###### 接口功能
@@ -613,7 +1072,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -656,8 +1115,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imagePath |ture |string| 图片路径 |
|savePath |ture |string| 保存路径 |
|imagePath |true |string| 图片路径 |
|savePath |true |string| 保存路径 |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -682,7 +1141,292 @@ vcpkg
```
#### 49.提取文字**
###### 接口功能
> 提取图片中的文字
###### 接口地址
> [/api/?type=49](/api/?type=49)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imagePath |true |string| 图片路径 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败,1 2 则是缓存或者正在进行中需再调用一次|
|result|string|成功提示|
|text|string|提取的相应文字|
#### 50.拍一拍**
###### 接口功能
> 群里拍一拍用户
###### 接口地址
> [/api/?type=50](/api/?type=50)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 微信群聊id |
|wxid |true |string| 要拍的用户wxid,如果使用用户自定义的微信号,则不会显示群内昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"123331@chatroom",
"wxid":"wxid_123456"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 51.群内消息置顶**
###### 接口功能
> 在群聊里置顶某条消息,可以置顶文字和图片消息,其他消息未测试,部分低版本移动端置顶消息点击后会直接取消,高版本会一直置顶,其他未测试。
###### 接口地址
> [/api/?type=51](/api/?type=51)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |true |string| 置顶消息的发送人wxid |
|msgid |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败,-2 未查到该消息|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_oy11111p4422",
"msgid":3334956046278903121
}
```
响应:
``` javascript
{"code":0,"result":"OK"}
```
#### 52.取消群内消息置顶**
###### 接口功能
> 取消置顶的消息。部分低版本移动端会不显示移除消息,但是会正常移除。
###### 接口地址
> [/api/?type=52](/api/?type=52)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 微信群聊id |
|msgid |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"2136311004@chatroom",
"msgid":3374951233278903120
}
```
响应:
``` javascript
{"code":0,"result":"OK"}
```
#### 53.朋友圈首页消息**
###### 接口功能
> 获取朋友圈最新消息,调用之后,会在tcpserver服务中收到朋友圈的消息。格式如下:
``` javascript
{
'data': [
{
'content': '朋友圈[玫瑰][玫瑰]',
'createTime': 1675827480,
'senderId': 'wxid_12333',
'snsId': 14057859804711563695,
'xml': '<TimelineObject><id><![CDATA[1405712322563695]]></id><username><![CDATA[wxid_12333]]></username><createTime><![CDATA[1675827480]]></createTime><contentDescShowType>0</contentDescShowType><contentDescScene>0</contentDescScene><private><![CDATA[0]]></private><contentDesc><![CDATA[朋友圈[玫瑰][玫瑰]]]></contentDesc><contentattr><![CDATA[0]]></contentattr><sourceUserName></sourceUserName><sourceNickName></sourceNickName><statisticsData></statisticsData><weappInfo><appUserName></appUserName><pagePath></pagePath><version><![CDATA[0]]></version><debugMode><![CDATA[0]]></debugMode><shareActionId></shareActionId><isGame><![CDATA[0]]></isGame><messageExtraData></messageExtraData><subType><![CDATA[0]]></subType><preloadResources></preloadResources></weappInfo><canvasInfoXml></canvasInfoXml><ContentObject><contentStyle><![CDATA[2]]></contentStyle><contentSubStyle><![CDATA[0]]></contentSubStyle><title></title><description></description><contentUrl></contentUrl></ContentObject><actionInfo><appMsg><mediaTagName></mediaTagName><messageExt></messageExt><messageAction></messageAction></appMsg></actionInfo><appInfo><id></id></appInfo><location poiClassifyId="" poiName="" poiAddress="" poiClassifyType="0" city=""></location><publicUserName></publicUserName><streamvideo><streamvideourl></streamvideourl><streamvideothumburl></streamvideothumburl><streamvideoweburl></streamvideoweburl></streamvideo></TimelineObject>'
}]
}
```
###### 接口地址
> [/api/?type=53](/api/?type=53)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 54.朋友圈下一页**
###### 接口功能
> 朋友圈下一页,会在tcpserver服务中收到朋友圈的消息。格式如下:
``` javascript
{
'data': [
{
'content': '朋友圈[玫瑰][玫瑰]',
'createTime': 1675827480,
'senderId': 'wxid_12333',
'snsId': 14057859804711563695,
'xml': '<TimelineObject><id><![CDATA[1405712322563695]]></id><username><![CDATA[wxid_12333]]></username><createTime><![CDATA[1675827480]]></createTime><contentDescShowType>0</contentDescShowType><contentDescScene>0</contentDescScene><private><![CDATA[0]]></private><contentDesc><![CDATA[朋友圈[玫瑰][玫瑰]]]></contentDesc><contentattr><![CDATA[0]]></contentattr><sourceUserName></sourceUserName><sourceNickName></sourceNickName><statisticsData></statisticsData><weappInfo><appUserName></appUserName><pagePath></pagePath><version><![CDATA[0]]></version><debugMode><![CDATA[0]]></debugMode><shareActionId></shareActionId><isGame><![CDATA[0]]></isGame><messageExtraData></messageExtraData><subType><![CDATA[0]]></subType><preloadResources></preloadResources></weappInfo><canvasInfoXml></canvasInfoXml><ContentObject><contentStyle><![CDATA[2]]></contentStyle><contentSubStyle><![CDATA[0]]></contentSubStyle><title></title><description></description><contentUrl></contentUrl></ContentObject><actionInfo><appMsg><mediaTagName></mediaTagName><messageExt></messageExt><messageAction></messageAction></appMsg></actionInfo><appInfo><id></id></appInfo><location poiClassifyId="" poiName="" poiAddress="" poiClassifyType="0" city=""></location><publicUserName></publicUserName><streamvideo><streamvideourl></streamvideourl><streamvideothumburl></streamvideothumburl><streamvideoweburl></streamvideoweburl></streamvideo></TimelineObject>'
}]
}
```
###### 接口地址
> [/api/?type=54](/api/?type=54)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|snsId |true |string| 朋友圈的snsId |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"snsId":"14056334227327177401"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 55.获取联系人或者群名称**
###### 接口功能
> 根据wxid,获取联系人微信名称,传入群id获取群名称,传入群内非好友获取的是微信名称不是群内昵称。
###### 接口地址
> [/api/?type=55](/api/?type=55)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|id |true |string| wxid或者群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|result|string|成功提示|
|name|string|名称|
###### 接口示例
入参:
``` javascript
{
"id":"wxid_123"
}
```
响应:
``` javascript
{"code":1,"name":"文件助手","result":"OK"}
```
#### 感谢
https://github.com/ljc545w/ComWeChatRobot
https://github.com/NationalSecurityAgency/ghidra
https://github.com/x64dbg/x64dbg
https://github.com/ljc545w/ComWeChatRobot
https://github.com/NationalSecurityAgency/ghidra
https://github.com/x64dbg/x64dbg
Binary file not shown.
+124 -1
View File
@@ -18,6 +18,11 @@
#include "chat_room.h"
#include "self_info.h"
#include "hook_img.h"
#include "ocr.h"
#include "pat.h"
#include "confirm_receipt.h"
#include "sns.h"
#include "search_contact.h"
#pragma comment(lib, "ws2_32.lib")
using namespace std;
@@ -265,7 +270,11 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
}
case WECHAT_MSG_START_HOOK: {
int port = get_http_req_param_int(hm, j_param, "port", is_post);
int success = HookRecvMsg(port);
wstring ip = get_http_req_param(hm, j_param, "ip", is_post);
string client_ip = Wstring2String(ip);
char ip_cstr[16];
strcpy_s(ip_cstr,client_ip.c_str());
int success = HookRecvMsg(ip_cstr,port);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
@@ -313,9 +322,33 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CONTACT_SEARCH_BY_NET: {
wstring keyword = get_http_req_param(hm, j_param, "keyword", is_post);
UserInfo *user = nullptr;
int success = SearchContactNetScene(WS2LW(keyword), &user);
json ret_data = {{"code", success}, {"result", "OK"}};
if (user) {
json info = {
{"bigImage", unicode_to_utf8(user->big_image)},
{"smallImage", unicode_to_utf8(user->small_image)},
{"city", unicode_to_utf8(user->city)},
{"nation", unicode_to_utf8(user->nation)},
{"nickname", unicode_to_utf8(user->nickname)},
{"province", unicode_to_utf8(user->province)},
{"sex", user->sex},
{"signature", unicode_to_utf8(user->signature)},
{"v2", unicode_to_utf8(user->v2)},
{"v3", unicode_to_utf8(user->v3)},
};
ret_data["userInfo"] = info;
}
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_ADD_BY_WXID: {
wstring user_id = get_http_req_param(hm, j_param, "wxid", is_post);
int success = AddFriendByWxid(WS2LW(user_id));
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_ADD_BY_V3: {
@@ -347,6 +380,12 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_GET_MEMBER_NICKNAME: {
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
wstring member_id = get_http_req_param(hm, j_param, "memberId", is_post);
wstring nickname = GetChatRoomMemberNickname(WS2LW(room_id),WS2LW(member_id));
json ret_data = {{"code", 1}, {"result", "OK"},{"nickname",unicode_to_utf8(WS2LW(nickname))}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_DEL_MEMBER: {
@@ -380,6 +419,12 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_SET_SELF_NICKNAME: {
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
wstring nick = get_http_req_param(hm, j_param, "nickName", is_post);
int success = ModChatRoomMemberNickName(WS2LW(room_id),WS2LW(wxid),WS2LW(nick));
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_DATABASE_GET_HANDLES: {
@@ -460,9 +505,18 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_LOGOUT: {
int success = Logout();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_GET_TRANSFER: {
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
wstring transcationid = get_http_req_param(hm, j_param, "transcationId", is_post);
wstring transferid = get_http_req_param(hm, j_param, "transferId", is_post);
BOOL response = DoConfirmReceipt(WS2LW(wxid), WS2LW(transcationid), WS2LW(transferid));
json ret_data = {{"msg", response}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_GET_CONTACT_ALL: {
@@ -535,6 +589,59 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
int success = GetImgByName(WS2LW(image_path),WS2LW(save_path));
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_DO_OCR:{
wstring image_path = get_http_req_param(hm, j_param, "imagePath", is_post);
string text("");
int success = DoOCRTask(WS2LW(image_path),text);
json ret_data = {{"code", success}, {"result", "OK"},{"text",text}};
ret = ret_data.dump();
break;
}
case WECHAT_SEND_PAT_MSG:{
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
int success = SendPatMsg(WS2LW(room_id),WS2LW(wxid));
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_SET_TOP_MSG:{
wstring wxid = get_http_req_param(hm, j_param, "wxid", is_post);
ULONG64 msgid = get_http_param_ulong64(hm, j_param, "msgid", is_post);
int success = SetTopMsg(WS2LW(wxid),msgid);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_REMOVE_TOP_MSG:{
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
ULONG64 msgid = get_http_param_ulong64(hm, j_param, "msgid", is_post);
int success = RemoveTopMsg(WS2LW(room_id),msgid);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_SNS_GET_FIRST_PAGE:{
int success = GetFirstPage();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_SNS_GET_NEXT_PAGE: {
ULONG64 snsid = get_http_param_ulong64(hm, j_param, "snsId", is_post);
int success = GetNextPage(snsid);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_NAME:{
wstring pri_id = get_http_req_param(hm, j_param, "id", is_post);
wstring name =GetContactOrChatRoomNickname(WS2LW(pri_id));
json ret_data = {{"code", 1}, {"result", "OK"},{"name",unicode_to_utf8(WS2LW(name))}};
ret = ret_data.dump();
break;
}
default:
break;
@@ -596,4 +703,20 @@ int http_start(int port) {
kHttpThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)http_server,
(LPVOID)port, NULL, 0);
return 0;
}
int http_close() {
if (!kHttpRuning) {
return 1;
}
kHttpRuning = false;
if (kHttpThread) {
WaitForSingleObject(kHttpThread, -1);
CloseHandle(kHttpThread);
kHttpThread = NULL;
}
UnHookRecvMsg();
UnHookImg();
UnHookSearchContact();
return 0;
}
+9 -1
View File
@@ -63,9 +63,17 @@ typedef enum WECHAT_HTTP_APISTag
WECHAT_GET_CONTACT_ALL,
WECHAT_GET_CHATROOM_INFO,
WECHAT_GET_IMG_BY_NAME,
WECHAT_DO_OCR,
WECHAT_SEND_PAT_MSG,
WECHAT_SET_TOP_MSG,
WECHAT_REMOVE_TOP_MSG,
WECHAT_SNS_GET_FIRST_PAGE,
WECHAT_SNS_GET_NEXT_PAGE,
WECHAT_CONTACT_NAME,
} WECHAT_HTTP_APIS,
*PWECHAT_HTTP_APIS;
int http_start(int port);
extern "C" __declspec(dllexport) int http_start(int port);
extern "C" __declspec(dllexport) int http_close();
#endif
+262 -28
View File
@@ -2,19 +2,31 @@
#include "chat_room.h"
#include "common.h"
#include "get_db_handle.h"
#include "wechat_data.h"
#define WX_CHAT_ROOM_MGR_OFFSET 0x686e40
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xa70920
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xd03ec0
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0x7226e0
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xa668f0
#define WX_INIT_CHAT_MSG_OFFSET 0xdbcc40
#define WX_FREE_CHAT_MSG_OFFSET 0x651c40
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xa66400
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xa71650
#define WX_INIT_CHAT_ROOM_OFFSET 0xd01c30
#define WX_FREE_CHAT_ROOM_OFFSET 0xa79310
#include "base64.h"
using namespace std;
#define WX_CHAT_ROOM_MGR_OFFSET 0x72cf60
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xb6f260
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xe15de0
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xe160b0
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xb64180
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xb63c50
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xB70260
#define WX_INIT_CHAT_ROOM_OFFSET 0xe13b30
#define WX_FREE_CHAT_ROOM_OFFSET 0xe13d50
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xb6adf0
#define WX_NEW_CHAT_MSG_OFFSET 0x70e2a0
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
#define WX_TOP_MSG_OFFSET 0xb727e0
#define WX_REMOVE_TOP_MSG_OFFSET 0xb725a0
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x6f5370
#define WX_GET_MEMBER_NICKNAME_OFFSET 0xb703f0
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x6f8990
#define WX_GET_CONTACT_OFFSET 0xb93b20
#define WX_FREE_CONTACT_OFFSET 0xe23690
int GetChatRoomDetailInfo(wchar_t* chat_room_id, ChatRoomInfoInner& room_info) {
int success = 0;
@@ -24,7 +36,7 @@ int GetChatRoomDetailInfo(wchar_t* chat_room_id, ChatRoomInfoInner& room_info) {
DWORD get_chat_room_detail_addr = base + WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET;
DWORD create_chat_room_info_addr = base + WX_NEW_CHAT_ROOM_INFO_OFFSET;
DWORD free_chat_room_info_addr = base + WX_FREE_CHAT_ROOM_INFO_OFFSET;
char chat_room_info[0xA4] = {0};
char chat_room_info[0xDC] = {0};
__asm {
PUSHAD
LEA ECX,chat_room_info
@@ -40,21 +52,54 @@ int GetChatRoomDetailInfo(wchar_t* chat_room_id, ChatRoomInfoInner& room_info) {
MOV success,EAX
POPAD
}
room_info.chat_room_id.ptr = *(wchar_t**)(chat_room_info + 0x4);
room_info.chat_room_id.length = *(DWORD*)(chat_room_info + 0x8);
room_info.chat_room_id.max_length = *(DWORD*)(chat_room_info + 0xC);
DWORD room_id_len = *(DWORD*)(chat_room_info + 0x8);
DWORD room_id_max_len = *(DWORD*)(chat_room_info + 0xC);
wchar_t * room_id = new wchar_t[room_id_len + 1];
wmemcpy(room_id,*(wchar_t**)(chat_room_info + 0x4),room_id_len + 1);
room_info.chat_room_id.ptr = room_id;
room_info.chat_room_id.length = room_id_len;
room_info.chat_room_id.max_length = room_id_max_len;
room_info.notice.ptr = *(wchar_t**)(chat_room_info + 0x18);
room_info.notice.length = *(DWORD*)(chat_room_info + 0x1C);
room_info.notice.max_length = *(DWORD*)(chat_room_info + 0x20);
DWORD notice_len = *(DWORD*)(chat_room_info + 0x1C);
DWORD notice_max_len = *(DWORD*)(chat_room_info + 0x20);
wchar_t* notice_ptr = *(wchar_t**)(chat_room_info + 0x18);
if(notice_len <= 0){
room_info.notice.ptr = nullptr;
}else{
wchar_t * notice = new wchar_t[notice_len + 1];
wmemcpy(notice,notice_ptr,notice_len+1);
room_info.notice.ptr = notice;
}
room_info.notice.length = notice_len;
room_info.notice.max_length = notice_max_len;
room_info.admin.ptr = *(wchar_t**)(chat_room_info + 0x2C);
room_info.admin.length = *(DWORD*)(chat_room_info + 0x30);
room_info.admin.max_length = *(DWORD*)(chat_room_info + 0x34);
DWORD admin_len = *(DWORD*)(chat_room_info + 0x30);
DWORD admin_max_len = *(DWORD*)(chat_room_info + 0x34);
wchar_t* admin_ptr = *(wchar_t**)(chat_room_info + 0x2C);
if(admin_len <= 0){
room_info.admin.ptr = nullptr;
}else{
wchar_t * admin = new wchar_t[admin_len + 1];
wmemcpy(admin,admin_ptr,admin_len+1);
room_info.admin.ptr = admin;
}
room_info.admin.length = admin_len;
room_info.admin.max_length = admin_max_len;
DWORD xml_len = *(DWORD*)(chat_room_info + 0x54);
DWORD xml_max_len = *(DWORD*)(chat_room_info + 0x58);
wchar_t* xml_ptr = *(wchar_t**)(chat_room_info + 0x50);
if (xml_len <= 0){
room_info.xml.ptr = nullptr;
}else{
wchar_t * xml = new wchar_t[xml_len + 1];
wmemcpy(xml,xml_ptr,xml_len+1);
room_info.xml.ptr = xml;
}
room_info.xml.length = xml_len;
room_info.xml.max_length = xml_max_len;
room_info.xml.ptr = *(wchar_t**)(chat_room_info + 0x50);
room_info.xml.length = *(DWORD*)(chat_room_info + 0x54);
room_info.xml.max_length = *(DWORD*)(chat_room_info + 0x58);
__asm {
PUSHAD
LEA ECX,chat_room_info
@@ -142,9 +187,9 @@ int AddMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids,int len){
int GetMemberFromChatRoom(wchar_t* chat_room_id,ChatRoomInner & out){
int success = 0;
WeChatString chat_room(chat_room_id);
DWORD chat_room_ptr = (DWORD) &chat_room;
char buffer[0x1A0] = {0};
WeChatString chat_room(chat_room_id);
DWORD chat_room_ptr = (DWORD) &chat_room;
char buffer[0x1D4] = {0};
DWORD base = GetWeChatWinBase();
DWORD get_member_addr = base + WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET;
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
@@ -182,3 +227,192 @@ int GetMemberFromChatRoom(wchar_t* chat_room_id,ChatRoomInner & out){
}
return success;
}
int ModChatRoomMemberNickName(wchar_t* chat_room_id,wchar_t* wxid,wchar_t * nick){
int success = 0;
WeChatString chat_room(chat_room_id);
WeChatString self_wxid(wxid);
WeChatString new_nick(nick);
DWORD base = GetWeChatWinBase();
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
DWORD mod_member_nick_name_addr = base + WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET;
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
__asm{
PUSHAD
CALL get_chat_room_mgr_addr
SUB ESP,0x14
MOV ECX,ESP
LEA EDI,new_nick
PUSH EDI
CALL init_chat_msg_addr
SUB ESP,0x14
LEA EAX,self_wxid
MOV ECX,ESP
PUSH EAX
CALL init_chat_msg_addr
SUB ESP,0x14
LEA EAX,chat_room
MOV ECX,ESP
PUSH EAX
CALL init_chat_msg_addr
CALL mod_member_nick_name_addr
MOVZX EAX,AL
MOV success,EAX
POPAD
}
return success;
}
int SetTopMsg(wchar_t* wxid,ULONG64 msg_id){
int success = -1;
char chat_msg[0x2C4] ={0};
DWORD base = GetWeChatWinBase();
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
DWORD handle_top_msg_addr = base + WX_TOP_MSG_OFFSET;
// DWORD free_addr = base + WX_FREE_CHAT_MSG_OFFSET;
DWORD free_addr = base + WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET;
vector<string> local_msg = GetChatMsgByMsgId(msg_id);
if(local_msg.empty()){
return -2;
}
string type = local_msg[3];
string status = local_msg[10];
string talker = local_msg[13];
string content = local_msg[14];
wstring w_talker = String2Wstring(talker);
wstring w_content = String2Wstring(content);
int msg_type =stoi(type);
int msg_status =stoi(status);
#ifdef _DEBUG
wcout << "w_talker:" <<w_talker <<endl;
wcout << "w_content:" <<w_content <<endl;
#endif
WeChatString chat_room(w_talker);
WeChatString msg_content(w_content);
WeChatString user_id(wxid);
__asm{
PUSHAD
LEA ECX,chat_msg
CALL new_chat_msg_addr
POPAD
}
memcpy(&chat_msg[0x30],&msg_id,sizeof(msg_id));
memcpy(&chat_msg[0x38],&msg_type,sizeof(msg_type));
memcpy(&chat_msg[0x40],&msg_status,sizeof(msg_status));
memcpy(&chat_msg[0x48],&chat_room,sizeof(chat_room));
memcpy(&chat_msg[0x70],&msg_content,sizeof(msg_content));
memcpy(&chat_msg[0x174],&user_id,sizeof(user_id));
__asm{
PUSHAD
CALL get_chat_room_mgr_addr
PUSH 0x0
LEA EAX,chat_msg
PUSH EAX
CALL handle_top_msg_addr
MOV success,EAX
LEA ECX,chat_msg
PUSH 0x0
CALL free_addr
POPAD
}
return success;
}
int RemoveTopMsg(wchar_t* chat_room_id,ULONG64 msg_id){
int success = -1;
WeChatString chat_room(chat_room_id);
DWORD base = GetWeChatWinBase();
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
DWORD remove_top_msg_addr = base + WX_REMOVE_TOP_MSG_OFFSET;
__asm{
PUSHAD
CALL get_chat_room_mgr_addr
MOV EDI,dword ptr [msg_id]
LEA EAX,chat_room
MOV ESI,dword ptr [msg_id + 0x4]
SUB ESP,0x14
MOV ECX,ESP
PUSH EAX
CALL init_chat_msg_addr
PUSH ESI
PUSH EDI
CALL remove_top_msg_addr
MOV success,EAX
POPAD
}
return success;
}
std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id,wchar_t* wxid){
WeChatString chat_room(chat_room_id);
WeChatString member_id(wxid);
WeChatString nickname(NULL);
DWORD base = GetWeChatWinBase();
DWORD get_chat_room_mgr_addr = base + WX_CHAT_ROOM_MGR_OFFSET;
DWORD get_nickname_addr = base + WX_GET_MEMBER_NICKNAME_OFFSET;
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
DWORD get_contact_addr = base + WX_GET_CONTACT_OFFSET;
DWORD free_contact_addr = base + WX_FREE_CONTACT_OFFSET;
__asm{
PUSHAD
PUSHFD
CALL get_chat_room_mgr_addr
LEA ECX,nickname
PUSH ECX
LEA ECX,member_id
PUSH ECX
LEA ECX,chat_room
PUSH ECX
MOV ECX,EAX
CALL get_nickname_addr
POPFD
POPAD
}
wstring name = L"";
if (nickname.ptr) {
name += wstring(nickname.ptr);
}else {
char buff[0x440] = {0};
__asm {
PUSHAD
PUSHFD
CALL contact_mgr_addr
LEA ECX,buff
PUSH ECX
LEA ECX,member_id
PUSH ECX
MOV ECX,EAX
CALL get_contact_addr
POPFD
POPAD
}
name += READ_WSTRING(buff, 0x6C);
__asm{
PUSHAD
PUSHFD
LEA ECX,buff
CALL free_contact_addr
POPFD
POPAD
}
}
return name;
}
+6
View File
@@ -7,4 +7,10 @@ int DelMemberFromChatRoom(wchar_t* chat_room_id,wchar_t** wxids,int len);
int AddMemberToChatRoom(wchar_t* chat_room_id, wchar_t** wxids,int len);
int GetMemberFromChatRoom(wchar_t* chat_room_id,ChatRoomInner & out);
int ModChatRoomMemberNickName(wchar_t* chat_room_id,wchar_t* wxid,wchar_t * nick);
int SetTopMsg(wchar_t* wxid,ULONG64 msg_id);
int RemoveTopMsg(wchar_t* chat_room_id,ULONG64 msg_id);
std::wstring GetChatRoomMemberNickname(wchar_t* chat_room_id,wchar_t* wxid);
#endif
+1 -1
View File
@@ -25,7 +25,7 @@ wstring utf8_to_unicode(const char *buffer) {
/// @param wstr unicode
/// @return string utf8
string unicode_to_utf8(wchar_t *wstr) {
int c_size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, FALSE);
int c_size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, FALSE);
if (c_size > 0) {
char *buffer = new char[c_size + 1];
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, buffer, c_size, NULL, FALSE);
+7 -8
View File
@@ -1,18 +1,17 @@
#ifndef COMMON_H_
#define COMMON_H_
#include <string>
using namespace std;
#define READ_WSTRING(addr, offset) ((*(DWORD *)(addr + offset + 0x4) == 0) ? wstring(L"") : wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)))
#define READ_WSTRING(addr, offset) ((*(DWORD *)(addr + offset + 0x4) == 0) ? std::wstring(L"") : std::wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)))
/// @brief utf8 转换成unicode
/// @param buffer utf8
/// @return unicode
wstring utf8_to_unicode(const char *buffer);
std::wstring utf8_to_unicode(const char *buffer);
/// @brief unicode转换utf8
/// @param wstr unicode
/// @return utf8
string unicode_to_utf8(wchar_t *wstr);
std::string unicode_to_utf8(wchar_t *wstr);
/// @brief 获取WeChatWin.dll基址
/// @return 基址
@@ -35,7 +34,7 @@ void UnHookAnyAddress(DWORD hook_addr, char *origin);
/// @brief get timeW
/// @param timestamp timestamp
/// @return str
wstring GetTimeW(long long timestamp);
std::wstring GetTimeW(long long timestamp);
/// @brief unicode trans utf8
/// @param str unicode str
/// @return utf8 str
@@ -43,11 +42,11 @@ std::string UnicodeToUtf8(const wchar_t *str);
/// @brief string convert wstring
/// @param str
/// @return
wstring String2Wstring(string str);
std::wstring String2Wstring(std::string str);
/// @brief wstring convert string
/// @param str
/// @return
string Wstring2String(wstring wstr);
std::string Wstring2String(std::wstring wstr);
/// @brief create dir
/// @param path
@@ -56,7 +55,7 @@ BOOL FindOrCreateDirectoryW(const wchar_t *path);
template <typename T1, typename T2>
vector<T1> split(T1 str, T2 letter) {
std::vector<T1> split(T1 str, T2 letter) {
vector<T1> arr;
size_t pos;
while ((pos = str.find_first_of(letter)) != T1::npos) {
+49
View File
@@ -0,0 +1,49 @@
#include "pch.h"
#include "confirm_receipt.h"
#include "common.h"
#include "wechat_data.h"
#define WX_NEW_WCPAYINFO_OFFSET 0x756340
#define WX_FREE_WCPAYINFO_OFFSET 0x73c170
#define WX_CONFIRM_RECEIPT_OFFSET 0x15287a0
int DoConfirmReceipt(wchar_t *wxid, wchar_t *transcationid,
wchar_t *transferid) {
int success = -1;
WeChatString recv_id(wxid);
WeChatString transcation_id(transcationid);
WeChatString transfer_id(transferid);
char pay_info[0x134] = {0};
DWORD base = GetWeChatWinBase();
DWORD new_pay_info_addr = base + WX_NEW_WCPAYINFO_OFFSET;
DWORD free_pay_info_addr = base + WX_FREE_WCPAYINFO_OFFSET;
DWORD do_confirm_addr = base + WX_CONFIRM_RECEIPT_OFFSET;
__asm {
PUSHAD
LEA ECX,pay_info
CALL new_pay_info_addr
MOV dword ptr [pay_info + 0x4], 0x1
MOV dword ptr [pay_info + 0x4C], 0x1
POPAD
}
memcpy(&pay_info[0x1c], &transcation_id, sizeof(transcation_id));
memcpy(&pay_info[0x38], &transfer_id, sizeof(transfer_id));
__asm {
PUSHAD
PUSH 0x1
SUB ESP,0x8
LEA EDX,recv_id
LEA ECX,pay_info
CALL do_confirm_addr
MOV success,EAX
ADD ESP,0xC
PUSH 0x0
LEA ECX,pay_info
CALL free_pay_info_addr
POPAD
}
return success;
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef CONFIRM_RECEIPT_H
#define CONFIRM_RECEIPT_H
int DoConfirmReceipt(wchar_t* wxid,wchar_t *transcationid, wchar_t *transferid);
#endif
+115 -29
View File
@@ -3,16 +3,18 @@
#include "common.h"
#include "wechat_data.h"
using namespace std;
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x6f8990
#define WX_CONTACT_GET_LIST_OFFSET 0xb97550
#define WX_CONTACT_DEL_OFFSET 0xb9b3b0
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_SYNC_MGR_OFFSET 0xa87fd0
#define WX_SET_VALUE_OFFSET 0x1f80900
#define WX_DO_DEL_CONTACT_OFFSET 0xca6480
#define WX_FREE_CONTACT_OFFSET 0xe23690
#define WX_GET_CONTACT_OFFSET 0xb93b20
#define WX_DO_VERIFY_USER_OFFSET 0xB91160
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x655d60
#define WX_CONTACT_GET_LIST_OFFSET 0xa97da0
#define WX_CONTACT_DEL_OFFSET 0xa9bd10
#define WX_INIT_CHAT_MSG_OFFSET 0xdbcc40
#define WX_DB_QUERY_OFFSET 0xa9ba20
#define WX_SYNC_MGR_OFFSET 0x993fa0
#define WX_SYNC_MGR_OFFSET 0x993fa0
#define WX_DO_DEL_CONTACT_OFFSET 0xb9a750
#define WX_DEL_CONTACT_VTABLE_OFFSET 0x2886990
int GetAllContact(vector<Contact> &vec) {
DWORD base = GetWeChatWinBase();
DWORD get_instance = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
@@ -66,41 +68,125 @@ int GetAllContact(vector<Contact> &vec) {
temp.type = *(DWORD *)(start + 0x50);
temp.verify_flag = *(DWORD *)(start + 0x54);
vec.push_back(temp);
start += 0x3E8;
start += 0x438;
}
return success;
}
// todo
// note maybe not delete
int DelContact(wchar_t *wxid) {
int success = 0;
int success = -1;
WeChatString user_id(wxid);
DWORD id_ptr = (DWORD) &user_id;
DWORD base = GetWeChatWinBase();
DWORD get_instance_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
DWORD del_addr = base + WX_CONTACT_DEL_OFFSET;
DWORD db_op_addr = base + WX_DB_QUERY_OFFSET;
DWORD sync_mgr_addr = base + WX_SYNC_MGR_OFFSET;
DWORD set_id_addr = base + WX_SET_VALUE_OFFSET;
DWORD del_contact_addr = base + WX_DO_DEL_CONTACT_OFFSET;
int len = user_id.length;
string id_cstr = unicode_to_utf8(wxid);
char id_[0x20]={0};
memcpy(id_,id_cstr.c_str(),id_cstr.size()+1);
char buff[0x10]={0};
__asm{
PUSHAD
PUSHFD
CALL get_instance_addr
MOV ECX,dword ptr[id_ptr]
PUSH ECX
CALL sync_mgr_addr
MOV ECX,EAX
MOV ESI,EAX
CALL db_op_addr
SUB ESP,0x14
MOV EAX,dword ptr[id_ptr]
MOV ECX,ESP
PUSH EAX
CALL init_chat_msg_addr
MOV ECX,ESI
CALL del_addr
MOV success,EAX
LEA EAX,buff
MOV [ECX + 4],EAX
LEA EAX,id_
Mov dword ptr[buff +0x4],EAX
CALL del_contact_addr
MOV success,EAX
POPFD
POPAD
}
return success;
}
std::wstring GetContactOrChatRoomNickname(wchar_t *id) {
int success = -1;
char buff[0x440] = {0};
WeChatString pri(id);
DWORD base = GetWeChatWinBase();
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
DWORD get_contact_addr = base + WX_GET_CONTACT_OFFSET;
DWORD free_contact_addr = base + WX_FREE_CONTACT_OFFSET;
wstring name = L"";
__asm {
PUSHAD
PUSHFD
CALL contact_mgr_addr
LEA ECX,buff
PUSH ECX
LEA ECX,pri
PUSH ECX
MOV ECX,EAX
CALL get_contact_addr
POPFD
POPAD
}
name += READ_WSTRING(buff, 0x6C);
__asm {
PUSHAD
PUSHFD
LEA ECX,buff
CALL free_contact_addr
POPFD
POPAD
}
return name;
}
int AddFriendByWxid(wchar_t *wxid){
int success = -1;
DWORD base = GetWeChatWinBase();
DWORD contact_mgr_addr = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
DWORD set_group_addr = base + 0x746E20;
DWORD fn2_addr = base + 0x285D968;
DWORD fn3_addr = base + 0x6F6050;
DWORD fn4_addr = base + 0xED3BE0;
DWORD do_verify_user_addr = base + WX_DO_VERIFY_USER_OFFSET;
DWORD instance =0;
WeChatString chat_room(NULL);
WeChatString user_id(wxid);
__asm{
PUSHAD
PUSHFD
CALL contact_mgr_addr
SUB ESP,0x18
MOV dword ptr [instance],EAX
MOV ECX,ESP
PUSH ECX
LEA ECX,chat_room
CALL set_group_addr
MOV EAX,fn2_addr
SUB ESP,0x18
MOV ECX,ESP
PUSH EAX
CALL fn3_addr
PUSH 0x0
PUSH 0XE
SUB ESP,0x14
MOV ESI,ESP
MOV dword ptr [ESI],0x0
MOV dword ptr [ESI+0x4],0x0
MOV dword ptr [ESI+0x8],0x0
MOV dword ptr [ESI+0xC],0x0
MOV dword ptr [ESI+0x10],0x0
PUSH 0x1
SUB ESP,0x14
MOV ECX,ESP
LEA EAX,user_id
PUSH EAX
CALL fn4_addr
MOV ECX,dword ptr [instance]
CALL do_verify_user_addr
MOV success,EAX
POPFD
POPAD
}
return success;
}
+5 -1
View File
@@ -3,9 +3,13 @@
#include <vector>
#include "wechat_data.h"
int GetAllContact(vector<Contact> &vec);
int GetAllContact(std::vector<Contact> &vec);
int DelContact(wchar_t* wxid);
std::wstring GetContactOrChatRoomNickname(wchar_t* id);
int AddFriendByWxid(wchar_t *wxid);
#endif
+3 -3
View File
@@ -4,7 +4,7 @@
#include "base64.h"
#include "common.h"
#include "new_sqlite3.h"
using namespace std;
/// @brief free data
void FreeResult(vector<vector<SqlResult>> &data) {
@@ -15,11 +15,11 @@ void FreeResult(vector<vector<SqlResult>> &data) {
for (unsigned j = 0; j < data[i].size(); j++) {
SqlResult *sr = (SqlResult *)&data[i][j];
if (sr->column_name) {
delete sr->column_name;
delete[] sr->column_name;
sr->column_name = NULL;
}
if (sr->content) {
delete sr->content;
delete[] sr->content;
sr->content = NULL;
}
}
+1 -2
View File
@@ -2,7 +2,6 @@
#define DB_OPERATION_H_
#include <windows.h>
#include <vector>
using namespace std;
struct SqlResult {
char *column_name;
DWORD column_name_len;
@@ -18,6 +17,6 @@ struct SqlResult {
/// @return
int ExecuteSQL(DWORD db, const char *sql, DWORD callback, void *data);
int Select(DWORD db_hanle, const char *sql,vector<vector<string>> &query_result);
int Select(DWORD db_hanle, const char *sql,std::vector<std::vector<std::string>> &query_result);
#endif
+1
View File
@@ -16,6 +16,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
break;
}
case DLL_PROCESS_DETACH: {
http_close();
break;
}
}
+4 -4
View File
@@ -4,8 +4,8 @@
#include "common.h"
#include "get_db_handle.h"
#include "wechat_data.h"
#define WX_FORWARD_MSG_OFFSET 0xb68c80
#define WX_INIT_CHAT_MSG_OFFSET 0xdbcc40
#define WX_FORWARD_MSG_OFFSET 0xc715f0
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
int ForwardMsg(wchar_t *wxid, unsigned long long msgid) {
int success = 0;
@@ -27,11 +27,11 @@ int ForwardMsg(wchar_t *wxid, unsigned long long msgid) {
PUSH EAX
SUB ESP,0x14
MOV ECX,ESP
LEA ESI, to_user;
LEA ESI,to_user
PUSH ESI
CALL init_chat_msg_addr
CALL forward_msg_addr
MOVZX EAX,AL;
MOVZX EAX,AL
MOV success,EAX
ADD ESP,0x1c
POPFD
+25 -6
View File
@@ -5,7 +5,7 @@
#include "new_sqlite3.h"
#include "pch.h"
#include "wechat_data.h"
#define CONTACT_G_PINSTANCE 0x2bee928
#define CONTACT_G_PINSTANCE_OFFSET 0x2e2d628
#define DB_MICRO_MSG_OFFSET 0x68
#define DB_CHAT_MSG_OFFSET 0x1C0
#define DB_MISC_OFFSET 0x3D8
@@ -15,10 +15,10 @@
#define DB_FUNCTION_MSG_OFFSET 0x11B0
#define DB_NAME_OFFSET 0x14
#define PUBLIC_MSG_MGR_OFFSET 0x2c294c0
#define MULTI_DB_MSG_MGR_OFFSET 0x2c2aff4
#define FAVORITE_STORAGE_MGR_OFFSET 0x2c2aa14
#define FTS_FAVORITE_MGR_OFFSET 0x2bef468
#define PUBLIC_MSG_MGR_OFFSET 0x2e6ce20
#define MULTI_DB_MSG_MGR_OFFSET 0x2e6ec84
#define FAVORITE_STORAGE_MGR_OFFSET 0x2e6e630
#define FTS_FAVORITE_MGR_OFFSET 0x2e2e168
using namespace std;
map<wstring, DatabaseInfo> dbmap;
@@ -64,7 +64,7 @@ std::vector<void *> GetDbHandles() {
dbs.clear();
dbmap.clear();
DWORD base = GetWeChatWinBase();
DWORD p_contact_addr = *(DWORD *)(base + CONTACT_G_PINSTANCE);
DWORD p_contact_addr = *(DWORD *)(base + CONTACT_G_PINSTANCE_OFFSET);
DWORD micro_msg_db_addr = *(DWORD *)(p_contact_addr + DB_MICRO_MSG_OFFSET);
DWORD chat_msg_db_addr = *(DWORD *)(p_contact_addr + DB_CHAT_MSG_OFFSET);
DWORD misc_db_addr = *(DWORD *)(p_contact_addr + DB_MISC_OFFSET);
@@ -296,4 +296,23 @@ unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex) {
return stoi(result[1][0]);
}
return 0;
}
vector<string> GetChatMsgByMsgId(ULONG64 msgid){
char sql[260] = {0};
sprintf_s(sql, "select localId,TalkerId,MsgSvrID,Type,SubType,IsSender,CreateTime,Sequence,StatusEx,FlagEx,Status,MsgServerSeq,MsgSequence,StrTalker,StrContent,BytesExtra from MSG where MsgSvrID=%llu;", msgid);
wchar_t dbname[20] = {0};
for (int i = 0;; i++) {
swprintf_s(dbname, L"MSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname);
if (handle == 0) return {};
vector<vector<string>> result;
int ret = Select(handle, (const char *)sql, result);
#ifdef _DEBUG
cout <<" size =" <<result.size()<<endl;
#endif
if (result.size() == 0) continue;
return result[1];
}
return {};
}
+2
View File
@@ -2,8 +2,10 @@
#define GET_DB_HANDLE_H_
#include "windows.h"
#include <vector>
#include <string>
std::vector<void *> GetDbHandles();
DWORD GetDbHandleByDbName(wchar_t *dbname);
unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex);
std::vector<std::string> GetChatMsgByMsgId(ULONG64 msgid);
#endif
+4 -4
View File
@@ -2,13 +2,13 @@
#include "hook_img.h"
#include "common.h"
using namespace std;
// #define WX_HOOK_IMG_OFFSET 0xd7eaa5
// #define WX_HOOK_IMG_NEXT_OFFSET 0xda56e0
#define WX_HOOK_IMG_OFFSET 0xc63ebc
#define WX_HOOK_IMG_NEXT_OFFSET 0xd7e9e0
#define WX_SELF_ID_OFFSET 0x2BEE08C
#define WX_HOOK_IMG_OFFSET 0xd723dc
#define WX_HOOK_IMG_NEXT_OFFSET 0xe91d90
#define WX_SELF_ID_OFFSET 0x2E2CD3C
#define BUFSIZE 1024
#define JPEG0 0xFF
+1 -2
View File
@@ -1,9 +1,8 @@
#ifndef HOOK_IMG_H_
#define HOOK_IMG_H_
#include "windows.h"
using namespace std;
int HookImg(wstring save_path);
int HookImg(std::wstring save_path);
int UnHookImg();
int GetImgByName(wchar_t* file_path,wchar_t* save_dir);
+89 -8
View File
@@ -10,8 +10,10 @@
using namespace nlohmann;
using namespace std;
#define WX_RECV_MSG_HOOK_OFFSET 0xb94796
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x6fe2c0
#define WX_RECV_MSG_HOOK_OFFSET 0xca0284
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x7d5030
#define WX_SNS_HOOK_OFFSET 0x143ef09
#define WX_SNS_HOOK_NEXT_OFFSET 0x143f1b0
// SyncMgr::addMsgListToDB
// #define WX_RECV_MSG_HOOK_OFFSET 0xB9C919
@@ -20,6 +22,7 @@ using namespace std;
#define CLIENT_IP "127.0.0.1"
static int kServerPort = 0;
static int kMessageHooked = FALSE;
static char kServerIp[16]= "127.0.0.1";
static DWORD kWeChatWinBase = GetWeChatWinBase();
static char kOriginReceMsgAsmCode[5] = {0};
@@ -28,6 +31,13 @@ static DWORD kReceMsgJmpBackAddress =
static DWORD kReceMsgNextAddress =
kWeChatWinBase + WX_RECV_MSG_HOOK_NEXT_OFFSET;
static char kOriginSnsMsgAsmCode[5] = {0};
static DWORD kSnsMsgJmpBackAddress =
kWeChatWinBase + WX_SNS_HOOK_OFFSET + 0x5;
static DWORD kSnsMsgNextAddress =
kWeChatWinBase + WX_SNS_HOOK_NEXT_OFFSET;
struct InnerMessageStruct {
char *buffer;
int length;
@@ -59,10 +69,12 @@ BOOL SendBySocket(const char *buffer, size_t len) {
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons((u_short)kServerPort);
InetPtonA(AF_INET, CLIENT_IP, &client_addr.sin_addr.s_addr);
InetPtonA(AF_INET, kServerIp, &client_addr.sin_addr.s_addr);
if (connect(client_socket, reinterpret_cast<sockaddr *>(&client_addr),
sizeof(sockaddr)) < 0) {
#ifdef _DEBUG
cout << "kServerIp:" << kServerIp <<endl;
cout << "port:" << kServerPort <<endl;
cout << "connect error,"
<< " errno:" << errno << endl;
#endif
@@ -109,7 +121,7 @@ void SendSocketMessage(InnerMessageStruct *msg) {
}
/// @brief msg handle
/// @param msg_addr msg address in memory
void OnRecvMsg(DWORD msg_addr) {
void __cdecl OnRecvMsg(DWORD msg_addr) {
json j_msg;
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
j_msg["msgId"] = msgid;
@@ -135,9 +147,6 @@ void OnRecvMsg(DWORD msg_addr) {
if (content_len > 0) {
j_msg["content"] =
unicode_to_utf8((wchar_t *)READ_WSTRING(msg_addr, 0x70).c_str());
#ifdef _DEBUG
printf("%s", j_msg["content"].get<std::string>().c_str());
#endif
}
int sign_len = *(DWORD *)(msg_addr + 0x18C);
if (sign_len > 0) {
@@ -172,6 +181,50 @@ void OnRecvMsg(DWORD msg_addr) {
CloseHandle(thread);
}
}
void __cdecl OnSnsTimeLineMsg(DWORD msg_addr) {
json j_sns;
DWORD begin_addr = *(DWORD *)(msg_addr + 0x20);
DWORD end_addr = *(DWORD *)(msg_addr + 0x24);
#ifdef _DEBUG
cout << "begin" <<begin_addr<<endl;
cout << "end" <<end_addr<<endl;
#endif
if (begin_addr == 0) {
j_sns = {{"data", json::array()}};
} else {
while (begin_addr < end_addr) {
json j_item;
j_item["snsId"] = *(unsigned long long *)(begin_addr);
j_item["createTime"] = *(DWORD *)(begin_addr + 0x2C);
j_item["senderId"] =
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x18).c_str());
j_item["content"] =
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x3c).c_str());
j_item["xml"] =
unicode_to_utf8((wchar_t *)READ_WSTRING(begin_addr, 0x384).c_str());
j_sns["data"].push_back(j_item);
begin_addr += 0xB48;
}
}
string jstr = j_sns.dump() + '\n';
InnerMessageStruct *inner_msg = new InnerMessageStruct;
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
HANDLE thread = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, inner_msg, NULL, 0);
if (thread) {
CloseHandle(thread);
}
}
/// @brief hook implement
_declspec(naked) void handle_sync_msg() {
__asm {
@@ -187,11 +240,29 @@ _declspec(naked) void handle_sync_msg() {
}
}
/// @brief hook sns msg implement
_declspec(naked) void handle_sns_msg() {
__asm {
PUSHAD
PUSHFD
PUSH [ESP + 0x24]
CALL OnSnsTimeLineMsg
ADD ESP, 0x4
POPFD
POPAD
CALL kSnsMsgNextAddress
JMP kSnsMsgJmpBackAddress
}
}
/// @brief hook any address address+0x5
/// @param port 端口
/// @return 成功返回1,已经hook返回2,失败返回-1
int HookRecvMsg(int port) {
int HookRecvMsg(char* client_ip,int port) {
kServerPort = port;
strcpy_s(kServerIp,client_ip);
kWeChatWinBase = GetWeChatWinBase();
if (!kWeChatWinBase) {
return -1;
@@ -206,6 +277,14 @@ int HookRecvMsg(int port) {
kReceMsgJmpBackAddress = hook_recv_msg_addr + 0x5;
HookAnyAddress(hook_recv_msg_addr, (LPVOID)handle_sync_msg,
kOriginReceMsgAsmCode);
DWORD hook_sns_msg_addr = kWeChatWinBase + WX_SNS_HOOK_OFFSET;
kSnsMsgNextAddress = kWeChatWinBase + WX_SNS_HOOK_NEXT_OFFSET;
kSnsMsgJmpBackAddress = hook_sns_msg_addr + 0x5;
HookAnyAddress(hook_sns_msg_addr, (LPVOID)handle_sns_msg,
kOriginSnsMsgAsmCode);
kMessageHooked = TRUE;
return 1;
}
@@ -214,7 +293,9 @@ int UnHookRecvMsg() {
kServerPort = 0;
if (!kMessageHooked) return 2;
DWORD hook_recv_msg_addr = kWeChatWinBase + WX_RECV_MSG_HOOK_OFFSET;
DWORD hook_sns_addr = kWeChatWinBase + WX_SNS_HOOK_OFFSET;
UnHookAnyAddress(hook_recv_msg_addr, kOriginReceMsgAsmCode);
UnHookAnyAddress(hook_sns_addr, kOriginSnsMsgAsmCode);
kMessageHooked = FALSE;
return 1;
}
+1 -1
View File
@@ -4,7 +4,7 @@
/// @brief hook any address address+0x5
/// @param port 端口
/// @return 成功返回1,已经hook返回2
int HookRecvMsg(int port);
int HookRecvMsg(char* client_ip,int port);
int UnHookRecvMsg();
#endif
+18 -18
View File
@@ -135,24 +135,24 @@
#define SQLITE_NULL 5
#define SQLITE_TEXT 3
#define SQLITE3_EXEC_OFFSET 0x1b623b0
#define SQLITE3_BACKUP_INIT_OFFSET 0x1b27d50
#define SQLITE3_PREPARE_OFFSET 0x1b68d00
#define SQLITE3_OPEN_OFFSET 0x1b96cf0
#define SQLITE3_BACKUP_STEP_OFFSET 0x1b28150
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1b28890
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1b288a0
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1b28790
#define SQLITE3_SLEEP_OFFSET 0x1b97530
#define SQLITE3_ERRCODE_OFFSET 0x1b95990
#define SQLITE3_CLOSE_OFFSET 0x1b94110
#define SQLITE3_STEP_OFFSET 0x1b30bc0
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1b310d0
#define SQLITE3_COLUMN_NAME_OFFSET 0x1b319c0
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1b31860
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1b31110
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1b311f0
#define SQLITE3_FINALIZE_OFFSET 0x1b2fb90
#define SQLITE3_EXEC_OFFSET 0x1d5cf70
#define SQLITE3_BACKUP_INIT_OFFSET 0x1d228d0
#define SQLITE3_PREPARE_OFFSET 0x1d638c0
#define SQLITE3_OPEN_OFFSET 0x1d918b0
#define SQLITE3_BACKUP_STEP_OFFSET 0x1d22ce0
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1d23420
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1d23430
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1d23320
#define SQLITE3_SLEEP_OFFSET 0x1d920f0
#define SQLITE3_ERRCODE_OFFSET 0x1d90550
#define SQLITE3_CLOSE_OFFSET 0x1d8ecd0
#define SQLITE3_STEP_OFFSET 0x1d2b750
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1d2bc60
#define SQLITE3_COLUMN_NAME_OFFSET 0x1d2c550
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1d2c3f0
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1d2bca0
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1d2bd80
#define SQLITE3_FINALIZE_OFFSET 0x1d2a720
typedef int (*Sqlite3_callback)(void*, int, char**, char**);
+64
View File
@@ -0,0 +1,64 @@
#include "pch.h"
#include "ocr.h"
#include "common.h"
#include "wechat_data.h"
#define WX_INIT_OBJ_OFFSET 0x7a98f0
#define WX_OCR_MANAGER_OFFSET 0x7ae470
#define WX_DO_OCR_TASK_OFFSET 0x13230c0
using namespace std;
int DoOCRTask(wchar_t *img_path, std::string &result) {
int success = -1;
WeChatString path(img_path);
WeChatString null_obj = {0};
WeChatString ocr_result = {0};
DWORD base = GetWeChatWinBase();
DWORD ocr_manager_addr = base + WX_OCR_MANAGER_OFFSET;
DWORD do_ocr_task_addr = base + WX_DO_OCR_TASK_OFFSET;
DWORD init_addr = base + WX_INIT_OBJ_OFFSET;
DWORD flag = 0;
__asm {
PUSHAD
PUSHFD
LEA ECX,ocr_result
CALL init_addr
CALL ocr_manager_addr
LEA ECX,null_obj
PUSH ECX
LEA ECX,flag
PUSH ECX
LEA ECX,ocr_result
PUSH ECX
PUSH 0x0
LEA ECX,path
PUSH ECX
MOV ECX,EAX
CALL do_ocr_task_addr
MOV success,EAX
POPFD
POPAD
}
if (success == 0) {
DWORD addr = (DWORD)&ocr_result;
DWORD ptr = *(DWORD *)addr;
DWORD num = *(DWORD *)(addr + 0x4);
if (num <= 0) {
return success;
}
DWORD header = *(DWORD *)ptr;
for (unsigned int i = 0; i < num -1; i++) {
DWORD content = *(DWORD *)header;
result += unicode_to_utf8((wchar_t *)READ_WSTRING(content, 0x14).c_str());
header = content;
}
#ifdef _DEBUG
cout << "num:" << num << endl;
cout << "all:" << result << endl;
#endif
}
return success;
}
+5
View File
@@ -0,0 +1,5 @@
#ifndef OCR_H_
#define OCR_H_
#include <string>
int DoOCRTask(wchar_t* img_path,std::string &result);
#endif
+34
View File
@@ -0,0 +1,34 @@
#include "pch.h"
#include "pat.h"
#include "common.h"
#include "wechat_data.h"
#define WX_PAT_MGR_OFFSET 0x8d0c00
#define WX_SEND_PAT_MSG_OFFSET 0x1369850
#define WX_RET_OFFSET 0x1C94D34
int SendPatMsg(wchar_t* chat_room_id, wchar_t* wxid) {
int success = -1;
WeChatString chat_room(chat_room_id);
WeChatString self_wxid(wxid);
DWORD base = GetWeChatWinBase();
DWORD get_pat_mgr_addr = base + WX_PAT_MGR_OFFSET;
DWORD send_pat_msg_addr = base + WX_SEND_PAT_MSG_OFFSET;
DWORD ret_addr = base + WX_RET_OFFSET;
__asm {
PUSHAD
CALL get_pat_mgr_addr
PUSH ret_addr
PUSH 0x0
PUSH EAX
LEA ECX,chat_room
LEA EDX,self_wxid
CALL send_pat_msg_addr
ADD ESP,0xc
MOVZX EAX,AL
MOV success,EAX
POPAD
}
return success;
}
+4
View File
@@ -0,0 +1,4 @@
#ifndef PAT_H_
#define PAT_H_
int SendPatMsg(wchar_t* chat_room_id,wchar_t* wxid);
#endif
+275
View File
@@ -0,0 +1,275 @@
#include "pch.h"
#include "search_contact.h"
#include "common.h"
#include "wechat_data.h"
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT 0xd94d1e
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT 0xed13a0
#define WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT 0xa2a260
#define WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT 0xa2a4c0
#define WX_SEARCH_CONTACT_OFFSeT 0xc5bb00
#define WX_SEARCH_CONTACT_MGR_OFFSeT 0xa0d550
static BOOL kSearchContactHooked = false;
static char kHookSearchContactErrcodeOldAsm[5] = {0};
static char kHookUserInfoOldAsm[5] = {0};
static DWORD kWeChatWinBase = GetWeChatWinBase();
static DWORD kHookSearchContactErrcodeNextAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
static DWORD kHookSearchContactErrcodeAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
static DWORD kHookSearchContactErrcodeJmpBackAddr =
kHookSearchContactErrcodeAddr + 0x5;
static DWORD kHookUserInfoNextAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
static DWORD kHookUserInfoAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
static DWORD kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
static UserInfo userinfo;
void SetErrorCode(int code) { userinfo.error_code = code; }
void SetUserInfoDetail(DWORD address) {
DWORD length = *(DWORD *)(address + 0x8);
userinfo.keyword = new wchar_t[length + 1];
userinfo.keyword_len = length;
if (length) {
memcpy(userinfo.keyword, (wchar_t *)(*(DWORD *)(address + 0x4)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.keyword, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x1C);
userinfo.v3 = new wchar_t[length + 1];
userinfo.v3_len = length;
if (length) {
memcpy(userinfo.v3, (wchar_t *)(*(DWORD *)(address + 0x18)),
(length + 1) * sizeof(wchar_t));
}else {
ZeroMemory(userinfo.v3, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x30);
userinfo.big_image = new wchar_t[length + 1];
userinfo.big_image_len = length;
if (length) {
memcpy(userinfo.big_image, (wchar_t *)(*(DWORD *)(address + 0x2C)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.big_image, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0xC8);
userinfo.nickname = new wchar_t[length + 1];
userinfo.nickname_len = length;
if (length) {
memcpy(userinfo.nickname, (wchar_t *)(*(DWORD *)(address + 0xC4)),
(length + 1) * sizeof(wchar_t));
}else {
ZeroMemory(userinfo.nickname, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x108);
userinfo.v2 = new wchar_t[length + 1];
userinfo.v2_len = length;
if (length) {
memcpy(userinfo.v2, (wchar_t *)(*(DWORD *)(address + 0x104)),
(length + 1) * sizeof(wchar_t));
}else {
ZeroMemory(userinfo.v2, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x16C);
userinfo.small_image = new wchar_t[length + 1];
userinfo.small_image_len = length;
if (length) {
memcpy(userinfo.small_image, (wchar_t *)(*(DWORD *)(address + 0x168)),
(length + 1) * sizeof(wchar_t));
}else {
ZeroMemory(userinfo.small_image, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x1F8);
userinfo.signature = new wchar_t[length + 1];
userinfo.signature_len = length;
if (length) {
memcpy(userinfo.signature, (wchar_t *)(*(DWORD *)(address + 0x1F4)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.signature, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x20C);
userinfo.nation = new wchar_t[length + 1];
userinfo.nation_len = length;
if (length) {
memcpy(userinfo.nation, (wchar_t *)(*(DWORD *)(address + 0x208)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.nation, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x220);
userinfo.province = new wchar_t[length + 1];
userinfo.province_len = length;
if (length) {
memcpy(userinfo.province, (wchar_t *)(*(DWORD *)(address + 0x21C)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.province, (length + 1) * sizeof(wchar_t));
}
length = *(DWORD *)(address + 0x234);
userinfo.city = new wchar_t[length + 1];
userinfo.city_len = length;
if (length) {
memcpy(userinfo.city, (wchar_t *)(*(DWORD *)(address + 0x230)),
(length + 1) * sizeof(wchar_t));
} else {
ZeroMemory(userinfo.city, (length + 1) * sizeof(wchar_t));
}
userinfo.sex = *(DWORD *)(address + 0x1BC);
userinfo.over = true;
}
static void DeleteUserInfoCache() {
if (userinfo.keyword) {
delete userinfo.keyword;
}
if (userinfo.v2) {
delete userinfo.v2;
}
if (userinfo.v3) {
delete userinfo.v3;
}
if (userinfo.nickname) {
delete userinfo.nickname;
}
if (userinfo.nation) {
delete userinfo.nation;
}
if (userinfo.province) {
delete userinfo.province;
}
if (userinfo.city) {
delete userinfo.city;
}
if (userinfo.signature) {
delete userinfo.signature;
}
if (userinfo.small_image) {
delete userinfo.small_image;
}
if (userinfo.big_image) {
delete userinfo.big_image;
}
ZeroMemory(&userinfo, sizeof(UserInfo));
userinfo.error_code = 1;
}
__declspec(naked) void HandleErrorCode() {
__asm {
pushad;
pushfd;
push edi;
call SetErrorCode;
add esp, 0x4;
popfd;
popad;
call kHookSearchContactErrcodeNextAddr;
jmp kHookSearchContactErrcodeJmpBackAddr;
}
}
__declspec(naked) void HandleUserInfoDetail() {
__asm {
pushad;
pushfd;
push dword ptr [ebp + 0x14];
call SetUserInfoDetail;
add esp, 0x4;
popfd;
popad;
call kHookUserInfoNextAddr;
jmp kHookUserInfoJmpBackAddr;
}
}
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user) {
int success = -1;
HookSearchContact();
DeleteUserInfoCache();
DWORD base = GetWeChatWinBase();
DWORD search_contact_mgr_addr = base + WX_SEARCH_CONTACT_MGR_OFFSeT;
DWORD search_contact_addr = base + WX_SEARCH_CONTACT_OFFSeT;
WeChatString key(keyword);
__asm {
pushad;
pushfd;
call search_contact_mgr_addr;
lea ebx, key;
push ebx;
mov ecx, eax;
call search_contact_addr;
popfd;
popad;
}
success = 1;
while (userinfo.error_code == 1 && kSearchContactHooked) {
Sleep(20);
}
if (userinfo.error_code == 0) {
while (userinfo.over == false && kSearchContactHooked) {
Sleep(20);
}
}
*user= &userinfo;
return success;
}
int HookSearchContact() {
kWeChatWinBase = GetWeChatWinBase();
if (!kWeChatWinBase) {
return -1;
}
if (kSearchContactHooked) {
return 2;
}
kHookSearchContactErrcodeNextAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
kHookSearchContactErrcodeAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
kHookSearchContactErrcodeJmpBackAddr = kHookSearchContactErrcodeAddr + 0x5;
kHookUserInfoNextAddr =
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
kHookUserInfoAddr = kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
HookAnyAddress(kHookSearchContactErrcodeAddr,
(LPVOID)HandleErrorCode,
kHookSearchContactErrcodeOldAsm);
HookAnyAddress(kHookUserInfoAddr, (LPVOID)HandleUserInfoDetail, kHookUserInfoOldAsm);
kSearchContactHooked = true;
return 1;
}
int UnHookSearchContact() {
if (!kSearchContactHooked) return 2;
UnHookAnyAddress(kHookSearchContactErrcodeAddr,
kHookSearchContactErrcodeOldAsm);
UnHookAnyAddress(kHookUserInfoAddr, kHookUserInfoOldAsm);
kSearchContactHooked = false;
return 1;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef SEARCH_CONTACT_H_
#define SEARCH_CONTACT_H_
#include "wechat_data.h"
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user);
int HookSearchContact();
int UnHookSearchContact();
#endif
+37 -14
View File
@@ -4,22 +4,24 @@
#include "common.h"
#include "wechat_data.h"
using namespace std;
#define WX_SELF_NAME_OFFSET 0x2bee198
#define WX_SELF_MOBILE_OFFSET 0x2BEE108
#define WX_SELF_CITY_OFFSET 0x2BEE168
#define WX_SELF_PROVINCE_OFFSET 0x2BEE150
#define WX_SELF_COUNTRY_OFFSET 0x2BEE138
#define WX_SELF_ACCOUNT_OFFSET 0x2BEE0F0
#define WX_SELF_ID_OFFSET 0x2BEE08C
#define WX_SELF_SMALL_IMG_OFFSET 0x2BEE34C
#define WX_SELF_BIG_IMG_OFFSET 0x2BEE364
#define WX_LOGIN_STATUS_OFFSET 0x2BEE4C0
#define WX_APP_DATA_ROOT_PATH_OFFSET 0x2c2f478
#define WX_APP_DATA_SAVE_PATH_OFFSET 0x2C10D04
#define WX_CURRENT_DATA_PATH_OFFSET 0x2C0EC38
#define WX_SELF_NAME_OFFSET 0x2E2CE48
#define WX_SELF_MOBILE_OFFSET 0x2E2CDB8
#define WX_SELF_CITY_OFFSET 0x2E2CE18
#define WX_SELF_PROVINCE_OFFSET 0x2E2CE00
#define WX_SELF_COUNTRY_OFFSET 0x2E2CDE8
#define WX_SELF_ACCOUNT_OFFSET 0x2e2d1d0
#define WX_SELF_ID_OFFSET 0x2E2CD3C
#define WX_SELF_SMALL_IMG_OFFSET 0x2E2D014
#define WX_SELF_BIG_IMG_OFFSET 0x2E2CFFC
#define WX_LOGIN_STATUS_OFFSET 0x2E2D1C0
#define WX_APP_DATA_ROOT_PATH_OFFSET 0x2E73010
#define WX_APP_DATA_SAVE_PATH_OFFSET 0x2E52DB0
#define WX_CURRENT_DATA_PATH_OFFSET 0x2E4F290
#define WX_LOGOUT_OFFSET 0xdd5c90
#define WX_ACCOUT_SERVICE_OFFSET 0x707960
int GetSelfInfo(SelfInfoInner &out) {
DWORD base = GetWeChatWinBase();
@@ -136,4 +138,25 @@ int GetSelfInfo(SelfInfoInner &out) {
int CheckLogin(){
DWORD base = GetWeChatWinBase();
return *(DWORD*) (base + WX_LOGIN_STATUS_OFFSET);
}
int Logout(){
int success = 0;
if(!CheckLogin()){
return success;
}
DWORD base = GetWeChatWinBase();
DWORD account_service_addr = base + WX_ACCOUT_SERVICE_OFFSET;
DWORD logout_addr = base + WX_LOGOUT_OFFSET;
__asm{
PUSHAD
CALL account_service_addr
PUSH 0x0
MOV ECX,EAX
CALL logout_addr
MOV success,EAX
POPAD
}
return success;
}
+2
View File
@@ -4,4 +4,6 @@
int GetSelfInfo(SelfInfoInner& out);
int CheckLogin();
int Logout();
#endif
+5 -5
View File
@@ -3,16 +3,16 @@
#include "common.h"
#include "wechat_data.h"
#define WX_APP_MSG_MGR_OFFSET 0x665f60
#define WX_SEND_FILE_OFFSET 0xa0ce20
#define WX_INIT_CHAT_MSG_OFFSET 0xdbcc40
#define WX_FREE_CHAT_MSG_OFFSET 0x651c40
#define WX_APP_MSG_MGR_OFFSET 0x709bb0
#define WX_SEND_FILE_OFFSET 0xb06240
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
int SendFile(wchar_t *wxid, wchar_t *file_path){
int success = 0;
WeChatString to_user(wxid);
WeChatString path(file_path);
char chat_msg[0x2A8] = {0};
char chat_msg[0x2C4] = {0};
DWORD base = GetWeChatWinBase();
DWORD app_msg_mgr_addr = base + WX_APP_MSG_MGR_OFFSET;
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
+5 -5
View File
@@ -3,17 +3,17 @@
#include "common.h"
#include "wechat_data.h"
#define WX_SEND_IMAGE_OFFSET 0xb68b90
#define WX_SEND_MESSAGE_MGR_OFFSET 0x663320
#define WX_INIT_CHAT_MSG_OFFSET 0xdbcc40
#define WX_FREE_CHAT_MSG_OFFSET 0x651c40
#define WX_SEND_IMAGE_OFFSET 0xc71500
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
int SendImage(wchar_t *wxid, wchar_t *image_path){
int success = 0;
WeChatString to_user(wxid);
WeChatString path(image_path);
char chat_msg[0x2A8] ={0};
char chat_msg[0x2C4] ={0};
DWORD base = GetWeChatWinBase();
DWORD send_message_mgr_addr = base + WX_SEND_MESSAGE_MGR_OFFSET;
DWORD init_chat_msg_addr = base + WX_INIT_CHAT_MSG_OFFSET;
+15 -12
View File
@@ -5,40 +5,43 @@
#include "common.h"
#include "wechat_data.h"
#define WX_SEND_TEXT_OFFSET 0xb690a0
#define WX_SEND_TEXT_OFFSET 0xc71a60
#define WX_SEND_MESSAGE_MGR_OFFSET 0x663320
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
#define WX_FREE_CHAT_MSG_OFFSET 0x651c40
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
/// @brief 发生文本消息
/// @param wxid wxid
/// @param msg 文本消息
/// @return 成功返回1
int SendText(wchar_t* wxid, wchar_t* msg) {
int SendText(wchar_t* wxid, wchar_t* msg) {
int success = 0;
WeChatString to_user(wxid);
WeChatString text_msg(msg);
wchar_t **msg_pptr = &text_msg.ptr;
char chat_msg[0x2A8] ={0};
DWORD base = GetWeChatWinBase();
DWORD send_message_mgr_addr = base + WX_SEND_MESSAGE_MGR_OFFSET;
DWORD send_text_msg_addr = base + WX_SEND_TEXT_OFFSET;
DWORD free_msg_addr = base + WX_FREE_CHAT_MSG_OFFSET;
DWORD free_chat_msg_addr = base + WX_FREE_CHAT_MSG_OFFSET;
char chat_msg[0x2C4] ={0};
__asm{
PUSHAD
CALL send_message_mgr_addr
PUSH 0x0
PUSH 0x0
PUSH 0x0
PUSH 0x1
PUSH 0x0
MOV EDI,msg_pptr
PUSH EDI
MOV EAX,msg_pptr
PUSH EAX
LEA EDX,to_user
LEA ECX,chat_msg
CALL send_text_msg_addr
ADD ESP,0x14
CALL send_text_msg_addr
MOV success,EAX
LEA ECX,chat_msg
CALL free_msg_addr
ADD ESP,0x18
LEA ECX,chat_msg
CALL free_chat_msg_addr
POPAD
}
return success;
+55
View File
@@ -0,0 +1,55 @@
#include "pch.h"
#include "sns.h"
#include "common.h"
#include "wechat_data.h"
using namespace std;
#define WX_SNS_DATA_MGR_OFFSET 0xbc4100
#define WX_SNS_GET_FIRST_PAGE_OFFSET 0x1427be0
#define WX_SNS_GET_NEXT_PAGE_OFFSET 0x1427c80
int GetFirstPage() {
int success = -1;
DWORD base = GetWeChatWinBase();
DWORD sns_data_mgr_addr = base + WX_SNS_DATA_MGR_OFFSET;
DWORD get_first_page_addr = base + WX_SNS_GET_FIRST_PAGE_OFFSET;
char buff[0xB44] = {};
__asm {
PUSHAD
CALL sns_data_mgr_addr
PUSH 0x1
LEA ECX,buff
PUSH ECX
MOV ECX,EAX
CALL get_first_page_addr
MOV success,EAX
POPAD
}
return success;
}
int GetNextPage(ULONG64 sns_id) {
int success = -1;
DWORD base = GetWeChatWinBase();
DWORD sns_data_mgr_addr = base + WX_SNS_DATA_MGR_OFFSET;
DWORD get_next_page_addr = base + WX_SNS_GET_NEXT_PAGE_OFFSET;
VectorInner temp = {};
__asm{
PUSHAD
CALL sns_data_mgr_addr
LEA ECX,temp
PUSH ECX
MOV EBX,dword ptr [sns_id + 0x4]
PUSH EBX
MOV EDI,dword ptr [sns_id ]
PUSH EDI
MOV ECX,EAX
CALL get_next_page_addr
MOV success,EAX
POPAD
}
return success;
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef SNS_H_
#define SNS_H_
int GetFirstPage();
int GetNextPage(ULONG64 sns_id);
#endif
+59 -15
View File
@@ -4,7 +4,6 @@
// #include <windows.h>
#include <vector>
using namespace std;
struct WeChatString {
wchar_t *ptr;
DWORD length;
@@ -13,7 +12,7 @@ struct WeChatString {
DWORD c_len = 0;
WeChatString() { WeChatString(NULL); }
WeChatString(wstring &s) {
WeChatString(std::wstring &s) {
ptr = (wchar_t *)(s.c_str());
length = s.length();
max_length = s.length() * 2;
@@ -51,7 +50,7 @@ struct DatabaseInfo {
DWORD handle = 0;
wchar_t *db_name = NULL;
DWORD db_name_len = 0;
vector<TableInfo> tables;
std::vector<TableInfo> tables;
DWORD count = 0;
DWORD extrainfo = 0;
};
@@ -101,6 +100,25 @@ struct ChatRoomInfoInner {
WeChatString notice;
WeChatString admin;
WeChatString xml;
~ChatRoomInfoInner(){
if(chat_room_id.ptr){
delete []chat_room_id.ptr;
chat_room_id.ptr = nullptr;
}
if(notice.ptr){
delete []notice.ptr;
notice.ptr = nullptr;
}
if(admin.ptr){
delete []admin.ptr;
admin.ptr = nullptr;
}
if(xml.ptr){
delete []xml.ptr;
xml.ptr = nullptr;
}
}
};
struct VectorInner {
@@ -124,17 +142,43 @@ struct ChatRoomInner{
};
struct SelfInfoInner{
string name;
string city;
string province;
string country;
string account;
string wxid;
string mobile;
string small_img;
string big_img;
string data_root_path;
string data_save_path;
string current_data_path;
std::string name;
std::string city;
std::string province;
std::string country;
std::string account;
std::string wxid;
std::string mobile;
std::string small_img;
std::string big_img;
std::string data_root_path;
std::string data_save_path;
std::string current_data_path;
};
struct UserInfo {
int error_code;
wchar_t *keyword;
int keyword_len;
wchar_t *v3;
int v3_len;
wchar_t *nickname;
int nickname_len;
wchar_t *signature;
int signature_len;
wchar_t *v2;
int v2_len;
wchar_t *nation;
int nation_len;
wchar_t *province;
int province_len;
wchar_t *city;
int city_len;
wchar_t *big_image;
int big_image_len;
wchar_t *small_image;
int small_image_len;
DWORD sex;
BOOL over;
};
#endif
Binary file not shown.