[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-92281":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":8,"languages":8,"totalLinesOfCode":8,"stars":9,"forks":10,"watchers":11,"openIssues":12,"contributorsCount":12,"subscribersCount":12,"size":12,"stars1d":12,"stars7d":12,"stars30d":13,"stars90d":12,"forks30d":12,"starsTrendScore":12,"compositeScore":14,"rankGlobal":8,"rankLanguage":8,"license":8,"archived":15,"fork":15,"defaultBranch":16,"hasWiki":17,"hasPages":15,"topics":18,"createdAt":8,"pushedAt":8,"updatedAt":19,"readmeContent":20,"aiSummary":21,"trendingCount":12,"starSnapshotCount":12,"syncStatus":22,"lastSyncTime":23,"discoverSource":24},92281,"gdid-reversal","SmtimesIWndr\u002Fgdid-reversal","SmtimesIWndr",null,349,23,3,0,150,48.14,false,"main",true,[],"2026-07-22 04:02:05","\u003Cdiv align=\"center\">\n\n# Full writeup of the Windows GDID\n\n### Global Device Identifier fully reverse engineered\n![Primary source](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fprimary_source-US_v._Stokes_(N.D._Ill._2026)-8a2be2)\n![Platform](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-Windows_11_(26200)-0078d6)\n![Symbols](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fsymbols-Microsoft_public_PDBs-2ea44f)\n![Method](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fmethod-ETW_%2B_static_RE-orange)\n![Claims](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fclaims-confidence_tagged-informational)\n\n*How Microsoft's \"Global Device Identifier\", the persistent Windows fingerprint named in the July 2026 Scattered Spider complaint, is actually generated, stored, and transmitted.*\n\n\u003C\u002Fdiv>\n\n---\n\n## TL;DR\n\n> [!NOTE]\n> **Listed below is true, but missing some information. Regardless of being logged in with a MSA you WILL have a GDID. I didn't realize this at the time of posting but I looked into it. CDP has an anonymous device path that is used if no MSA has been connected. The underlying system is still factually correct just missing a few things.**\n\n- **GDID is a real telemetry item.** It shows up in the U.S. federal criminal complaint (*United States v. Peter Stokes*, N.D. Ill., July 2026) as `Global Device Identifier g:6755467234350028`.\n- **It is a Microsoft Account \"Device PUID\".** A 64 bit Passport Unique ID assigned to a Windows installation when it registers with a Microsoft Account, written in the device graph as `g:\u003Cdecimal>`.\n- **The claims are wrong.** It is **not** \"128 bit\" and **not** \"generated from serial numbers.\" The court record itself says a *reinstall produces a new GDID*, which rules out it being derived from hardware serials like your GPU.\n- **The stack, bottom to top:** `wlidsvc` (Microsoft Account service) provisions the device with `login.live.com` and gets back a device PUID -> stores it in the registry -> the Connected Devices Platform (`cdp.dll` \u002F `CDPSvc`) reads it and registers it into the **Device Directory Service (DDS)** graph -> Delivery Optimization reports it as the documented `UCDOStatus.GlobalDeviceId`.\n- All of it was reproduced on a live Windows 11 (26200) machine with public symbols. **You can find your own GDID in one registry read** ([§7](#7-find-your-own-gdid)).\n\n> [!NOTE]\n> **Confidence labelling.** Every claim is tagged so you can weigh each one yourself: `[COURT]` primary source fact, `[OBSERVED]` reproduced live on my test machine, `[STATIC]` proven from binaries and public Windows PDBs, `[ASSESSED]` strong inference from the evidence.\n\n---\n\n## Contents\n\n1. [Background: what the court actually said](#1-background-what-the-court-actually-said)\n2. [Debunking the viral myths](#2-debunking-the-viral-narrative)\n3. [Where GDID surfaces: Delivery Optimization](#3-where-gdid-surfaces-delivery-optimization)\n4. [Who owns it: Connected Devices Platform to DDS](#4-who-owns-it-the-connected-devices-platform-to-dds)\n5. [How CDP gets it: it consumes, it does not compute](#5-how-cdp-gets-it-it-consumes-it-does-not-compute)\n6. [The mint: MSA Device PUID (`wlidsvc`)](#6-the-mint-msa-device-puid-wlidsvc)\n7. [Find your own GDID](#7-find-your-own-gdid)\n8. [Reducing the exposure](#8-reducing-the-exposure)\n9. [Methodology (reproducible)](#9-methodology-reproducible)\n10. [Limitations and honest caveats](#10-limitations--honest-caveats)\n\n---\n\n## 1. Background: what the court actually said\n\nOn July 1, 2026 the DOJ unsealed a criminal complaint against Peter Stokes, an alleged member of *Scattered Spider* (a.k.a. Octo Tempest \u002F UNC3944 \u002F 0ktapus). The affidavit describes how Microsoft helped the FBI attribute activity to a device.\n\n> [!IMPORTANT]\n> **`[COURT]`** From the superseding complaint (¶25, p.34), verbatim:\n>\n> *\"the ngrok account was set up through **Global Device Identifier g:6755467234350028** ('the GDID'). According to a Microsoft representative, a Global Device Identifier in the Windows ecosystem is a **persistent, device level identifier designed to uniquely identify an installation of a Windows operating system** on a device... A GDID is a globally unique identifier tied to the **installation** of Windows on a device. A GDID remains consistent across Windows operating system updates on a device, but a **reinstall of Windows... will be tied to a new unique GDID.**\"*\n\nA footnote adds that one Microsoft user can have multiple GDIDs. The affidavit then correlates the GDID's IP history and browsing (e.g. `empirehotelnyc.com`, a Growtopia\u002FUbisoft login URL) with the accounts the suspect was logged into.\n\nTwo things here carry the rest of this writeup:\n\n1. The value is **`g:` plus a decimal integer** (`g:6755467234350028`). In hex that is `0x0018000FC8CB93CC`, so a **64 bit** number.\n2. **A reinstall gives a new GDID.** So it can't just be a function of unchanging hardware.\n\n---\n\n## 2. Debunking the viral narrative\n\nThe social media summary claimed the GDID is *\"a 128 bit identifier generated from serial numbers on install.\"* **Both halves are false:**\n\n| Claim (social media) | Reality (primary source) |\n|---|---|\n| \"128 bit\" | The value in the complaint is `g:6755467234350028`, a decimal that fits in **64 bits** (`0x0018000FC8CB93CC`). |\n| \"generated from serial numbers on install\" | The complaint says a **reinstall produces a new GDID**. A value derived from fixed serials would come back the same after a reinstall, not change. |\n\n> [!NOTE]\n> **After some more reversing of CDP. I provided some misinfo. Using a local account does not prevent a GDID. CDP has an anonymous device path that is taken if no microsoft account. Keep this in mind when reading.**\n\n---\n\n## 3. Where GDID surfaces: Delivery Optimization\n\n**`[STATIC]`** Microsoft's public Azure Monitor docs define a `GlobalDeviceId` column in the **`UCDOStatus`** (Update Compliance \u002F Delivery Optimization) table:\n\n> `GlobalDeviceId` (string): *\"Microsoft global device identifier. This is an identifier used by Microsoft internally.\"*\n\nIt sits right next to `LastCensusSeenTime`, `ISP`, `City`, `Country`, so a device id lined up with geo and IP. This is the one place Microsoft names the value in public docs. But Delivery Optimization only **reports** it. Importantly it does NOT own it. Follow it upstream and you land on the Connected Devices Platform.\n\n---\n\n## 4. Who owns it: the Connected Devices Platform to DDS\n\n**`[STATIC]`** `C:\\Windows\\System32\\cdp.dll` (the Connected Devices Platform, services `CDPSvc` + `CDPUserSvc`) contains the `GlobalDeviceId` symbol and an entire **Device Directory Service** registration subsystem:\n\n```\nddsregistrationclient.cpp   ddsregistrationmanager.cpp   ddsregistrationinfo.cpp\nDdsRegistrationClient   RegisterUserDevicesObserver   DdsRegistrationInfoProviderForCDP\nendpoints: dds.microsoft.com  fd.dds.microsoft.com  aad.cs.dds.microsoft.com  cdpcs.access.microsoft.com\ndevice-id format string: \"g:%s\"\n```\n\n**DDS = Device Directory Service**, Microsoft's cross device identity graph (the backend behind Phone Link, cloud clipboard, \"Continue on PC\", Nearby Share). CDP is the Windows client that **registers the installation into that graph**, where it gets keyed as `g:\u003Cdecimal>`.\n\n### 4.1 Captured live\n\n**`[OBSERVED]`** Forcing a fresh registration (restart `CDPSvc` with its local state cleared) and capturing CDP's own ETW providers produced the whole handshake:\n\n```text\nDdsClient::RegisterUserDeviceAsync()   RegistrationReason: Startup   Account Type: MSA\nDDSClient: Registration response received. HTTP status code: 200\nOnRegisterUserDeviceComplete\nGetDeviceIdAndTicketActivity -> deviceid: 0018XXXXXXXXXXXX\n```\n\nThat `deviceid`, written as `g:\u003Cdecimal>`, matches the complaint's value structurally:\n\n| | value | hex (64 bit) | class prefix |\n|---|---|---|:---:|\n| **My machine (redacted)** | `g:XXXXXXXXXXXXXXXX` | `0x0018XXXXXXXXXXXX` | `0018` |\n| **Court exhibit** | `g:6755467234350028` | `0x0018000FC8CB93CC` | `0018` |\n\nBoth are 64 bit values in the same `0x0018` high word class (the device PUID namespace, see [§6](#6-the-mint-msa-device-puid-wlidsvc)). The `g:` prefix is just that integer in decimal.\n\n---\n\n## 5. How CDP gets it: it consumes, it does not compute\n\n**`[STATIC]`** With the public PDB (`cdp.pdb`), the device id path in `cdp.dll` is just a request and wait against the identity stack. CDP never computes the id itself:\n\n```mermaid\nflowchart TD\n    A[\"GetStableDeviceIdFromProvider\u003Cbr\u002F>0x0A3140\"] --> B[\"provider.GetStableDeviceIdAsync\u003Cbr\u002F>(vtable +0x48)\"]\n    B --> C[\"OneCoreAccountProvider::\u003Cbr\u002F>GetStableDeviceIdAsync 0x0C8370\"]\n    C --> D[\"IWebAccountBackedAccountProvider\u003Cbr\u002F>(MSA \u002F AAD identity COM)\"]\n    D --> E[\"OnGetStableDeviceIdCompleted\u003Cbr\u002F>(const char* deviceId) 0x06CEA0\"]\n    E -->|\"assign() string, signal flag\"| A\n```\n\nThe callback that receives it makes it obvious. The id shows up as a **string** and just gets stored:\n\n```asm\n; OnGetStableDeviceIdCompleted\nmov  rbp, r9                 ; r9 = device-id STRING handed in by the identity provider\nlea  rcx, [rsi+0xD8]         ; CDP member field\nmov  rdx, rbp\ncall assign@basic_string     ; store it, no computation, no serials\ncall Set@CdpWaitableFlag      ; unblock the waiter\n```\n\n**Bottom line:** the GDID is minted below CDP, down in the Windows identity stack, and handed to CDP as an opaque string. That points at the Microsoft Account service.\n\n---\n\n## 6. The mint: MSA Device PUID (`wlidsvc`)\n\n**`[STATIC]`** `C:\\Windows\\System32\\wlidsvc.dll`, the **Microsoft Account \u002F Passport (Windows Live ID) service**, is the only identity binary that contains the literal `GlobalDeviceId`, and it holds the full device provisioning machinery:\n\n```\nCDeviceIdentityBase::CreateNewDeviceIdentity \u002F Provision \u002F BindDeviceToHardware \u002F GetDeviceCert\nDeviceAssociateRequest      (Passport PPCRL SOAP -> login.live.com)\n\u003Cps:DevicePUID> ... \u003C\u002Fps:DevicePUID>\nDeviceIdStore::LogToRegistry\nBCryptGenRandom \u002F CCryptRandom::GenRandom     (device KEY, not the id)\n```\n\nThe identifier is a **Device PUID** (Passport Unique ID), a 64 bit MSA identifier. The `BCryptGenRandom` in there makes the device *authentication key* that `BindDeviceToHardware` pins to the machine, **not** the PUID.\n\n### 6.1 It is server assigned\n\n**`[STATIC]`** The client pulls the PUID out of the **server's SOAP response**, with an XPath into the response body:\n\n```\n\u002FS:Envelope\u002FS:Body\u002Fps:DeviceUpdatePropertiesResponse\u002FHWPUIDFlipped\n```\n\n`CAssociateDeviceRequest::ParseResponseBody` and the related `ParseResponse` methods read response XML nodes into BSTRs. So the flow is: **client provisions the device -> `login.live.com` assigns and returns the device PUID -> client stores it.** That is exactly why a reinstall produces a *new* GDID (new provisioning, new server assigned PUID), and why it is not a hardware hash.\n\n### 6.2 It is persisted in cleartext\n\n**`[OBSERVED]`** The Microsoft Account identity store keeps the value right in the registry, in your own user hive:\n\n```\nHKCU\\SOFTWARE\\Microsoft\\IdentityCRL\\ExtendedProperties\n    LID = 0018XXXXXXXXXXXX\n\nHKCU\\SOFTWARE\\Microsoft\\IdentityCRL\\Immersive\\production\\Token\\{...}\n    DeviceId = 0018XXXXXXXXXXXX\n```\n\nByte for byte the same value CDP registered into DDS live. Your user account PUID is a different number stored elsewhere as `puid = 0003...` (e.g. `00034002XXXXXXXX`). There's also an HKLM cache key named after the PUID (`HKLM\\SOFTWARE\\Microsoft\\IdentityCRL\\NegativeCache\\\u003CPUID>_\u003CuserSID>`), but that one is SYSTEM only, so you read the value out of HKCU.\n\n> [!NOTE]\n> **The prefix tells you what it is.** User PUIDs are `0003` class, **device** PUIDs are `0018` class. The court's GDID (`0018000FC8CB93CC`) is in the `0018` device PUID space, same as mine.\n\n### 6.3 It authenticates the graph endpoints\n\n**`[OBSERVED]`** The MSA token cache (`HKLM\\SOFTWARE\\Microsoft\\IdentityCRL\\NegativeCache\\...`) has device tokens scoped to exactly the endpoints CDP uses:\n\n```\nscope=service::dds.microsoft.com::MBI_SSL_TOKEN_BROKER\nscope=service::activity.windows.com::MBI_SSL_SA_TOKEN_BROKER\n```\n\nSo the Microsoft Account service hands out the device credentials that authenticate the DDS registration and the activity uploads that carry the GDID.\n\n### 6.4 The complete chain\n\n```mermaid\nflowchart TD\n    subgraph MSA[\"MSA identity layer: wlidsvc.dll\"]\n        A1[\"Provision device with login.live.com\u003Cbr\u002F>(Passport PPCRL SOAP)\"] --> A2[\"Server assigns Device PUID\u003Cbr\u002F>&lt;ps:DevicePUID&gt; \u002F HWPUIDFlipped\"]\n        A2 --> A3[\"Store DeviceId \u002F LID = PUID\u003Cbr\u002F>HKLM\\...\\IdentityStore\"]\n        A3 --> A4[\"Issue device tokens for\u003Cbr\u002F>dds.microsoft.com and activity.windows.com\"]\n    end\n    subgraph CDP[\"Device graph client: cdp.dll \u002F CDPSvc\"]\n        B1[\"GetStableDeviceId -> receives PUID string\"] --> B2[\"RegisterUserDeviceAsync -> DDS\u003Cbr\u002F>OBSERVED: HTTP 200\"]\n    end\n    subgraph SRV[\"Server: Device Directory Service\"]\n        C1[\"Keys g:PUID to the MSA account,\u003Cbr\u002F>activity and IP history\"]\n    end\n    subgraph REP[\"Reporting\"]\n        D1[\"Delivery Optimization ->\u003Cbr\u002F>UCDOStatus.GlobalDeviceId\"]\n    end\n    A4 --> B1\n    B2 --> C1\n    C1 --> D1\n```\n\nEverything the complaint pins on \"the GDID\", persistent per install, survives updates, new on reinstall, tied to a Microsoft Account, trackable across IPs and browsing, all of it falls out of this being a **server assigned MSA Device PUID that CDP registers into the device graph.**\n\n---\n\n## 7. Find your own GDID\n\n**`[OBSERVED]`** On a machine signed into a Microsoft Account, one registry read from your own user hive, no admin needed:\n\n```powershell\n(Get-ItemProperty 'HKCU:\\SOFTWARE\\Microsoft\\IdentityCRL\\ExtendedProperties').LID\n```\n\nThat gives you your device PUID as 16 hex digits (e.g. `0018XXXXXXXXXXXX`). To see it in the `g:\u003Cdecimal>` form the way it shows up server side:\n\n```powershell\n$hex = (Get-ItemProperty 'HKCU:\\SOFTWARE\\Microsoft\\IdentityCRL\\ExtendedProperties').LID\n\"g:$([Convert]::ToUInt64($hex,16))\"\n```\n\nIf `ExtendedProperties\\LID` is empty on your box, the same value is sitting under `HKCU\\SOFTWARE\\Microsoft\\IdentityCRL\\Immersive\\production\\Token\\{...}\\DeviceId`.\n\n> [!WARNING]\n> **Do not post your own value.** Your device PUID, your MSA CID (`0003...`), and your user SID all deanonymize you. Redact them in any public writeup. The only value that's safe to quote is the court's, because it's already public.\n\n---\n\n## 8. Reducing the exposure\n\nThe GDID exists because your device is registered into the Microsoft Account device graph and the Connected Devices Platform keeps it synced. To cut it back:\n\n- **Kill the Connected Devices Platform** (`CDPSvc`, `CDPUserSvc`) and turn off **Activity History** (Settings, Privacy, Activity history) to stop the graph sync and the activity uploads.\n- Deleting `%LOCALAPPDATA%\\ConnectedDevicesPlatform` only wipes local CDP state. The PUID comes right back from the identity store, so that alone won't cut it.\n- A **reinstall** gives you a new GDID (the complaint says so), but it gets tied to a fresh one the second it registers again.\n\n---\n\n## 9. Methodology (reproducible)\n\nAll of this came off a stock Windows 11 (build 26200) machine.\n- **Live capture:** CDP's TraceLogging ETW providers (`Microsoft.Windows.CDP.*`) via `logman` while forcing a fresh `CDPSvc` registration, decoded with `tracerpt`.\n- **Registry and token cache:** `IdentityStore` and `IdentityCRL` under `HKLM\\SOFTWARE\\Microsoft`.\n\nETW and static analysis is what actually worked. A proxy will just waste your time.\n\n\u003Cdetails>\n\u003Csummary>\u003Cb>Appendix: CDP ETW provider GUIDs\u003C\u002Fb> (click to expand)\u003C\u002Fsummary>\n\nComputed with the EventSource name hash (SHA1 of the namespace plus the UTF-16BE uppercased provider name). Verify it against the known `System.Runtime` value `49592c0f-5a05-516d-aa4b-a64e02026c89`:\n\n```\nMicrosoft.Windows.CDP.Core                    {7762de0c-b0a6-571a-68d3-c018bf009496}\nMicrosoft.Windows.CDP.Core.Error              {a1ea5efc-402e-5285-3898-22a5acce1b76}\nMicrosoft.Windows.CDP.CDS                     {dfa6e32a-095f-5f57-d025-0887d33507a1}\nMicrosoft.Windows.CDP.Aggr                    {bc1826c8-369c-5b0b-4cd1-3c6ae5bfe2e7}\nMicrosoft.Windows.CDP.AFS                     {5fe36556-c4cd-509a-8c3e-2a547ea568ae}\nMicrosoft.Windows.CDP.OnecoreAccountProvider  {4ee5bf9a-3e8f-540b-8bfb-12457a2854b6}\nMicrosoft.Windows.CDP                          {9f4cc6dc-1bab-5772-0c71-a89954718d66}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cb>Appendix: key binaries and symbols\u003C\u002Fb> (click to expand)\u003C\u002Fsummary>\n\n| Binary | Role | Notable symbols |\n|---|---|---|\n| `wlidsvc.dll` | Microsoft Account \u002F Passport service, **mints** the Device PUID | `CDeviceIdentityBase::CreateNewDeviceIdentity`, `CAssociateDeviceRequest::ParseResponseBody`, `DeviceIdStore::LogToRegistry` |\n| `cdp.dll` | Connected Devices Platform, **registers** PUID into DDS | `DdsRegistrationClient`, `GetStableDeviceIdFromProvider` (0x0A3140), `OnGetStableDeviceIdCompleted` (0x06CEA0) |\n| `dosvc.dll` \u002F DO | Reports the id as `UCDOStatus.GlobalDeviceId` | n\u002Fa |\n\nRegistry: `HKLM\\SOFTWARE\\Microsoft\\IdentityStore` (`DeviceId` and `LID`), `HKLM\\SOFTWARE\\Microsoft\\IdentityCRL\\NegativeCache` (token scopes).\n\n\u003C\u002Fdetails>\n\n> [!NOTE]\n> NullZeroX on twitter has told me that GDID is also sent regardless of being logged in with a ms account on your device. I'm not sure how true it is, but worth taking note.\n\n---\n\n\u003Cdiv align=\"center\">\n\n*Firsthand analysis. Corrections welcome. Also thanks claude for helping with this writeup and the diagrams :3*\n\n\n\u003C\u002Fdiv>\n","该项目完整逆向分析了Windows系统中的全局设备标识符（GDID），揭示其真实生成机制、存储位置与传输路径。核心发现包括：GDID实为64位Microsoft Account设备PUID，由wlidsvc服务从login.live.com获取并存于注册表，经CDP和DDS服务上报至Delivery Optimization；它并非128位或基于硬件序列号生成，重装系统即重置。项目结合ETW日志分析与静态逆向（基于微软公开PDB符号），在Windows 11 26200版本上全程复现验证。适用于隐私审计、合规评估、Windows遥测机制研究及司法技术取证等场景。",2,"2026-07-08 04:29:57","CREATED_QUERY"]