生成相同的计算机硬件 ID。 (CHID) 喜欢来自 Windows SDK 的 computerhardwareids.exe

Generate the same computer hardware id. (CHID) like computerhardwareids.exe from Windows SDK

简介

本帖应该是 2017 年 this first thread from 2014 and this second one 的完结篇。

简而言之,您只需要知道 Microsoft Windows SDK 包含一个名为 computerhardwareids.exe 的程序,正如其名称一样建议,它为计算机生成(多个)硬件标识符,我想使用 .NET 复制 CHID 算法以生成与该程序生成的标识符相同的标识符。

此程序可以在 Windows 10 上生成的 CHIDS 列表,这是我正在使用的 O.S,列出 here:

  1. HardwareID-0 制造商 + 系列 + 产品名称 + SKU 编号 + BIOS 供应商 + BIOS 版本 + BIOS 主要版本 + BIOS 次要版本
  2. HardwareID-1 制造商 + 系列 + 产品名称 + BIOS 供应商 + BIOS 版本 + BIOS 主要版本 + BIOS 次要版本
  3. HardwareID-2 制造商 + 产品名称 + BIOS 供应商 + BIOS 版本 + BIOS 主要版本 + BIOS 次要版本
  4. HardwareID-3 制造商 + 系列 + 产品名称 + SKU 编号 + 底板制造商 + 底板产品
  5. HardwareID-4 制造商 + 系列 + 产品名称 + SKU 编号
  6. HardwareID-5 制造商 + 系列 + 产品名称
  7. HardwareID-6 制造商 + SKU 编号 + 底板制造商 + 底板产品
  8. HardwareID-7 制造商 + SKU 编号
  9. HardwareID-8 制造商+产品名称+底板制造商+底板产品
  10. HardwareID-9 制造商 + 产品名称
  11. HardwareID-10 制造商 + 系列 + 底板制造商 + 底板产品
  12. HardwareID-11 制造商 + 系列
  13. HardwareID-12 制​​造商 + 外壳类型
  14. HardwareID-13厂商+底板厂商+底板产品
  15. HardwareID-14 制造商

问题

我设法复制了所有硬件 ID,除了:0、1、2 和 12

我发现这四个有问题的标识符有一个共同点,即它们是唯一包含数值以附加到用于生成 UUID 的字符串的标识符。请参阅 table in this link 或阅读此列表:

我认为这是一个明显的迹象,表明我在构建用于生成 UUID 的字符串时不知道如何处理这些数值。

问题

我不知道在哪个 WMI class 中找到 Enclosure Type 值,但这没关系,因为我真的不关心复制HardwareID-12 / Enclosure Type 值,但我希望能够复制 HardwareID-0, HardwareID-1HardwareID-2

我已经知道从哪个 WMI class 获取 HardwareID-0HardwareID-1[= 的 BIOS 主要和次要发行版本109=] 和 HardwareID-2,但问题是,当我将这些 BIOS 值附加到用于生成 UUID 的字符串时,我得到的 UUID 与 computerhardwareids.exe 生成.

我的问题是:

  • 我需要做些什么才能为 HardwareID-0HardwareID-1 复制完全相同的生成 UUID和 HardwareID-2?.

  • 也许我需要以特殊方式处理这些数值,在将它们附加到用于生成 UUID 的字符串时应用一些我不知道的格式?

请注意,我没有逆向工程经验。

代码

