- 逆向工程
- 即时通讯
【免费下载链接】wxhelper
Hook WeChat / 微信逆向
导读
本文围绕 wxhelper 仓库中 注入器文档 展开,讲解如何在 Windows 环境下使用命令行注入工具,将wxhelper.dll注入 PC 端微信进程,从而拉起内置 HTTP 服务并开始调用各类 Hook 接口。读完本文,你将掌握注入器的全部命令行参数(注入 / 卸载 / 多开 / 指定端口 / 按 PID 注入)、底层注入原理(LoadLibraryW+CreateRemoteThread远程线程注入)、HTTP 服务端口的配置方式,以及如何基于 源码 自行编译该注入工具。
说明:wxhelper 是 PC 端微信逆向学习项目,仓库 README 明确声明「本仓库发布的内容,仅用于学习研究,请勿用于非法用途和商业用途」,逆向与注入操作可能造成封号等后果,请自行评估风险。文中所有行为均限定在受控实验环境内进行。
一、注入器在 wxhelper 项目中的定位
wxhelper 的整体工作流程(参见 README.md)可以概括为:
- 逆向分析 PC 端微信客户端,定位关键 Call,编写 DLL 调用这些关键 Call;
- 通过注入工具将
wxhelper.dll注入WeChat.exe进程; - DLL 注入成功后创建一个默认端口为 19088 的 HTTP 服务端;
- 客户端通过 HTTP 协议调用全部功能接口(发消息、收消息、加好友、群管理、数据库查询等)。
因此,命令行注入器是连接「DLL 本体」与「微信进程」的关键前置工具。仓库中与注入器相关的资源集中在两个位置:
| 资源 | 路径 | 说明 |
|---|---|---|
| 注入器使用文档 | tool/injector/readme.md | 编译好的 x64 注入器ConsoleApplication.exe及注入/卸载命令 |
| 注入器编译产物 | tool/injector/ | ConsoleApplication.exe、injector.dll、图形界面注入器微信DLL注入器V1.0.3.exe |
| 注入器源码 | source/injector.cc | 命令行远程注入完整实现(1170 行) |
| 注入器构建脚本 | source/CMakeLists.txt | CMake 工程,输出可执行文件injector |
| 命令参数解析依赖 | source/getopt.h | 随源码附带的 getopt 实现(源自 mingw-w64 runtime) |
| DLL 入口 | src/dllMain.cc | wxhelper.dll的DllMain,注入后初始化全局上下文 |
注入器文档与仓库主线的关系是:文档给出了现成二进制与最常用的注入/卸载命令,源码则揭示了完整参数集与底层注入实现,两者结合即可无死角地掌握这套工具。
二、两种使用方式:现成二进制与源码自行编译
文档原文指出:「可以使用对应分支下的注入工具,或者自己编译一下 source 目录下的注入程序。」这对应两种路径:
方式一:直接使用编译好的注入器
tool/injector/目录下的ConsoleApplication.exe是编译好的 x64 版本命令行注入器。直接将其与wxhelper.dll放在方便访问的目录即可使用,无需任何编译环境。
目录中还提供了图形界面注入器微信DLL注入器V1.0.3.exe(文档未展开说明其用法,属于另一套交互式工具),以及injector.dll。
方式二:从源码自行编译
source/目录下是注入器的完整源码工程,核心文件为 source/injector.cc,构建脚本为 source/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0.0) project(injector VERSION 1.0.0) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D '_UNICODE' /D 'UNICODE'") file(GLOB INJECT_CPP_FILES ${PROJECT_SOURCE_DIR}/*.cc ${PROJECT_SOURCE_DIR}/*.cpp) add_executable (injector ${INJECT_CPP_FILES}) SET_TARGET_PROPERTIES(injector PROPERTIES LINKER_LANGUAGE C ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin OUTPUT_NAME "injector" PREFIX "")编译要点:
- 工程名为
injector,输出可执行文件名被固定为injector(OUTPUT_NAME "injector"),产物位于build/bin/下。README 中的命令行示例沿用旧名ConsoleInject.exe,实际二进制名称以你手头文件为准。 - 定义了
_UNICODE/UNICODE宏,源码内部大量使用宽字符 API(如wcslen、CreateToolhelp32Snapshot的 Wide 版本)。 - 参数解析依赖随源码附带的 source/getopt.h(BSD 许可的 getopt 实现),无需外部库。
- 仓库主项目使用 Visual Studio 2022 + CMake + vcpkg 构建(详见 README.md 编译章节),注入器源码同样适用于该工具链。源码中的
ntstatus.h头文件需保证在编译环境中可被找到。
三、命令行参数全解(注入 / 卸载 / 多开 / 指定端口 / 按 PID 注入)
3.1 文档给出的基础命令
注入器文档 原文给出了注入与卸载两条命令:
//-i 注入程序名 -p 注入dll路径 // -u 卸载程序名 -d 卸载dll名称 //注入 ConsoleInject.exe -i demo.exe -p E:\wxhelper.dll //卸载 ConsoleInject.exe -u demo.exe -d wxhelper.dll- 注入:
-i指定目标进程的可执行文件名(如微信的WeChat.exe),-p指定待注入 DLL 的完整路径(如E:\wxhelper.dll)。工具会按进程名查找到对应 PID,再把 DLL 注入进去。 - 卸载:
-u指定进程名,-d指定要卸载的 DLL 名称(只需文件名,如wxhelper.dll)。工具会从目标进程中定位该模块的基址并执行远程卸载。
3.2 源码揭示的完整参数集
从 source/injector.cc 的参数解析循环可以看到,注入器实际支持的参数远比文档示例更丰富:
while ((param = getopt(argc, argv, "i:p:u:d:m:P:I:h")) != -1)对照main函数中的-h帮助输出与各case分支,完整参数表如下:
| 参数 | 含义 | 示例 | 源码依据 |
|---|---|---|---|
-i <program name> | 目标进程名(注入) | -i WeChat.exe | injector.cc |
-u <program name> | 目标进程名(卸载) | -u WeChat.exe | injector.cc |
-p <path> | 待注入 DLL 的完整路径 | -p E:\wxhelper.dll | injector.cc |
-d <file> | 待卸载 DLL 的文件名 | -d wxhelper.dll | injector.cc |
-m <pid> | 关闭微信互斥体(用于多开),参数为目标 PID | -m 1222 | injector.cc |
-P <port> | 指定注入后 HTTP 服务的端口(需配合支持端口参数的 DLL) | -P 18888 | injector.cc |
-I <pid> | 按 PID 注入,不依赖进程名查找 | -I 15048 | injector.cc |
-h | 打印帮助信息并退出 | -h | injector.cc |
README 中还给出了对应的组合用法:
//注入 ConsoleInject.exe -i demo.exe -p E:\testInject.dll //卸载 ConsoleInject.exe -u demo.exe -d testInject.dll //多开:关闭微信互斥体 ConsoleInject.exe -m 1222 // 注入并指定http端口 ConsoleInject.exe -i demo.exe -p E:\testInject.dll -P 18888 // 注入指定pid并关闭多开限制 ConsoleInject.exe -I 15048 -p E:\testInject.dll -m 150483.3 参数组合与执行逻辑
从 source/injector.cc 的主流程可以看清各参数的组合关系:
-m <pid>(多开):只要给出了pid,就调用FindHandles(pid, "_WeChat_App_Instance_Identity_Mutex_Name", TRUE, TRUE)。该调用以后缀匹配方式(suffix = TRUE)枚举目标进程全部句柄,找到微信的单实例互斥体_WeChat_App_Instance_Identity_Mutex_Name后将其关闭(closeHandle = TRUE,走DUPLICATE_CLOSE_SOURCE复制关闭路径),从而解除「微信只能开一个实例」的限制。-m与注入可同时使用(如-I 15048 -p ... -m 15048)。-I <pid>+-p <path>(按 PID 注入):当injectPid != 0且 DLL 路径非空时执行。若未给-P,调用InjectDllByPid(纯注入,不启 HTTP);若给了-P <port>,调用InjectDllAndStartHttpByPid(pid, dllPath, port),注入后进一步拉起 HTTP 服务。-i <name>+-p <path>(按进程名注入):当进程名与 DLL 路径均非空时执行。无-P时调用InjectDll;有-P时调用InjectDllAndStartHttp(program, dllPath, port)。-u <name>+-d <file>(卸载):调用UnInjectDll(program, dllName),打印「卸载结果」。
每个注入/卸载分支执行后都会以printf输出结果码(注入结果:%i/卸载结果:%i,1 为成功,0 为失败)。
3.4 命令行参数的实际运行形态
对于 wxhelper 场景,典型操作是(假定WeChat.exe已在运行):
// 按进程名注入 wxhelper.dll(默认端口 19088) ConsoleInject.exe -i WeChat.exe -p E:\wxhelper.dll // 按进程名注入并显式指定 HTTP 端口 ConsoleInject.exe -i WeChat.exe -p E:\wxhelper.dll -P 18888 // 按 PID 注入并关闭单实例互斥体(多开场景) ConsoleInject.exe -I 15048 -p E:\wxhelper.dll -m 15048 // 验证注入效果后卸载 ConsoleInject.exe -u WeChat.exe -d wxhelper.dll注入成功后即可通过 Postman 或 postman.json 中的接口集合直接调用http://127.0.0.1:19088/...下的功能接口;仓库 python/client.py 也提供了简单测试脚本。
四、注入器的底层实现原理
4.1 核心注入路径:VirtualAllocEx + WriteProcessMemory + CreateRemoteThread
无论按进程名还是按 PID 注入,最终都收敛到同一套远程线程注入流程。以InjectDll(injector.cc)为例,其步骤为:
- 提权:调用
EnableDebugPrivilege()(injector.cc),通过OpenProcessToken+LookupPrivilegeValue(SE_DEBUG_NAME)+AdjustTokenPrivileges为当前进程开启SeDebugPrivilege,这是跨进程注入的基础前提(通常需要以管理员身份运行注入器)。 - 定位目标进程:
GetPIDForProcess(injector.cc)用CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)枚举进程快照,按szExeFile精确匹配进程名,返回 PID。 - 打开目标进程:
OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)。 - 远程分配内存:
VirtualAllocEx(hProcess, NULL, (wcslen(szDllPath)+1)*sizeof(wchar_t), MEM_COMMIT, PAGE_READWRITE),在目标进程地址空间中为 DLL 完整路径字符串(宽字符)申请内存。 - 写入路径字符串:
WriteProcessMemory将 DLL 路径写入目标进程。 - 拉起远程线程:取
kernel32.dll的LoadLibraryW地址,通过CreateRemoteThread(hProcess, NULL, 0, LoadLibraryW, lpRemoteDllBase, 0, NULL)在目标进程内执行LoadLibraryW(路径),实现 DLL 加载;随后WaitForSingleObject等待加载完成。 - 清理:
VirtualFreeEx释放远程内存并关闭句柄。成功时输出dll inject success并打印 DLL 路径与 PID。
InjectDllByPid(injector.cc)与上述流程完全一致,区别仅在于直接用传入的 PID 打开进程、跳过进程名查找,从而支持注入同名多进程(如多开后的微信)中的指定实例。
4.2 注入并拉起 HTTP 服务:InjectDllAndStartHttp
-P参数启用的是InjectDllAndStartHttp(injector.cc)这条增强路径。它在完成 4.1 的 DLL 加载后,还额外做了三件事:
- 写入 shellcode:
FillAsmCode(injector.cc)在目标进程内以VirtualAllocEx(..., PAGE_EXECUTE)分配可执行内存,写入一段手写 x86 机器码(GetProcAddressAsmCode,injector.cc)。该 shellcode 等价于GetProcAddress(GetModuleHandleW(param[0]), param[1]),用于在目标进程上下文中解析导出函数地址。 - 解析
http_start:在目标进程中分配参数块(dllName = L"wxhelper.dll"、funcName = "http_start"),CreateRemoteThread执行 shellcode,通过线程退出码(GetExitCodeThread)拿到wxhelper.dll导出的http_start函数地址。 - 启动 HTTP 服务:再次
CreateRemoteThread,入口为http_start,参数为-P指定的端口值。http_start内部会创建监听指定端口的 HTTP 服务端(对应 src/http_server.cc 的HttpServer实现)。
注:该 shellcode 路径使用 32 位 x86 指令编码;仓库 README 说明主项目多为 x86 构建、3.9.5.81 分支为 x64 环境,具体以对应分支的生成物为准。
4.3 卸载原理:FreeLibraryAndExitThread
UnInjectDll(injector.cc)走的是与注入对称的路径:
GetPIDForProcess按进程名定位 PID;GetDLLHandle(injector.cc)用CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dPid)枚举目标进程已加载模块,按模块名(如wxhelper.dll)找到hModule基址;- 取
kernel32.dll的FreeLibraryAndExitThread地址,CreateRemoteThread在目标进程中以该模块基址为参数执行远程卸载,WaitForSingleObject等待卸载线程结束。
4.4 句柄枚举与互斥体关闭(多开)
-m参数背后的FindHandles(injector.cc)是一个完整的系统级句柄枚举器:
- 动态加载
ntdll.dll的NtQuerySystemInformation、NtQueryObject、NtDuplicateObject; - 以
SystemExtendedHandleInformation信息类循环查询全部系统句柄(缓冲区从0x10000起倍增,处理STATUS_INFO_LENGTH_MISMATCH,上限0x4000000); - 按 PID 过滤,再对每个句柄执行
NtDuplicateObject复制到当前进程,用NtQueryObject获取对象名称与类型(宽字符转 ANSI 后输出); - 当句柄名称以目标串
_WeChat_App_Instance_Identity_Mutex_Name结尾时,通过DuplicateHandle(..., DUPLICATE_CLOSE_SOURCE)关闭该互斥体句柄,从而突破微信单实例限制。
五、注入后的端口配置:默认 19088 与 config.ini
注入器本身不带端口时,DLL 侧的端口由 src/config.cc 决定:
void Config::Initialize() { port_ = GetPrivateProfileInt("config", "Port", 19088, "./config.ini"); } int Config::GetPort() { return port_; }GetPrivateProfileInt的第三个参数是默认值19088:即只要不在微信目录(DLL 工作目录)下放置config.ini,HTTP 服务就监听默认的 19088 端口。如需自定义端口,按 README 的做法在微信目录创建配置文件:
[config] port=19099写入后 DLL 加载时会读取./config.ini的[config]/port项,将 HTTP 服务端口改为 19099。这与注入器-P参数的效果互补:-P在注入时直接向http_start传端口,而config.ini则在 DLL 内部初始化时生效。
服务启动后,客户端统一通过http://127.0.0.1:<port>/访问功能接口,接口清单见 doc/postman.json 与各版本接口文档(如 doc/3.9.5.81.md)。
六、常见问题与注意事项
综合 注入器文档、README.md 与源码行为,整理实操要点如下:
- 以管理员身份运行:注入依赖
SeDebugPrivilege(EnableDebugPrivilege位于 injector.cc),普通权限下OpenProcess(PROCESS_ALL_ACCESS)对受保护进程可能失败。 - 目标进程需已运行:按进程名注入时工具只做名称匹配,
WeChat.exe未启动或名字不匹配会返回 0;多开场景建议改用-I <pid>精确定位。 - 注入失败排查:README 明确提示「如果注入不成功,请先检查注入工具,或者使用其他注入工具」,也可换用图形界面的
微信DLL注入器V1.0.3.exe。 - Hook 接口需先开启:README 特别说明,hook 相关的接口必须先调用对应 hook 接口,服务端才会收到相应消息;部分接口在个别版本未实现,以版本功能预览为准。
- 版本匹配:
wxhelper.dll按微信版本区分(支持 3.8.0.41、3.8.1.26、3.9.0.28、3.9.2.23、3.9.2.26、3.9.5.81 等,DLL 前缀带版本号),注入器与 DLL 需与目标微信版本对应;README 说明相关功能主要在 win11 环境简单测试,其他环境无法保证。 - 端口冲突:若 19088 被占用,要么用
-P指定端口(需对应支持端口参数的 DLL),要么通过config.ini修改端口后重启注入。 - 环境要求:注入器为 Windows 平台工具(依赖
Windows.h、tlhelp32.h、ntdll.dll导出函数),仅在 Windows 系统上可运行。
七、小结
wxhelper 的命令行注入器虽然文档篇幅很短,但配套源码展示了完整的工程能力:-i/-u/-p/-d覆盖注入与卸载,-m通过系统级句柄枚举关闭微信单实例互斥体实现多开,-P/-I支持指定 HTTP 端口与按 PID 注入,底层则基于VirtualAllocEx + WriteProcessMemory + CreateRemoteThread的经典远程线程注入模型,并配合手写 shellcode 在目标进程内解析http_start导出函数。无论是直接使用tool/injector/下的现成二进制,还是按 source/CMakeLists.txt 自行编译,本文给出的参数表与源码调用链都能帮助你快速上手这套「注入 → 启 HTTP → 调接口」的完整链路。
- 逆向工程
- 即时通讯
【免费下载链接】wxhelper
Hook WeChat / 微信逆向
相关推荐
微信逆向实战指南:wxhelper高效配置与DLL注入技术详解
在当今数字化时代,微信作为国内最大的社交平台,其功能扩展和自动化操作需求日益增长。wxhelper项目作为一款专业的微信逆向工具,通过DLL注入技术实现了对微信
逆向工程即时通讯Click 参数详解:用 @click.option 与 @click.argument 为命令行命令注入输入
Click 参数详解:用 @click.option 与 @click.argument 为命令行命令注入输入 本篇技术指南深入讲解 Python CLI 框架
人工智能AI 应用AI AgentYimMenu项目DLL注入使用指南
YimMenu项目DLL注入使用指南 项目背景 YimMenu是一款针对GTA5游戏的修改工具,通过DLL注入技术实现游戏功能扩展。对于初次接触游戏修改的新手用
逆向工程游戏开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考