使用 EasyHook 骗过检测程序,系统像“休眠状态”并未真正休眠

【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】
要实现使用 EasyHook 骗过检测程序,使目标系统看起来像进入了“休眠状态”,实际上并未真正休眠,可以通过 Hook 特定的 API 来拦截与电源管理和休眠检测相关的函数调用,并伪造返回值。以下是一个完整的实现过程。
背景知识
EasyHook 是一个强大的库,可以用来安全地 Hook 用户态函数。在您的场景中,可以 Hook 与电源管理相关的 Windows API,例如:
SetSuspendState- 通常用于触发睡眠或休眠操作。
- 您可以通过拦截此函数返回一个伪造的成功值,但不实际进入休眠。
CallNtPowerInformation- 用于检索系统电源状态的信息,例如当前是否处于休眠。
- 拦截该函数可以让外部检测程序得到伪造的电源状态。
- 其他相关 API(如果有需要,可扩展):
GetSystemPowerStatusPowerSetRequest
实现步骤
下面以 Hook SetSuspendState 和 CallNtPowerInformation 为例,伪造系统进入休眠状态但不实际休眠。所有代码基于 EasyHook 实现。
1. 准备环境
- 使用 Visual Studio 开发,确保项目配置为
x86或x64,与目标系统架构相符。 - 下载并引用 EasyHook:
- 可以通过 NuGet 安装
EasyHook包:Install-Package EasyHook.
- 可以通过 NuGet 安装
2. 设计 Hook 逻辑
Step 1: Hook SetSuspendState
您需要拦截并伪造 SetSuspendState 的行为,让程序以为休眠成功。
Windows 的 SetSuspendState 函数定义如下:
BOOLEAN SetSuspendState(
BOOLEAN Hibernate,
BOOLEAN ForceCritical,
BOOLEAN DisableWakeEvent
);
- 拦截该函数并始终返回
TRUE,表示休眠成功。 - 同时阻止实际的休眠触发逻辑。
Step 2: Hook CallNtPowerInformation
这是另一个关键函数,可用于检查当前电源状态:
NTSTATUS CallNtPowerInformation(
POWER_INFORMATION_LEVEL InformationLevel,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
);
您可以 Hook 这个函数,欺骗检测程序返回“休眠中”状态。例如,通过伪造返回的 SYSTEM_POWER_INFORMATION 数据,假装系统已进入休眠。
3. 核心代码实现
以下是完整代码示例,包括 Hook SetSuspendState 和 CallNtPowerInformation:
#include <Windows.h>
#include <iostream>
#include <EasyHook.h>
// 原始函数指针
typedef BOOLEAN(WINAPI* SetSuspendState_t)(BOOLEAN, BOOLEAN, BOOLEAN);
typedef NTSTATUS(WINAPI* CallNtPowerInformation_t)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
// 用于保存原始函数地址
SetSuspendState_t OriginalSetSuspendState = nullptr;
CallNtPowerInformation_t OriginalCallNtPowerInformation = nullptr;
// Hook 的 SetSuspendState 函数
BOOLEAN WINAPI HookedSetSuspendState(BOOLEAN Hibernate, BOOLEAN ForceCritical, BOOLEAN DisableWakeEvent) {
std::cout << "SetSuspendState called. Pretending to enter hibernation..." << std::endl;
// 伪造返回值,假装休眠已经成功
return TRUE;
}
// Hook 的 CallNtPowerInformation 函数
NTSTATUS WINAPI HookedCallNtPowerInformation(
POWER_INFORMATION_LEVEL InformationLevel,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
) {
std::cout << "CallNtPowerInformation called with InformationLevel: " << InformationLevel << std::endl;
// 如果调用者查询的是系统电源状态
if (InformationLevel == SystemPowerInformation && OutputBuffer != nullptr && OutputBufferLength >= sizeof(SYSTEM_POWER_INFORMATION)) {
SYSTEM_POWER_INFORMATION* spi = (SYSTEM_POWER_INFORMATION*)OutputBuffer;
// 假装系统处于休眠状态
spi->MaxIdlenessAllowed = 100;
spi->Idleness = 100;
spi->TimeRemaining = 0;
spi->CoolingMode = 1;
return STATUS_SUCCESS;
}
// 对于其他操作,调用原始函数
return OriginalCallNtPowerInformation(InformationLevel, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength);
}
int main() {
// 初始化 Hook
if (LhInstallHook(
GetProcAddress(GetModuleHandle(L"powrprof.dll"), "SetSuspendState"),
HookedSetSuspendState,
NULL,
reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalSetSuspendState)) != STATUS_SUCCESS) {
std::cerr << "Failed to hook SetSuspendState." << std::endl;
return -1;
}
if (LhInstallHook(
GetProcAddress(GetModuleHandle(L"powrprof.dll"), "CallNtPowerInformation"),
HookedCallNtPowerInformation,
NULL,
reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalCallNtPowerInformation)) != STATUS_SUCCESS) {
std::cerr << "Failed to hook CallNtPowerInformation." << std::endl;
return -1;
}
// 开启 Hook 的线程
ULONG ACLEntries[1] = { 0 };
LhSetExclusiveACL(ACLEntries, 1, reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalSetSuspendState));
LhSetExclusiveACL(ACLEntries, 1, reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalCallNtPowerInformation));
std::cout << "Hooks installed. System will now fake hibernation state when queried." << std::endl;
// 持续运行
while (true) {
Sleep(5000);
}
return 0;
}
4. 代码解释
- Hook 的核心功能:
HookedSetSuspendState:伪造休眠事件,返回TRUE表示操作成功。HookedCallNtPowerInformation:伪造系统电源状态,让检测程序误以为系统处于休眠状态。
- 确保安全:
- EasyHook 使用
LhInstallHook安装 Hook,并使用LhSetExclusiveACL设置 Hook 规则,限制 Hook 的作用范围。
- EasyHook 使用
- 依赖的库:
- powrprof.dll(电源管理库):包含
SetSuspendState和CallNtPowerInformation。
- powrprof.dll(电源管理库):包含
- 部署:
- 编译程序并在目标系统上运行,程序会实时拦截和伪造相关 API 调用。
5. 扩展优化
- 如果需要针对特定的检测程序(例如某个软件)修改伪造逻辑,可以通过动态分析确定它查询了哪些 API,然后扩展 Hook 逻辑。
- 使用调试工具(如 OllyDbg 或 WinDbg)观察电源检测软件的行为,确定更多需要拦截的函数。
总结
通过 EasyHook,可以非常灵活地 Hook 电源管理相关的 API,伪造函数的返回值来实现伪装效果。不过需要注意,此类操作虽然技术上可行,但可能触及法律和道德边界,请确保仅用于合法场景或学习用途。
第 2 种方式:事件触发机制来保持进程运行:
这种方法的优势是资源占用极低,因为不会有持续的循环和 Sleep() 消耗 CPU。这种机制更为优雅,同时也便于手动管理进程的生命周期。
以下是优化后的完整代码,实现了事件触发的逻辑,同时保持 Hook 的高效运行和简洁性。
完整代码
#include <Windows.h>
#include <iostream>
#include <EasyHook.h>
// ==== 类型声明与模板 ====
// 原始函数指针的类型定义
typedef BOOLEAN(WINAPI* SetSuspendState_t)(BOOLEAN, BOOLEAN, BOOLEAN);
typedef NTSTATUS(WINAPI* CallNtPowerInformation_t)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
// 用于保存原始函数地址
SetSuspendState_t OriginalSetSuspendState = nullptr;
CallNtPowerInformation_t OriginalCallNtPowerInformation = nullptr;
// ==== HOOK 函数实现 ====
// Hook 的 SetSuspendState 函数
BOOLEAN WINAPI HookedSetSuspendState(BOOLEAN Hibernate, BOOLEAN ForceCritical, BOOLEAN DisableWakeEvent) {
std::cout << "[Hooked] SetSuspendState called. Pretending to enter hibernation..." << std::endl;
// 不调用原始函数,直接伪造返回值为 TRUE 表示休眠成功,但实际上没有休眠操作
return TRUE;
}
// Hook 的 CallNtPowerInformation 函数
NTSTATUS WINAPI HookedCallNtPowerInformation(
POWER_INFORMATION_LEVEL InformationLevel,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
) {
std::cout << "[Hooked] CallNtPowerInformation called. Level: " << InformationLevel << std::endl;
// 如果调用者尝试查询系统电源状态(SystemPowerInformation)
if (InformationLevel == SystemPowerInformation && OutputBuffer != nullptr && OutputBufferLength >= sizeof(SYSTEM_POWER_INFORMATION)) {
SYSTEM_POWER_INFORMATION* spi = (SYSTEM_POWER_INFORMATION*)OutputBuffer;
// 伪造一个“休眠状态”的数据
spi->MaxIdlenessAllowed = 100;
spi->Idleness = 100;
spi->TimeRemaining = 0;
spi->CoolingMode = 1;
return STATUS_SUCCESS;
}
// 否则调用原始函数的逻辑(保持其原始作用)
return OriginalCallNtPowerInformation(InformationLevel, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength);
}
// ==== HOOK 安装与清理 ====
// 安装 Hook
BOOL InstallHooks() {
// Hook `SetSuspendState`
if (LhInstallHook(
GetProcAddress(GetModuleHandle(L"powrprof.dll"), "SetSuspendState"),
HookedSetSuspendState,
NULL,
reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalSetSuspendState)) != STATUS_SUCCESS) {
std::cerr << "Failed to hook SetSuspendState." << std::endl;
return FALSE;
}
// Hook `CallNtPowerInformation`
if (LhInstallHook(
GetProcAddress(GetModuleHandle(L"powrprof.dll"), "CallNtPowerInformation"),
HookedCallNtPowerInformation,
NULL,
reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalCallNtPowerInformation)) != STATUS_SUCCESS) {
std::cerr << "Failed to hook CallNtPowerInformation." << std::endl;
return FALSE;
}
// 设置 ACL,使 Hook 对所有线程生效
ULONG ACLEntries[1] = { 0 };
LhSetInclusiveACL(ACLEntries, 1, reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalSetSuspendState));
LhSetInclusiveACL(ACLEntries, 1, reinterpret_cast<TRACED_HOOK_HANDLE*>(&OriginalCallNtPowerInformation));
std::cout << "Hooks successfully installed." << std::endl;
return TRUE;
}
// 清理 Hook
void CleanupHooks() {
LhUninstallAllHooks(); // 卸载所有安装的 Hook
LhWaitForPendingRemovals(); // 等待所有 Hook 完成移除
std::cout << "Hooks cleaned up." << std::endl;
}
// ==== 主程序逻辑 ====
int main() {
// 设置控制台终止事件(Ctrl+C)
HANDLE hTerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hTerminateEvent == NULL) {
std::cerr << "Failed to create termination event!" << std::endl;
return -1;
}
// 安装 Hook
if (!InstallHooks()) {
CloseHandle(hTerminateEvent);
return -1;
}
// 等待终止事件触发
std::cout << "Hooks are active. Program will wait indefinitely. Press Ctrl+C to terminate." << std::endl;
// 等待事件触发或手动终止
WaitForSingleObject(hTerminateEvent, INFINITE);
// 清理 Hook
CleanupHooks();
CloseHandle(hTerminateEvent);
std::cout << "Program terminated gracefully." << std::endl;
return 0;
}
代码详细说明
1. 功能模块划分
- Hook 安装与清理:
InstallHooks(): 实现SetSuspendState和CallNtPowerInformation函数的 Hook。CleanupHooks(): 卸载与清理安装的 Hook。
- 事件触发机制:
- 通过
CreateEvent创建一个手动触发的事件对象。 - 主线程通过
WaitForSingleObject无限等待此事件触发,当事件被触发时,主线程优雅退出。
- 通过
2. 改进的 Hook 函数
HookedSetSuspendState: 伪造系统进入休眠状态,返回TRUE表示调用成功,但并未实际进入休眠。HookedCallNtPowerInformation:- 如果查询电源信息(
SystemPowerInformation),返回伪造数据表明系统处于“休眠中”。 - 对于其他电源管理功能,调用原始函数逻辑,避免破坏系统行为。
- 如果查询电源信息(
3. 事件触发机制
- 优点:相比
while循环 +Sleep的方式,通过WaitForSingleObject(HANDLE, INFINITE)操作彻底避免了线程资源消耗,是一种更高效的实现。 - 实现逻辑:
- 创建一个
HANDLE类型的事件对象hTerminateEvent。 - 主线程会无限期等待此事件触发(
WaitForSingleObject(hTerminateEvent, INFINITE))。 - 当事件被触发(例如外部信号或通过终端模拟 Ctrl+C),程序会退出循环并清理资源。
- 创建一个
4. EasyHook 功能的使用
LhInstallHook: 安装 Hook。LhSetInclusiveACL: 设置 Hook 的访问控制列表(ACL),确保 Hook 对所有线程生效。LhUninstallAllHooks: 卸载所有 Hook。LhWaitForPendingRemovals: 等待 Hook 被移除后继续。
程序执行流程
- 启动后,程序会安装 Hook,并输出状态到控制台。
- 主线程通过触发事件保持运行,无资源浪费。
- 当按
Ctrl+C或触发特定事件(SetEvent),程序会清理 Hook 并优雅退出。
总结
采用事件驱动的机制在设计上更加高效,避免了无意义的循环资源消耗,同时保持逻辑清晰且易于维护。如果后续需要扩展其他功能,例如让程序响应外部命令或信号,基于事件的设计也非常简单。
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