Серийный номер жесткого диска перевернулся каждые 2 байта в Windows XP, Vista и 7, но не в Windows 8 - программирование

Серийный номер жесткого диска перевернулся каждые 2 байта в Windows XP, Vista и 7, но не в Windows 8

Мне нужно получить серийный номер жесткого диска, чтобы использовать его в качестве ключа для лицензирования программного обеспечения. Я использовал diskid32 код в этом URL: http://www.winsim.com/diskid32/diskid32.html Он использовал DeviceIoControl Win32 API с кодом управления IO IOCTL_STORAGE_QUERY_PROPERTY.

Это сработало. Однако, когда я дважды проверяю фактический серийный номер, напечатанный на самом жестком диске, я обнаружил, что каждые 2 байта числа были перевернуты.

Простым решением может быть просто перевернуть байты назад. Он работал в Windows XP, Vista и 7, но в Windows 8 не нужно переворачиваться!

Я хочу знать точную причину, по которой байты были перевернуты в Windows XP, Vista и 7, и почему бы не перевернуть в Windows 8. Что относительно следующей Windows?

Часть кода с незначительными изменениями:

  int drive = 0;
  HANDLE hPhysicalDriveIOCTL = 0;
  char driveName [256];
  sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
  //  Windows NT, Windows 2000, Windows XP - admin rights not required
  hPhysicalDriveIOCTL = CreateFile (driveName, 0,
                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                           OPEN_EXISTING, 0, NULL);
  if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
  {
     _STORAGE_PROPERTY_QUERY query;
     DWORD cbBytesReturned = 0;
     char buffer [10000];

     memset ((void *) & query, 0, sizeof (query));
     query.PropertyId = StorageDeviceProperty;
     query.QueryType = PropertyStandardQuery;

     memset (buffer, 0, sizeof (buffer));

     if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
               & query,
               sizeof (query),
               & buffer,
               sizeof (buffer),
               & cbBytesReturned, NULL) )
     {
         _STORAGE_DEVICE_DESCRIPTOR * descrip = (_STORAGE_DEVICE_DESCRIPTOR *) & buffer;
         char serialNumber [1000];
         char modelNumber [1000];
         char vendorId [1000];
         char productRevision [1000];

         flipAndCodeBytes (buffer,
                           descrip -> SerialNumberOffset,
                           1, serialNumber );

        ...
     }
4b9b3361

Ответ 1

Я использую тот же подход (и тот же код) в моем лицензировании программного обеспечения. Да, Windows 8 по какой-то причине возвращает измененные значения для этого метода, я не могу сказать, почему (поэтому я не могу ответить на ваш вопрос).

Мое решение - это тот, который вы указали: снова переверните значения. Итак, после вызова "flipAndCodeBytes" вы можете проверить, есть ли ОС Windows 8, и перевернуть значения.

В моем случае он работает сейчас (я получил те же значения для Windows XP/Vista/7 и Windows 8).

Удачи!

Ответ 2

Просто выключите флип, используя флаг "flip" функции flibAndCodeBytes, когда Windows 8 или больше.

bool shoulFlipBytes = true;
if(IsWin8OrLater()) shouldFlipBytes = false;

flipAndCodeBytes(buffer,
                 descrip->SerialNumberOffset,
                 shouldFlipBytes,
                 serialNumber);

Вы можете использовать это для проверки версии Windows:

#include <windows.h>

bool IsWin8OrLater() {
    DWORD version = GetVersion();
    DWORD major = (DWORD) (LOBYTE(LOWORD(version)));
    DWORD minor = (DWORD) (HIBYTE(LOWORD(version)));

    return (major > 6) || ((major == 6) && (minor >= 2));
}

Согласно http://msdn.microsoft.com/en-us/library/ms724832%28VS.85%29.aspx (Благодаря ChrisV Определите, является ли O/S Windows 7)

Ответ 3

В основном вы полагаетесь на данные, которые не являются строго надежными для начала. Приводы могут меняться в течение всего срока службы компьютера; все время получая точно правильный серийный номер, даже не важно для вашего продукта.

Один простой хак, о котором я могу думать, это нормализовать серийный номер, например. путем сортировки цифр; это заставит больше дисков выглядеть одинаково, но я сомневаюсь, что это станет проблемой.

Другой способ взглянуть на проблему заключается в том, что приложение должно предусматривать изменения серийного номера; пользователь может быть проинформирован о проблеме лицензирования (по каким-либо причинам) и попросил связаться с отделом поддержки с помощью сгенерированного кода (не обязательно самого серийного номера). Учитывая этот код, поддержка может затем создать новую лицензию для клиента.

Ответ 4

Кажется, вам нужно проверить версию Windows через API и добавить if() в ваш код, если версия достаточно высока

Мои разработчики нашли другую проблему с этим методом - такой код IOCtl полагается на программу, которая запускается с правами администратора на Win7\Win8+. В связи с нашим программным обеспечением это сервис, который запускается с правами системы и клиентским программным обеспечением, которое строго выполняется с правами пользователя

Ответ 5

Для целей проверки лицензий вам все равно. Все, что вам нужно знать, это то, что некоторые конфигурации приводят к перевороту, некоторые - нет, и это может измениться в течение срока действия лицензии.

Так что принимайте оба варианта:

string serial = get_serial();
if (license_check(serial)) {
    licensed = true;
    return;
}
serial = swap_bytes(serial);
if (license_check(serial)) {
    licensed = true;
    return;
}

(Я вижу, что Раймонд предложил это в комментарии)

Отсутствует хрупкая проверка ОС, не стоит беспокоиться о том, не удалось ли она щелкнуть, когда пользователь подал заявку на получение лицензии. Просто счастливые пользователи.