ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

windows 驱动实例分析系列: HidHide 驱动分析 - drivers 篇(二)

windows 驱动实例分析系列: HidHide 驱动分析 - drivers 篇(二) HidHide 驱动分析 - drivers 篇二同步与并发控制一、并发场景分析内核驱动在运行过程中面临多种并发挑战并发来源说明影响多处理器系统不同 CPU 核心可同时执行驱动代码共享数据结构需要同步保护IRQL 提升代码在高 IRQL 被中断可能被重新调度锁的选择需匹配 IRQL 级别异步回调进程/镜像回调在任意线程上下文触发回调函数必须可重入多线程应用多个用户态线程同时访问控制设备IOCTL 处理需要序列化HidHide 通过组合使用多种同步机制应对这些挑战。二、WDFWAITLOCK全局同步锁2.1 锁的创建与类型WdfWaitLockCreate(wdfObjectAttributes,s_criticalSectionLock);WdfWaitLock在 WDF 内部实现为快速互斥体Fast Mutex具有以下特性可以在 PASSIVE_LEVEL IRQL 获取和释放。支持递归获取同一线程可多次获取而不会死锁。获取锁时若被其他线程持有当前线程进入等待状态不会自旋。2.2 锁保护的关键数据所有共享数据结构都在s_criticalSectionLock保护之下BST进程-路径映射树插入、查找、删除、缓存刷新操作。控制设备上下文白名单集合、黑名单集合的原子替换。引用计数numberOfDevicesCreated的增减。2.3 加锁模式与粒度HidHide 采用粗粒度锁策略整个驱动只有一个全局锁。理由如下并发度低BST 操作发生在进程创建/终止时频率远低于 I/O 请求。实现简单避免复杂的多锁嵌套和死锁分析。锁持有时间短所有临界区操作查找、比较、指针交换都在微秒级完成。加锁示例HidHideProcessIdRegisterWdfWaitLockAcquire(wdfWaitLock,NULL);nodeBstLookup(s_ProcessIdToFullLoadImageNameMappingTree,processId);if(NULL!node){WdfWaitLockRelease(wdfWaitLock);returnSTATUS_PROCESS_IN_JOB;}ntstatusBstNewNode(processId,fullImageName,node);ntstatusBstInsert(s_ProcessIdToFullLoadImageNameMappingTree,node);WdfWaitLockRelease(wdfWaitLock);锁在函数入口获取在函数出口释放最小化了锁持有时间。三、IRQL 管理与锁兼容性3.1 不同回调函数的 IRQL 级别回调函数IRQL 级别说明DriverEntryPASSIVE_LEVEL驱动加载阶段EvtDriverDeviceAddPASSIVE_LEVELPnP 设备枚举OnDeviceFileCreatePASSIVE_LEVEL用户态文件创建请求OnSystemLoadImagePASSIVE_LEVEL镜像加载通知APC 级别OnSystemProcessChangePASSIVE_LEVEL进程创建/终止通知OnControlDeviceIoDeviceControlDISPATCH_LEVELIOCTL 处理可达 DISPATCH_LEVEL所有回调都运行在 PASSIVE_LEVEL 或更低因此WdfWaitLock需要 PASSIVE_LEVEL在所有上下文中都是安全的。3.2 避免在提升 IRQL 时持有锁OnControlDeviceIoDeviceControl虽然声明为_IRQL_requires_max_(DISPATCH_LEVEL)但在实际执行中WDF 默认队列将请求从 DISPATCH_LEVEL 降级到 PASSIVE_LEVEL 处理。因此持有WdfWaitLock是安全的。驱动文档明确标注了 IRQL 要求_IRQL_requires_same__IRQL_requires_max_(PASSIVE_LEVEL)NTSTATUSHidHideProcessIdRegister(...);这提醒调用者必须在 PASSIVE_LEVEL 调用此函数。四、WDF 自动同步机制4.1 设备对象的同步范围wdfObjectAttributes.SynchronizationScopeWdfSynchronizationScopeNone;HidHide 的过滤设备明确设置WdfSynchronizationScopeNone即 WDF 框架不为该设备提供自动同步保护。决策依据是性能优先自动同步会序列化所有请求影响 I/O 吞吐量。手动保护充分OnDeviceFileCreate只读取共享数据白名单/黑名单且读取操作使用原子指针交换无需额外锁。4.2 控制设备的独占模式WdfDeviceInitSetExclusive(wdfDeviceInit,TRUE);控制设备设置为独占模式确保同一时刻只有一个用户态进程可以打开\\.\HidHide。这避免了以下竞态两个配置工具同时修改白名单导致数据不一致。在配置更新过程中另一个进程读取到半完成状态。五、原子指针交换无锁读取5.1 双缓冲技术的核心配置更新的核心操作是对集合指针的原子替换WdfWaitLockAcquire(s_criticalSectionLock,NULL);WdfObjectDelete(pControlDeviceContext-whitelistedFullImageNames);pControlDeviceContext-whitelistedFullImageNamesnewCollection;WdfWaitLockRelease(s_criticalSectionLock);关键设计指针赋值在 x64 上是原子操作。因此当读取线程OnDeviceFileCreate访问whitelistedFullImageNames时它总是看到完整的旧集合或完整的新集合而不会看到中间状态。5.2 读取端的无锁访问// 在 OnDeviceFileCreate 中BOOLEANWhitelisted(HANDLE processId,BOOLEAN*cacheHit){pControlDeviceContextControlDeviceGetContext(s_wdfControlDevice);// 直接读取指针无需加锁BOOLEAN resultHidHideProcessIdCheckFullImageNameAgainstWhitelist(s_criticalSectionLock,processId,pControlDeviceContext-whitelistedFullImageNames,cacheHit);returnGetInverse()?!result:result;}读取时未持有s_criticalSectionLock但仍安全因为指针赋值是原子的。旧的集合对象在指针交换后不会被立即释放通过WdfObjectDelete延迟释放。WDFCOLLECTION对象在删除时引用计数为零才会真正释放。这种设计实现了读操作无锁对高频 I/O 路径影响极小。六、进程回调的上下文隔离6.1 系统线程上下文OnSystemLoadImage和OnSystemProcessChange运行在系统进程上下文中而非调用者进程上下文。这意味着不能使用PsGetCurrentProcessId()获取调用者 PID因为当前进程是 System。回调参数明确提供了HANDLE processId必须使用此值。6.2 安全的数据传递BST 节点存储的fullImageName字符串在插入时被完整复制到非分页池中ntstatusRtlStringCchCopyUnicodeStringEx(temp-fullImageName[0],_countof(temp-fullImageName),fullImageName,...);这确保了在回调函数返回后字符串数据依然有效不受栈空间释放的影响。七、自检与防御性编程7.1 启动时 BST 自检HidHideVerifyInternalConsistency在驱动启动时执行完整 BST 验证。这种Fail-Fast策略确保若 BST 算法实现存在缺陷驱动在加载阶段即失败而非在运行时触发蓝屏。为后续的进程追踪功能提供正确性保证。7.2 断言与验证虽然代码中未直接使用ASSERT宏但通过NT_SUCCESS检查和LOG_AND_RETURN_NTSTATUS实现了相似效果if(!NT_SUCCESS(ntstatus)){LOG_AND_RETURN_NTSTATUS(LWdfDriverOpenParametersRegistryKey,ntstatus);}所有 API 调用的返回值都被检查失败时记录详细错误信息并返回。
返回列表