windows xusb21.sys驱动对虚拟手柄个数限制
由于windows授权限制,云游戏服务器上的windows版本多数为server 2019
部分游戏用到了手柄,调研后基于 https://github.com/nefarius/ViGEmBus 来魔改虚拟出84个手柄
(一个容器只跑一个游戏,一个游戏独立使用4个手柄,一台云游戏服务器预开21个容器,所以理论至少需要能创建84个手柄)
但是实际过程中发现ViGEmBus只能虚拟21个手柄,第22个时候系统就返回失败,
由于是必现且windows没有反调试/代码混淆
所以很快定位到ViGEmBus会调用系统的xusb21.sys,但是xusb21.sys返回了false
ida64加载xusb21.sys,但是不清楚微软的符号服务器为什么没有xusb21.sys的pdb,而xusb22.sys就有,
所以先分析xusb22.sys,如果代码逻辑类似而且能解决的话再把修改移植回xusb21.sys
1 xusb22.sys DriverEntry会申请288字节的内存作为驱动的全局的私有结构体,整个结构体初始化为0
通过函数对DriverGlobals内存的使用,大概分析出结构体的定义
//size 288
struct DriverGlobals{
//offet 0
int64 unknown0;
//offset 8
char flag[64];
//offset 72
XenonBusInformation* bus_info[16];
//offset 200
GamepadInformation* gamepad_info[4];
//offset 232
AudioInformation* audio_info[4]
//offset 264 66*4
ulong unknown1;
//offset 268 67*4
ulong unknown2;
//offset 272 68*4
ulong unknown3;
//offset 276 69*4
ulong unknown4;
//offset 280 70*4
ulong unknown5;
}
2 通过windbg调试得知 InterfaceDevice::Initialize 返回了false,分析手柄的创建流程
创建一个手柄xusb22.sys需要分配三个设备,每个设备需要占用DriverGlobals中char flag[64]的一个字节,如果没有可用的flag那么函数返回失败。 64//3=21, 所以21个手柄的限制就来自这里
d:\>python
Python 3.11.9 (tags/v3.11.9:de54cf5, Apr 2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 64//3
21
3 知道了问题,接下来就是如何修复了
由于设备驱动同时会以单字节保存在flag的index(为了设备卸载时候重置对应的flag数组)
一个手柄使用3个设备,一个容器使用4个手柄,一共21个容器,0xfc刚好在一个字节范围内, 那么目前也无需修正设备驱动对Index的存储
d:\>python
Python 3.11.9 (tags/v3.11.9:de54cf5, Apr 2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> hex(3*4*21)
'0xfc'
首先扩大DriverGlobals结构体的大小 (ida的keypatch插件可直接修改汇编)
然后修正对flag数组的所有访问,原先偏移是8,这里修改成512 (512大于288, 也不会覆盖原始的结构体信息)
以某处为例
原来的指令只有5个字节,不够patch,所以在代码段中寻找缝隙来填充
call cmp完直接ret了,也可以改成jmp然后cmp再jmp回去
所有引用处修改后验证成功,再把xusb22.sys的修改移植回xusb21.sys,同样满足需求