>_ DevTrendszh

语言

首页

语言

板块

前端 后端 移动端 DevOps AI / ML 游戏开发 区块链 嵌入式 安全
Rust

Windhawk 的工作原理以及为何 Windows 定制再次变得便捷

任何尝试按照自己的偏好定制 Windows 的人都不可避免地会遇到系统限制。Windows 11 移除了熟悉的任务栏功能,资源管理器会定期改变其行为,而第三方程序中需要的小功能无法通过内置工具进行配置。以前,每个这样的修复都需要搜索单独的小工具、修补系统库或从论坛下载可疑的二进制文件。

Windhawk 项目从不同的角度处理这个任务。它的理念类似于浏览器的 Tampermonkey 或智能手机的 Magisk,但运行在经典 Windows 应用程序的环境中。

Screenshot

什么是 Windhawk

Windhawk 由开发者 m417z 创建,他在系统工具社区中因 7+ Taskbar Tweaker 项目而闻名。与旧的独立式小工具不同,作者在这里构建了一个开放平台。

其本质很简单:有一个统一的代码注入引擎和一个小型 mods 目录。每个 mod 解决一个特定问题——恢复经典任务栏、在托盘区域添加鼠标滚轮音量调节,或移除资源管理器中不必要的按钮。

用户看到一个简洁的图形界面,只需单击一下即可启用所需的修复。对于开发者,Windhawk 在程序内部打开了一个功能完整的 C++ 钩子创建环境,内置代码编辑器和即时编译功能。

架构和技术细节

在 Windows 中修改程序时,主要挑战是确保代码及时注入、稳定运行,并且不会破坏相邻进程。

High level architecture diagram

在仓库中,源代码分为三个主要组件:

  • windhawk — 系统服务 windhawk.exe,以及负责全局注入和函数拦截的 32 位和 64 位 windhawk.dll 库;
  • vscode-windhawk — 管理 mod 安装、更新和配置的后端界面;
  • vscode-windhawk-ui — 基于 Web 技术和 Monaco 编辑器的前端,用于配置 mod 参数和编写代码。

该引擎使用全局拦截和 DLL 注入到目标进程。当被修改规则覆盖的程序启动时,Windhawk 会注入其库。这个库拦截 Win32 API 调用或应用程序内部的未公开函数,用 mod 中描述的行为替换它们。

这种方法保护操作系统免受损坏。磁盘上的文件不会被修改,系统库保持不变,sfc /scannow 完整性检查也不会报告错误。如果某个 mod 在 Windows 更新后开始失效,你可以在界面中简单地禁用它,或者以安全模式启动系统。

如何编写 Mods

编写修改不需要设置包含所有系统 SDK 的重型 Visual Studio。Windhawk 在后台下载必要的编译器工具链。

mod 的源代码是一个带有特殊元数据注释的 C++ 文件,类似于浏览器用户脚本:

// ==WindhawkMod==
// @id              custom-window-title
// @name            Custom Window Title
// @description     Изменяет заголовок окна блокнота
// @version         1.0
// @include         notepad.exe
// ==/WindhawkMod==

#include <windhawk_api.h>

typedef HWND (WINAPI *CreateWindowExW_t)(
    DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName,
    DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
    HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam
);

CreateWindowExW_t pOriginalCreateWindowExW;

HWND WINAPI Hook_CreateWindowExW(
    DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName,
    DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
    HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam
) {
    if (lpWindowName && wcscmp(lpWindowName, L"Untitled - Notepad") == 0) {
        lpWindowName = L"Мой кастомный блокнот";
    }
    return pOriginalCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}

BOOL Wh_ModInit() {
    Wh_Log(L"Инициализация мода");
    
    HMODULE hUser32 = GetModuleHandle(L"user32.dll");
    void* pCreateWindowExW = (void*)GetProcAddress(hUser32, "CreateWindowExW");
    
    Wh_SetFunctionHook(pCreateWindowExW, (void*)Hook_CreateWindowExW, (void**)&pOriginalCreateWindowExW);
    return TRUE;
}

mod 在应用程序中直接编译。引擎监控文件变化并在目标进程中重新加载动态库,无需重启操作系统。

实际好处

该工具解决了几个以前需要变通方法的场景。

首先,资源管理器和任务栏界面的微调。有各种 mod 可用于更改任务栏高度、隐藏不必要的上下文菜单项、用鼠标滚轮切换标签页以及自定义托盘区域。

其次,修复第三方软件的烦人行为。如果一个程序缺少热键或其窗口默认不最小化到托盘,你可以为 user32.dllwin32u.dll 编写一个钩子并重新定义窗口消息处理。

第三,它是逆向工程的优秀基础。如果你正在研究 Windows 应用程序的内部机制,Windhawk 简化了函数拦截、参数记录和假设测试的实验。

细节和限制

在使用全局注入时,考虑安全软件的特性很重要。杀毒软件有时会对系统进程中的函数拦截产生反应,尽管项目的可执行文件有有效的数字签名。

为未公开的资源管理器接口编写复杂的 mod 仍然需要逆向工程技能以及理解 x64dbg 或 IDA Pro 等调试器的使用。Windows 接口经常在不同版本之间变化,因此作者必须为不同的库版本维护函数签名。

值得一试吗

Windhawk 将碎片化的 Windows 调整世界转变为一个结构化和透明的环境。该项目使用 C++ 和 Rust 编写,基于 GPL-3.0 许可证分发,并拥有活跃的开发者社区。

如果你怀念 Windows 11 中熟悉的功能,这个项目值得至少为了现成的 mod 目录而安装它。对于对底层 Win32 API 感兴趣的 C++ 开发者,仓库源代码将展示许多关于库注入和钩子的实用技术。

相关项目