In my previous blog post about the hardware hash used with Windows Autopilot, as well as in the official documentation, it mentions that the exact algorithm for identifying a machine isn’t documented. But that doesn’t mean we can’t narrow it down.
Going back even further in the blog archive, I posted about using Fiddler to watch the network traffic generated during OOBE. In theory, I can use this same technique to see what was going on prior to what I looked at in that previous post. (One quick note: If you try this approach with Windows 11, you won’t see any network traffic from the key components that run during OOBE. This is caused by a “tweak” in Windows 11 OOBE: Instead of the machine OOBE process running as the Administrator account, it runs as defaultUser0. So when you exclude UWP apps in Fiddler to allow them to communicate with the loopback proxy server that Fiddler uses, you miss half of the apps that are needed. Prior to Windows 11, it didn’t switch to defaultUser0 until user OOBE. Not sure why this change was made, or where it is documented, but it does impact scenarios like this where you’re trying to capture network traffic from UWP apps, like the OOBE components. Hence I used Windows 10 for this post.)
Seeing the Autopilot profile-related settings received by the device is useful, but it doesn’t help answer the real question: How is the Autopilot hardware hash that you uploaded (or that the OEM handled for you) linked back to the device itself? Or flipping that around, what does the device send off to the cloud to ask “what do you have for me”?
Now you might think that all it really needs to do is send the hardware hash to the cloud and let the cloud do some calculations until it finds a match. But looking at the network trace shows that there is something else going on. First, the device registers itself via a request to https://login.live.com/ppsecure/deviceaddcredential.srf. Included in that request is a generated device “membername” and password — the device is registering itself with Passport.NET (remember that thing?), and passing along some device information at the same time:
But what do those DeviceInfo strings represent? Each is a base64-encoded string, so we can use Fiddler to decode them one by one, and then try to figure it out by looking at them:
- 4128: This one contains the MAC address of the computer (00 15 5D E9 DB 15).
- 4130: This one has the MAC address and the name of the bus the network adapter is connected to (e.g. VMBUS for a Hyper-V VM).
- 4112: This one has the details about the disk(s) in the computer, including the serial number of the device. (Weirdly, on a Hyper-V VM, the serial number reported in the hash is a string “|Virtual Disk |Msft “; physical disks appear to have a real serial number before that initial vertical bar).
- 4113: This one is a subset of the previous one, containing only the disk serial number.
- 4097, 4098: This is the manufacturer of the machine or system board (hard to tell for sure since the values are the same).
- 4099: This is the model of the computer.
- 4100: This is the SMBIOS board version.
- 4101: This is the SMBIOS serial number (the serial number assigned by the OEM to the device).
- 4102: This is the SMBIOS UUID (assigned by the OEM to the device).
8195: Our first mystery value, 56 bytes of “something.”
8196 and 8197: Our second and third mystery values. They are very similar in content, varying in the first few bytes and some toward the end.
4144: Another mystery, 32 bytes of something, perhaps a sha256 hash of something or a certificate thumbprint?
4145: Probably the SMBIOS chassis type for the computer (0x03 = desktop)
TPMInfo: This has the public key info for the certificate contained in the TPM.
4160, 4161: These are missing (at least in a VM), no value specified. I would guess that these contain product key information, which would only be populated on a machine that has an embedded Windows product key (not a VM).
So that takes us to another location in the Autopilot documentation. The answer is right under our noses:
“At a minimum, the following SMBIOS fields need to have unique values:
It’s logical that the list above corresponds to what is sent via this URL. So, I’ve got it covered. (It is a little weird for the Autopilot docs to talk about the OA/OA3 tool, but you can certainly see how it is related — normally that’s what the OEMs use to generate the hardware hash, hence the FAQ items in this section are targeting OEMs.)
But then what happens? If we look at the rest of the response, we can see it includes Windows licensing information (logical as the Autopilot process was built on top of the Windows Activation process):
It also includes some device IDs:
So at this point, Autopilot doesn’t need to provide details about the device hardware. Instead, it can just say “I am the device with this unique device ID.” Of course it doesn’t do that directly; instead it asks the system for a device token, and it provides that device token when it asks if there is an Autopilot profile assigned to the device:
How does it get that device token? That’s not entirely obvious — presumably there is a Windows API call that it uses to ask for that, and it can generate that token. That appears to be what the requests to https://login.live.com/RST2.srf are doing, especially this one as it references the Autopilot URL (ztd.dds.microsoft.com):
More “antiqueness” in that: SOAP requests, oasis-open.org references, etc. Think “precursor to MSA and AAD.” (There is similar code on GitHub, going back to the Passport SDK days.) And somewhere in the response is likely something usable to create the device token (one of these days, maybe I’ll figure out where), which is provided in the headers for the request to the Autopilot service:
So, we can see that this is an Autopilot-registered device, with all the values I configured in my Autopilot profile. (If you could come up with that token, you’d be able to make that GET request yourself — it would be nice to be able to check if a device presently has an Autopilot profile assigned.)
Looking a couple of frames higher, there is also a call to “cs.dds.microsoft.com” — it happens for every device, but the response is always the same:
So there was this idea of providing a consumer service that could welcome you to your new device (as you might see from an Apple or Amazon device) with a personalized message (e.g. with your name). And that was never actually delivered. Yet Windows still keeps calling the service, just in case someone ever changes their mind.
So we know what properties of the device are used, we just don’t know the how they are used, either hierarchically (e.g. use the TPM EKpub first, then fall back to another combination). That’s the subject for another blog…
Categories: Geeking Out
Hi Michael, I am trying to reach you on the Powershell script -Get-AutopilotDiagnostics that you want to run for diagnosing the issue. I want to make sure where this script can be run from? Should I run it from the laptop I am trying to join or should I run it from any other location? I tried downloading the file from the following location and I could not download the script as a .PS1 file from this location. It says copy and paste this “Install-Script -Name Get-AutopilotDiagnostics”
My concern is that the laptop I am trying to CONNECT is not getting the Domain Join profile that has been created. I need to troubleshoot that part and then why it is not getting the BLOB file from the Active Directory server. We have the Intune Connectors installed and delegated permissions to the OU where the objects are supposed to be joined in AD, but that is not happening. I am getting the error “Something went wrong” – Error code 80070774.
I unassigned the user, reset the PC, re-uploaded the device hash file but still nothing is happening same error. Any suggestions or thoughts?
It is designed to be run on the Autopilot device itself (e.g. shift-F10 after you get the error). The 80070774 error typically means the device never received an AD offline domain join blob. Check the logs on the ODJ server to see if it even processed a request. If it never received a request, then it’s a targeting issue for the domain join profile (especially tricky if this is a device you’ve deployed before). If it received a request but failed to generate the blob, then it’s an AD permissions issue most likely. If it generated a computer account (which you would be able to see in AD) but that didn’t make it back to the client, then a support case would be in order 🙂