From 19d146db9943ebe0c985a23e00f19af0fe9b23e9 Mon Sep 17 00:00:00 2001 From: hugy <504650082@qq.com> Date: Tue, 21 Mar 2023 12:32:17 +0800 Subject: [PATCH] =?UTF-8?q?hook=E8=AF=AD=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 180 +++++++++++++++++++--------------------------- src/api.cc | 8 +++ src/hook_voice.cc | 88 +++++++++++++++++++++++ src/hook_voice.h | 8 +++ 4 files changed, 177 insertions(+), 107 deletions(-) create mode 100644 src/hook_voice.cc create mode 100644 src/hook_voice.h diff --git a/README.md b/README.md index 4f6e2e6..484e7c7 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,3 @@ -# 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添加好友和查找微信。 #### 功能预览: 0.检查是否登录 @@ -114,7 +8,9 @@ vcpkg 9.hook消息 10.取消hook消息 11.hook图片 -12.取消hook图片 +12.取消hook图片 +13.hook语音 +14.取消hook语音 17.删除好友 19.通过手机或qq查找微信 20.通过wxid添加好友 @@ -515,7 +411,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.删除好友** ###### 接口功能 diff --git a/src/api.cc b/src/api.cc index db5fe42..e66e0e3 100644 --- a/src/api.cc +++ b/src/api.cc @@ -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; @@ -310,9 +311,16 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) { 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: { diff --git a/src/hook_voice.cc b/src/hook_voice.cc new file mode 100644 index 0000000..e8b8d00 --- /dev/null +++ b/src/hook_voice.cc @@ -0,0 +1,88 @@ +#include "pch.h" +#include "hook_voice.h" + +#include "common.h" + +using namespace std; + +#define WX_HOOK_VOICE_OFFSET 0xccd561 +#define WX_HOOK_VOICE_NEXT_OFFSET 0x1f74560 +#define WX_SELF_ID_OFFSET 0x2E2CD3C + +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; +} diff --git a/src/hook_voice.h b/src/hook_voice.h new file mode 100644 index 0000000..429221a --- /dev/null +++ b/src/hook_voice.h @@ -0,0 +1,8 @@ +#ifndef HOOK_VOICE_H_ +#define HOOK_VOICE_H_ +#include + +int HookVoice(std::wstring save_path); + +int UnHookVoice(); +#endif \ No newline at end of file