
マイクロソフトのGlobal Device Identifier (GDID)のリバースエンジニアリング分析。サーバー割り当てのMSA Device PUIDとしての生成、レジストリへの保存、Connected Devices Platformを介した送信、および再現可能なフォレンジック手法を明らかにする。
2026年7月のScattered Spider告訴状に記載された、Microsoftの永続的なWindowsフィンガープリント「Global Device Identifier」が、実際にどのように生成、保存、送信されるか。
[!NOTE] 以下に列挙した内容は真実ですが、一部情報が不足しています。MSAでログインしているかどうかにかかわらず、GDIDは存在します。投稿時点ではこれに気づいていませんでしたが、調査しました。CDPには、MSAが接続されていない場合に使用される匿名のデバイスパスがあります。基盤システムは事実上正しいですが、いくつかの点が欠けています。
Global Device Identifier g:6755467234350028 として登場します。g:<10進数> として書き込まれます。wlidsvc(Microsoftアカウントサービス)がデバイスを login.live.com にプロビジョニングし、Device PUIDを取得 -> レジストリに保存 -> Connected Devices Platform(cdp.dll / CDPSvc)がそれを読み取り、Device Directory Service(DDS) グラフに登録 -> Delivery Optimizationが文書化された UCDOStatus.GlobalDeviceId として報告します。[!NOTE] 信頼性ラベリング。 すべての主張にはタグが付いているので、各自で評価できます:
[COURT]一次情報源の事実、[OBSERVED]テストマシンで実際に再現、[STATIC]バイナリと公開Windows PDBから証明済み、[ASSESSED]証拠に基づく強い推定。
wlidsvc)2026年7月1日、DOJはScattered Spider(別名 Octo Tempest / UNC3944 / 0ktapus)のメンバーとされるPeter Stokesに対する刑事告訴状を公開しました。宣誓供述書は、MicrosoftがFBIがアクティビティをデバイスに関連付けるのをどのように支援したかを説明しています。
[!IMPORTANT]
[COURT]補充告訴状(¶25、p.34)からそのまま引用:「ngrokアカウントは、Global Device Identifier g:6755467234350028('GDID') を介して設定されました。Microsoftの担当者によると、WindowsエコシステムにおけるGlobal Device Identifierは、デバイス上のWindowsオペレーティングシステムのインストールを一意に識別するための永続的でデバイスレベルの識別子です...GDIDはデバイス上のWindowsのインストールに結び付けられたグローバルに一意の識別子です。GDIDはデバイス上のWindows OSアップデート全体で一貫していますが、Windowsの再インストール... は新しい一意のGDIDに結び付けられます。」
脚注には、1人のMicrosoftユーザーが複数のGDIDを持つことができると記載されています。宣誓供述書はその後、GDIDのIP履歴とブラウジング(例:empirehotelnyc.com、Growtopia/UbisoftログインURL)を、容疑者がログインしていたアカウントと関連付けています。
ここで2つの点がこの解析の残りを支えます:
g: に続く10進整数(g:6755467234350028)です。16進数では 0x0018000FC8CB93CC なので、64ビットの数値です。ソーシャルメディアの要約では、GDIDは*「インストール時にシリアル番号から生成された128ビットの識別子」*と主張していました。両方とも誤りです:
| 主張(ソーシャルメディア) | 現実(一次情報源) |
|---|---|
| 「128ビット」 | 告訴状の値は g:6755467234350028 で、64ビット(0x0018000FC8CB93CC)に収まる10進数です。 |
| 「インストール時にシリアル番号から生成」 | 告訴状は再インストールで新しいGDIDが生成されると述べています。固定シリアルから派生した値は再インストール後も同じになるはずであり、変化しません。 |
[!NOTE] CDPのリバースをさらに進めた結果、いくつかの誤情報を提供しました。ローカルアカウントを使用してもGDIDを防げるわけではありません。CDPには、Microsoftアカウントがない場合に使用される匿名のデバイスパスがあります。読む際はこれを考慮してください。
[STATIC] Microsoftの公開Azure Monitorドキュメントは、UCDOStatus(Update Compliance / Delivery Optimization)テーブルに GlobalDeviceId 列を定義しています:
GlobalDeviceId(文字列):「Microsoftグローバルデバイス識別子。これはMicrosoftが内部で使用する識別子です。」
これは LastCensusSeenTime、ISP、City、Country のすぐ隣にあり、デバイスIDが地理情報やIPと並んでいます。これがMicrosoftが公開ドキュメントで値を名前付きで示す唯一の場所です。しかし、Delivery Optimizationはそれを報告するだけです。重要なのは、これを所有していないことです。上流を追跡すると、Connected Devices Platformにたどり着きます。
[STATIC] C:\Windows\System32\cdp.dll(Connected Devices Platform、サービス 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 = Device Directory Service、Microsoftのクロスデバイス識別グラフ(Phone Link、クラウドクリップボード、「PCに続ける」、Nearby Shareの背後にあるバックエンド)。CDPは、インストールをそのグラフに登録するWindowsクライアントであり、g:<10進数> としてキー設定されます。
[OBSERVED] 新規登録を強制(CDPSvc をローカル状態をクリアして再起動)し、CDP自身のETWプロバイダーをキャプチャすると、ハンドシェイク全体が生成されました:
DdsClient::RegisterUserDeviceAsync() RegistrationReason: Startup Account Type: MSA
DDSClient: Registration response received. HTTP status code: 200
OnRegisterUserDeviceComplete
GetDeviceIdAndTicketActivity -> deviceid: 0018XXXXXXXXXXXX
その deviceid は g:<10進数> として書き込まれ、告訴状の値と構造的に一致します:
どちらも同じ 0x0018 上位ワードクラス(デバイスPUID名前空間、§6 参照)の64ビット値です。g: プレフィックスはその整数を10進数で表したものです。
[STATIC] cdp.pdb(公開PDB)を使用すると、cdp.dll 内のデバイスIDパスは、IDスタックに対する単なる要求と待機です。CDPはIDを自分で計算しません:
flowchart TD
A["GetStableDeviceIdFromProvider<br/>0x0A3140"] --> B["provider.GetStableDeviceIdAsync<br/>(vtable +0x48)"]
B --> C["OneCoreAccountProvider::<br/>GetStableDeviceIdAsync 0x0C8370"]
C --> D["IWebAccountBackedAccountProvider<br/>(MSA / AAD identity COM)"]
D --> E["OnGetStableDeviceIdCompleted<br/>(const char* deviceId) 0x06CEA0"]
E -->|"assign() string, signal flag"| Aそれを受け取るコールバックは明白です。IDは文字列として現れ、単に保存されます:
; OnGetStableDeviceIdCompleted
mov rbp, r9 ; r9 = IDプロバイダーから渡されたdevice-id STRING
lea rcx, [rsi+0xD8] ; CDPメンバーフィールド
mov rdx, rbp
call assign@basic_string ; 保存する、計算もシリアルもなし
call Set@CdpWaitableFlag ; 待機者をブロック解除
結論: GDIDはCDPの下、Windows IDスタックの奥で発行され、不透明な文字列としてCDPに渡されます。つまり、Microsoftアカウントサービスを指しています。
wlidsvc)[STATIC] C:\Windows\System32\wlidsvc.dll、Microsoftアカウント / Passport(Windows Live ID)サービスは、リテラル GlobalDeviceId を含む唯一のIDバイナリであり、完全なデバイスプロビジョニング機構を保持しています:
CDeviceIdentityBase::CreateNewDeviceIdentity / Provision / BindDeviceToHardware / GetDeviceCert
DeviceAssociateRequest (Passport PPCRL SOAP -> login.live.com)
<ps:DevicePUID> ... </ps:DevicePUID>
DeviceIdStore::LogToRegistry
BCryptGenRandom / CCryptRandom::GenRandom (デバイスKEY、IDではない)
識別子はDevice PUID(Passport Unique ID)、64ビットのMSA識別子です。BCryptGenRandom は、BindDeviceToHardware がマシンにピン留めするデバイス認証キーを作成するもので、PUIDではありません。
[STATIC] クライアントはサーバーのSOAP応答からPUIDを抽出し、応答本文へのXPathを使用します:
/S:Envelope/S:Body/ps:DeviceUpdatePropertiesResponse/HWPUIDFlipped
CAssociateDeviceRequest::ParseResponseBody および関連する ParseResponse メソッドは、応答XMLノードをBSTRに読み取ります。したがって、フローは次のようになります:クライアントがデバイスをプロビジョニング -> login.live.com がデバイスPUIDを割り当てて返す -> クライアントが保存します。 これこそが、再インストールで新しいGDIDが生成される理由(新しいプロビジョニング、新しいサーバー割り当てPUID)であり、ハードウェアハッシュではない理由です。
[OBSERVED] MicrosoftアカウントIDストアは、値を自分のユーザーハイブのレジストリに直接保持します:
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\<PUID>_<userSID>)が、それはSYSTEMのみなので、HKCUから値を読み取ります。
[!NOTE] プレフィックスで種類が分かります。 ユーザーPUIDは
0003クラス、デバイス PUIDは0018クラスです。裁判所のGDID(0018000FC8CB93CC)は、私のものと同じ0018デバイスPUID空間にあります。
[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を運ぶアクティビティアップロードを認証するデバイス資格情報を提供します。
flowchart TD
subgraph MSA["MSA IDレイヤー: wlidsvc.dll"]
A1["login.live.com でデバイスをプロビジョニング<br/>(Passport PPCRL SOAP)"] --> A2["サーバーがDevice PUIDを割り当て<br/><ps:DevicePUID> / HWPUIDFlipped"]
A2 --> A3["DeviceId / LID = PUID を保存<br/>HKLM\...\IdentityStore"]
A3 --> A4["dds.microsoft.com および<br/>activity.windows.com 用のデバイストークンを発行"]
end
subgraph CDP["デバイスグラフクライアント: cdp.dll / CDPSvc"]
B1["GetStableDeviceId -> PUID文字列を受信"] --> B2["RegisterUserDeviceAsync -> DDS<br/>OBSERVED: HTTP 200"]
end
subgraph SRV["サーバー: Device Directory Service"]
C1["g:PUID を MSAアカウント、<br/>アクティビティおよびIP履歴にキー設定"]
end
subgraph REP["報告"]
D1["Delivery Optimization -><br/>UCDOStatus.GlobalDeviceId"]
end
A4 --> B1
B2 --> C1
C1 --> D1告訴状が「GDID」に帰するすべてのもの(インストールごとに永続的、アップデート後も存続、再インストールで新規、Microsoftアカウントに結び付けられる、IPやブラウジング全体で追跡可能)は、これがサーバー割り当てのMSA Device PUIDであり、CDPがデバイスグラフに登録するものであるという事実からすべて導き出せます。
[OBSERVED] Microsoftアカウントでサインインしているマシンで、自分のユーザーハイブからレジストリを1回読むだけで、管理者権限は不要です:
(Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\IdentityCRL\ExtendedProperties').LID
これでデバイスPUIDが16桁の16進数で得られます(例:0018XXXXXXXXXXXX)。サーバー側で表示される g:<10進数> の形式で見るには:
$hex = (Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\IdentityCRL\ExtendedProperties').LID
"g:$([Convert]::ToUInt64($hex,16))"
自分のマシンで ExtendedProperties\LID が空の場合、同じ値が HKCU\SOFTWARE\Microsoft\IdentityCRL\Immersive\production\Token\{...}\DeviceId にあります。
[!WARNING] 自分の値を投稿しないでください。 デバイスPUID、MSA CID(
0003...)、ユーザーSIDはすべて匿名性を失わせます。公開記事では編集してください。安全に引用できる値は裁判所のものだけです。それはすでに公開されているからです。
GDIDが存在するのは、あなたのデバイスがMicrosoftアカウントのデバイスグラフに登録され、Connected Devices Platformがそれを同期し続けるためです。これを減らすには:
CDPSvc、CDPUserSvc)を停止し、アクティビティ履歴(設定、プライバシー、アクティビティ履歴)をオフにして、グラフ同期とアクティビティアップロードを停止します。%LOCALAPPDATA%\ConnectedDevicesPlatform を削除しても、ローカルのCDP状態が消えるだけです。PUIDはIDストアからすぐに戻ってくるため、それだけでは不十分です。これらはすべて、ストックのWindows 11(ビルド26200)マシンから得られました。
logman を使用してCDPのTraceLogging ETWプロバイダー(Microsoft.Windows.CDP.*)を、CDPSvc の新規登録を強制しながらキャプチャし、tracerpt でデコード。HKLM\SOFTWARE\Microsoft 以下の IdentityStore および IdentityCRL。実際に機能したのはETWと静的解析です。プロキシは時間の無駄になります。
EventSource名ハッシュ(名前空間のSHA1にUTF-16BE大文字化したプロバイダー名を連結)で計算。既知の 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}
[!NOTE] TwitterのNullZeroXから、デバイスにMSアカウントでログインしているかどうかに関係なく、GDIDも送信されると聞きました。どの程度真実かはわかりませんが、注意しておく価値はあります。
独自の分析。訂正歓迎。この記事と図の作成に協力してくれたclaudeにも感謝します。:3
| 値 | 16進数(64ビット) | クラスプレフィックス |
|---|
| 私のマシン(編集済み) | g:XXXXXXXXXXXXXXXX | 0x0018XXXXXXXXXXXX | 0018 |
| 法廷証拠 | g:6755467234350028 | 0x0018000FC8CB93CC | 0018 |
| バイナリ | 役割 | 注目すべきシンボル |
|---|
wlidsvc.dll | Microsoftアカウント / Passportサービス、Device PUIDを発行 | CDeviceIdentityBase::CreateNewDeviceIdentity、CAssociateDeviceRequest::ParseResponseBody、DeviceIdStore::LogToRegistry |
cdp.dll | Connected Devices Platform、PUIDをDDSに登録 | DdsRegistrationClient、GetStableDeviceIdFromProvider(0x0A3140)、OnGetStableDeviceIdCompleted(0x06CEA0) |
dosvc.dll / DO | IDを UCDOStatus.GlobalDeviceId として報告 | なし |
レジストリ:HKLM\SOFTWARE\Microsoft\IdentityStore(DeviceId および LID)、HKLM\SOFTWARE\Microsoft\IdentityCRL\NegativeCache(トークンスコープ)。