Windows GDID 完整分析报告
摘要
对微软全局设备标识符(GDID)的详细逆向工程揭示,它是一个通过微软账户分配的64位Passport唯一ID,打破了其源自硬件序列号的传言。该报告记录了从wlidsvc到Connected Devices Platform再到Delivery Optimization的完整技术栈。
查看缓存全文
缓存时间: 2026/07/06 23:07
SmtimesIWndr/gdid-reversal 来源:https://github.com/SmtimesIWndr/gdid-reversal
完整逆向分析 Windows GDID
全局设备标识符完整逆向工程
主要来源‑8a2be2) 平台‑0078d6) 符号方法声明 微软的“全局设备标识符”(Global Device Identifier),即2026年7月Scattered Spider起诉书中提到的持久性Windows指纹,其实际生成、存储和传输方式。
TL;DR
下方所列内容正确,但缺少部分信息。无论是否登录Microsoft帐户,你都会拥有一个GDID。我发帖时并未意识到这一点,但后来进行了调查。CDP有一条匿名设备路径,当未连接MSA时会被使用。底层系统在事实上仍然正确,只是缺少了几点内容。
- GDID是真实的遥测项。 它出现在美国联邦刑事起诉书(United States v. Peter Stokes,伊利诺伊州北区,2026年7月)中,格式为
Global Device Identifier g:6755467234350028。 - 它是Microsoft帐户的“设备PUID”。 一个64位的Passport唯一标识符(Passport Unique ID),当Windows安装注册到Microsoft帐户时分配,在设备图中写作
g:。 - 那些说法是错误的。 它不是“128位”,也不是“由序列号生成”。法院记录本身说明重新安装会产生新的GDID,这排除了它是由GPU等硬件序列号推导而来的可能。
- 从下到上的堆栈:
wlidsvc(Microsoft帐户服务)使用login.live.com配置设备,得到设备PUID -> 存储到注册表 -> 连接设备平台(cdp.dll/CDPSvc)读取该值并将其注册到**设备目录服务(Device Directory Service,DDS)**图中 -> 传递优化(Delivery Optimization)将其报告为文档中的UCDOStatus.GlobalDeviceId。 - 所有步骤均在一台运行Windows 11(26200)的实机上使用公共符号进行了复现。你可以通过一次注册表读取找到自己的GDID(§7)。
可信度标注。 每项声明都带有标签,供自行判断:
[COURT]原始来源事实,[OBSERVED]在我的测试机上实机复现,[STATIC]通过二进制文件和公共Windows PDB证明,[ASSESSED]基于证据的有力推断。
目录
- 背景:法院实际说了什么
- 戳破那些爆火的谣言
- GDID出现在哪里:传递优化
- 谁拥有它:连接设备平台到DDS
- CDP如何获取:它消费,不计算
- 铸造者:MSA设备PUID(
wlidsvc) - 找到你自己的GDID
- 减少暴露风险
- 方法论(可复现)
- 局限与坦诚说明
1. 背景:法院实际说了什么
2026年7月1日,美国司法部公布了对Peter Stokes的刑事起诉书,他被指控是Scattered Spider(又名Octo Tempest / UNC3944 / 0ktapus)的成员。宣誓书描述了微软如何帮助FBI将活动归因到一台设备。
[COURT]来自补充起诉书(¶25,第34页),原文:“该ngrok账户是通过全局设备标识符 g:6755467234350028(以下简称“GDID”)设置的。据微软代表称,Windows生态系统中的全局设备标识符是一种持久的、设备级别的标识符,旨在唯一标识一台设备上的Windows操作系统安装……GDID是全局唯一的标识符,与设备上Windows的安装绑定。GDID在设备上的Windows操作系统更新过程中保持不变,但重新安装Windows……将产生一个新的唯一GDID。”
脚注还提到一个Microsoft用户可以拥有多个GDID。宣誓书随后将GDID的IP历史记录和浏览记录(例如 empirehotelnyc.com,一个Growtopia/Ubisoft登录URL)与嫌疑人登录的账户关联起来。
这里有两件事支撑了本报告的其余部分:
- 该值是
g:加上一个十进制整数(g:6755467234350028)。转为十六进制是0x0018000FC8CB93CC,因此是一个 64位 数字。 - 重新安装会产生新的GDID。 因此它不可能仅仅是固定硬件参数的函数。
2. 戳破那些爆火的谣言
社交媒体摘要声称GDID是*“安装时由序列号生成的128位标识符”。* 两个部分都是错误的:
| 声明(社交媒体) | 现实(原始来源) |
|---|---|
| “128位” | 起诉书中的值是 g:6755467234350028,这是一个十进制数,适合 64位(0x0018000FCB8CB93CC)。 |
| “安装时由序列号生成” | 起诉书指出重新安装会产生新的GDID。如果是从固定序列号派生出来的值,重新安装后应该相同,不会改变。 |
在进一步逆向CDP后,我提供了一些错误信息。使用本地帐户并不能阻止GDID。如果未使用Microsoft帐户,CDP会采用匿名设备路径。阅读时请记住这一点。
3. GDID出现在哪里:传递优化
[STATIC] 微软公共Azure Monitor文档在 UCDOStatus(更新合规性 / 传递优化)表中定义了一个 GlobalDeviceId 列:
GlobalDeviceId(string):“Microsoft global device identifier. This is an identifier used by Microsoft internally.”
它紧挨着 LastCensusSeenTime、ISP、City、Country 等字段,因此设备ID与地理位置和IP对齐。这是微软在公开文档中命名该值的唯一地方。但传递优化只是报告它。重要的是它并不拥有这个值。向上游追踪,你会到达连接设备平台。
4. 谁拥有它:连接设备平台到DDS
[STATIC] C:\Windows\System32\cdp.dll(连接设备平台,服务 CDPSvc + CDPUserSvc)包含 GlobalDeviceId 符号以及一整套**设备目录服务(Device Directory Service)**注册子系统:
ddsregistrationclient.cpp ddsregistrationmanager.cpp ddsregistrationinfo.cpp DdsRegistrationClient RegisterUserDevicesObserver DdsRegistrationInfoProviderForCDP endpoints: dds.microsoft.com fd.dds.microsoft.com aad.cs.dds.microsoft.com cdpcs.access.microsoft.com device-id format string: "g:%s"
DDS = 设备目录服务,微软的跨设备身份图(Phone Link、云端剪贴板、“在电脑上继续”、Nearby Share的后端)。CDP是注册安装到该图中的Windows客户端,其键值为 g:。
4.1 实机捕获
[OBSERVED] 强制进行全新注册(在清除本地状态后重启 CDPSvc)并捕获CDP自身的ETW提供程序,得到了完整握手:
text DdsClient::RegisterUserDeviceAsync() RegistrationReason: Startup Account Type: MSA DDSClient: Registration response received. HTTP status code: 200 OnRegisterUserDeviceComplete GetDeviceIdAndTicketActivity -> deviceid: 0018XXXXXXXXXXXX
该 deviceid 写作 g:,结构与起诉书中的值匹配:
| | 值 | 十六进制(64位) | 类别前缀 |
|—|—|—|—:|—|
| 我的机器(已遮盖) | g:XXXXXXXXXXXXXXXX | 0x0018XXXXXXXXXXXX | 0018 |
| 法院证据 | g:6755467234350028 | 0x0018000FC8CB93CC | 0018 |
两者都是64位值,位于相同的 0x0018 高位类别中(设备PUID命名空间,参见§6)。g: 前缀只是该整数的十进制表示。
5. CDP如何获取:它消费,不计算
[STATIC] 使用公共PDB(cdp.pdb),cdp.dll 中的设备ID路径仅仅是向身份栈发起请求并等待。CDP从不自行计算ID:
mermaid flowchart TD A["GetStableDeviceIdFromProvider0x0A3140"] --> B["provider.GetStableDeviceIdAsync(vtable +0x48)"] B --> C["OneCoreAccountProvider::GetStableDeviceIdAsync 0x0C8370"] C --> D["IWebAccountBackedAccountProvider(MSA / AAD identity COM)"] D --> E["OnGetStableDeviceIdCompleted(const char* deviceId) 0x06CEA0"] E -->|"assign() string, signal flag"| A
接收它的回调函数使其显而易见。该ID作为字符串出现,仅被存储:
asm ; OnGetStableDeviceIdCompleted mov rbp, r9 ; r9 = device-id STRING handed in by the identity provider lea rcx, [rsi+0xD8] ; CDP member field mov rdx, rbp call assign@basic_string ; store it, no computation, no serials call Set@CdpWaitableFlag ; unblock the waiter
底线: GDID是在CDP之下,在Windows身份栈底部铸造而成,然后作为一个不透明的字符串交给CDP。这指向了Microsoft帐户服务。
6. 铸造者:MSA设备PUID(wlidsvc)
[STATIC] C:\Windows\System32\wlidsvc.dll,即 Microsoft帐户 / Passport(Windows Live ID)服务,是唯一包含字面 GlobalDeviceId 的身份二进制文件,并拥有完整的设备配置机制:
CDeviceIdentityBase::CreateNewDeviceIdentity / Provision / BindDeviceToHardware / GetDeviceCert DeviceAssociateRequest (Passport PPCRL SOAP -> login.live.com) ... DeviceIdStore::LogToRegistry BCryptGenRandom / CCryptRandom::GenRandom (device KEY, not the id)
该标识符是一个设备PUID(Passport Unique ID),一个64位的MSA标识符。其中的 BCryptGenRandom 生成的是设备身份验证密钥,BindDeviceToHardware 将其绑定到机器,而不是PUID。
6.1 由服务器分配
[STATIC] 客户端从服务器的SOAP响应中提取PUID,通过XPath进入响应体:
/S:Envelope/S:Body/ps:DeviceUpdatePropertiesResponse/HWPUIDFlipped
CAssociateDeviceRequest::ParseResponseBody 及相关 ParseResponse 方法将响应XML节点读入BSTR。因此流程是:客户端配置设备 -> login.live.com 分配并返回设备PUID -> 客户端存储该PUID。这正是为什么重新安装会产生新的GDID(新的配置,新的服务器分配PUID),以及为什么它不是一个硬件哈希。
6.2 以明文形式持久化存储
[OBSERVED] Microsoft帐户身份存储将值直接保留在注册表中,位于你自己的用户配置单元中:
HKCU\SOFTWARE\Microsoft\IdentityCRL\ExtendedProperties LID = 0018XXXXXXXXXXXX HKCU\SOFTWARE\Microsoft\IdentityCRL\Immersive\production\Token\{...} DeviceId = 0018XXXXXXXXXXXX
与CDP实时注册到DDS的值逐字节相同。你的用户帐户PUID是一个不同的数字,存储在其他地方,如 puid = 0003...(例如 00034002XXXXXXXX)。还有一个以PUID命名的HKLM缓存键(HKLM\SOFTWARE\Microsoft\IdentityCRL\NegativeCache\_),但那个是系统(SYSTEM)级别的,因此你需要从HKCU中读取该值。
前缀告诉你它是什么。 用户PUID是
0003类别,设备PUID是0018类别。法院的GDID(0018000FCB8CB93CC)位于0018设备PUID空间内,与我的相同。
6.3 它验证图端点
[OBSERVED] MSA令牌缓存(HKLM\SOFTWARE\Microsoft\IdentityCRL\NegativeCache\...)包含设备令牌,其范围正好是CDP使用的端点:
scope=service::dds.microsoft.com::MBI_SSL_TOKEN_BROKER scope=service::activity.windows.com::MBI_SSL_SA_TOKEN_BROKER
因此,Microsoft帐户服务提供设备凭据,用于验证DDS注册和携带GDID的活动上传。
6.4 完整链路
mermaid flowchart TD subgraph MSA["MSA identity layer: wlidsvc.dll"] A1["Provision device with login.live.com(Passport PPCRL SOAP)"] --> A2["Server assigns Device PUID<ps:DevicePUID> / HWPUIDFlipped"] A2 --> A3["Store DeviceId / LID = PUIDHKLM\...\IdentityStore"] A3 --> A4["Issue device tokens fordds.microsoft.com and activity.windows.com"] end subgraph CDP["Device graph client: cdp.dll / CDPSvc"] B1["GetStableDeviceId -> receives PUID string"] --> B2["RegisterUserDeviceAsync -> DDSOBSERVED: HTTP 200"] end subgraph SRV["Server: Device Directory Service"] C1["Keys g:PUID to the MSA account,activity and IP history"] end subgraph REP["Reporting"] D1["Delivery Optimization ->UCDOStatus.GlobalDeviceId"] end A4 --> B1 B2 --> C1 C1 --> D1
起诉书中所指出的关于“GDID”的一切——每次安装持久存在、更新后保持不变、重新安装后更新、与Microsoft帐户绑定、可跨IP和浏览记录追踪——全部源于它是服务器分配的MSA设备PUID,由CDP注册到设备图中。
7. 找到你自己的GDID
[OBSERVED] 在已登录Microsoft帐户的机器上,只需一次从你自己的用户配置单元中读取注册表,无需管理员权限:
powershell (Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\IdentityCRL\ExtendedProperties').LID
这将给出你的设备PUID,为16位十六进制数字(例如 0018XXXXXXXXXXXX)。要查看服务器端显示的 g: 形式:
powershell $hex = (Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\IdentityCRL\ExtendedProperties').LID "g:$([Convert]::ToUInt64($hex,16))"
如果 ExtendedProperties\LID 在你的机器上为空,相同的值位于 HKCU\SOFTWARE\Microsoft\IdentityCRL\Immersive\production\Token\{...}\DeviceId 下。
不要发布你自己的值。 你的设备PUID、你的MSA CID(
0003...)以及你的用户SID都可以去匿名化。在任何公开发布中请遮盖它们。唯一安全引用的值是法院的那个,因为它已经是公开的。
8. 减少暴露风险
GDID的存在是因为你的设备已注册到Microsoft帐户设备图中,并且连接设备平台保持同步。要减少它:
- 关闭连接设备平台(
CDPSvc、CDPUserSvc)并关闭活动历史记录(设置 → 隐私 → 活动历史记录)以停止图同步和活动上传。 - 删除
%LOCALAPPDATA%\ConnectedDevicesPlatform仅会清除本地CDP状态。PUID会从身份存储中立即回来,因此单独这样做是不够的。 - 重新安装会给你一个新的GDID(起诉书如此说明),但一旦再次注册,它就会与一个新的GDID绑定。
9. 方法论(可复现)
所有内容均来自一台标准Windows 11(build 26200)机器。
- 实机捕获: 使用
logman在强制全新CDPSvc注册时捕获CDP的TraceLogging ETW提供程序(Microsoft.Windows.CDP.*),并使用tracerpt解码。 - 注册表和令牌缓存:
IdentityStore和IdentityCRL位于HKLM\SOFTWARE\Microsoft下。ETW和静态分析是实际有效的方法。代理只会浪费你的时间。
附录:CDP ETW提供程序GUID(点击展开)
通过EventSource名称哈希(命名空间加上UTF-16BE大写的提供程序名称的SHA1)计算。对照已知的 System.Runtime 值 49592c0f-5a05-516d-aa4b-a64e02026c89 进行验证:
Microsoft.Windows.CDP.Core {7762de0c-b0a6-571a-68d3-c018bf009496} Microsoft.Windows.CDP.Core.Error {a1ea5efc-402e-5285-3898-22a5acce1b76} Microsoft.Windows.CDP.CDS {dfa6e32a-095f-5f57-d025-0887d33507a1} Microsoft.Windows.CDP.Aggr {bc1826c8-369c-5b0b-4cd1-3c6ae5bfe2e7} Microsoft.Windows.CDP.AFS {5fe36556-c4cd-509a-8c3e-2a547ea568ae} Microsoft.Windows.CDP.OnecoreAccountProvider {4ee5bf9a-3e8f-540b-8bfb-12457a2854b6} Microsoft.Windows.CDP {9f4cc6dc-1bab-5772-0c71-a89954718d66}
附录:关键二进制文件和符号(点击展开)
| 二进制文件 | 角色 | 显著符号 |
|---|---|---|
wlidsvc.dll | Microsoft帐户 / Passport服务,铸造设备PUID | CDeviceIdentityBase::CreateNewDeviceIdentity,CAssociateDeviceRequest::ParseResponseBody,DeviceIdStore::LogToRegistry |
cdp.dll | 连接设备平台,注册PUID到DDS | DdsRegistrationClient,GetStableDeviceIdFromProvider(0x0A3140),OnGetStableDeviceIdCompleted(0x06CEA0) |
dosvc.dll / DO | 将ID报告为 UCDOStatus.GlobalDeviceId | 无 |
注册表:HKLM\SOFTWARE\Microsoft
相似文章
微软确认Windows GDID设备标识符无法禁用,已在FBI案件文件中记录
微软确认存在无法禁用的Windows GDID设备标识符,该信息已在FBI案件文件中记录,引发隐私担忧。
GDID Windows – 切断即使在VPN下仍追踪你的跟踪器
一篇文章解释Windows如何携带一个持久标识符(GDID),即使在VPN后方仍能追踪用户,以及如何禁用发送该标识符的服务。
微软可以通过Windows设备ID追踪用户
微软可能通过唯一的Windows设备ID追踪用户,引发隐私担忧。
@DragonsCyberHQ: Windows PnP is the loader here. Attacker-controlled device identities can make Windows fetch and run vendor code as SYS…
Security researchers release a DEF CON 34 talk and tooling showing that Windows Plug and Play can silently download and execute vendor code as SYSTEM via attacker-controlled device identities, including through USB emulation and RDP USB redirection.
MS Paint 和 Photos 在即使本地生成的输出中隐形添加 GUID 水印
逆向工程揭示,Microsoft Paint 和 Photos 在本地生成的 AI 图像中嵌入服务器颁发的 GUID 作为隐形水印,即使图像生成是本地的,但提示词审核仍由远程处理。