在 C++ 中使用 HOOK 技术修改 sleep 函数(通常指 Windows API 的 Sleep 函数或 Unix/Linux 的 sleep/usleep)是一种常见的底层编程技术,主要用于拦截和修改函数的行为。下面我将分别介绍在 Windows 和 Linux 环境下的实现方法。
![图片[1]_在C++中使用HOOK修改sleep函数的方法_知途无界](https://zhituwujie.com/wp-content/uploads/2025/12/d2b5ca33bd20251215091852.png)
🪟 Windows 环境(Hook Sleep API)
方法 1:使用 Detours(微软官方推荐库)
Detours 是微软研究院开发的 DLL 注入和 API Hook 库。
步骤:
- 下载并配置 Detours
从 GitHub 获取:https://github.com/microsoft/Detours - 编写 Hook 代码
// hook_sleep.cpp
#include <windows.h>
#include <detours.h>
#include <iostream>
// 原始 Sleep 函数指针
static VOID(WINAPI* OriginalSleep)(DWORD dwMilliseconds) = Sleep;
// Hook 后的 Sleep 函数
VOID WINAPI HookedSleep(DWORD dwMilliseconds) {
std::cout << "Sleep called with: " << dwMilliseconds << " ms" << std::endl;
// 修改睡眠时间:例如减半
DWORD newTime = dwMilliseconds / 2;
if (newTime == 0 && dwMilliseconds != 0)
newTime = 1;
// 调用原始函数
OriginalSleep(newTime);
}
// 安装 Hook
void InstallHook() {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OriginalSleep, HookedSleep);
DetourTransactionCommit();
}
// 卸载 Hook
void UninstallHook() {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OriginalSleep, HookedSleep);
DetourTransactionCommit();
}
// DLL 入口点(如果是 DLL 注入方式)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
InstallHook();
break;
case DLL_PROCESS_DETACH:
UninstallHook();
break;
}
return TRUE;
}
- 编译并注入目标进程
使用 Detours 提供的withdll.exe或手动注入 DLL。
方法 2:Inline Hook(直接修改机器码)
适用于无第三方库的场景,但更复杂。
#include <windows.h>
#include <iostream>
typedef void(WINAPI* SleepFunc)(DWORD);
SleepFunc originalSleep = &Sleep;
__declspec(naked) void HookedSleep(DWORD ms) {
__asm {
push ebp
mov ebp, esp
pushad
}
// 这里可以修改 ms 参数
// 注意:参数在栈上 [ebp + 8]
__asm {
popad
jmp originalSleep // 跳回原始函数
}
}
void SetupInlineHook() {
DWORD oldProtect;
VirtualProtect((LPVOID)Sleep, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
// JMP rel32 指令覆盖前5字节
BYTE jmpCode[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
DWORD offset = (DWORD)((BYTE*)HookedSleep - (BYTE*)Sleep - 5);
memcpy(jmpCode + 1, &offset, 4);
memcpy((LPVOID)Sleep, jmpCode, 5);
VirtualProtect((LPVOID)Sleep, 5, oldProtect, &oldProtect);
}
⚠️ 注意:Inline Hook 可能被反病毒软件检测,且需处理不同编译器/架构的差异。
🐧 Linux 环境(Hook sleep/sleep_us)
Linux 下可使用 LD_PRELOAD 劫持共享库函数。
示例:劫持 sleep() 函数
// hook_sleep.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
// 原始 sleep 函数指针
static unsigned int (*original_sleep)(unsigned int seconds) = NULL;
unsigned int sleep(unsigned int seconds) {
if (!original_sleep)
original_sleep = dlsym(RTLD_NEXT, "sleep");
printf("Hooked sleep: %u seconds\n", seconds);
// 修改睡眠时间,例如减半
unsigned int new_seconds = seconds / 2;
if (new_seconds == 0 && seconds != 0)
new_seconds = 1;
return original_sleep(new_seconds);
}
编译与使用
gcc -shared -fPIC -o hook_sleep.so hook_sleep.c -ldl
运行目标程序时预加载该库:
LD_PRELOAD=./hook_sleep.so ./your_program
劫持 usleep() 或 nanosleep()
类似地,可以劫持更精确的时间函数:
// hook_usleep.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
static int (*original_usleep)(useconds_t usec) = NULL;
int usleep(useconds_t usec) {
if (!original_usleep)
original_usleep = dlsym(RTLD_NEXT, "usleep");
printf("Hooked usleep: %d us\n", usec);
useconds_t new_usec = usec / 2;
if (new_usec == 0 && usec != 0)
new_usec = 1;
return original_usleep(new_usec);
}
编译方式相同。
⚠️ 注意事项
- 权限问题:Hook 通常需要管理员/root 权限。
- 稳定性:错误的 Hook 可能导致程序崩溃或死锁。
- 兼容性:不同系统版本、编译器可能影响 Hook 效果。
- 法律与道德:仅在授权环境下使用,勿用于恶意目的。
- 线程安全:确保 Hook 函数是线程安全的。
✅ 总结
| 平台 | 方法 | 优点 | 缺点 |
|---|---|---|---|
| Windows | Detours | 稳定、易用 | 需第三方库 |
| Windows | Inline Hook | 无需库、灵活 | 复杂、易被检测 |
| Linux | LD_PRELOAD | 简单、无需修改目标程序 | 仅适用于动态链接库函数 |
| 通用 | 源码替换 | 最可靠 | 需有源码控制权 |
如果你只是想在自己的程序中修改 sleep 行为,更简单的方法是封装自己的 MySleep 函数,而不是全局 Hook。但如果是调试或监控外部程序,上述 HOOK 技术则非常有用。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容