Windows 8 在Windows XP、Vista和7中,HDD序列号每2个字节翻转一次,但在Windows 8中不翻转

Windows 8 在Windows XP、Vista和7中,HDD序列号每2个字节翻转一次,但在Windows 8中不翻转,windows-8,ioctl,deviceiocontrol,Windows 8,Ioctl,Deviceiocontrol,我需要获取硬盘序列号才能将其用作软件许可的密钥。 我在这个url中使用了diskid32代码: 它使用了DeviceIoControlWin32 API,IO控制代码为IOCTL\u STORAGE\u QUERY\u属性 成功了。然而,当我仔细检查打印在硬盘上的实际序列号时,我发现数字的每两个字节都会被翻转 一个简单的解决方案可以是简单地翻转字节。它在WindowsXP、Vista和Windows7中工作,但在Windows8中不需要翻转 我想知道为什么在Windows XP、Vista和7中

我需要获取硬盘序列号才能将其用作软件许可的密钥。 我在这个url中使用了diskid32代码: 它使用了DeviceIoControlWin32 API,IO控制代码为IOCTL\u STORAGE\u QUERY\u属性

成功了。然而,当我仔细检查打印在硬盘上的实际序列号时,我发现数字的每两个字节都会被翻转

一个简单的解决方案可以是简单地翻转字节。它在WindowsXP、Vista和Windows7中工作,但在Windows8中不需要翻转

我想知道为什么在Windows XP、Vista和7中翻转字节,为什么在Windows 8中不翻转字节下一个窗口如何

代码的一部分有一些小改动:

  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 );

        ...
     }

基本上,你所依赖的数据一开始并不严格可靠。驱动器可能会在计算机的整个生命周期内发生变化;一直以来,获得准确的序列号对您的产品甚至都不重要

我能想到的一个简单的方法是规范序列号,例如对数字进行排序;这将使更多的驱动器看起来相似,但我怀疑这是否会成为一个问题

看待这个问题的另一种方式是,应用程序应该提供序列号更改;可以将许可问题告知用户(无论出于何种原因),并要求用户使用生成的代码(不一定是序列号本身)联系支持部门。有了这些代码,支持人员就可以为客户创建新的许可证。

我在软件许可中使用相同的方法(和相同的代码)。是的,Windows 8出于某种原因正在为此方法返回翻转的值,我说不出原因(因此我无法回答您的问题)

我的解决方案就是您指出的:再次翻转值。 因此,在调用“flipAndCodeBytes”之后,您可以测试是否是Windows 8操作系统,并翻转值

在我的例子中,它现在可以工作了(我在Windows XP/Vista/7和Windows 8中得到了相同的值)


祝你好运

当windows 8或更高版本时,只需使用flibAndCodeBytes函数的“flip”标志关闭翻转

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));
}
#包括
bool IsWin8OrLater(){
DWORD版本=GetVersion();
德沃德大调=(德沃德)(洛比特(洛沃德(版本));
德沃德小调=(德沃德)(希比特(洛沃德(版本));
返回(大调>6)| |((大调==6)和&(小调>=2));
}

(感谢ChrisV)

似乎您必须通过API检查windows版本,并在版本足够高时将if()分支添加到代码中


我的开发人员发现了这个方法的另一个问题——这种IOCtl代码依赖于程序在Win7\Win8+上以管理员权限运行。由于我们的软件,它是使用系统权限运行的服务,而客户端软件严格使用用户权限运行。出于许可证检查的目的,您真的不在乎。您需要知道的是,有些配置会导致翻转,有些则不会,并且在许可证的有效期内可能会发生更改

因此,接受这两种变体:

string serial = get_serial();
if (license_check(serial)) {
    licensed = true;
    return;
}
serial = swap_bytes(serial);
if (license_check(serial)) {
    licensed = true;
    return;
}
(我看到雷蒙德在评论中提出了这一点)


没有脆弱的操作系统检查,不必担心当用户申请许可证时,操作系统是否无法向右翻转。只是快乐的用户。

Win8通常有很多针对旧Windows错误的修复程序,这些错误由于兼容性原因而被搁置。通过使用WMI、Win32_DiskDrive类、SerialNumber属性将自己与此隔离。虽然我同意@HansPassant,但我强烈反对将硬盘序列号用作软件的唯一标识符,这不是因为它很容易伪造,但是,由于序列号是产品供应商的独立编号,因此在最坏的情况下,您可能会得到重复的产品密钥。据我所知,计算机上唯一“认证”的唯一标识符是MAC地址或IPv6地址。所有这些解决方案的问题在于,它们只将您绑定到特定的硬件组件,而不是特定的盒子。如果您只需要它是一种独特的方式来阻止偶然的盗版,为什么还要费心翻转它们呢?每次你在同一台计算机上阅读时,它都会与最初的翻转阅读相匹配。虽然如果用户升级到windows 8并选择“保留我的程序和数据”可能会导致问题,但某些系统中可能不存在@Kris网络适配器,或者我的网络适配器可能已禁用。在像我这样的小企业中,复制HDD序列号的可能性很低,可以忽略。@Luke我的主要问题是一些用户将其系统从windows 7升级到windows 8,以前的激活码在他们的系统上不起作用。如果用户只使用windows 7或8,则根本没有问题。另一种算法:检查序列号。如果不匹配,请翻转字节并再次检查。或者直接调用。当然,
bool应该翻转字节=!iWindows8OrCreater()