如何在用户态移除IORegistryEntry中的属性?
问题:无法在用户态移除IORegistryEntry中的HIDAccelCurves键值对
背景信息
- 目标IORegistryEntry属于
AppleUserHIDEventDriver类,每个外接键盘/鼠标连接后都会生成该类的实例 - macOS版本:Ventura 13.3.1,需在用户态完成操作
- 使用
IORegistryEntrySetCFProperty()或IORegistryEntrySetCFProperties()时,值会自动存入HIDEventServiceProperties子字典,符合需求,无此方面问题
已尝试方案
- 调用
IORegistryEntryCreateCFProperties()导出完整属性字典,移除目标键后通过IORegistryEntrySetCFProperties()写回:仅能修改现有值,被移除的键会被驱动忽略,无法真正删除 - 通过
IOHIDServiceClientRef调用IOHIDServiceClientSetProperty():可在HIDEventServiceProperties子字典中添加或编辑键值对,但同样无法移除已有键 - 考虑过使用IOConnect的属性设置方法,判断效果与上述API一致,未实际尝试
- 已知内核态提供C++方法
IORegistryEntry::removeProperty(),但用户态无法调用,未尝试 - 考虑过修改
AppleUserHIDEventDriver实例的父/子/孙节点属性,或使用IOHIDDeviceRef的COM接口操作,但均未验证可行性
核心问题(更新)
实际需求是自定义外接鼠标的指针加速算法,无需编写内核级/DriverKit驱动,仅通过用户态参数化Apple原生驱动:
- Apple的指针加速逻辑在开源代码
IOHIDPointerScrollFilter.cpp中实现(IOHIPointing.cpp中的实现已废弃),支持两种曲线机制:- 参数化曲线:4次多项式,平滑度高、效率优,对应属性键为
HIDAccelCurves(即kHIDAccelParametricCurvesKey) - 表格型曲线:通过多点连线生成,导数不连续,但可用数千个点近似连续,M1 MacBook测试无明显CPU负载差异,对应属性键为
HIDPointerAccelerationTable(即kIOHIDPointerAccelerationTableKey)
- 参数化曲线:4次多项式,平滑度高、效率优,对应属性键为
- 自定义流程:修改曲线参数后,修改
kIOHIDPointerAccelerationTypeKey(属于IOHIDPointerScrollFilter.cpp中_cachedPropertyList定义的缓存属性),触发驱动调用setupPointerAcceleration()重新初始化加速算法 - Ventura版本兼容性问题:只要
HIDAccelCurves键存在值,驱动就会优先使用参数化曲线;而Ventura中第三方鼠标默认存在该键(Monterey及之前版本默认无此键)
注:Ventura 13.3.1中存在特殊现象:开机未连接鼠标,后续再连接时
HIDAccelCurves不存在;但开机时已连接鼠标,该键始终存在,即使重新插拔也不会消失。另外发现开机连接鼠标后,IOHIDServiceClientRef中存在该键,但对应IORegistryEntry的HIDEventServiceProperties子字典中无此键,两者未同步,需进一步测试验证。
当前核心诉求:移除AppleUserHIDEventDriver类IORegistryEntry中的HIDAccelCurves键,让IOHIDPointerScrollFilter.cpp的setupPointerAcceleration()切换为使用表格型曲线。目前仅能将该键设为随机值,但触发重新初始化后会导致WindowServer崩溃,无法彻底移除该键值。
注:这情况甚至能用来找安全漏洞倒逼Apple修复代码,简直荒谬,哈哈。
待验证思路
- 调查Ventura下开机未连鼠标时
HIDAccelCurves缺失的原因,但该方案依赖系统特殊状态,可靠性不足 - 逆向
IOHIDPointerScrollFilter.cpp中的私有COM接口IOHIDServiceFilterPlugInInterface,尝试通过IOCreatePlugInInterfaceForService()获取实例引用,在用户态操作属性;但对COM接口机制不熟悉,缺乏参考示例,尚未尝试
内容的提问来源于stack exchange,提问作者Noah Nuebling
相关产品推荐
相关产品推荐

