The
SystemIdentification
runtime class
(introduced in the Windows 10 Anniversary Update)
gives you a signature for a Windows system that
will remain unchanged even if the user reinstalls Windows.
There are some caveats, though.
To obtain a value that is consistent across reinstalls of Windows,
the method uses the Trusted Platform Module (TPM),
or if a TPM is not available, the
Unified Extensible Firmware Interface (UEFI).
If neither is available,
then starting in the Fall Creators Update,
the method creates a unique ID and saves it in the registry.
The registry value is preserved across upgrades, but is lost
if the user performs a clean install of Windows.
You can use the Source property to determine how
the signature was generated.
The value you receive is specific to the publisher specified in your application manifest. If you are a classic Win32 app with no manifest, then the system will use a generic "publisher" that is used for all publisher-less apps. Signatures generated for apps with the same publisher will match. Signatures generated for apps with different publishers will not match.
Here's some sample code:
// JavaScript
var buffer = Windows.System.Profile.SystemIdentification.
getSystemIdForPublisher();
var id = buffer.id;
var asHex = Windows.Security.Cryptography.CryptographicBuffer.
encodeToHexString(id);
var asBase64 = Windows.Security.Cryptography.CryptographicBuffer.
encodeToBase64String(id);
// C#
var buffer = Windows.System.Profile.SystemIdentification.
GetSystemIdForPublisher();
var id = buffer.Id;
var asHex = Windows.Security.Cryptography.CryptographicBuffer.
EncodeToHexString(id);
var asBase64 = Windows.Security.Cryptography.CryptographicBuffer.
EncodeToBase64String(id);
// C++/CX
auto buffer = Windows::System::Profile::SystemIdentification::
GetSystemIdForPublisher();
auto id = buffer->Id;
auto asHex = Windows::Security::Cryptography::CryptographicBuffer::
EncodeToHexString(id);
auto asBase64 = Windows::Security::Cryptography::CryptographicBuffer.
EncodeToBase64String(id);
// C++/WinRT
auto buffer = Windows::System::Profile::SystemIdentification::
GetSystemIdForPublisher();
auto id = buffer.Id();
auto asHex = Windows::Security::Cryptography::CryptographicBuffer::
EncodeToHexString(id);
auto asBase64 = Windows::Security::Cryptography::CryptographicBuffer.
EncodeToBase64String(id);
// Raw C++ with WRL
using namespace ABI::Windows::Storage::Streams;
using namespace ABI::Windows::System::Profile;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
ComPtr<ISystemIdentificationStatics> systemIdStatics;
RoGetActivationFactory(HStringReference(
RuntimeClass_Windows_System_Profile_SystemIdentification).Get(),
IID_PPV_ARGS(&systemIdStatics));
ComPtr<ISystemIdentificationInfo> info;
systemIdStatics->GetSystemIdForPublisher(&info);
ComPtr<IBuffer> id;
info->get_Id(&id);
ComPtr<ICryptographicBufferStatics> cryptoBufferStatics;
RoGetActivationFactory(HStringReference(
RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(),
IID_PPV_ARGS(&cryptoBufferStatics));
HString asHex;
cryptoBufferStatics->EncodeToHexString(id.Get(),
asHex.GetAddressOf());
HString asBase64;
cryptoBufferStatics->EncodeToBase64String(id.Get(),
asBase64.GetAddressOf());
If you want to operate with the raw bytes instead of just
encoding them into hex or base64,
you can
use the IBufferByteAccess interface
or the CryptographicBuffer.CopyToByteArray method.
You ask how, I ask why.
What is the legitimate use case for this technology? I can think of plenty of reasons why I’d love to see something like this if I was writing malware, (or advertising, but I repeat myself,) but no reasons to want to do it that don’t involve causing problems for the person on whose computer this code is running.
From what I can gather, the intended audience is mobile device management. If the phone gets wiped and then re-enrolls, the enrollment utility can detect this and reuse the provisioning resources.
Could this also be used for “Trial-Ware” where time-limited versions of programs can’t have the clock reset by reinstalling?
Licensing. Like it or not, Windows, Quickbooks, Oracle, and so many others pin activation to some magic mix of hardware and software; no one has to use it, but at least Microsoft is providing a transparent API instead of some wholly private one.
Thou has summoned the third rail.
About 20 years ago Intel wanted to put a per-CPU identifier in the processor and the consumer market said NO!
This time it got done silently. Expect in a couple of years a consumer demand at the system level to break this trick.
How is this different from Intel’s processor ID that made everyone so angry in the 1990s ?
How does that compare to HKLM\Software\Microsoft\Cryptography\MachineGuid? That has been available for longer
This is one of two things people call “the machine guid” and you can reset this one by deleting the registry value (you will probably loose the ability to decrypt certain secrets already stored on the machine by crypto stuff). It might also be the same value on different machines when a machine is cloned etc.
What would be the implications if the identifier was the same for all publishers, rather than being publisher-specific?
The code libraries published by advertisers for inclusion in sundry applications would be able to positively identify when different instances in different apps were in fact running on the same device. That in turn would allow the advertiser to aggregate information across uses and interests spanning different apps by different publishers, which by many is seen as a violation of individuals’ expectations of privacy.
I can sort of see the argument, Real Men Use Raw C++
The times they are a-changing. I remember when the Pentium CPU introduced a serial number to identify customers at the end of the nineties. A huge backlash caused Intel to disable it. 20 years later, no one seems to care.
Anyway, https://en.wikipedia.org/wiki/Pentium_III#Controversy_about_privacy_issues if you want to know more