1

我在 Windows 中编写了一个驱动程序,我需要磁盘驱动器序列号,对于用户模式,我找到了这个答案。我的问题是是否可以将上述代码转换为内核模式,以及如何?过滤器驱动程序中是否提供 WMI 查询?示例代码可以提供很大帮助。

编辑:

我在这里找到了这段代码,但是我如何重写他以获得序列号?

void GetSmbios()
{

    NTSTATUS status;
    GUID smbiosGUID = SMBIOS_DATA_GUID; // defined in wmiguid.h
    PVOID wmiObject = NULL;
    PWNODE_ALL_DATA dataBuffer;

    ULONG bufferSize;
    int TAG_SMBIOS = 'smbi';
    //
    // Get a WMI block handle to the SMBIOS_DATA_GUID
    //
    status = IoWMIOpenBlock((GUID *)&smbiosGUID, WMIGUID_QUERY,
        &wmiObject);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }

    //
    // Determine how much space is required for the data
    //
    status = IoWMIQueryAllData(wmiObject, &bufferSize, NULL);
    if (status != STATUS_BUFFER_TOO_SMALL) 
    {
        ObDereferenceObject(wmiObject);
        return status;
    }

    //
    // Allocate the necessary storage. This space must come out of NP-pool
    //
    dataBuffer = ExAllocatePoolWithTag(
        NonPagedPool,
        bufferSize,
        TAG_SMBIOS);

    if (dataBuffer == NULL) 
    {
        ObDereferenceObject(wmiObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

}
4

2 回答 2

1

分配完内存后,相信你需要IoWMIQueryAllData()再次调用,这次传递的是dataBuffer。

SMBIOS 似乎与磁盘驱动器无关,因此您需要将不同的 GUID 传递给IoWMIOpenBlock(). 也许这个( {BF253431-1E4D-4F57-00E7-64B2CACC801E}),因为您的用户模式示例和其他人查询 Win32_PhysicalMedia 以获取序列号。

但是,引用了一个(可能是用户模式)DLL,它是 Win32_PhysicalMedia 的提供程序。所以这在内核模式下可能无法访问。

但它也提示了如何从内核模式获取信息:IOCTLs。它提到了 IOCTL_SMART_GET_VERSION,它应该只是 SMART_GET_VERSION,这是一个示例:(在用户模式下,但您应该能够使用内核模式执行类似操作ZwDeviceIoControlFile())。请注意,它会使用另一个 ioctl 命令 SMART_RCV_DRIVE_DATA 来获取序列号。

另一个听起来很有希望(并且更通用)的 ioctl 是 IOCTL_STORAGE_QUERY_PROPERTY,输入 STORAGE_PROPERTY_QUERY.PropertyId 设置为 StorageDeviceProperty,因此输出将是一个 STORAGE_DEVICE_DESCRIPTOR 结构,它具有字段 SerialNumberOffset:

指定从结构开头到包含设备序列号的以 null 结尾的 ASCII 字符串的字节偏移量。如果设备没有序列号,则该成员为零。

于 2016-10-14T05:38:55.410 回答
1

FILE_FS_VOLUME_INFORMATION包含字段VolumeSerialNumber。可以使用 检索此数据结构ZwQueryVolumeInformationFile(... FileFsVolumeInformation)

这需要卷的句柄或卷中的文件/目录。如果这不可行,但你有一个DEVICE_OBJECT,你可以尝试用 构建你自己的 IRPIRP_MJ_QUERY_VOLUME_INFORMATION并用它发送它IoCallDriver(),虽然我不知道这是否被批准——文档说这样一个“请求是由 I/O 管理器发送的。 "

于 2016-10-13T20:05:04.953 回答