Эта ветка должна стать завершающей главой для этот первый поток от 2014 года и этот второй от 2017 года.
Короче говоря, вам просто нужно знать, что Microsoft Windows SDK включает в себя программу под названием computerhardwareids.exe, которая, как следует из ее названия, генерирует (несколько) аппаратных идентификаторов для компьютера, и я хотел бы воспроизвести алгоритм CHID, используя .NET для создания тех же идентификаторов, что и эта программа.
Список CHIDS, которые эта программа может генерировать в Windows 10, которую я использую, указан как здесь:
Мне удалось воспроизвести все идентификаторы оборудования, кроме: 0, 1, 2 и 12.
Я обнаружил, что эти четыре проблемных идентификатора имеют общее то, что они единственные, которые содержат числовые значения для добавления к строке, с помощью которой генерируется UUID. См. таблицу по этой ссылке или прочтите этот список:
Имя | Длина | Тип
Основная версия системного BIOS | БАЙТ | Варьируется
Второстепенная версия системного BIOS | БАЙТ | Варьируется
Тип корпуса | БАЙТ | Варьируется
Я думаю, что это явный признак того, что я не знаю, как обращаться с этими числовыми значениями при построении строки, с помощью которой генерируется UUID.
Я не знаю, в каком классе WMI найти значение Тип корпуса, но это не имеет значения, потому что я действительно не забочусь о репликации значения HardwareID-12/Тип корпуса, но я хотел бы иметь возможность реплицировать HardwareID-0, HardwareID-1 и HardwareID-2
Я уже знаю, из какого класса WMI получить основную и дополнительную версию BIOS для HardwareID-0, HardwareID-1 и HardwareID-2, но проблема в том, что когда я добавляю эти значения BIOS к строке, с помощью которой создается UUID, я получаю совершенно другое UUID из того, что генерирует computerhardwareids.exe.
Мои вопросы:
Что мне нужно сделать, чтобы воспроизвести точно такой же сгенерированный UUID для HardwareID-0, HardwareID-1 и HardwareID-2?.
Может быть, мне нужно обрабатывать эти числовые значения особым образом, применяя какой-то формат, который я не знаю, при добавлении их к строке, с которой генерируется UUID?
Обратите внимание, что у меня НЕТ опыта реверс-инжиниринга.
Это код, который я использую, написанный на VB.NET. В его текущем состоянии я считаю его рабочим решением, которое реплицирует (или должно реплицировать) те же идентификаторы оборудования компьютера, что и программа computerhardwareids.exe, за исключением идентификаторов оборудования 0, 1, 2 и 12 по причинам, которые я объяснил.
Перечисление типа идентификатора компьютерного оборудования
' 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
Метод генерации идентификатора аппаратного обеспечения компьютера:
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://stackoverflow.com/questions/25190906/get-hardware-ids-like-microsoft-does/43619888#43619888
' 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.
' https://stackoverflow.com/questions/61267254/generating-uuid-based-on-strings
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
Пример использования:
'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")
Путем проб и ошибок, пробуя возможные форматы, я обнаружил, что числовые значения (типа byte) должны быть преобразованы в шестнадцатеричные числа и они должны быть в нижнем регистре.
Итак, единственные изменения, которые мне нужно внести в исходный код, который я опубликовал в основном посте, и для репликации Hardware-Id 0, 1, 2, это:
biosMajorRelease = CByte(biosInfo.Properties("SystemBiosMajorVersion").Value).ToString("X2").ToLower()
biosMinorRelease = CByte(biosInfo.Properties("SystemBiosMinorVersion").Value).ToString("X2").ToLower()
Это и, конечно же, удалить строку Нереализованное исключение.
Теперь код работает, чтобы получить все идентификаторы оборудования, кроме HardwareId-12, потому что я не знаю, в каком классе WMI найти значение типа корпуса, которое, кстати, тоже является байтовым типом.
Но на самом деле это не имеет значения. У меня есть 13 работающих CHIDS из 14, и я считаю, что это очень хорошая оценка, чтобы наконец сказать, что это полное управляемое решение для воспроизведения того, что делает computerhardwareids.exe, хотя я не тестировал его на своем ПК.