使用 IOCTL_STORAGE_QUERY_PROPERTY 获取序列号

Getting Serial Number using IOCTL_STORAGE_QUERY_PROPERTY

所以我正在尝试编写一个仅附加到特定 USB 设备的微过滤器驱动程序,以区分我使用产品 ID + 供应商 ID + 序列号组合的所述设备。

我可以成功将 IOCTL_STORAGE_QUERY_PROPERTY 发送到 returns 产品 ID、供应商 ID、序列号的设备。

我遇到的问题是返回到我的 minifilter 的序列号对于某些 USB 是正确的,但不是全部。

例如:当我打电话时

C:\Windows\system32>wmic diskdrive get pnpdeviceid PNPDeviceID USBSTOR\DISK&VEN_SONY&PROD_STORAGE_MEDIA&REV_PMAPC3000637C2070A595&0 USBSTOR\DISK&VEN_BM&PROD_&REV_1.100007AA1F02CF40063F&0

这些是从我的微过滤器返回的序列号:

Serial Number found 57C03A050905. Serial Number found 070007AA1F02CF400630.

可以看出,第二台设备的序列号返回成功,但第一台没有。那么我的微过滤器收到的序列号是多少?这是否存储在可以查询的地方?

如果需要,我可以附上代码,但由于我正确地获得了一些序列号,我怀疑我的代码是错误的。

编辑:代码

STORAGE_PROPERTY_QUERY query;
pQuery.PropertyId = StorageDeviceProperty;
pQuery.QueryType = PropertyStandardQuery

KeInitializeEvent(&event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, pDeviceObject, (PVOID)&query, sizeof(query), infoBuffer,
                                        sizeof(infoBuffer), FALSE, &event, &ioStatusBlock);
if (Irp) {
    if(!NT_SUCCESS(IoCallDriver(pDeviceObject, Irp)))
        return STATUS_FLT_DO_NOT_ATTACH;
}
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
pDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)infoBuffer;

ULONG offset = pDescriptor->SerialNumberOfffset;
size_t size;
if (offset == 0) 
    return;

PCHAR c = offset + &buffer[0];
size = strlen(c);
*dest = ExAllocatePoolWithTag(PagedPool, size + 1, 'DIcI');
RtlZeroMemory(*dest, size + 1);
RtlCopyMemory(*dest, c, size + 1);

DbgPrint("Serial Number Found %s \n", *dest);
// String comparison of serial number and more processing

在我的外部硬盘上测试,这是我从设备管理器中得到的结果

575834314137363534565656 

来自我的微过滤器:

WX41A7654VVV 

设备管理器中的序列号似乎是我从微过滤器中获得的序列号的十六进制表示

57 58 34 31 41 37 36 35 34 56 56 56 

W  X  4  1  A  7  6  5  4  V  V  V 

所以对于某些设备,它以十六进制格式表示,而其他设备则以字符格式表示?

那么是否可以从内核级别获取序列号,或者调用用户应用程序会更容易?

STORAGE_DEVICE_DESCRIPTOR is variable length structure. after success call IOCTL_STORAGE_QUERY_PROPERTY需要

check its Size member to determine the number of bytes the structure actually requires.

但是在你的代码中我看到了 infoBuffer, sizeof(infoBuffer) - 这意味着你对 STORAGE_DEVICE_DESCRIPTOR.

使用了硬编码大小

确实需要发送 IOCTL_STORAGE_QUERY_PROPERTY 并将 Size 成员与您的 OutputBufferLength 进行比较,如果它更大 - 发送 IOCTL_STORAGE_QUERY_PROPERTY 再次使用更大的 OutputBufferLength .

void PrintSerial(PDEVICE_OBJECT DeviceObject)
{
    STORAGE_PROPERTY_QUERY spq = { StorageDeviceProperty, PropertyStandardQuery }; 

    union {
        PVOID buf;
        PSTR psz;
        PSTORAGE_DEVICE_DESCRIPTOR psdd;
    };

    ULONG size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 0x100;

    NTSTATUS status;

    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (buf = ExAllocatePool(PagedPool, size))
        {
            switch (status = IoControlDevice(DeviceObject, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), buf, size))
            {
            case STATUS_SUCCESS:
            case STATUS_BUFFER_OVERFLOW:

                if (psdd->Version == sizeof(STORAGE_DEVICE_DESCRIPTOR))
                {
                    if (psdd->Size > size)
                    {
                        size = psdd->Size;
                        status = STATUS_BUFFER_OVERFLOW;
                    }
                    else
                    {
                        if (psdd->SerialNumberOffset)
                        {
                            DbgPrint("SerialNumber = %s\n", psz + psdd->SerialNumberOffset);
                        }
                        else
                        {
                            DbgPrint("SerialNumberOffset==0\n");
                        }
                    }
                }
                else
                {
                    status = STATUS_INVALID_PARAMETER;
                }
                break;
            }

            ExFreePool(buf);
        }
    } while (status == STATUS_BUFFER_OVERFLOW);
}

NTSTATUS IoControlDevice(
                       PDEVICE_OBJECT DeviceObject,
                       ULONG IoControlCode,
                       PVOID InputBuffer,
                       ULONG InputBufferLength,
                       PVOID OutputBuffer,
                       ULONG OutputBufferLength,
                       BOOLEAN InternalDeviceIoControl = FALSE
                       )
{
    KEVENT Event;
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    IO_STATUS_BLOCK  IoStatusBlock;

    if (PIRP Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer, InputBufferLength,
        OutputBuffer, OutputBufferLength, InternalDeviceIoControl, &Event, &IoStatusBlock))
    {
        NTSTATUS status = IofCallDriver(DeviceObject, Irp);

        if (status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);

            status = IoStatusBlock.Status;
        }

        return status;
    }

    return STATUS_INSUFFICIENT_RESOURCES;
}