1. GHOST29.04.2025 в 17:23от
Загрузка...
Загрузка...

Подмена disk serial number на время сессии

Тема в разделе "Софт", создана пользователем lordoleg, 16.04.2025.

Метки:
  1. lordoleg

    lordoleg

    Статус:
    Оффлайн
    Регистрация:
    05.04.17
    Сообщения:
    54
    Репутация:
    25 +/-
    Занялся вопрос об написании драйвера, который смог бы перехватывать
    IOCTL_STORAGE_QUERY_PROPERTY данные о всех дисках и подменять их. Написал драйвер, создал подпись и смог даже запустить его(установить в системе), но, он не видит никаких данных по этому полю и ничего не подменяет. wmi API возвращает старые значения.

    ВАЖНО: изменить не VolumeId, а именно серийник

    Вот кусок кода С++, который занимался обработкой:

    Код:
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
        UNREFERENCED_PARAMETER(DeviceObject);
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    
        // Log IOCTL type
        char logMessage[256];
        RtlStringCchPrintfA(logMessage, sizeof(logMessage), "[DiskSpoof] IOCTL received: 0x%x\n", stack->Parameters.DeviceIoControl.IoControlCode);
        WriteToLog(logMessage);
    
        if (stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY) {
            PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
            if (query && query->PropertyId == StorageDeviceProperty) {
                PSTORAGE_DEVICE_DESCRIPTOR desc = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
                if (desc->SerialNumberOffset != 0 && desc->SerialNumberOffset < Irp->IoStatus.Information) {
                    CHAR* serial = (CHAR*)desc + desc->SerialNumberOffset;
                    RtlCopyMemory(serial, SPOOF_SERIAL, min(strlen(SPOOF_SERIAL), 20));
    
                    // Log the spoofed serial number
                    RtlStringCchPrintfA(logMessage, sizeof(logMessage), "[DiskSpoof] Serial spoofed to: %s\n", SPOOF_SERIAL);
                    WriteToLog(logMessage);
                }
            }
        }
    
        return DispatchPassThrough(DeviceObject, Irp);
    }
    Вопрос: может существует уже созданный софт или же драйвер, который это делает? Подойдет даже сырой код для драйвера, думаю, смогу его собрать для своей системы
     
  2. Lux Manager

    Lux Manager

    Статус:
    Оффлайн
    Регистрация:
    13.10.23
    Сообщения:
    118
    Репутация:
    50 +/-
    ПОРА НЕЙРОНКИ ОСВАИВАТЬ

    Почему ваш код не работает
    Ваш текущий код в функции DispatchDeviceControl пытается перехватить IOCTL_STORAGE_QUERY_PROPERTY и подменить серийный номер, но делает это неправильно. Вот ключевые проблемы:

    1. Неправильный момент модификации:
      • В методе DispatchDeviceControl вы пытаетесь изменить буфер до передачи IRP (I/O Request Packet) вниз по стеку драйверов, вызывая DispatchPassThrough. На этом этапе буфер Irp->AssociatedIrp.SystemBuffer содержит входные данные (STORAGE_PROPERTY_QUERY), а не выходные данные (STORAGE_DEVICE_DESCRIPTOR), которые заполняются нижними драйверами (например, disk.sys).
      • Поскольку вы изменяете буфер до того, как нижние драйверы заполнят его реальными данными, ваши изменения либо перезаписываются, либо вообще не доходят до приложения.
    2. WMI возвращает оригинальные значения:
      • Даже если вы исправите перехват, WMI может продолжать возвращать оригинальные серийные номера, так как он, вероятно, запрашивает данные через другой IOCTL или напрямую у оборудования, обходя ваш фильтрующий драйвер.
    Чтобы подмена сработала, вам нужно изменять данные после того, как нижние драйверы заполнят буфер, на этапе возврата IRP вверх к приложению. Для этого потребуется использовать completion routine (обработчик завершения).

    Как исправить драйвер
    Чтобы ваш драйвер корректно подменял серийный номер, нужно перехватывать и изменять выходной буфер после его заполнения нижними драйверами. Вот шаги:

    1. Проверка IOCTL в DispatchDeviceControl
    В функции DispatchDeviceControl проверяйте, что поступил нужный IOCTL, и устанавливайте обработчик завершения:

    Код:
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    
        // Логирование IOCTL
        char logMessage[256];
        RtlStringCchPrintfA(logMessage, sizeof(logMessage), "[DiskSpoof] IOCTL received: 0x%x\n",
                            stack->Parameters.DeviceIoControl.IoControlCode);
        WriteToLog(logMessage);
    
        if (stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY) {
            PSTORAGE_PROPERTY_QUERY query = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
            if (query && query->PropertyId == StorageDeviceProperty) {
                // Устанавливаем обработчик завершения
                IoCopyCurrentIrpStackLocationToNext(Irp);
                IoSetCompletionRoutine(Irp, SpoofSerialCompletionRoutine, NULL, TRUE, TRUE, TRUE);
                return IoCallDriver(DeviceObject->NextLowerDriver, Irp);
            }
        }
    
        // Передаем IRP вниз, если это не наш IOCTL
        return DispatchPassThrough(DeviceObject, Irp);
    }
    • Здесь мы проверяем, что IOCTL — это IOCTL_STORAGE_QUERY_PROPERTY с PropertyId == StorageDeviceProperty.
    • Вместо немедленной модификации буфера мы устанавливаем обработчик завершения с помощью IoSetCompletionRoutine и передаем IRP вниз.
    2. Обработчик завершения для подмены серийного номера
    Создайте функцию SpoofSerialCompletionRoutine, которая будет вызвана после того, как нижние драйверы заполнят буфер:

    Код:
    NTSTATUS SpoofSerialCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) {
        UNREFERENCED_PARAMETER(DeviceObject);
        UNREFERENCED_PARAMETER(Context);
    
        // Проверяем, успешно ли завершен IRP
        if (Irp->IoStatus.Status == STATUS_SUCCESS) {
            PSTORAGE_DEVICE_DESCRIPTOR desc = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
    
            // Убеждаемся, что буфер достаточно большой и содержит серийный номер
            if (Irp->IoStatus.Information >= sizeof(STORAGE_DEVICE_DESCRIPTOR) &&
                desc->SerialNumberOffset != 0 &&
                desc->SerialNumberOffset < Irp->IoStatus.Information) {
                CHAR* serial = (CHAR*)desc + desc->SerialNumberOffset;
                size_t originalLen = strnlen(serial, Irp->IoStatus.Information - desc->SerialNumberOffset);
                size_t spoofLen = strlen(SPOOF_SERIAL);
    
                // Копируем подмененный серийный номер, не превышая доступное пространство
                size_t copyLen = min(spoofLen, originalLen);
                RtlCopyMemory(serial, SPOOF_SERIAL, copyLen);
    
                // Убеждаемся, что строка завершается нулем
                if (copyLen < originalLen) {
                    serial[copyLen] = '\0';
                }
    
                // Логируем результат
                char logMessage[256];
                RtlStringCchPrintfA(logMessage, sizeof(logMessage), "[DiskSpoof] Serial spoofed to: %s\n", SPOOF_SERIAL);
                WriteToLog(logMessage);
            }
        }
    
        // Завершаем IRP
        if (Irp->PendingReturned) {
            IoMarkIrpPending(Irp);
        }
        return Irp->IoStatus.Status;
    }
    • Проверка успеха: Убеждаемся, что IRP завершился успешно (STATUS_SUCCESS), и буфер заполнен.
    • Доступ к данным: Теперь SystemBuffer содержит STORAGE_DEVICE_DESCRIPTOR, и мы можем изменить серийный номер по смещению SerialNumberOffset.
    • Безопасность буфера: Проверяем, что SerialNumberOffset в пределах Irp->IoStatus.Information (размер данных, возвращенных нижними драйверами), и копируем подмененный серийный номер, не превышая оригинальную длину.
    3. Особенности реализации
    • Длина строки: В примере выше подмененный серийный номер (SPOOF_SERIAL) обрезается до длины оригинального, чтобы избежать переполнения буфера. Если вам нужен серийный номер фиксированной длины, убедитесь, что он соответствует длине оригинала.
    • Позиция драйвера: Ваш драйвер, вероятно, является верхним фильтрующим драйвером (upper filter driver) для класса дисков. Это правильная позиция, так как вы хотите изменить данные на пути обратно к приложению.
    Почему WMI может не отражать изменения
    WMI может использовать другой способ получения серийных номеров (например, прямой запрос к драйверу диска или другой IOCTL), который не проходит через ваш фильтр. Чтобы подменить данные для WMI, нужно исследовать, какие именно запросы он выполняет, и, возможно, перехватывать дополнительные IOCTLs или работать на более низком уровне стека. Однако это сложнее и выходит за рамки данного ответа. Пока сосредоточьтесь на том, чтобы подмена работала для приложений, использующих IOCTL_STORAGE_QUERY_PROPERTY.

    Существует ли готовый софт или код?
    Готовые решения
    Скорее всего, существуют инструменты или драйверы, которые могут подменять серийные номера дисков, например:

    • Программы для виртуализации дисков (виртуальные диски могут представлять поддельные свойства).
    • Инструменты для тестирования или защиты конфиденциальности. Однако конкретные рекомендации затруднительны, так как такие инструменты могут использоваться в том числе для нелегальных целей (например, обхода лицензий). Если вам нужно готовое решение, ищите легальные утилиты для разработчиков или тестирования оборудования.
    Сырой код
    Поскольку вы готовы собрать драйвер самостоятельно, вот где можно найти примеры:

    • Windows Driver Samples: На GitHub есть примеры фильтрующих драйверов (например, в разделе filter). Вы можете адаптировать их, добавив логику перехвата IOCTL_STORAGE_QUERY_PROPERTY.
    • ReactOS: В проекте ReactOS есть открытый код для дисковых фильтров, но совместимость с Windows не гарантирована.
    • OSR Community: Форум OSR Online содержит обсуждения и примеры кода для работы с IOCTLs в драйверах.
    Вы можете взять пример фильтрующего драйвера и добавить описанную выше логику с обработчиком завершения.

    Важные замечания
    1. Юридические и этические аспекты:
      • Подмена серийных номеров может нарушать законы или условия использования ПО, если используется для обмана систем лицензирования или сокрытия данных. Убедитесь, что у вас есть легитимная цель (например, тестирование).
    2. Безопасность буфера:
      • Убедитесь, что подмененный серийный номер не превышает доступное пространство в буфере, чтобы избежать краха системы.
    3. Ограничения:
      • Ваш драйвер подменит серийный номер только для приложений, использующих IOCTL_STORAGE_QUERY_PROPERTY. Другие методы запроса (например, WMI) могут потребовать дополнительных усилий.
    Итог
    Чтобы ваш драйвер заработал:

    1. Переместите логику подмены в обработчик завершения (completion routine), чтобы изменять данные после их заполнения нижними драйверами.
    2. Используйте приведенные выше примеры для реализации DispatchDeviceControl и SpoofSerialCompletionRoutine.
    Если вам нужен сырой код, ищите примеры фильтрующих драйверов в открытых источниках (Windows Driver Samples, OSR) и адаптируйте их под свою задачу. Готовые инструменты существуют, но будьте осторожны с их использованием и происхождением.
     
  3. lordoleg

    lordoleg

    Статус:
    Оффлайн
    Регистрация:
    05.04.17
    Сообщения:
    54
    Репутация:
    25 +/-
    Я пытался использовать ГПТ(у меня там подписка). Он помог лишь в корректном логировании. То, что тут написано в ответе - это один из вариантов, я попробую его. ИИшки просто выдают то, что валяется в инете на форумах, и, как я проверил, многое из этого не работает

    Если у вас есть знания в этой теме - готов выслушать, если же вы просто скопипиздили ответ ИИшки - спасибо, я это уже пробовал
     
  4. Lux Manager

    Lux Manager

    Статус:
    Оффлайн
    Регистрация:
    13.10.23
    Сообщения:
    118
    Репутация:
    50 +/-


    Сейчас много вариантов ИИ.

    ChatGPT очень плохие ответы дает и поэтому использую новые