From 579044d0cf5d5953c288833f241d863fa95962c2 Mon Sep 17 00:00:00 2001 From: Bilel MEDIMEGH Date: Fri, 16 Dec 2022 16:50:24 +0100 Subject: [PATCH 1/2] Fix machine_id on windows to be like the steam client First, the first available physical network interface is found. Using registry keys to differentiate the physical ones. Then, instead of hashing only the MAC address, we hash 16 bytes where the first 8 are the MAC address. That is because the steam client on windows hashes the first 16 bytes of a struct containing the mac address at the start and only zeroes afterwards. --- SteamKit2/SteamKit2/Util/HardwareUtils.cs | 33 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/SteamKit2/SteamKit2/Util/HardwareUtils.cs b/SteamKit2/SteamKit2/Util/HardwareUtils.cs index 9e722ae84..75f8f632a 100644 --- a/SteamKit2/SteamKit2/Util/HardwareUtils.cs +++ b/SteamKit2/SteamKit2/Util/HardwareUtils.cs @@ -9,7 +9,6 @@ using SteamKit2.Util; using SteamKit2.Util.MacHelpers; using Microsoft.Win32; - using static SteamKit2.Util.MacHelpers.LibC; using static SteamKit2.Util.MacHelpers.CoreFoundation; using static SteamKit2.Util.MacHelpers.DiskArbitration; @@ -107,7 +106,37 @@ sealed class WindowsMachineInfoProvider : IMachineInfoProvider return Encoding.UTF8.GetBytes( guid.ToString()! ); } - public byte[]? GetMacAddress() => null; + // On windows, the steam client hashes the first 16 bytes of a struct of 4 uint, + // containing the mac address as the first field, in practice the second field is always zeroes + // So the hashed data ends up being (8bytes of mac address, 8 bytes of zeroes) + public byte[]? GetMacAddress() + { + // This part of the code finds the first *Physical* network interface + // based on : https://social.msdn.microsoft.com/Forums/en-US/46c86903-3698-41bc-b081-fcf444e8a127/get-the-ip-address-of-the-physical-network-card-?forum=winforms + NetworkInterface? goodAdapter = NetworkInterface.GetAllNetworkInterfaces() + .FirstOrDefault( adapter => + { + //Accessing the registry key corresponding to each adapter + string fRegistryKey = + $@"SYSTEM\CurrentControlSet\Control\Network\{{4D36E972-E325-11CE-BFC1-08002BE10318}}\{adapter.Id}\Connection"; + RegistryKey? rk = Registry.LocalMachine.OpenSubKey( fRegistryKey, false ); + if ( rk == null ) return false; + + string? pnpInstanceId = rk.GetValue( "PnpInstanceID", "" )?.ToString(); + + return pnpInstanceId?.Length > 3 && pnpInstanceId.StartsWith( "PCI" ); + } ); + + + if ( goodAdapter == null ) return null; + byte[] macAddress = goodAdapter.GetPhysicalAddress().GetAddressBytes(); + + // we need to pad the mac address to 16 bytes + byte[] macAddressPadded = new byte[ 16 ]; + Array.Copy( macAddress, macAddressPadded, macAddress.Length ); + + return macAddressPadded; + } public byte[]? GetDiskId() { From 472c19453b6b3ff7c8ba98b21c7ddd918eb785fd Mon Sep 17 00:00:00 2001 From: Bilel MEDIMEGH Date: Sat, 17 Dec 2022 13:36:48 +0100 Subject: [PATCH 2/2] Fix code, it is now accurate. --- SteamKit2/SteamKit2/Util/HardwareUtils.cs | 43 ++++++++++++----------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/SteamKit2/SteamKit2/Util/HardwareUtils.cs b/SteamKit2/SteamKit2/Util/HardwareUtils.cs index 75f8f632a..84742107c 100644 --- a/SteamKit2/SteamKit2/Util/HardwareUtils.cs +++ b/SteamKit2/SteamKit2/Util/HardwareUtils.cs @@ -9,6 +9,7 @@ using SteamKit2.Util; using SteamKit2.Util.MacHelpers; using Microsoft.Win32; + using static SteamKit2.Util.MacHelpers.LibC; using static SteamKit2.Util.MacHelpers.CoreFoundation; using static SteamKit2.Util.MacHelpers.DiskArbitration; @@ -106,15 +107,16 @@ sealed class WindowsMachineInfoProvider : IMachineInfoProvider return Encoding.UTF8.GetBytes( guid.ToString()! ); } - // On windows, the steam client hashes the first 16 bytes of a struct of 4 uint, - // containing the mac address as the first field, in practice the second field is always zeroes - // So the hashed data ends up being (8bytes of mac address, 8 bytes of zeroes) - public byte[]? GetMacAddress() + // On windows, the steam client hashes a 16 bytes struct + // containing the mac address of the first *Physical* network adapter padded to 8 bytes (mac addresses are 6 bytes) + // and the mac address of the second *Physical* network adapter also padded to 8 bytes. + // So the hashed data ends up being (6bytes of mac address, 10 bytes of zeroes) + public byte[] GetMacAddress() { - // This part of the code finds the first *Physical* network interface + // This part of the code finds *Physical* network interfaces // based on : https://social.msdn.microsoft.com/Forums/en-US/46c86903-3698-41bc-b081-fcf444e8a127/get-the-ip-address-of-the-physical-network-card-?forum=winforms - NetworkInterface? goodAdapter = NetworkInterface.GetAllNetworkInterfaces() - .FirstOrDefault( adapter => + return NetworkInterface.GetAllNetworkInterfaces() + .Where( adapter => { //Accessing the registry key corresponding to each adapter string fRegistryKey = @@ -122,20 +124,19 @@ sealed class WindowsMachineInfoProvider : IMachineInfoProvider RegistryKey? rk = Registry.LocalMachine.OpenSubKey( fRegistryKey, false ); if ( rk == null ) return false; - string? pnpInstanceId = rk.GetValue( "PnpInstanceID", "" )?.ToString(); - - return pnpInstanceId?.Length > 3 && pnpInstanceId.StartsWith( "PCI" ); - } ); - - - if ( goodAdapter == null ) return null; - byte[] macAddress = goodAdapter.GetPhysicalAddress().GetAddressBytes(); - - // we need to pad the mac address to 16 bytes - byte[] macAddressPadded = new byte[ 16 ]; - Array.Copy( macAddress, macAddressPadded, macAddress.Length ); - - return macAddressPadded; + return rk.GetValue( "PnpInstanceID", "" )?.ToString()?.Length > 3 && (rk.GetValue( "PnpInstanceID", "" )?.ToString()).StartsWith( "PCI" ); + } ) + .Select( networkInterface => networkInterface.GetPhysicalAddress().GetAddressBytes() + //pad all found mac addresses to 8 bytes + .Append( ( byte )0 ) + .Append( ( byte )0 ) + ) + //add fallbacks in case less than 2 adapters are found + .Append( Enumerable.Repeat( ( byte )0, 8 )) + .Append( Enumerable.Repeat( ( byte )0, 8 )) + .Take( 2 ) + .SelectMany( b => b ) + .ToArray(); } public byte[]? GetDiskId()