Compare commits

...
Author SHA1 Message Date
hugy 4a3ef64467 3.9.2.23版本更新 2023-03-28 10:01:55 +08:00
hugy 789b4b6e75 3.9.2.23部分更新 2023-03-27 17:52:30 +08:00
hugy 1a1a1fe964 hook语音 2023-03-27 11:58:04 +08:00
hugy 93798ddeca 转发消息 2023-03-27 11:48:00 +08:00
hugy df57bb3317 文档更新 2023-03-27 11:42:59 +08:00
hugy a097ae334a sqlite3 偏移 2023-03-27 11:40:57 +08:00
hugy 4b88354f46 好友列表 2023-03-23 14:03:42 +08:00
hugy 8ea5cbec8a hook消息 2023-03-23 11:04:58 +08:00
hugy b8db52d522 可以使用的功能 2023-03-22 17:55:07 +08:00
hugy e52a9b87ed 3.9.2.23 测试版 2023-03-22 17:52:51 +08:00
hugy 19d146db99 hook语音 2023-03-21 12:32:17 +08:00
20 changed files with 359 additions and 217 deletions
+91 -123
View File
@@ -1,112 +1,7 @@
# wxhelper
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: 简单的服务器,用以接收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.相应分支的文档对应相应版本,带有删除线的接口表示该版本的暂未实现,其他版本有实现。后续会继续实现。
#### 编译环境
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添加好友和查找微信。
## 3.9.2.23版本,预览功能没有的接口,不能使用,文档仅供参考。
#### 功能预览:
0.检查是否登录
0.检查是否登录
1.获取登录微信信息
2.发送文本
5.发送图片
@@ -114,33 +9,35 @@ vcpkg
9.hook消息
10.取消hook消息
11.hook图片
12.取消hook图片
17.删除好友
19.通过手机或qq查找微信
20.通过wxid添加好友
12.取消hook图片
13.hook语音
14.取消hook语音
<!-- 17.删除好友 -->
<!-- 19.通过手机或qq查找微信 -->
<!-- 20.通过wxid添加好友 -->
25.获取群成员
26.获取群成员昵称
<!-- 26.获取群成员昵称
27.删除群成员
28.增加群成员
31.修改群昵称
31.修改群昵称 -->
32.获取数据库句柄
34.查询数据库
35.hook日志
36.关闭hook日志
<!-- 35.hook日志
36.关闭hook日志 -->
40.转发消息
44.退出登录
45.确认收款
<!-- 45.确认收款 -->
46.联系人列表
47.获取群详情
<!-- 47.获取群详情 -->
48.获取解密图片
49.图片提取文字ocr
<!-- 49.图片提取文字ocr -->
50.拍一拍
51.群消息置顶消息
52.群消息取消置顶
<!-- 51.群消息置顶消息
52.群消息取消置顶 -->
53.朋友圈首页
54.朋友圈下一页
55.获取联系人或者群名称
56.获取消息附件(图片,视频,文件)
<!-- 55.获取联系人或者群名称 -->
56.获取消息附件(图片,视频,文件)
### 接口文档:
@@ -210,6 +107,7 @@ vcpkg
|province|string|省|
|wxid|string|wxid|
|signature|string|个人签名|
|dbKey|string|数据库的SQLCipher的加密key,可以使用该key配合decrypt.py解密数据库
###### 接口示例
入参:
@@ -217,7 +115,7 @@ vcpkg
```
响应:
``` javascript
{"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"}
{"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","dbKey":"aaa2222"},"result":"OK"}
```
@@ -515,7 +413,77 @@ vcpkg
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 13.hook语音**
###### 接口功能
> hook语音
###### 接口地址
> [/api/?type=13](/api/?type=13)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|voiceDir |true |string| 语音保存的目录 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
{
"voiceDir":"C:\\other"
}
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 14.取消hook语音**
###### 接口功能
> 取消hook语音
###### 接口地址
> [/api/?type=14](/api/?type=14)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, 0失败|
|result|string|成功提示|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{"code":1,"result":"OK"}
```
#### 17.删除好友**
###### 接口功能
+27
View File
@@ -25,6 +25,7 @@
#include "search_contact.h"
#include "download.h"
#include "hook_log.h"
#include "hook_voice.h"
#pragma comment(lib, "ws2_32.lib")
using namespace std;
@@ -227,6 +228,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
{"signature",self_info.signature},
{"dataSavePath",self_info.data_save_path},
{"currentDataPath",self_info.current_data_path},
{"dbKey",self_info.db_key},
};
ret_data["data"] = j_info;
}
@@ -242,6 +244,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_MSG_SEND_AT: {
break;
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);
@@ -297,6 +300,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_MSG_START_IMAGE_HOOK: {
break;
wstring img_dir = get_http_req_param(hm, j_param, "imgDir", is_post);
int success = HookImg(img_dir);
json ret_data = {{"code", success}, {"result", "OK"}};
@@ -304,15 +308,23 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_MSG_STOP_IMAGE_HOOK: {
break;
int success = UnHookImg();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_START_VOICE_HOOK: {
wstring voice_dir = get_http_req_param(hm, j_param, "voiceDir", is_post);
int success = HookVoice(voice_dir);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_STOP_VOICE_HOOK: {
int success = UnHookVoice();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_GET_LIST: {
@@ -323,6 +335,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CONTACT_DEL: {
break;
wstring user_id = get_http_req_param(hm, j_param, "wxid", is_post);
int success = DelContact(WS2LW(user_id));
json ret_data = {{"code", success}, {"result", "OK"}};
@@ -333,6 +346,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CONTACT_SEARCH_BY_NET: {
break;
wstring keyword = get_http_req_param(hm, j_param, "keyword", is_post);
UserInfo *user = nullptr;
int success = SearchContactNetScene(WS2LW(keyword), &user);
@@ -356,6 +370,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CONTACT_ADD_BY_WXID: {
break;
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"}};
@@ -391,6 +406,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_GET_MEMBER_NICKNAME: {
break;
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);
@@ -400,6 +416,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_DEL_MEMBER: {
break;
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
vector<wstring> wxids = get_http_param_array(hm, j_param, "memberIds", is_post);
vector<wchar_t *> wxid_list;
@@ -412,6 +429,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_ADD_MEMBER: {
break;
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
vector<wstring> wxids = get_http_param_array(hm, j_param, "memberIds", is_post);
vector<wchar_t *> wxid_list;
@@ -430,6 +448,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CHATROOM_SET_SELF_NICKNAME: {
break;
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);
@@ -487,12 +506,14 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_LOG_START_HOOK: {
break;
int success = HookLog();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_LOG_STOP_HOOK: {
break;
int success = UnHookLog();
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
@@ -528,6 +549,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_GET_TRANSFER: {
break;
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);
@@ -574,6 +596,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_GET_CHATROOM_INFO: {
break;
wstring room_id = get_http_req_param(hm, j_param, "chatRoomId", is_post);
ChatRoomInfoInner chat_room_detail{0};
int success = GetChatRoomDetailInfo(WS2LW(room_id), chat_room_detail);
@@ -609,6 +632,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_DO_OCR:{
break;
wstring image_path = get_http_req_param(hm, j_param, "imagePath", is_post);
string text("");
int success = DoOCRTask(WS2LW(image_path),text);
@@ -625,6 +649,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_SET_TOP_MSG:{
break;
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);
@@ -633,6 +658,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_REMOVE_TOP_MSG:{
break;
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);
@@ -654,6 +680,7 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
break;
}
case WECHAT_CONTACT_NAME:{
break;
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))}};
+4 -4
View File
@@ -7,16 +7,16 @@
#include "base64.h"
using namespace std;
#define WX_CHAT_ROOM_MGR_OFFSET 0x72cf60
#define WX_CHAT_ROOM_MGR_OFFSET 0x78cf20
#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_GET_MEMBER_FROM_CHAT_ROOM_OFFSET 0xbdf260
#define WX_INIT_CHAT_ROOM_OFFSET 0xe97890
#define WX_FREE_CHAT_ROOM_OFFSET 0xe97ab0
#define WX_MOD_CHAT_ROOM_MEMBER_NICK_NAME_OFFSET 0xb6adf0
#define WX_NEW_CHAT_MSG_OFFSET 0x70e2a0
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
+46 -1
View File
@@ -142,4 +142,49 @@ void CloseConsole(){
fclose(stdout);
fclose(stderr);
FreeConsole();
}
}
std::string EncodeHexString(const std::string &str) {
const std::string hex_table = "0123456789abcdef";
string sb;
for (int i = 0; i < str.length(); i++) {
sb += hex_table.at((str[i] & 0xf0) >> 4);
sb += hex_table.at((str[i] & 0x0f) >> 0);
}
return sb;
}
std::string Hex2String(const std::string &hex_str) {
std::string ret;
const std::string hex_table = "0123456789abcdef";
for (int i = 0; i < hex_str.length(); i += 2) {
ret += BYTE(hex_table.find(hex_str.at(i)) << 4 |
hex_table.find(hex_str.at(i + 1)));
}
return ret;
}
std::string Bytes2Hex(const BYTE *bytes, const int length) {
if (bytes == NULL) {
return "";
}
std::string buff;
const int len = length;
for (int j = 0; j < len; j++) {
int high = bytes[j] / 16, low = bytes[j] % 16;
buff += (high < 10) ? ('0' + high) : ('a' + high - 10);
buff += (low < 10) ? ('0' + low) : ('a' + low - 10);
}
return buff;
}
void Hex2Bytes(const std::string &hex, BYTE *bytes) {
int byte_len = hex.length() / 2;
std::string str;
unsigned int n;
for (int i = 0; i < byte_len; i++) {
str = hex.substr(i * 2, 2);
sscanf_s(str.c_str(), "%x", &n);
bytes[i] = n;
}
}
+8
View File
@@ -55,6 +55,14 @@ BOOL FindOrCreateDirectoryW(const wchar_t *path);
void CloseConsole();
std::string EncodeHexString(const std::string &str);
std::string Hex2String(const std::string &hex_str);
std::string Bytes2Hex(const BYTE *bytes, const int length);
void Hex2Bytes(const std::string &hex, BYTE *bytes);
template <typename T1, typename T2>
std::vector<T1> split(T1 str, T2 letter) {
vector<T1> arr;
+2 -2
View File
@@ -4,8 +4,8 @@
#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_MGR_INSTANCE_OFFSET 0x75a4a0
#define WX_CONTACT_GET_LIST_OFFSET 0xc089f0
#define WX_CONTACT_DEL_OFFSET 0xb9b3b0
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_SYNC_MGR_OFFSET 0xa87fd0
+16 -16
View File
@@ -6,20 +6,20 @@
#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
#define WX_NEW_CHAT_MSG_OFFSET 0x76f010
#define WX_GET_PRE_DOWNLOAD_MGR_OFFSET 0x80f110
#define WX_PUSH_ATTACH_TASK_OFFSET 0x82bb40
#define WX_FREE_CHAT_MSG_INSTANCE_COUNTER_OFFSET 0x756e30
#define WX_FREE_CHAT_MSG_OFFSET 0x756960
#define WX_CHAT_MGR_OFFSET 0x792700
#define WX_GET_MGR_BY_PREFIX_LOCAL_ID_OFFSET 0xbc0370
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc872c0
#define WX_APP_MSG_INFO_OFFSET 0x7b3d20
#define WX_GET_APP_MSG_XML_OFFSET 0xe628a0
#define WX_FREE_APP_MSG_INFO_OFFSET 0x79d900
#define WX_PUSH_THUMB_TASK_OFFSET 0x82ba40
#define WX_VIDEO_MGR_OFFSET 0x829820
#define WX_DOWNLOAD_VIDEO_IMG_OFFSET 0xd46c30
using namespace std;
@@ -31,7 +31,7 @@ int DoDownloadTask(ULONG64 msg_id) {
return -2;
}
char chat_msg[0x2C4] = {0};
char chat_msg[0x2D8] = {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;
@@ -143,7 +143,7 @@ int DoDownloadTask(ULONG64 msg_id) {
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));
memcpy(&chat_msg[0x29C], &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.
+4 -3
View File
@@ -4,8 +4,8 @@
#include "common.h"
#include "get_db_handle.h"
#include "wechat_data.h"
#define WX_FORWARD_MSG_OFFSET 0xc715f0
#define WX_INIT_CHAT_MSG_OFFSET 0xed3be0
#define WX_FORWARD_MSG_OFFSET 0xce6730
#define WX_INIT_CHAT_MSG_OFFSET 0xf59e40
int ForwardMsg(wchar_t *wxid, unsigned long long msgid) {
int success = 0;
@@ -29,7 +29,8 @@ int ForwardMsg(wchar_t *wxid, unsigned long long msgid) {
MOV ECX,ESP
LEA ESI,to_user
PUSH ESI
CALL init_chat_msg_addr
CALL init_chat_msg_addr
XOR ECX,ECX
CALL forward_msg_addr
MOVZX EAX,AL
MOV success,EAX
+6 -6
View File
@@ -5,7 +5,7 @@
#include "new_sqlite3.h"
#include "pch.h"
#include "wechat_data.h"
#define CONTACT_G_PINSTANCE_OFFSET 0x2e2d628
#define CONTACT_G_PINSTANCE_OFFSET 0x2ffddc8
#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 0x2e6ce20
#define MULTI_DB_MSG_MGR_OFFSET 0x2e6ec84
#define FAVORITE_STORAGE_MGR_OFFSET 0x2e6e630
#define FTS_FAVORITE_MGR_OFFSET 0x2e2e168
#define PUBLIC_MSG_MGR_OFFSET 0x303df74
#define MULTI_DB_MSG_MGR_OFFSET 0x30403b8
#define FAVORITE_STORAGE_MGR_OFFSET 0x303fd40
#define FTS_FAVORITE_MGR_OFFSET 0x2ffe908
using namespace std;
map<wstring, DatabaseInfo> dbmap;
@@ -227,7 +227,7 @@ std::vector<void *> GetDbHandles() {
}
// Favorite.db
DWORD favItems_ptr = *(DWORD *)(*(DWORD *)(favorite_storage_mgr_addr) + 0x8);
DWORD favItems_ptr = *(DWORD *)(*(DWORD *)(*(DWORD *)(favorite_storage_mgr_addr) + 0x8) + 0x4);
if (favItems_ptr) {
DWORD favorite_db_addr = *(DWORD *)(favItems_ptr + 0x38);
DatabaseInfo favorite_db{0};
+5 -5
View File
@@ -10,10 +10,10 @@
using namespace nlohmann;
using namespace std;
#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
#define WX_RECV_MSG_HOOK_OFFSET 0xd19a0b
#define WX_RECV_MSG_HOOK_NEXT_OFFSET 0x756960
#define WX_SNS_HOOK_OFFSET 0x14f9e15
#define WX_SNS_HOOK_NEXT_OFFSET 0x14fa0a0
// SyncMgr::addMsgListToDB
// #define WX_RECV_MSG_HOOK_OFFSET 0xB9C919
@@ -230,7 +230,7 @@ _declspec(naked) void handle_sync_msg() {
__asm {
PUSHAD
PUSHFD
PUSH ECX
PUSH ECX
CALL OnRecvMsg
ADD ESP, 0x4
POPFD
+88
View File
@@ -0,0 +1,88 @@
#include "pch.h"
#include "hook_voice.h"
#include "common.h"
using namespace std;
#define WX_HOOK_VOICE_OFFSET 0xd4d8d8
#define WX_HOOK_VOICE_NEXT_OFFSET 0x203d130
#define WX_SELF_ID_OFFSET 0x2FFD484
static wstring kVoiceStorePath = L"";
static int kVoiceHooked = FALSE;
static DWORD kWeChatWinBase = GetWeChatWinBase();
static char kOriginVoiceAsmCode[5] = {0};
static DWORD kHookVoiceNextAddress = kWeChatWinBase + WX_HOOK_VOICE_NEXT_OFFSET;
static DWORD kHookVoiceJmpBackAddress =
kWeChatWinBase + WX_HOOK_VOICE_OFFSET + 0x5;
void OnHookVoice(DWORD buff,int len , DWORD msg_addr) {
DWORD wxid_addr = GetWeChatWinBase() + WX_SELF_ID_OFFSET;
string wxid = string(*(char **)wxid_addr, *(DWORD *)(wxid_addr + 0x10));
wstring self_id = utf8_to_unicode(wxid.c_str());
wstring save_path = kVoiceStorePath + self_id;
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return;
}
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
save_path = save_path + L"\\" + to_wstring(msgid) + L".amr";
HANDLE file_handle = CreateFileW(save_path.c_str(), GENERIC_ALL, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle == INVALID_HANDLE_VALUE) {
return;
}
DWORD bytes_write = 0;
WriteFile(file_handle, (LPCVOID)buff, len, &bytes_write, 0);
CloseHandle(file_handle);
}
/// @brief hook voice implement
_declspec(naked) void handle_voice() {
__asm {
PUSHAD
PUSHFD
PUSH EDI
PUSH EDX
PUSH EAX
CALL OnHookVoice
ADD ESP, 0xC
POPFD
POPAD
CALL kHookVoiceNextAddress
JMP kHookVoiceJmpBackAddress
}
}
int HookVoice(std::wstring save_path) {
kWeChatWinBase = GetWeChatWinBase();
if (!kWeChatWinBase) {
return -1;
}
if (kVoiceHooked) {
return 2;
}
kVoiceStorePath = save_path;
if (kVoiceStorePath.back() != '\\') {
kVoiceStorePath += L"\\";
}
wstring createpath = kVoiceStorePath.substr(0, kVoiceStorePath.length() - 1);
if (!FindOrCreateDirectoryW(createpath.c_str())) {
return -2;
}
DWORD hook_voice_addr = kWeChatWinBase + WX_HOOK_VOICE_OFFSET;
kHookVoiceNextAddress = kWeChatWinBase + WX_HOOK_VOICE_NEXT_OFFSET;
static DWORD kHookVoiceJmpBackAddress = hook_voice_addr + 0x5;
HookAnyAddress(hook_voice_addr, (LPVOID)handle_voice, kOriginVoiceAsmCode);
kVoiceHooked = TRUE;
return 1;
}
int UnHookVoice() {
if (!kVoiceHooked) return 1;
DWORD hook_voice_addr = kWeChatWinBase + WX_HOOK_VOICE_OFFSET;
UnHookAnyAddress(hook_voice_addr, kOriginVoiceAsmCode);
kVoiceHooked = FALSE;
return 1;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef HOOK_VOICE_H_
#define HOOK_VOICE_H_
#include <string>
int HookVoice(std::wstring save_path);
int UnHookVoice();
#endif
+18 -18
View File
@@ -135,24 +135,24 @@
#define SQLITE_NULL 5
#define SQLITE_TEXT 3
#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
#define SQLITE3_EXEC_OFFSET 0x1e24f70
#define SQLITE3_BACKUP_INIT_OFFSET 0x1dea900
#define SQLITE3_PREPARE_OFFSET 0x1e2b8c0
#define SQLITE3_OPEN_OFFSET 0x1e598b0
#define SQLITE3_BACKUP_STEP_OFFSET 0x1dead00
#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1deb440
#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1deb450
#define SQLITE3_BACKUP_FINISH_OFFSET 0x1deb340
#define SQLITE3_SLEEP_OFFSET 0x1e5a0f0
#define SQLITE3_ERRCODE_OFFSET 0x1e58550
#define SQLITE3_CLOSE_OFFSET 0x1e56cd0
#define SQLITE3_STEP_OFFSET 0x1df3770
#define SQLITE3_COLUMN_COUNT_OFFSET 0x1df3c80
#define SQLITE3_COLUMN_NAME_OFFSET 0x1df4570
#define SQLITE3_COLUMN_TYPE_OFFSET 0x1df4410
#define SQLITE3_COLUMN_BLOB_OFFSET 0x1df3cc0
#define SQLITE3_COLUMN_BYTES_OFFSET 0x1df3da0
#define SQLITE3_FINALIZE_OFFSET 0x1df2740
typedef int (*Sqlite3_callback)(void*, int, char**, char**);
+3 -3
View File
@@ -4,9 +4,9 @@
#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
#define WX_PAT_MGR_OFFSET 0x931730
#define WX_SEND_PAT_MSG_OFFSET 0x1421940
#define WX_RET_OFFSET 0x1D58751
int SendPatMsg(wchar_t* chat_room_id, wchar_t* wxid) {
int success = -1;
+14 -17
View File
@@ -6,24 +6,12 @@
#include "wechat_data.h"
using namespace std;
#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_ACCOUNT_SERVICE_OFFSET 0x707960
#define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xeb4b00
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc11140
#define WX_LOGOUT_OFFSET 0xe58870
#define WX_ACCOUNT_SERVICE_OFFSET 0x768c80
#define WX_GET_APP_DATA_SAVE_PATH_OFFSET 0xf3a610
#define WX_GET_CURRENT_DATA_PATH_OFFSET 0xc872c0
int GetSelfInfo(SelfInfoInner &out) {
DWORD base = GetWeChatWinBase();
DWORD accout_service_addr = base + WX_ACCOUNT_SERVICE_OFFSET;
@@ -153,6 +141,15 @@ int GetSelfInfo(SelfInfoInner &out) {
*(DWORD *)(service_addr + 0x304 + 0x10));
}
}
if (*(DWORD *)(service_addr + 0x4CC) == 0 ||
*(DWORD *)(service_addr +0x4D0) == 0) {
out.db_key = string();
} else {
DWORD byte_addr = *(DWORD *)(service_addr + 0x4CC);
DWORD len = *(DWORD *)(service_addr +0x4D0);
out.db_key = Bytes2Hex((BYTE *)byte_addr,len);
}
}
WeChatString data_save_path;
+5 -5
View File
@@ -3,16 +3,16 @@
#include "common.h"
#include "wechat_data.h"
#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
#define WX_APP_MSG_MGR_OFFSET 0x76ae20
#define WX_SEND_FILE_OFFSET 0xb6d1f0
#define WX_INIT_CHAT_MSG_OFFSET 0xf59e40
#define WX_FREE_CHAT_MSG_OFFSET 0x756960
int SendFile(wchar_t *wxid, wchar_t *file_path){
int success = 0;
WeChatString to_user(wxid);
WeChatString path(file_path);
char chat_msg[0x2C4] = {0};
char chat_msg[0x2D8] = {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 -6
View File
@@ -3,17 +3,16 @@
#include "common.h"
#include "wechat_data.h"
#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
#define WX_SEND_IMAGE_OFFSET 0xce6640
#define WX_SEND_MESSAGE_MGR_OFFSET 0x768140
#define WX_INIT_CHAT_MSG_OFFSET 0xf59e40
#define WX_FREE_CHAT_MSG_OFFSET 0x756960
int SendImage(wchar_t *wxid, wchar_t *image_path){
int success = 0;
WeChatString to_user(wxid);
WeChatString path(image_path);
char chat_msg[0x2C4] ={0};
char chat_msg[0x2D8] ={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;
+5 -5
View File
@@ -6,11 +6,11 @@
#include "wechat_data.h"
#include "contact.h"
#define WX_SEND_TEXT_OFFSET 0xc71a60
#define WX_SEND_TEXT_OFFSET 0xce6c80
#define WX_SEND_MESSAGE_MGR_OFFSET 0x706d30
#define WX_SEND_MESSAGE_MGR_OFFSET 0x768140
#define WX_FREE_CHAT_MSG_OFFSET 0x6f4ea0
#define WX_FREE_CHAT_MSG_OFFSET 0x756960
using namespace std;
/// @brief 发生文本消息
/// @param wxid wxid
@@ -26,7 +26,7 @@ int SendText(wchar_t* wxid, wchar_t* msg) {
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};
char chat_msg[0x2D8] ={0};
__asm{
PUSHAD
CALL send_message_mgr_addr
@@ -59,7 +59,7 @@ int SendAtText(wchar_t* chat_room_id,wchar_t** wxids,int len,wchar_t* msg){
for (int i = 0; i < len; i++) {
wstring nickname;
if (!lstrcmpiW((wchar_t *)wxids[i], (wchar_t *)L"notify@all")) {
nickname = L"所有人";
nickname = L"������";
} else {
nickname = GetContactOrChatRoomNickname(wxids[i]);
}
+3 -3
View File
@@ -4,9 +4,9 @@
#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
#define WX_SNS_DATA_MGR_OFFSET 0xc39680
#define WX_SNS_GET_FIRST_PAGE_OFFSET 0x14e2140
#define WX_SNS_GET_NEXT_PAGE_OFFSET 0x14e21e0
int GetFirstPage() {
int success = -1;
+1
View File
@@ -153,6 +153,7 @@ struct SelfInfoInner{
std::string data_save_path;
std::string signature;
std::string current_data_path;
std::string db_key;
};
struct UserInfo {