Compare commits

...
Author SHA1 Message Date
hugy 67949e16fc 日志hook退出还原 2023-03-16 12:06:56 +08:00
hugy 9f7b1dd273 新增日志hook 2023-03-16 12:02:44 +08:00
hugy 4eab2a2414 新增下载消息附件内容 2023-03-04 11:30:59 +08:00
hugy b8dc032525 发送@消息 2023-03-02 11:38:47 +08:00
hugy 7e89c6ef2d fix:修复获取个人信息错误的bug 2023-03-01 17:02:15 +08:00
hugy 82a5ca28db 修复个人信息获取错误 2023-03-01 14:11:06 +08:00
hugy 861a04e7a0 修复无法正确卸载dll 2023-02-21 16:24:39 +08:00
hugy 04e7967236 错误查询导致的崩溃 2023-02-20 10:38:22 +08:00
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
29 changed files with 1724 additions and 262 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ 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)
+395 -62
View File
@@ -7,11 +7,11 @@ wechat hook 。PC端微信逆向学习。支持3.8.0.41,3.8.1.26,3.9.0.28版
本项目是个人学习学习逆向的项目,主要参考 https://github.com/ljc545w/ComWeChatRobot ,在此基础上实现了微信的的其它版本的部分内容。
#### 使用说明:
支持的版本3.8.0.41,3.8.1.26,3.9.0.28。
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端口。
@@ -99,7 +99,11 @@ vcpkg
2023-02-08 : 新增朋友圈消息。
2023-02-09 : 新增3.9.0.28版本基础功能。
2023-02-09 : 新增3.9.0.28版本基础功能。
2023-02-13 : 新增查询联系人昵称功能。
2023-02-17 : 新增通过wxid添加好友和查找微信。
#### 功能预览:
0.检查是否登录
@@ -109,27 +113,34 @@ vcpkg
6.发送文件
9.hook消息
10.取消hook消息
~~11.hook图片~~
~~12.取消hook图片~~
~~17.删除好友~~
~~25.获取群成员~~
~~27.删除群成员~~
~~28.增加群成员~~
~~31.修改群昵称~~
~~32.获取数据库句柄~~
~~34.查询数据库~~
~~40.转发消息~~
11.hook图片
12.取消hook图片
17.删除好友
19.通过手机或qq查找微信
20.通过wxid添加好友
25.获取群成员
26.获取群成员昵称
27.删除群成员
28.增加群成员
31.修改群昵称
32.获取数据库句柄
34.查询数据库
35.hook日志
36.关闭hook日志
40.转发消息
44.退出登录
~~45.确认收款~~
45.确认收款
46.联系人列表
~~47.获取群详情~~
47.获取群详情
48.获取解密图片
~~49.图片提取文字ocr~~
~~50.拍一拍~~
~~51.群消息置顶消息~~
~~52.群消息取消置顶~~
49.图片提取文字ocr
50.拍一拍
51.群消息置顶消息
52.群消息取消置顶
53.朋友圈首页
54.朋友圈下一页
54.朋友圈下一页
55.获取联系人或者群名称
56.获取消息附件(图片,视频,文件)
### 接口文档:
@@ -189,17 +200,16 @@ vcpkg
|result|string|成功提示|
|data|object|响应内容|
|account|string|账号|
|bigImage|string|头像大图|
|headImage|string|头像|
|city|string|城市|
|country|string|国家|
|currentDataPath|string|当前数据目录|
|dataRootPath|string|根目录|
|dataSavePath|string|保存目录|
|currentDataPath|string|当前数据目录,登录的账号目录|
|dataSavePath|string|微信保存目录|
|mobile|string|手机|
|name|string|昵称|
|province|string|省|
|smallImage|string|小头像|
|wxid|string|wxid|
|signature|string|个人签名|
###### 接口示例
入参:
@@ -207,7 +217,7 @@ vcpkg
```
响应:
``` javascript
{"code":1,"data":{"account":"xx","bigImage":"https://wx.qlogo.cn/mmhead/ver_1xx","city":"xx","country":"CN","currentDataPath":"xxx","dataRootPath":"C:\\xx","dataSavePath":"C:\\xx","mobie":"13949175447","name":"xx","province":"xx","smallImage":"xx","wxid":"xx"},"result":"OK"}
{"code":1,"data":{"account":"xx","headImage":"https://wx.qlogo.cn/mmhead/ver_1xx","city":"xx","country":"CN","currentDataPath":"C:\\xx\\wxid_xxxxx","dataSavePath":"C:\\xx","mobie":"13812345678","name":"xx","province":"xx","signature":"xx","wxid":"xx"},"result":"OK"}
```
@@ -226,7 +236,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|msg|true |string|消息文本内容|
###### 返回字段
@@ -252,6 +262,47 @@ vcpkg
#### 3.发送@文本消息**
###### 接口功能
> 发送@文本消息
###### 接口地址
> [/api/?type=3](/api/?type=3)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|msg|true |string|消息文本内容|
|wxids |true |string| @的用户微信id用,号分隔, @所有人 传 notify@all ,区分大小写 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,不为0成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"chatRoomId": "123333@chatroom",
"wxids":"notify@all,wxid_122221",
"msg": "12333"
}
```
响应:
``` javascript
{"code":345686720,"result":"OK"}
```
#### 5.发送图片消息**
###### 接口功能
> 发送图片消息
@@ -265,7 +316,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|imagePath|true |string|图片路径|
###### 返回字段
@@ -303,7 +354,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 接收人wxid |
|wxid |true |string| 接收人wxid |
|filePath|true |string|文件路径|
###### 返回字段
@@ -340,8 +391,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|port |ture |string| 本地服务端端口,用来接收消息内容 |
|ip |ture |string| 服务端ip地址,用来接收消息内容,可以是任意ip,即tcp客户端连接的服务端的ip (3.8.1.26版本)|
|port |true |string| 本地服务端端口,用来接收消息内容 |
|ip |true |string| 服务端ip地址,用来接收消息内容,可以是任意ip,即tcp客户端连接的服务端的ip (3.8.1.26版本)|
###### 返回字段
|返回字段|字段类型|说明 |
@@ -410,7 +461,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imgDir |ture |string| 图片保存的目录 |
|imgDir |true |string| 图片保存的目录 |
###### 返回字段
@@ -468,7 +519,7 @@ vcpkg
#### 17.删除好友**
###### 接口功能
> 删除好友
> 删除好友,该接口不够完善,删除后,只会在通讯录里删除,如果点击聊天记录,又会重新加回来,删除的不彻底。
###### 接口地址
> [/api/?type=17](/api/?type=17)
@@ -479,13 +530,13 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 好友wxid |
|wxid |true |string| 好友wxid |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|code|int|返回状态,0成功, -1失败|
|result|string|成功提示|
@@ -498,9 +549,105 @@ vcpkg
```
响应:
``` javascript
{"code":1,"result":"OK"}
{"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.获取群成员**
@@ -516,7 +663,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|chatRoomId |true |string| 群id |
###### 返回字段
@@ -543,6 +690,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.删除群成员**
###### 接口功能
@@ -557,8 +741,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|memberIds |ture |string| 成员id,以,分割 |
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,以,分割 |
###### 返回字段
@@ -596,8 +780,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|memberIds |ture |string| 成员id,以,分割 |
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,以,分割 |
###### 返回字段
@@ -634,9 +818,9 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|wxid |ture |string| 自己的id,只能修改自己的群名片 |
|nickName |ture |string| 修改的昵称 |
|chatRoomId |true |string| 群id |
|wxid |true |string| 自己的id,只能修改自己的群名片 |
|nickName |true |string| 修改的昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -733,8 +917,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|dbHandle |ture |int| 句柄 |
|sql |ture |string| sql语句 |
|dbHandle |true |int| 句柄 |
|sql |true |string| sql语句 |
###### 返回字段
@@ -760,6 +944,73 @@ vcpkg
```
#### 35.hook日志**
###### 接口功能
> hook微信日志,在控制台打印日志,方便调试
###### 接口地址
> [/api/?type=35](/api/?type=35)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 36.取消hook日志**
###### 接口功能
> 取消hook日志
###### 接口地址
> [/api/?type=36](/api/?type=36)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 40.转发消息**
###### 接口功能
> 直接转发消息
@@ -773,8 +1024,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 消息接收人wxid |
|msgid |ture |number| 消息id,hook消息接口中返回的消息id |
|wxid |true |string| 消息接收人wxid |
|msgid |true |number| 消息id,hook消息接口中返回的消息id |
###### 返回字段
@@ -931,7 +1182,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 群id |
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -974,8 +1225,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imagePath |ture |string| 图片路径 |
|savePath |ture |string| 保存路径 |
|imagePath |true |string| 图片路径 |
|savePath |true |string| 保存路径 |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -1014,7 +1265,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|imagePath |ture |string| 图片路径 |
|imagePath |true |string| 图片路径 |
###### 返回字段
|返回字段|字段类型|说明 |
@@ -1037,8 +1288,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 微信群聊id |
|wxid |ture |string| 要拍的用户wxid,如果使用用户自定义的微信号,则不会显示群内昵称 |
|chatRoomId |true |string| 微信群聊id |
|wxid |true |string| 要拍的用户wxid,如果使用用户自定义的微信号,则不会显示群内昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
@@ -1075,8 +1326,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |ture |string| 置顶消息的发送人wxid |
|msgid |ture |string| 消息id |
|wxid |true |string| 置顶消息的发送人wxid |
|msgid |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
@@ -1113,8 +1364,8 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |ture |string| 微信群聊id |
|msgid |ture |string| 消息id |
|chatRoomId |true |string| 微信群聊id |
|msgid |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
@@ -1215,7 +1466,7 @@ vcpkg
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|snsId |ture |string| 朋友圈的snsId |
|snsId |true |string| 朋友圈的snsId |
@@ -1241,6 +1492,88 @@ vcpkg
{"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"}
```
#### 56.获取消息附件**
###### 接口功能
> 根据消息id,下载消息附件(图片,视频,文件)
###### 接口地址
> [/api/?type=56](/api/?type=56)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|msgId |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, 非0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"msgId": 3224560917391784099
}
```
响应:
``` javascript
{"code":0,"result":"OK"}
```
#### 感谢
https://github.com/ljc545w/ComWeChatRobot
+84 -5
View File
@@ -22,6 +22,9 @@
#include "pat.h"
#include "confirm_receipt.h"
#include "sns.h"
#include "search_contact.h"
#include "download.h"
#include "hook_log.h"
#pragma comment(lib, "ws2_32.lib")
using namespace std;
@@ -220,9 +223,8 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
{"account", self_info.account},
{"wxid", self_info.wxid},
{"mobile", self_info.mobile},
{"smallImage", self_info.small_img},
{"bigImage", self_info.big_img},
{"dataRootPath",self_info.data_root_path},
{"headImage", self_info.head_img},
{"signature",self_info.signature},
{"dataSavePath",self_info.data_save_path},
{"currentDataPath",self_info.current_data_path},
};
@@ -240,6 +242,16 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_MSG_SEND_AT: {
wstring chat_room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
vector<wstring> wxids = get_http_param_array(hm, j_param, "wxids", is_post);
wstring msg = get_http_req_param(hm, j_param, "msg", is_post);
vector<wchar_t *> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++){
wxid_list.push_back(WS2LW(wxids[i]));
}
int success = SendAtText(WS2LW(chat_room_id), wxid_list.data(), wxid_list.size(),WS2LW(msg));
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_CARD: {
@@ -321,9 +333,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: {
@@ -355,6 +391,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: {
@@ -445,9 +487,15 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_LOG_START_HOOK: {
int success = HookLog();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_LOG_STOP_HOOK: {
int success = UnHookLog();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_BROWSER_OPEN_WITH_URL: {
@@ -598,13 +646,27 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
ret = ret_data.dump();
break;
}
case WECHAT_SNS_GET_NEXT_PAGE:{
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;
}
case WECHAT_ATTACH_DOWNLOAD:{
ULONG64 msg_id = get_http_param_ulong64(hm, j_param, "msgId", is_post);
int success = DoDownloadTask(msg_id);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
default:
break;
}
@@ -663,6 +725,23 @@ int http_start(int port) {
#endif
kHttpRuning = true;
kHttpThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)http_server,
(LPVOID)port, NULL, 0);
(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();
UnHookLog();
return 0;
}
+4 -1
View File
@@ -69,9 +69,12 @@ typedef enum WECHAT_HTTP_APISTag
WECHAT_REMOVE_TOP_MSG,
WECHAT_SNS_GET_FIRST_PAGE,
WECHAT_SNS_GET_NEXT_PAGE,
WECHAT_CONTACT_NAME,
WECHAT_ATTACH_DOWNLOAD,
} 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
+87 -20
View File
@@ -7,21 +7,26 @@
#include "base64.h"
using namespace std;
#define WX_CHAT_ROOM_MGR_OFFSET 0x67ee70
#define WX_GET_CHAT_ROOM_DETAIL_INFO_OFFSET 0xa73a80
#define WX_NEW_CHAT_ROOM_INFO_OFFSET 0xd07010
#define WX_FREE_CHAT_ROOM_INFO_OFFSET 0xd072f0
#define WX_DEL_CHAT_ROOM_MEMBER_OFFSET 0xa69a50
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
#define WX_FREE_CHAT_MSG_OFFSET 0x649ac0
#define WX_ADD_MEMBER_TO_CHAT_ROOM_OFFSET 0xa69560
#define WX_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xa749b0
#define WX_INIT_CHAT_ROOM_OFFSET 0xd04d80
#define WX_FREE_CHAT_ROOM_OFFSET 0xa7c620
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xa6f8f0
#define WX_NEW_CHAT_MSG_OFFSET 0x64adc0
#define WX_TOP_MSG_OFFSET 0xa76e60
#define WX_REMOVE_TOP_MSG_OFFSET 0xa76c50
#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;
@@ -182,8 +187,8 @@ 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;
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;
@@ -261,12 +266,13 @@ int ModChatRoomMemberNickName(wchar_t* chat_room_id,wchar_t* wxid,wchar_t * nick
int SetTopMsg(wchar_t* wxid,ULONG64 msg_id){
int success = -1;
char chat_msg[0x2A8] ={0};
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_ROOM_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;
@@ -288,6 +294,7 @@ int SetTopMsg(wchar_t* wxid,ULONG64 msg_id){
WeChatString msg_content(w_content);
WeChatString user_id(wxid);
__asm{
PUSHAD
LEA ECX,chat_msg
@@ -307,12 +314,13 @@ int SetTopMsg(wchar_t* wxid,ULONG64 msg_id){
__asm{
PUSHAD
CALL get_chat_room_mgr_addr
PUSH 0x1
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
}
@@ -348,4 +356,63 @@ int RemoveTopMsg(wchar_t* chat_room_id,ULONG64 msg_id){
}
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;
}
+2
View File
@@ -11,4 +11,6 @@ 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
+8 -1
View File
@@ -126,7 +126,7 @@ string Wstring2String(wstring wstr) {
BOOL FindOrCreateDirectoryW(const wchar_t *path) {
WIN32_FIND_DATAW fd;
HANDLE hFind = ::FindFirstFileW(path, &fd);
if (hFind != INVALID_HANDLE_VALUE) {
if (hFind != INVALID_HANDLE_VALUE && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
FindClose(hFind);
return true;
}
@@ -135,4 +135,11 @@ BOOL FindOrCreateDirectoryW(const wchar_t *path) {
return false;
}
return true;
}
void CloseConsole(){
fclose(stdin);
fclose(stdout);
fclose(stderr);
FreeConsole();
}
+1
View File
@@ -53,6 +53,7 @@ std::string Wstring2String(std::wstring wstr);
/// @return
BOOL FindOrCreateDirectoryW(const wchar_t *path);
void CloseConsole();
template <typename T1, typename T2>
std::vector<T1> split(T1 str, T2 letter) {
+3 -3
View File
@@ -4,9 +4,9 @@
#include "common.h"
#include "wechat_data.h"
#define WX_NEW_WCPAYINFO_OFFSET 0x69d2b0
#define WX_FREE_WCPAYINFO_OFFSET 0x68d610
#define WX_CONFIRM_RECEIPT_OFFSET 0x13d5e00
#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) {
+112 -22
View File
@@ -6,9 +6,15 @@
using namespace std;
#define WX_CONTACT_MGR_INSTANCE_OFFSET 0x6f8990
#define WX_CONTACT_GET_LIST_OFFSET 0xb97550
#define WX_CONTACT_DEL_OFFSET 0xa9ef40
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
#define WX_DB_QUERY_OFFSET 0xa9ec40
#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
int GetAllContact(vector<Contact> &vec) {
DWORD base = GetWeChatWinBase();
DWORD get_instance = base + WX_CONTACT_MGR_INSTANCE_OFFSET;
@@ -66,37 +72,121 @@ int GetAllContact(vector<Contact> &vec) {
}
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;
}
+4
View File
@@ -8,4 +8,8 @@ int GetAllContact(std::vector<Contact> &vec);
int DelContact(wchar_t* wxid);
std::wstring GetContactOrChatRoomNickname(wchar_t* id);
int AddFriendByWxid(wchar_t *wxid);
#endif
+6 -1
View File
@@ -97,10 +97,15 @@ int Select(DWORD db_hanle, const char *sql,
if (status == 0) {
return 0;
}
if(data.size() == 0){
return 1;
}
vector<string> index;
for (size_t i = 0; i < data[0].size(); i++)
for (size_t i = 0; i < data[0].size(); i++){
index.push_back(data[0][i].column_name);
}
query_result.push_back(index);
for (auto it : data) {
vector<string> item;
for (size_t i = 0; i < it.size(); i++) {
+2
View File
@@ -16,6 +16,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
break;
}
case DLL_PROCESS_DETACH: {
CloseConsole();
http_close();
break;
}
}
+183
View File
@@ -0,0 +1,183 @@
#include "pch.h"
#include "download.h"
#include "common.h"
#include "get_db_handle.h"
#include "wechat_data.h"
#define WX_NEW_CHAT_MSG_OFFSET 0x70e2a0
#define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x7ae310
#define WX_PUSH_ATTACH_TASK_OFFSET 0x7c94a0
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x6f5370
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
#define WX_CHAT_MGR_OFFSET 0x732660
#define WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET 0xb54950
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc11140
#define WX_APP_MSG_INFO_OFFSET 0x7571d0
#define WX_GET_APP_MSG_XML_OFFSET 0xddef80
#define WX_FREE_APP_MSG_INFO_OFFSET 0x73d820
#define WX_PUSH_THUMB_TASK_OFFSET 0x7c93a0
#define WX_VIDEO_MGR_OFFSET 0x7c7300
#define WX_DOWNLOAD_VIDEO_IMG_OFFSET 0xcc6d80
using namespace std;
int DoDownloadTask(ULONG64 msg_id) {
int success = -1;
int db_index = 0;
int local_id = GetLocalIdByMsgId(msg_id, db_index);
if (local_id < 1) {
return -2;
}
char chat_msg[0x2C4] = {0};
DWORD base = GetWeChatWinBase();
DWORD new_chat_msg_addr = base + WX_NEW_CHAT_MSG_OFFSET;
DWORD get_chat_mgr_addr = base + WX_CHAT_MGR_OFFSET;
DWORD pre_download_mgr_addr = base + WX_GET_PRE_DOWNLOAD_MGR_OFFSET;
DWORD push_attach_task_addr = base + WX_PUSH_ATTACH_TASK_OFFSET;
DWORD free_addr = base + WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET;
DWORD get_by_local_Id_addr = base + WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET;
DWORD get_current_data_path_addr = base + WX_GET_CURRENT_DATA_PATH_OFFSET;
DWORD free_app_msg_info_addr = base + WX_FREE_APP_MSG_INFO_OFFSET;
DWORD push_thumb_task_addr = base + WX_PUSH_THUMB_TASK_OFFSET;
DWORD video_mgr_addr = base + WX_VIDEO_MGR_OFFSET;
DWORD download_video_image_addr = base + WX_VIDEO_MGR_OFFSET;
WeChatString current_data_path;
__asm {
PUSHAD
PUSHFD
LEA ECX,current_data_path
CALL get_current_data_path_addr
LEA ECX,chat_msg
CALL new_chat_msg_addr
CALL get_chat_mgr_addr
PUSH dword ptr [db_index]
LEA ECX,chat_msg
PUSH dword ptr [local_id]
CALL get_by_local_Id_addr
ADD ESP,0x8
POPFD
POPAD
}
wstring save_path = L"";
wstring thumb_path = L"";
if (current_data_path.length > 0) {
save_path += current_data_path.ptr;
save_path += L"wxhelper";
} else {
return -1;
}
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
DWORD type = *(DWORD *)(chat_msg + 0x38);
wchar_t *content = *(wchar_t **)(chat_msg + 0x70);
switch (type) {
case 0x3: {
save_path += L"\\image";
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
save_path = save_path +L"\\"+ to_wstring(msg_id) + L".png";
break;
}
case 0x3E:
case 0x2B: {
save_path += L"\\video";
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
thumb_path = save_path + L"\\"+ to_wstring(msg_id) + L".jpg";
save_path = save_path + L"\\"+ to_wstring(msg_id) + L".mp4";
break;
}
case 0x31: {
save_path += L"\\file";
wcout << save_path << endl;
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return -3;
}
char xml_app_msg[0xC80] = {0};
DWORD new_app_msg_addr = base + WX_APP_MSG_INFO_OFFSET;
DWORD get_xml_addr = base + WX_GET_APP_MSG_XML_OFFSET;
WeChatString w_content(content);
__asm {
PUSHAD
PUSHFD
LEA ECX,xml_app_msg
CALL new_app_msg_addr
PUSH 0x1
LEA EAX,w_content
PUSH EAX
LEA ECX,xml_app_msg
CALL get_xml_addr
MOV success,EAX
LEA ECX,xml_app_msg
CALL free_app_msg_info_addr
POPFD
POPAD
}
if (success != 1) {
return -4;
}
WeChatString *file_name = (WeChatString *)((DWORD)xml_app_msg + 0x44);
save_path = save_path +L"\\" + to_wstring(msg_id) + L"_" +
wstring(file_name->ptr, file_name->length);
break;
}
default:
break;
}
WeChatString w_save_path(save_path);
WeChatString w_thumb_path(thumb_path);
int temp =1;
memcpy(&chat_msg[0x19C], &w_thumb_path, sizeof(w_thumb_path));
memcpy(&chat_msg[0x1B0], &w_save_path, sizeof(w_save_path));
memcpy(&chat_msg[0x290], &temp, sizeof(temp));
// note: the image has been downloaded and will not be downloaded again
// use low-level method
// this function does not work, need to modify chatmsg.
// if (type == 0x3E || type == 0x2B){
// __asm{
// PUSHAD
// PUSHFD
// CALL video_mgr_addr
// LEA ECX,chat_msg
// PUSH ECX
// MOV ECX,EAX
// CALL download_video_image_addr
// POPFD
// POPAD
// }
// }
__asm {
PUSHAD
PUSHFD
CALL pre_download_mgr_addr
PUSH 0x1
PUSH 0x0
LEA ECX,chat_msg
PUSH ECX
MOV ECX,EAX
CALL push_attach_task_addr
MOV success,EAX
LEA ECX,chat_msg
PUSH 0x0
CALL free_addr
POPFD
POPAD
}
return success;
}
+5
View File
@@ -0,0 +1,5 @@
#ifndef DOWNLOAD_H_
#define DOWNLOAD_H_
int DoDownloadTask(ULONG64 msg_id);
#endif
+2 -2
View File
@@ -4,8 +4,8 @@
#include "common.h"
#include "get_db_handle.h"
#include "wechat_data.h"
#define WX_FORWARD_MSG_OFFSET 0xb6a4e0
#define WX_INIT_CHAT_MSG_OFFSET 0xdbf380
#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;
+6 -6
View File
@@ -5,7 +5,7 @@
#include "new_sqlite3.h"
#include "pch.h"
#include "wechat_data.h"
#define CONTACT_G_PINSTANCE 0x2c42e78
#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 0x2c7ec88
#define MULTI_DB_MSG_MGR_OFFSET 0x2c807d0
#define FAVORITE_STORAGE_MGR_OFFSET 0x2c801f8
#define FTS_FAVORITE_MGR_OFFSET 0x2c439b8
#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);
+3 -3
View File
@@ -6,9 +6,9 @@ using namespace std;
// #define WX_HOOK_IMG_OFFSET 0xd7eaa5
// #define WX_HOOK_IMG_NEXT_OFFSET 0xda56e0
#define WX_HOOK_IMG_OFFSET 0xc672cc
#define WX_HOOK_IMG_NEXT_OFFSET 0xd82370
#define WX_SELF_ID_OFFSET 0x2C42A38
#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
+78
View File
@@ -0,0 +1,78 @@
#include "pch.h"
#include "hook_log.h"
#include "common.h"
using namespace std;
#define WX_HOOK_LOG_OFFSET 0xed1675
#define WX_HOOK_LOG_NEXT_OFFSET 0x2344832
static int kLogHooked = FALSE;
static DWORD kWeChatWinBase = GetWeChatWinBase();
static char kOriginLogAsmCode[5] = {0};
static DWORD kHookLogAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
static DWORD kHookLogNextAddress = kWeChatWinBase + WX_HOOK_LOG_NEXT_OFFSET;
static DWORD kHookLogJmpBackAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET + 0x5;
void log_print(DWORD addr) {
if (!addr) {
return;
}
DWORD dwId = 0;
char *msg = (char *)addr;
int size = MultiByteToWideChar(CP_UTF8, 0, msg, -1, 0, 0);
wchar_t *w_msg = new wchar_t[size + 1];
memset(w_msg, 0, (size + 1) * 2);
MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, size);
size = WideCharToMultiByte(CP_ACP, 0, w_msg, -1, 0, 0, 0, 0);
char *ansi_message = new char[size + 1];
memset(ansi_message, 0, size + 1);
WideCharToMultiByte(CP_ACP, 0, w_msg, -1, ansi_message, size, 0, 0);
delete[] w_msg;
w_msg = NULL;
cout << ansi_message;
delete[] ansi_message;
ansi_message = NULL;
}
_declspec(naked) void handle_log() {
__asm {
PUSHAD
PUSHFD
PUSH EAX
CALL log_print
ADD ESP, 0x4
POPFD
POPAD
CALL kHookLogNextAddress
JMP kHookLogJmpBackAddress
}
}
int HookLog() {
kWeChatWinBase = GetWeChatWinBase();
if (!kWeChatWinBase) {
return -1;
}
if (kLogHooked) {
return 2;
}
kHookLogAddress = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
kHookLogNextAddress = kWeChatWinBase + WX_HOOK_LOG_NEXT_OFFSET;
kHookLogJmpBackAddress = kHookLogAddress + 0x5;
HookAnyAddress(kHookLogAddress, (LPVOID)handle_log, kOriginLogAsmCode);
kLogHooked = TRUE;
return 1;
}
int UnHookLog() {
if (!kLogHooked) {
return 1;
}
DWORD hook_img_addr = kWeChatWinBase + WX_HOOK_LOG_OFFSET;
UnHookAnyAddress(hook_img_addr, kOriginLogAsmCode);
kLogHooked = FALSE;
return 1;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_LOG_H_
#define HOOK_LOG_H_
#include "windows.h"
int HookLog();
int UnHookLog();
#endif
+18 -18
View File
@@ -135,24 +135,24 @@
#define SQLITE_NULL 5
#define SQLITE_TEXT 3
#define SQLITE3_EXEC_OFFSET 0x1ba9de0
#define SQLITE3_BACKUP_INIT_OFFSET 0x1b6f760
#define SQLITE3_PREPARE_OFFSET 0x1bb0730
#define SQLITE3_OPEN_OFFSET 0x1bde730
#define SQLITE3_BACKUP_STEP_OFFSET 0x1b6fb60
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1b702a0
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1b702b0
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1b701a0
#define SQLITE3_SLEEP_OFFSET 0x1bdef70
#define SQLITE3_ERRCODE_OFFSET 0x1bdd3d0
#define SQLITE3_CLOSE_OFFSET 0x1bdbb20
#define SQLITE3_STEP_OFFSET 0x1b785d0
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1b78ae0
#define SQLITE3_COLUMN_NAME_OFFSET 0x1b793d0
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1b79270
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1b78b20
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1b78c00
#define SQLITE3_FINALIZE_OFFSET 0x1b775a0
#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**);
+7 -4
View File
@@ -4,9 +4,9 @@
#include "common.h"
#include "wechat_data.h"
#define WX_INIT_OBJ_OFFSET 0x6cbab0
#define WX_OCR_MANAGER_OFFSET 0x6cff00
#define WX_DO_OCR_TASK_OFFSET 0x11e3210
#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;
@@ -17,6 +17,7 @@ int DoOCRTask(wchar_t *img_path, std::string &result) {
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
@@ -25,9 +26,11 @@ int DoOCRTask(wchar_t *img_path, std::string &result) {
CALL ocr_manager_addr
LEA ECX,null_obj
PUSH ECX
LEA ECX,flag
PUSH ECX
LEA ECX,ocr_result
PUSH ECX
PUSH ECX
PUSH 0x0
LEA ECX,path
PUSH ECX
MOV ECX,EAX
+1 -1
View File
@@ -5,7 +5,7 @@
#include "wechat_data.h"
#define WX_PAT_MGR_OFFSET 0x8d0c00
#define WX_SEND_PAT_MSG_OFFSET 0x1228510
#define WX_SEND_PAT_MSG_OFFSET 0x1369850
#define WX_RET_OFFSET 0x1C94D34
int SendPatMsg(wchar_t* chat_room_id, wchar_t* wxid) {
+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
+169 -108
View File
@@ -20,136 +20,197 @@ using namespace std;
#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
#define WX_LOGOUT_OFFSET 0xdd5c90
#define WX_ACCOUNT_SERVICE_OFFSET 0x707960
#define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xeb4b00
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc11140
int GetSelfInfo(SelfInfoInner &out) {
DWORD base = GetWeChatWinBase();
#ifdef _DEBUG
cout << "mobile:" << (char *)(base + WX_SELF_MOBILE_OFFSET) << endl;
cout << "name:" << (char *)(base + WX_SELF_NAME_OFFSET) << endl;
cout << "city:" << (char *)(base + WX_SELF_CITY_OFFSET) << endl;
cout << "city:" << (char *)(base + WX_SELF_CITY_OFFSET) << endl;
cout << "province:" << (char *)(base + WX_SELF_PROVINCE_OFFSET) << endl;
cout << "country:" << (char *)(base + WX_SELF_COUNTRY_OFFSET) << endl;
cout << "account:" << (char *)(base + WX_SELF_ACCOUNT_OFFSET) << endl;
cout << "wxid:" << (char *)(base + WX_SELF_ID_OFFSET) << endl;
cout << "small_img:" << (char *)(base + WX_SELF_SMALL_IMG_OFFSET) << endl;
cout << "big_img:" << (char *)(base + WX_SELF_BIG_IMG_OFFSET) << endl;
#endif
if (*(DWORD *)(base + WX_SELF_NAME_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_NAME_OFFSET + 0x10) == 0) {
out.name = string();
} else {
out.name = string((char *)(base + WX_SELF_NAME_OFFSET),
*(DWORD *)(base + WX_SELF_NAME_OFFSET + 0x10));
DWORD accout_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
DWORD get_app_save_addr = base + WX_GET_APP_DATA_SAVE_PATH_OFFSET;
DWORD get_current_data_path_addr = base + WX_GET_CURRENT_DATA_PATH_OFFSET;
DWORD service_addr = NULL;
__asm {
PUSHAD
CALL accout_service_addr
MOV service_addr,EAX
POPAD
}
if (*(DWORD *)(base + WX_SELF_MOBILE_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_MOBILE_OFFSET + 0x10) == 0) {
out.mobile = string();
} else {
out.mobile = string((char *)(base + WX_SELF_MOBILE_OFFSET),
*(DWORD *)(base + WX_SELF_MOBILE_OFFSET + 0x10));
if (service_addr) {
if (*(DWORD *)(service_addr + 0x44) == 0 ||
*(DWORD *)(service_addr + 0x44 + 0x10) == 0) {
out.wxid = string();
} else {
if (*(DWORD *)(service_addr + 0x44 + 0x14) == 0xF) {
out.wxid = string((char *)(service_addr + 0x44),
*(DWORD *)(service_addr + 0x44 + 0x10));
} else {
out.wxid = string(*(char **)(service_addr + 0x44),
*(DWORD *)(service_addr + 0x44 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0xA8) == 0 ||
*(DWORD *)(service_addr + 0xA8 + 0x10) == 0) {
out.account = string();
} else {
if (*(DWORD *)(service_addr + 0xA8 + 0x14) == 0xF) {
out.account = string((char *)(service_addr + 0xA8),
*(DWORD *)(service_addr + 0xA8 + 0x10));
} else {
out.account = string(*(char **)(service_addr + 0xA8),
*(DWORD *)(service_addr + 0xA8 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0xC0) == 0 ||
*(DWORD *)(service_addr + 0xC0 + 0x10) == 0) {
out.mobile = string();
} else {
if (*(DWORD *)(service_addr + 0xC0 + 0x14) == 0xF) {
out.mobile = string((char *)(service_addr + 0xC0),
*(DWORD *)(service_addr + 0xC0 + 0x10));
} else {
out.mobile = string(*(char **)(service_addr + 0xC0),
*(DWORD *)(service_addr + 0xC0 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0xD8) == 0 ||
*(DWORD *)(service_addr + 0xD8 + 0x10) == 0) {
out.signature = string();
} else {
if (*(DWORD *)(service_addr + 0xD8 + 0x14) == 0xF) {
out.signature = string((char *)(service_addr + 0xD8),
*(DWORD *)(service_addr + 0xD8 + 0x10));
} else {
out.signature = string(*(char **)(service_addr + 0xD8),
*(DWORD *)(service_addr + 0xD8 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0xF0) == 0 ||
*(DWORD *)(service_addr + 0xF0 + 0x10) == 0) {
out.country = string();
} else {
if (*(DWORD *)(service_addr + 0xF0 + 0x14) == 0xF) {
out.country = string((char *)(service_addr + 0xF0),
*(DWORD *)(service_addr + 0xF0 + 0x10));
} else {
out.country = string(*(char **)(service_addr + 0xF0),
*(DWORD *)(service_addr + 0xF0 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0x108) == 0 ||
*(DWORD *)(service_addr + 0x108 + 0x10) == 0) {
out.province = string();
} else {
if (*(DWORD *)(service_addr + 0x108 + 0x14) == 0xF) {
out.province = string((char *)(service_addr + 0x108),
*(DWORD *)(service_addr + 0x108 + 0x10));
} else {
out.province = string(*(char **)(service_addr + 0x108),
*(DWORD *)(service_addr + 0x108 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0x120) == 0 ||
*(DWORD *)(service_addr + 0x120 + 0x10) == 0) {
out.city = string();
} else {
if (*(DWORD *)(service_addr + 0x120 + 0x14) == 0xF) {
out.city = string((char *)(service_addr + 0x120),
*(DWORD *)(service_addr + 0x120 + 0x10));
} else {
out.city = string(*(char **)(service_addr + 0x120),
*(DWORD *)(service_addr + 0x120 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0x150) == 0 ||
*(DWORD *)(service_addr + 0x150 + 0x10) == 0) {
out.name = string();
} else {
if (*(DWORD *)(service_addr + 0x150 + 0x14) == 0xF) {
out.name = string((char *)(service_addr + 0x150),
*(DWORD *)(service_addr + 0x150 + 0x10));
} else {
out.name = string(*(char **)(service_addr + 0x150),
*(DWORD *)(service_addr + 0x150 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0x304) == 0 ||
*(DWORD *)(service_addr + 0x304 + 0x10) == 0) {
out.head_img = string();
} else {
if (*(DWORD *)(service_addr + 0x304 + 0x14) == 0xF) {
out.head_img = string((char *)(service_addr + 0x304),
*(DWORD *)(service_addr + 0x304 + 0x10));
} else {
out.head_img = string(*(char **)(service_addr + 0x304),
*(DWORD *)(service_addr + 0x304 + 0x10));
}
}
}
if (*(DWORD *)(base + WX_SELF_CITY_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_CITY_OFFSET + 0x10) == 0) {
out.city = string();
} else {
out.city = string((char *)(base + WX_SELF_CITY_OFFSET),
*(DWORD *)(base + WX_SELF_CITY_OFFSET + 0x10));
WeChatString data_save_path;
WeChatString current_data_path;
__asm {
PUSHAD
LEA ECX,data_save_path
CALL get_app_save_addr
LEA ECX,current_data_path
CALL get_current_data_path_addr
POPAD
}
if (*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET + 0x10) == 0) {
out.province = string();
} else {
out.province = string((char *)(base + WX_SELF_PROVINCE_OFFSET),
*(DWORD *)(base + WX_SELF_PROVINCE_OFFSET + 0x10));
if (data_save_path.ptr) {
out.data_save_path =
Wstring2String(wstring(data_save_path.ptr, data_save_path.length));
}
if (*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET + 0x10) == 0) {
out.country = string();
} else {
out.country = string((char *)(base + WX_SELF_COUNTRY_OFFSET),
*(DWORD *)(base + WX_SELF_COUNTRY_OFFSET + 0x10));
}
if (*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET + 0x10) == 0) {
out.account = string();
} else {
out.account = string(*(char **)(base + WX_SELF_ACCOUNT_OFFSET),
*(DWORD *)(base + WX_SELF_ACCOUNT_OFFSET + 0x10));
}
if (*(DWORD *)(base + WX_SELF_ID_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_ID_OFFSET + 0x10) == 0) {
out.wxid = string();
} else {
out.wxid = string(*(char **)(base + WX_SELF_ID_OFFSET),
*(DWORD *)(base + WX_SELF_ID_OFFSET + 0x10));
}
if (*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET + 0x10) == 0) {
out.small_img = string();
} else {
out.small_img = string(*(char **)(base + WX_SELF_SMALL_IMG_OFFSET),
*(DWORD *)(base + WX_SELF_SMALL_IMG_OFFSET + 0x10));
}
if (*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET) == 0 ||
*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET + 0x10) == 0) {
out.big_img = string();
} else {
out.big_img = string(*(char **)(base + WX_SELF_BIG_IMG_OFFSET),
*(DWORD *)(base + WX_SELF_BIG_IMG_OFFSET + 0x10));
}
if (*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET) == 0 ||
*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET + 0x4) == 0) {
out.data_root_path = string();
} else {
out.data_root_path = Wstring2String(wstring(*(wchar_t **)(base + WX_APP_DATA_ROOT_PATH_OFFSET),
*(DWORD *)(base + WX_APP_DATA_ROOT_PATH_OFFSET + 0x4)));
}
if (*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET) == 0 ||
*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET + 0x4) == 0) {
else {
out.data_save_path = string();
} else {
out.data_save_path = Wstring2String(wstring(*(wchar_t **)(base + WX_APP_DATA_SAVE_PATH_OFFSET),
*(DWORD *)(base + WX_APP_DATA_SAVE_PATH_OFFSET + 0x4)));
}
if (*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET) == 0 ||
*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET + 0x4) == 0) {
out.current_data_path = string();
} else {
out.current_data_path = Wstring2String(wstring(*(wchar_t **)(base + WX_CURRENT_DATA_PATH_OFFSET),
*(DWORD *)(base + WX_CURRENT_DATA_PATH_OFFSET + 0x4)));
}
if (current_data_path.ptr) {
out.current_data_path = Wstring2String(
wstring(current_data_path.ptr, current_data_path.length));
} else {
out.current_data_path = string();
}
return 1;
}
int CheckLogin(){
int CheckLogin() {
DWORD base = GetWeChatWinBase();
return *(DWORD*) (base + WX_LOGIN_STATUS_OFFSET);
DWORD accout_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
DWORD service_addr = NULL;
__asm {
PUSHAD
CALL accout_service_addr
MOV service_addr,EAX
POPAD
}
if (service_addr) {
return *(DWORD *)(service_addr + 0x4C8);
}
else {
return 0;
}
}
int Logout(){
int Logout() {
int success = 0;
if(!CheckLogin()){
if (!CheckLogin()) {
return success;
}
DWORD base = GetWeChatWinBase();
DWORD account_service_addr = base + WX_ACCOUT_SERVICE_OFFSET;
DWORD account_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
DWORD logout_addr = base + WX_LOGOUT_OFFSET;
__asm{
__asm {
PUSHAD
CALL account_service_addr
PUSH 0x0
+70
View File
@@ -4,12 +4,14 @@
#include "common.h"
#include "wechat_data.h"
#include "contact.h"
#define WX_SEND_TEXT_OFFSET 0xc71a60
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
using namespace std;
/// @brief 发生文本消息
/// @param wxid wxid
/// @param msg 文本消息
@@ -45,4 +47,72 @@ int SendText(wchar_t* wxid, wchar_t* msg) {
POPAD
}
return success;
}
int SendAtText(wchar_t* chat_room_id,wchar_t** wxids,int len,wchar_t* msg){
int success = -1;
WeChatString * at_users = new WeChatString[len+1];
wstring at_msg = L"";
int number =0;
for (int i = 0; i < len; i++) {
wstring nickname;
if (!lstrcmpiW((wchar_t *)wxids[i], (wchar_t *)L"notify@all")) {
nickname = L"ËùÓÐÈË";
} else {
nickname = GetContactOrChatRoomNickname(wxids[i]);
}
if (nickname.length() == 0) {
continue;
}
WeChatString temp = {0};
temp.ptr = (wchar_t *)wxids[i];
temp.length = wcslen((wchar_t *)wxids[i]);
temp.max_length = wcslen((wchar_t *)wxids[i]) * 2;
memcpy(&at_users[number], &temp, sizeof(WeChatString));
at_msg = at_msg + L"@" + nickname + L" ";
number++;
}
if (number < 1){
return success;
}
wstring origin(msg);
at_msg += origin;
AtInner at_list = {0};
at_list.start = (DWORD)at_users;
at_list.finsh = (DWORD)&at_users[number];
at_list.end = (DWORD)&at_users[number];
WeChatString to_user(chat_room_id);
WeChatString text_msg((wchar_t *)at_msg.c_str());
wchar_t **msg_pptr = &text_msg.ptr;
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_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
LEA EAX,at_list
PUSH EAX
MOV EAX,msg_pptr
PUSH EAX
LEA EDX,to_user
LEA ECX,chat_msg
CALL send_text_msg_addr
MOV success,EAX
ADD ESP,0x18
LEA ECX,chat_msg
CALL free_chat_msg_addr
POPAD
}
return success;
}
+1 -1
View File
@@ -2,5 +2,5 @@
#define SEND_TEXT_H_
int SendText(wchar_t* wxid, wchar_t* msg);
int SendAtText(wchar_t* chat_room_id,wchar_t** wxids,int len,wchar_t* msg);
#endif
+181 -3
View File
@@ -149,10 +149,188 @@ struct SelfInfoInner{
std::string account;
std::string wxid;
std::string mobile;
std::string small_img;
std::string big_img;
std::string data_root_path;
std::string head_img;
std::string data_save_path;
std::string signature;
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;
};
struct AtInner{
DWORD start;
DWORD finsh;
DWORD end;
};
struct ChatMsg {
DWORD **field0_0x0;
DWORD field1_0x4;
ULONG64 sequence;
DWORD field3_0x10;
DWORD field4_0x14;
ULONG64 msgSequence;
DWORD localId;
DWORD field7_0x24;
DWORD field8_0x28;
DWORD field9_0x2c;
ULONG64 msgId;
DWORD type;
DWORD isSendMsg;
DWORD msgStatus;
DWORD timestamp;
WeChatString talker;
DWORD field16_0x5c;
DWORD field17_0x60;
DWORD field18_0x64;
DWORD field19_0x68;
DWORD field20_0x6c;
WeChatString content;
DWORD field22_0x84;
DWORD field23_0x88;
DWORD field24_0x8c;
DWORD field25_0x90;
DWORD field26_0x94;
DWORD field27_0x98;
DWORD field28_0x9c;
DWORD field29_0xa0;
DWORD field30_0xa4;
DWORD field31_0xa8;
DWORD field32_0xac;
DWORD field33_0xb0;
DWORD field34_0xb4;
DWORD field35_0xb8;
DWORD field36_0xbc;
DWORD field37_0xc0;
DWORD field38_0xc4;
DWORD field39_0xc8;
DWORD field40_0xcc;
DWORD field41_0xd0;
DWORD field42_0xd4;
DWORD field43_0xd8;
DWORD field44_0xdc;
DWORD field45_0xe0;
DWORD field46_0xe4;
DWORD field47_0xe8;
DWORD field48_0xec;
DWORD field49_0xf0;
DWORD field50_0xf4;
DWORD field51_0xf8;
DWORD field52_0xfc;
DWORD field53_0x100;
DWORD field54_0x104;
DWORD field55_0x108;
DWORD field56_0x10c;
DWORD field57_0x110;
DWORD field58_0x114;
DWORD field59_0x118;
DWORD field60_0x11c;
DWORD field61_0x120;
DWORD field62_0x124;
DWORD field63_0x128;
DWORD field64_0x12c;
DWORD field65_0x130;
DWORD field66_0x134;
DWORD field67_0x138;
DWORD field68_0x13c;
DWORD field69_0x140;
DWORD field70_0x144;
DWORD field71_0x148;
DWORD field72_0x14c;
DWORD field73_0x150;
DWORD field74_0x154;
DWORD field75_0x158;
DWORD field76_0x15c;
DWORD field77_0x160;
DWORD field78_0x164;
DWORD field79_0x168;
DWORD field80_0x16c;
DWORD field81_0x170;
WeChatString fromGroup;
WeChatString sign;
WeChatString thumbPath;
WeChatString path;
DWORD field86_0x1c4;
DWORD field87_0x1c8;
DWORD field88_0x1cc;
DWORD field89_0x1d0;
DWORD field90_0x1d4;
DWORD field91_0x1d8;
DWORD field92_0x1dc;
DWORD field93_0x1e0;
DWORD field94_0x1e4;
DWORD field95_0x1e8;
DWORD field96_0x1ec;
WeChatString signature;
DWORD field98_0x204;
DWORD field99_0x208;
DWORD field100_0x20c;
DWORD field101_0x210;
DWORD field102_0x214;
DWORD field103_0x218;
DWORD field104_0x21c;
DWORD field105_0x220;
DWORD field106_0x224;
DWORD field107_0x228;
DWORD field108_0x22c;
DWORD field109_0x230;
DWORD field110_0x234;
DWORD field111_0x238;
DWORD field112_0x23c;
DWORD field113_0x240;
DWORD field114_0x244;
DWORD field115_0x248;
DWORD field116_0x24c;
DWORD field117_0x250;
DWORD field118_0x254;
DWORD field119_0x258;
DWORD field120_0x25c;
DWORD field121_0x260;
DWORD field122_0x264;
DWORD field123_0x268;
DWORD field124_0x26c;
DWORD field125_0x270;
DWORD field126_0x274;
DWORD field127_0x278;
DWORD field128_0x27c;
DWORD field129_0x280;
DWORD field130_0x284;
DWORD field131_0x288;
DWORD field132_0x28c;
DWORD field133_0x290;
DWORD field134_0x294;
DWORD field135_0x298;
DWORD field136_0x29c;
DWORD field137_0x2a0;
DWORD field138_0x2a4;
DWORD field139_0x2a8;
DWORD field140_0x2ac;
DWORD field141_0x2b0;
int field142_0x2b4;
};
#endif