Windows内核:初探 ELAM
字数 1880 2025-08-20 18:17:31
Windows内核安全机制:Early Launch Anti-Malware (ELAM) 深入解析
1. ELAM概述
Early Launch Anti-Malware (ELAM)是Windows 8引入的一种内核安全机制,旨在防止恶意代码在内核地址空间中执行。该机制特别针对Rootkit攻击,使Rootkit更难破坏系统。
1.1 核心功能
- 允许第三方安全软件注册内核模式驱动程序
- 确保安全驱动程序在系统启动早期执行
- 在其他第三方驱动程序加载前进行安全检查
- 阻止恶意驱动程序加载到内核地址空间
2. ELAM工作原理
2.1 Windows启动阶段
Windows系统引导过程分为多个阶段:
- 固件初始化
- 引导加载程序
- Windows启动管理器
- Windows内核加载
- 内核初始化
- 会话管理器初始化
- 用户登录
ELAM在内核加载阶段发挥作用,由Windows加载器(Winload.exe)加载。
2.2 ELAM驱动加载时机
- 在内核加载后,但未开始初始化驱动程序时
- ELAM驱动程序定义为Boot Start驱动程序,具有最高优先级
- 先于其他驱动程序加载和初始化
2.3 注册表配置
ELAM驱动程序在注册表中的位置:
HKLM\SYSTEM\CurrentControlSet\Services\[ELAMDriverName]
关键值:
start:0x0表示引导启动驱动程序type:0x1表示内核驱动程序
3. ELAM核心API
3.1 注册表回调API
CmRegisterCallbackEx:注册监视注册表数据的回调CmUnRegisterCallback:注销注册表回调
函数原型:
NTSTATUS CmRegisterCallbackEx(
PCALLBACK_FUNCTION CallbackFunction,
PCUNICODE_STRING Altitude,
PVOID DriverObject,
PVOID Context,
PLARGE_INTEGER Cookie
);
NTSTATUS CmUnRegisterCallback(
LARGE_INTEGER Cookie
);
3.2 启动驱动程序回调API
IoRegisterBootDriverCallback:注册启动驱动程序回调IoUnRegisterBootDriverCallback:注销启动驱动程序回调
函数原型:
NTSTATUS IoRegisterBootDriverCallback(
PIO_BOOT_DRIVER_CALLBACK CallbackFunction,
PVOID Context
);
NTSTATUS IoUnRegisterBootDriverCallback(
PIO_BOOT_DRIVER_CALLBACK CallbackFunction
);
3.3 回调函数原型
typedef VOID (*EX_CALLBACK_FUNCTION)(
PVOID CallbackContext,
PVOID Argument1,
PVOID Argument2
);
4. ELAM回调类型
4.1 BdCbStatusUpdate
提供驱动程序依赖项或引导驱动程序加载的状态更新。
数据结构:
typedef struct _BOOT_DRIVER_STATUS_UPDATE {
UNICODE_STRING DriverPath; // 当前驱动的路径
NTSTATUS Status; // 加载状态
} BOOT_DRIVER_STATUS_UPDATE, *PBOOT_DRIVER_STATUS_UPDATE;
4.2 BdCbInitializeImage
提供引导驱动程序的元数据,允许ELAM驱动对其进行分类。
分类选项:
BootDriverGood:信任并加载BootDriverBad:阻止加载BootDriverUnknown:未知状态,根据策略处理
数据结构:
typedef struct _BOOT_DRIVER_INFO {
UNICODE_STRING FilePath; // 驱动程序文件路径
PVOID ImageBase; // 内存中的基地址
ULONG ImageSize; // 映像大小
ULONG Classification; // 分类状态
} BOOT_DRIVER_INFO, *PBOOT_DRIVER_INFO;
5. ELAM分类依据
ELAM驱动程序只能基于以下有限数据对驱动程序映像进行分类:
- 映像名称
- 映像注册为引导驱动程序的注册表位置
- 映像文件的证书发布者和所有者
- 映像的散列值和对应的算法名称
- 证书指纹和指纹算法的名称
限制:无法访问硬件驱动器上的二进制映像文件,因为存储设备驱动程序栈尚未初始化。
6. ELAM执行策略
策略注册表位置:
HKLM\System\CurrentControlSet\Control\EarlyLaunch\DriverLoadPolicy
策略选项:
| 策略值名称 | 策略值 | 描述 |
|---|---|---|
| PNP_INITIALIZE_DRIVERS_DEFAULT | 0x00 | 仅加载已知为非恶意的驱动程序 |
| PNP_INITIALIZE_UNKNOWN_DRIVERS | 0x01 | 加载已知非恶意和未知的驱动程序 |
| PNP_INITIALIZE_BAD_CRITICAL_DRIVERS | 0x03 | 加载已知非恶意、未知和已知为恶意的关键驱动程序(默认设置) |
| PNP_INITIALIZE_BAD_DRIVERS | 0x07 | 加载所有驱动程序 |
默认策略分析:
- 允许加载恶意的关键驱动程序
- 确保系统关键组件能够启动
- 牺牲部分安全性以提高系统可用性
7. ELAM的局限性
7.1 对Bootkit无效
- ELAM只能监视合法加载的驱动程序
- Bootkit使用未注册的操作系统功能加载内核模式驱动程序
- Bootkit可以在ELAM加载前执行恶意代码
7.2 初始化时机问题
- 大多数Bootkit在内核初始化期间加载代码
- 在I/O子系统、对象管理器等初始化后,ELAM执行前加载
8. ELAM驱动开发示例
8.1 基本结构
#include <ntddk.h>
// 上下文结构体
typedef struct _ELAM_CONTEXT {
BOOLEAN AllowUnknownDrivers; // 策略:是否允许未知驱动
} ELAM_CONTEXT, *PELAM_CONTEXT;
// 回调函数原型
VOID ElamBootDriverCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2);
// 上下文全局变量
ELAM_CONTEXT g_ElamContext = { TRUE }; // 默认允许未知驱动
8.2 DriverEntry实现
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
NTSTATUS status;
// 注册ELAM回调函数
status = IoRegisterBootDriverCallback(ElamBootDriverCallback, &g_ElamContext);
if (!NT_SUCCESS(status)) {
KdPrint(("Failed to register ELAM callback. Status: 0x%x\n", status));
return status;
}
KdPrint(("ELAM driver loaded successfully.\n"));
// 设置驱动卸载函数
DriverObject->DriverUnload = [](PDRIVER_OBJECT DriverObject) {
// 注销回调
IoUnRegisterBootDriverCallback(ElamBootDriverCallback);
KdPrint(("ELAM driver unloaded.\n"));
};
return STATUS_SUCCESS;
}
8.3 回调函数实现
VOID ElamBootDriverCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
PELAM_CONTEXT pContext = (PELAM_CONTEXT)CallbackContext;
// 检查回调类型
if ((ULONG_PTR)Argument1 == BdCbInitializeImage) {
// 获取驱动信息
PBOOT_DRIVER_INFO BootDriverInfo = (PBOOT_DRIVER_INFO)Argument2;
// 检查驱动路径
if (wcsstr(BootDriverInfo->FilePath.Buffer, L"TrustedDriver.sys")) {
BootDriverInfo->Classification = BootDriverGood; // 可信驱动
KdPrint(("Driver %wZ classified as Good.\n", &BootDriverInfo->FilePath));
} else if (pContext->AllowUnknownDrivers) {
BootDriverInfo->Classification = BootDriverUnknown; // 未知驱动
KdPrint(("Driver %wZ classified as Unknown.\n", &BootDriverInfo->FilePath));
} else {
BootDriverInfo->Classification = BootDriverBad; // 阻止加载
KdPrint(("Driver %wZ classified as Bad.\n", &BootDriverInfo->FilePath));
}
}
}
9. 总结
ELAM是Windows内核中重要的安全机制,通过:
- 早期加载安全驱动程序
- 监控和分类其他引导驱动程序
- 阻止已知恶意驱动加载
虽然对Rootkit有较好的防御效果,但对Bootkit攻击防护有限。开发者可以通过注册适当的回调函数来实现自定义的安全策略,增强系统安全性。