这是我使用的代码,用 VB.NET 编写。在目前的状态下,我认为它是一个可行的解决方案,可以复制(或者应该复制)与 computerhardwareids.exe 程序生成的相同的计算机硬件 ID,但硬件 ID 0、1、2 除外和 12 因为我已经解释过的原因。

  1. 计算机硬件id类型枚举

     ' https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer
     Public Enum ComputerHardwareIdMicrosoftType
    
         ''' <summary>
         ''' HardwareID-0
         ''' <para></para>
         ''' Manufacturer + Family + Product Name + SKU Number + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
         ''' </summary>
         HardwareID_0 = 0
    
         ''' <summary>
         ''' HardwareID-1
         ''' <para></para>
         ''' Manufacturer + Family + Product Name + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
         ''' </summary>
         HardwareID_1 = 1
    
         ''' <summary>
         ''' HardwareID-2
         ''' <para></para>
         ''' Manufacturer + Product Name + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
         ''' </summary>
         HardwareID_2 = 2
    
         ''' <summary>
         ''' HardwareID-3
         ''' <para></para>
         ''' Manufacturer + Family + Product Name + SKU Number + Baseboard Manufacturer + Baseboard Product
         ''' </summary>
         HardwareID_3 = 3
    
         ''' <summary>
         ''' HardwareID-4
         ''' <para></para>
         ''' Manufacturer + Family + Product Name + SKU Number
         ''' </summary>
         HardwareID_4 = 4
    
         ''' <summary>
         ''' HardwareID-5
         ''' <para></para>
         ''' Manufacturer + Family + Product Name
         ''' </summary>
         HardwareID_5 = 5
    
         ''' <summary>
         ''' HardwareID-6
         ''' <para></para>
         ''' Manufacturer + SKU Number + Baseboard Manufacturer + Baseboard Product
         ''' </summary>
         HardwareID_6 = 6
    
         ''' <summary>
         ''' HardwareID-7
         ''' <para></para>
         ''' Manufacturer + SKU Number
         ''' </summary>
         HardwareID_7 = 7
    
         ''' <summary>
         ''' HardwareID-8
         ''' <para></para>
         ''' Manufacturer + Product Name + Baseboard Manufacturer + Baseboard Product
         ''' </summary>
         HardwareID_8 = 8
    
         ''' <summary>
         ''' HardwareID-9
         ''' <para></para>
         ''' Manufacturer + Product Name
         ''' </summary>
         HardwareID_9 = 9
    
         ''' <summary>
         ''' HardwareID-10
         ''' <para></para>
         ''' Manufacturer + Family + Baseboard Manufacturer + Baseboard Product
         ''' </summary>
         HardwareID_10 = 10
    
         ''' <summary>
         ''' HardwareID-11
         ''' <para></para>
         ''' Manufacturer + Family
         ''' </summary>
         HardwareID_11 = 11
    
         ''' <summary>
         ''' HardwareID-12
         ''' <para></para>
         ''' Manufacturer + Enclosure Type
         ''' </summary>
         HardwareID_12 = 12
    
         ''' <summary>
         ''' HardwareID-13
         ''' <para></para>
         ''' Manufacturer + Baseboard Manufacturer + Baseboard Product
         ''' </summary>
         HardwareID_13 = 13
    
         ''' <summary>
         ''' HardwareID-14
         ''' <para></para>
         ''' Manufacturer
         ''' </summary>
         HardwareID_14 = 14
    
     End Enum
    
  2. 计算机硬件id生成方法:

     Public Shared Function GetComputerHardwareIdFromMicrosoftHwIdType(hwidType As ComputerHardwareIdMicrosoftType) As Guid
    
         Select Case hwidType
             Case Is < 0, Is > 14
                 Throw New InvalidEnumArgumentException(argumentName:=NameOf(hwidType), invalidValue:=hwidType, enumClass:=GetType(ComputerHardwareIdMicrosoftType))
    
         '' *************************************************************
         '' HARDWARE TYPE ID. 0, 1 AND 2 ARE NOT GIVING THE CORRECT GUID.
         '' *************************************************************
             Case 0, 1, 2, 12
                 Throw New NotImplementedException("This hardware id type is not implemented.")
         End Select
    
         ' Namespace used by 'computerhardwareids.exe' program included in the Windows SDK.
         ' 
         ' https://blogs.gnome.org/hughsie/2017/04/25/reverse-engineering-computerhardwareids-exe-with-winedbg/
         Dim namespaceUUID As Guid = Guid.Parse("70ffd812-4c7f-4c7d-0000-000000000000")
    
         ' Win32_ComputerSystem fields
         Dim manufacturer, family, productName, skuNumber As String
    
         ' Win32_BaseBoard fields
         Dim baseBoardManufacturer, baseBoardProduct As String
    
         ' Win32_BIOS fields
         Dim biosVendor, biosVersion, biosMajorRelease, biosMinorRelease As String
    
         ' Retrieve computer info.
         Using mos As New Management.ManagementObjectSearcher()
    
             ' Win32_ComputerSystem
             mos.Query.QueryString = "select Manufacturer,Model,SystemFamily,SystemSKUNumber from Win32_ComputerSystem"
             Using systemInfo As Management.ManagementObject = mos.Get(0)
                 manufacturer = CStr(systemInfo.Properties("Manufacturer").Value).Trim()
                 productName = CStr(systemInfo.Properties("Model").Value).Trim()
                 family = CStr(systemInfo.Properties("SystemFamily").Value).Trim()
                 skuNumber = CStr(systemInfo.Properties("SystemSKUNumber").Value).Trim()
             End Using
    
             ' Win32_BaseBoard
             mos.Query.QueryString = "select Manufacturer,Product from Win32_BaseBoard"
             Using baseBoardInfo As Management.ManagementObject = mos.Get(0)
                 baseBoardManufacturer = CStr(baseBoardInfo.Properties("Manufacturer").Value).Trim()
                 baseBoardProduct = CStr(baseBoardInfo.Properties("Product").Value).Trim()
             End Using
    
             ' Win32_BIOS
             mos.Query.QueryString = "select Manufacturer,SMBIOSBIOSVersion,SystemBiosMajorVersion,SystemBiosMinorVersion from Win32_BIOS"
             Using biosInfo As Management.ManagementObject = mos.Get(0)
                 biosVendor = CStr(biosInfo.Properties("Manufacturer").Value).Trim()
                 biosVersion = CStr(biosInfo.Properties("SMBIOSBIOSVersion").Value).Trim()
                 biosMajorRelease = CStr(biosInfo.Properties("SystemBiosMajorVersion").Value).Trim()
                 biosMinorRelease = CStr(biosInfo.Properties("SystemBiosMinorVersion").Value).Trim()
             End Using
    
         End Using
    
     #If DEBUG Then
         ' Console.WriteLine($"{NameOf(manufacturer)}          = {manufacturer}")
         ' Console.WriteLine($"{NameOf(productName)}           = {productName}")
         ' Console.WriteLine($"{NameOf(family)}                = {family}")
         ' Console.WriteLine($"{NameOf(skuNumber)}             = {skuNumber}")
         ' Console.WriteLine($"{NameOf(baseBoardManufacturer)} = {baseBoardManufacturer}")
         ' Console.WriteLine($"{NameOf(baseBoardProduct)}      = {baseBoardProduct}")
         ' Console.WriteLine($"{NameOf(biosVendor)}            = {biosVendor}")
         ' Console.WriteLine($"{NameOf(biosVersion)}           = {biosVersion}")
         ' Console.WriteLine($"{NameOf(biosMajorRelease)}      = {biosMajorRelease}")
         ' Console.WriteLine($"{NameOf(biosMinorRelease)}      = {biosMinorRelease}")
     #End If
    
         Dim stringToHash As String = String.Empty
    
         Select Case hwidType
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_0
                 stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_1
                 stringToHash = $"{manufacturer}&{family}&{productName}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_2
                 stringToHash = $"{manufacturer}&{productName}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_3
                 stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}&{baseBoardManufacturer}&{baseBoardProduct}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_4
                 stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_5
                 stringToHash = $"{manufacturer}&{family}&{productName}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_6
                 stringToHash = $"{manufacturer}&{skuNumber}&{baseBoardManufacturer}&{baseBoardProduct}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_7
                 stringToHash = $"{manufacturer}&{skuNumber}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_8
                 stringToHash = $"{manufacturer}&{productName}&{baseBoardManufacturer}&{baseBoardProduct}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_9
                 stringToHash = $"{manufacturer}&{productName}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_10
                 stringToHash = $"{manufacturer}&{family}&{baseBoardManufacturer}&{baseBoardProduct}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_11
                 stringToHash = $"{manufacturer}&{family}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_13
                 stringToHash = $"{manufacturer}&{baseBoardManufacturer}&{baseBoardProduct}"
    
             Case ComputerHardwareIdMicrosoftType.HardwareID_14
                 stringToHash = manufacturer
    
         End Select
    
         ' Creates a name-based UUID using the algorithm from RFC 4122 §4.3.
         ' 
         Dim generateGuidDelegate As Func(Of Guid, String, Guid) =
             Function(namespaceId As Guid, name As String) As Guid
    
                 ' Converts a GUID (expressed as a byte array) to/from network order (MSB-first).
                 Dim swapByteOrderDelegate As New Action(Of Byte())(
                     Sub(ByVal guid() As Byte)
                         Dim temp As Byte = guid(0)
                         guid(0) = guid(3)
                         guid(3) = temp
    
                         temp = guid(1)
                         guid(1) = guid(2)
                         guid(2) = temp
    
                         temp = guid(4)
                         guid(4) = guid(5)
                         guid(5) = temp
    
                         temp = guid(6)
                         guid(6) = guid(7)
                         guid(7) = temp
                     End Sub)
    
                 ' Convert the name to a sequence of octets (as defined by the standard or conventions of its namespace) (step 3).
                 Dim nameBytes() As Byte = Encoding.Unicode.GetBytes(name)
    
                 ' Convert the namespace UUID to network order (step 3).
                 Dim namespaceBytes() As Byte = namespaceId.ToByteArray()
                 swapByteOrderDelegate.Invoke(namespaceBytes)
    
                 ' Compute the hash of the name space ID concatenated with the name (step 4).
                 Dim hash As Byte()
                 Using algorithm As HashAlgorithm = SHA1.Create()
                     algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, Nothing, 0)
                     algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length)
                     hash = algorithm.Hash
                 End Using
    
                 ' Most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12).
                 Dim newGuid(15) As Byte
                 Array.Copy(hash, 0, newGuid, 0, 16)
    
                 ' Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field
                 ' to the appropriate 4-bit version number from Section 4.1.3 (step 8).
                 newGuid(6) = CByte((newGuid(6) And &HF) Or (5 << 4))
    
                 ' Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved
                 ' to zero and one, respectively (step 10).
                 newGuid(8) = CByte((newGuid(8) And &H3F) Or &H80)
    
                 ' Convert the resulting UUID to local byte order (step 13).
                 swapByteOrderDelegate.Invoke(newGuid)
                 Return New Guid(newGuid)
             End Function
    
         Return generateGuidDelegate.Invoke(namespaceUUID, stringToHash)
    
     End Function
    
  3. 用法示例:

     'Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(0)}}}    <- Manufacturer + Family + ProductName + SKUNumber + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
     'Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(1)}}}    <- Manufacturer + Family + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
     'Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(2)}}}    <- Manufacturer + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(3)}}}    <- Manufacturer + Family + ProductName + SKUNumber + Baseboard Manufacturer + Baseboard Product")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(4)}}}    <- Manufacturer + Family + ProductName + SKUNumber")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(5)}}}    <- Manufacturer + Family + ProductName")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(6)}}}    <- Manufacturer + SKUNumber + Baseboard Manufacturer + Baseboard Product")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(7)}}}    <- Manufacturer + SKUNumber")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(8)}}}    <- Manufacturer + ProductName + Baseboard Manufacturer + Baseboard Product")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(9)}}}    <- Manufacturer + ProductName")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(10)}}}    <- Manufacturer + Family + Baseboard Manufacturer + Baseboard Product")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(11)}}}    <- Manufacturer + Family")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(13)}}}    <- Manufacturer + Baseboard Manufacturer + Baseboard Product")
     Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(14)}}}    <- Manufacturer")
    

通过反复尝试可能的格式,我发现数值(字节类型)必须转换为十六进制,并且它们必须是 lower-casing.

因此,我在主 post 中发布的 source-code 中唯一需要做的更改是为了复制 Hardware-Id 0、1、2,这是:

biosMajorRelease = CByte(biosInfo.Properties("SystemBiosMajorVersion").Value).ToString("X2").ToLower()
biosMinorRelease = CByte(biosInfo.Properties("SystemBiosMinorVersion").Value).ToString("X2").ToLower()

当然还有删除 NotImplementedException 行。

现在代码可以获取除 HardwareId-12 之外的所有硬件 ID,因为我不知道在哪个 WMI class 中可以找到 Enclosure Type 值,顺便说一下,它也是一个字节类型。

但这并不重要。在 14 个中,我有 13 个正在工作的 CHIDS,我认为这是一个非常好的比率,最终说这是一个完整的托管解决方案,可以复制 computerhardwareids.exe 所做的事情,尽管我没有我没有在我的电脑上测试它。