ZLUDA 中的 Microsoft Detours(ext/detours):Windows API Hook 的原理、构建与工程化集成
ZLUDA 中的 Microsoft Detoursext/detoursWindows API Hook 的原理、构建与工程化集成【免费下载链接】ZLUDACUDA on non-NVIDIA GPUs项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA本篇围绕仓库中引入的ext/detours目录Microsoft Research Detours Package v4.0.1展开覆盖其定位、许可与兼容性边界、官方示例的构建方式并结合 ZLUDA 仓库中detours-sys、zluda_redirect等 crate 的源码说明这套 Hook 库是如何被编译进 Rust 生态并实际用于 Windows 进程注入与 DLL 重定向的。读完后你能理解 Detours 的核心 API 模型、在本仓库中的集成链路以及如何独立构建其示例与测试。一、Detours 是什么为什么 ZLUDA 要引入它根据 ext/detours/README.md 的描述Detours 是一个用于在 Windows 上监控和插桩instrumentingAPI 调用的软件包长期被众多 ISV 以及微软的产品团队使用。该 README 明确了几个关键事实Detours 当前以标准开源许可发布MIT简化了下游使用者的授权流程它兼容 Windows NT 家族的操作系统Windows NT、Windows XP、Windows Server 2003、Windows 7、Windows 8 与 Windows 10它不能用于 Windows Store 应用因为 Detours 依赖了这些应用无法访问的 API本仓库包含的是Detours 4.0.1版本的源码。对 ZLUDACUDA on non-NVIDIA GPUs而言Windows 侧的一个核心诉求是让原本调用 NVIDIA 驱动库cuDLL的进程改为加载 ZLUDA 的替代实现。这必须依赖进程级 API 拦截——拦截LoadLibrary*、CreateProcess*等系统调用并在其中改写行为。Detours 提供了在 x86/x64 代码流中安全重写指令前缀、建立跳板trampoline的能力是这类透明替换 DLL方案的基础设施。从仓库结构看Detours 源码整体 vendored 在 ext/detours 下包含src/核心实现、samples/官方示例集、tests/模块与映像 API 的 C 测试、vc/Visual Studio 工程文件以及 LICENSE.md、CREDITS.TXT。核心 C 实现入口在 ext/detours/src/detours.cpp对外接口声明集中在 ext/detours/src/detours.h。二、构建环境与官方示例从 samples/README.TXT 继承的完整操作路径ZLUDA 的 README 指向了 Detours 官方的 samples 文档对应本仓库中的 ext/detours/samples/README.TXT。其中的构建流程是完整可执行的实操路径这里完整保留并整理2.1 构建环境准备安装 Visual Studio IDE并确保安装了C/C 工具与Windows SDK将 Detours 源码放置到一个完整路径中不含空格的目录本仓库中即位于ext/detours。2.2 构建步骤打开 Developer Command Prompt for VS。注意有多种架构变体默认的命令提示符目标是 x86若要构建 x64 目标应选择 X64 Native Tools Command Prompt for VS切换到 samples 目录执行nmake构建全部示例注意setdll和syelog必须先构建成功许多其他示例依赖它们。2.3 测试步骤每个示例目录自带测试执行nmake test即可演示该示例的用法几乎所有可执行文件都支持/?参数打印用法说明在 samples 根目录执行nmake test可运行全部测试部分示例是架构相关的仅在其支持的架构上运行其他架构会被跳过。2.4 通过 vcpkg 安装外部使用场景官方 README 也给出了用 vcpkg 依赖管理器安装 detours 的路径git clone vcpkg 仓库地址 cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install vcpkg install detours2.5 trace* 示例的运行模式samples README 的最后一段解释了一个重要的运行特征trace*系列示例通过syelogd.exe守护进程记录日志并 hookCreateProcessW以把自身注入到所有子进程中。例如执行withdll -d:traceapi.dll cmd.exe会创建一个命令 shell其下所有进程都会通过traceapi.dll记录 API 调用。这正是 Detours 随进程树扩散能力的典型演示也是理解 ZLUDA 注入行为的参照系。三、核心 API 面事务模型、进程注入与二进制编辑从 ext/detours/src/detours.h 的声明约 L539–L823可以完整梳理 Detours 的 API 家族按功能分为四组3.1 Hook 事务TransactionLONG WINAPI DetourTransactionBegin(VOID); LONG WINAPI DetourTransactionAbort(VOID); LONG WINAPI DetourTransactionCommit(VOID); LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, _In_ PVOID pDetour); LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, _In_ PVOID pDetour); LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread);这是 Detours 的标志性设计所有 Hook 的挂接/卸载都发生在DetourTransactionBegin与DetourTransactionCommit之间的事务中DetourAttach将一个目标函数指针ppPointer替换为替换函数pDetourDetourUpdateThread则把 hook 应用到指定线程。事务化保证了多个 hook 要么全部生效、要么整体回滚避免进程停留在半改写状态。配套的开关如DetourSetIgnoreTooSmall、DetourSetRetainRegions、DetourSetSystemRegionLowerBound/UpperBound用于控制代码区改写策略。3.2 二进制编辑离线修改 PE 文件PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, ...); BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary);这一组 API 允许在不运行目标程序的情况下打开一个 PE 文件、编辑其导入表、嵌入/读取 GUID 负载payload后写回。这为预先改写二进制再运行的部署方式提供了底层能力。3.3 进程创建与动态注入BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, ...); BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, ...); BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, ...); BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, ...); BOOL WINAPI DetourRestoreAfterWith(VOID); BOOL WINAPI DetourIsHelperProcess(VOID);DetourCreateProcessWithDll(W)创建新进程的同时把指定 DLL 注入其中DetourUpdateProcessWithDll对已运行的进程注入 DLLDetourCopyPayloadToProcess向目标进程传送自定义二进制负载例如覆盖用的 DLL 字节配合 payload 机制使用DetourIsHelperProcess/DetourRestoreAfterWithDetours 内部借助helper 进程完成跨进程改写这两个 API 让注入的 DLL 能够识别自己是否处于 helper 上下文中并在恢复时正确清理。3.4 模块与代码工具函数DetourFindFunction、DetourGetContainingModule、DetourEnumerateModules、DetourGetEntryPoint、DetourGetModuleSize、DetourEnumerateImports(Ex)、DetourBinaryFindPayload(Ex)等用于在运行时枚举模块、定位导出函数与导入表是编写 hook 前搞清楚要 hook 什么的基础工具。四、ZLUDA 如何编译并使用这份 vendored 源码4.1 detours-sysRust 侧的 FFI 绑定与自动编译仓库中的 detours-sys/Cargo.toml 声明了一个links detours的 FFI 绑定 crate关键词包括hooking、injection其构建脚本 detours-sys/build.rs 展示了 vendored 源码的实际编译方式直接编译ext/detours/src下的 5 个核心 C 文件creatwth.cpp进程注入辅助、detours.cpp核心 hook 引擎、disasm.cpp指令反汇编用于跳板改写、image.cpp映像操作、modules.cpp模块枚举针对 MSVC 目标CARGO_CFG_TARGET_ENV msvc走原生 MSVC 编译路径否则回退到clang -fms-extensions以兼容 MinGW/Clang 环境并加-Wno-everything抑制告警编译产物通过try_compile(detours)自动链接进最终 crate。绑定头文件通过 bindgen 一次性生成并内嵌为 detours-sys/src/bundled_bindings.rsdetours-sys/src/lib.rs 第 7–9 行的注释保留了生成命令--whitelist-function Detour.*表明只导出Detour*系列符号。4.2 一个最小可运行的 Hook 测试detours-sys/src/lib.rs 自带一个hook_self测试它完整演示了 Detours 事务模型的正确姿势值得作为最小范例// 1) 保存原始 Sleep 函数指针 static mut TRUE_SLEEP: unsafe extern system fn(DWORD) Sleep; // 2) 替换函数调用前记录 GetTickCount()再调用原 Sleep记录实际耗时 unsafe extern system fn TimedSleep(dwMilliseconds: DWORD) { ... } // 3) 在 DllMain 的 DLL_PROCESS_ATTACH 中挂接 DetourRestoreAfterWith(); // 先清理可能残留的 helper 状态 DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread() as _); DetourAttach(tru, new); // 把 Sleep 替换为 TimedSleep DetourTransactionCommit(); // 4) DLL_PROCESS_DETACH 中对称地 DetourDetach 恢复测试随后调用Sleep(500)验证替换生效SLEPT ! 0恢复后再调用Sleep验证已还原slept SLEPT语义上的对比断言。这段测试同时印证了 Detours 的对称性纪律DetourRestoreAfterWith必须在挂接前调用且 attach/detach 需要镜像执行——这是使用 Detours 编写注入 DLL 时必须遵守的基本契约。4.3 zluda_redirectDetours 在 ZLUDA Windows 链路中的真实用途zluda_redirect/Cargo.toml 显示zluda_redirect是一个仅 Windows 可用、32 位的cdylib即会被加载进目标进程的 DLL依赖detours-sys与zluda_windows。其实现 zluda_redirect/src/lib.rs 从detours_sys中直接导入了一批符号use detours_sys::{ DetourAttach, DetourCopyPayloadToProcess, DetourDetach, DetourRestoreAfterWith, DetourTransactionAbort, DetourTransactionBegin, DetourTransactionCommit, DetourUpdateProcessWithDll, DetourUpdateThread, LPCWSTR, };结合其导入的 Windows API 列表CreateProcessA/W、CreateProcessAsUserA/W、CreateProcessWithLogonW、CreateProcessWithTokenW、LoadLibraryA/W、LoadLibraryExA/W见同文件 L29–L39 的use声明可以推断zluda_redirect的工作方式与 samples 中withdll/trace*的模式一致用 Detours 事务挂接进程内所有创建子进程与加载 DLL 的入口在加载路径命中 CUDA 相关库名时改写为 ZLUDA 提供的实现文件中的DetourPaths结构维护了按 GUID 编码的 DLL 路径覆盖表override_paths与zluda_windows::LIBRARIES一一对应并利用DetourUpdateProcessWithDllDetourCopyPayloadToProcess将重定向 DLL 传播到子进程。这与 zluda_windowsWindows 侧加载入口和detours-sys共同构成了 ZLUDA 在 Windows 上的透明替换驱动 DLL基础设施。五、许可与版本边界ext/detours目录下的代码遵循 MIT 许可见 ext/detours/LICENSE.md 与 README 的 License 小节仓库自身的detours-sys等 crate 采用 Apache-2.0 / MIT 双许可见 detours-sys/Cargo.toml 的license字段。版本事实以仓库为准vendored 的是4.0.1兼容边界为 Windows NT 家族且明确排除 Windows Store 应用。若在非 MSVC 工具链上构建detours-sysbuild.rs会强制要求 Clang 并启用 MS 扩展语法-fms-extensions这一点在跨工具链移植时需要提前准备。六、小结ext/detours在 ZLUDA 仓库中并非孤立的历史代码而是一条可验证的完整集成链vendored 的 Detours 4.0.1 源码 →detours-sys的 build.rs 自动编译五个核心 cpp 文件并导出Detour*FFI 符号 →zluda_redirect以 cdylib 形式利用事务化DetourAttach挂接进程创建与 DLL 加载 API把 CUDA 库调用透明重定向到 ZLUDA。构建官方示例时以 ext/detours/samples/README.TXT 中的 nmake 流程为准理解注入与 payload 机制时可参照 samples 中的withdll、traceapi以及 detours-sys/src/lib.rs 的hook_self测试。【免费下载链接】ZLUDACUDA on non-NVIDIA GPUs项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考