服务/驱动程序(.sys)启动后,通常通过文件(客户端伪代码)进行通信:
HANDLE gHandle = CreateFileA("\\\\.\\DriverFile",
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
...
DeviceIoControl(gHandle, MY_MSG_ID, NULL, 0, &refCount,
sizeof(refCount), &length, NULL);
...
CloseHandle(gHandle);
有没有办法知道有多少客户端与驱动程序文件建立了开放连接?实现它的一种方法是在驱动程序端处理IRP_MJ_CREATE / IRP_MJ_CLOSE并手动保留引用计数;然后向驱动程序客户端代码发送一些消息可以检索计数。有没有办法在不涉及驱动程序端更改的情况下做到这一点?
您不需要任何引用计数(系统已经为您完成了这项工作)并且不需要等待客户端。如果您想卸载/删除驱动程序 - 只需这样做。如果驱动程序上仍然存在打开的文件(更确切地说是在某些 IT 设备上),系统将卸载驱动程序,此时最后一个文件将被关闭。
让我们用Null.sys驱动程序做演示。尝试停止/卸载它,直到其设备上存在打开的文件(
\Device\Null
)。为了检查内存中的驱动程序,我们可以使用下一个函数
如果是Null.sys,对象
\Driver\Null
将一直存在于内存中,直到驱动程序为止。我们可以尝试用打开此对象NtOpenFile
。无论如何我们都会失败(不可能从用户模式和使用此 api 打开驱动程序对象)。但错误代码会有所不同。STATUS_OBJECT_TYPE_MISMATCH
- 表示\Driver\Null
存在 并且STATUS_OBJECT_NAME_NOT_FOUND
- 表示\Driver\Null
不存在为了在驾驶员停止期间模拟客户端,我们可以使用下一个代码
因此我们首先启动客户端并等待它在Null.sys(
L"\\\\?\\NUL"
)上打开设备,然后尝试停止驱动程序 -StopDriver(L"Null", L"\\Driver\\Null");
因为我们在这里等待演示 - 我们将循环旋转,直到消息框ClientThread
不会关闭。在实际代码中 - 你通常不需要调用DoesDriverObjectExist
并等待其他值STATUS_OBJECT_TYPE_MISMATCH
- 你可以简单地删除服务或者根本不关心。所有这些代码 - 用于演示和更好地理解所有内容。和实用功能