
Windows XP / Windows Server 2003 VLK キージェネレーターです。このツールを使用すると、Raw Product Key に基づいて 有効な Windows XP キー を生成できます。このキーはランダムでかまいません。
Raw Product Key (RPK) は、9桁の XXX-YYYYYY の形式で提供され、Windows XP キーを生成するためにのみ必要です。

Releases タブに移動して、そこから最新バージョンをダウンロードしてください。
このプロジェクトは終了していません — 完成に向けて最善を尽くします。
一般に、あらゆるエディションとあらゆるビルド向けの有効な Windows XP キーを生成するうえで唯一の障壁となっているのは、pidgen.dll 内の公開鍵に対応する秘密鍵がそれぞれ存在しないことです。楕円曲線離散対数関数のコードはオンライン上で広く入手できず、その実行方法に関する曖昧な情報しかありません。
時が経つにつれ、この問題は 部分的に 解決されました。
BINK リソースは一切エンコードされておらず、データは単にリソースへ順番に書き込まれていました。sk00ter 氏は MDL フォーラムで BINK 形式についても完全に説明しました。 このテーマに関する先行するコミュニティの知識を活用して、Python 3 で BINK Reader を作成しました。このファイルはこのリポジトリで公開されており、ソースコードを表示するには ここをクリック してください。
離散対数問題の解法は、2023年5月28日 時点で最も研究が進んでいない領域です。しかし、私の友人である nephacks 氏は、インターネットの最も暗い隅でその難問を解決する入手困難なツールを実際に見つけました。 それは Mr. HAANDI による ECDLP (Elliptic Curve Discrete Logarithm Problem) Solver と呼ばれるものです。オンラインで見つけるのが非常に困難だったため、私の Web サイトに再アップロードしました。ツールは ここ からダウンロードできます。
ソルバーのバージョン 0.2a に付属する ReadMe ファイルはそれ自体で十分に優れているため、賢い人なら誰でもそのツールをセットアップできます。ただし、オープンソースではないため、私のキージェネレーターへの統合は不可能であることが実証されています。
理想的なシナリオでは、キージェネレーターは pidgen.dll から抽出した BINK リソースを入力として求め、それを次のセグメントに展開します:
pubX; pubY)genX; genY)a; b)pこれらのセグメントが分かれば、キージェネレーターは Schoof のアルゴリズムを使用してジェネレーターの位数 genOrder を総当たりで求め、続いて秘密鍵 privateKey を導出します。その際、計算された genOrder を活用して、最適な Pollard の Rho アルゴリズムを使用します。動作するアルゴリズムがあれば、最新の計算能力を使えば 20 分ほどでどんな秘密鍵もクラックできることに疑いの余地はありません。
キージェネレーターが正しい秘密鍵の総当たりを完了すると、タスクは実際にキーを生成することに帰着します。このキージェネレーターはまさにそれを行います。 よりよく理解していただくために、理想的なキージェネレーターの流れを示します。取り消し線が引かれているのは、私のキージェネレーターが実装している部分です:
genOrder, privateKey)ランダムな Raw Product Key をベースとして使用し、AAAAA-BBB-CCCCCCS-DDEEE の形式の Product ID を生成する必要があります。
OS ファミリ定数 AAAAA は Windows XP のシリーズごとに異なります。たとえば、SP3 では 76487 です。
BBB と CCCCCC の部分は、基本的に Raw Product Key をエンコードします。たとえば、最初の部分が XXX、2番目の部分が YYYYYY の場合、Raw Product Key は XXX-YYYYYY としてエンコードされます。
チェックディジット S は、それとすべての C の数字を加えた合計が 7 で割り切れる数になるように選択されます。
公開鍵インデックス DD は、Product Key の真正性の検証に使用された公開鍵がどれかを示します。たとえば、Professional キーでは 22、VLK キーでは 23 です。
ランダムな数 EEE は、毎回異なる Installation ID を生成するために使用されます。
Product Key 自体は (RPK と混同しないでください) FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK の形式で、アルファベット BCDFGHJKMPQRTVWXY2346789 を使用して Base-24 でエンコードされます。I と 1、O と 0 のように混同しやすい文字を除外するためです。
アルファベット容量の公式によれば、キーは最大 114 ビットの情報を含むことができます。 $$N = \log_2(24^{25}) \approx 114$$
この計算に基づいて、114 ビットの Product Key を 4 つの順序付きセグメントに展開します:
| セグメント |
|---|
簡単のため、Upgrade と Serial のセグメントを Data と呼ばれる単一のセグメントに結合します。この考え方により、Data を右にシフトして RPK を抽出し、ビットを左にシフトして戻すことができます。私が確認した有効なプロダクトキーのほとんどでは、Upgrade ビットが 1 に設定されていたからです。
Microsoft は Windows Server 2003 で Product Key 形式を再設計し、バックエンドサーバー認証キーを含めるようにしました。これはライセンス検証において実際に安全な手法であり、プライベートサーバーで採用した検証アルゴリズムを誰も推測できないようにするためです。オンライン検証メカニズムの追加に加えて、全体的な演算を 384 ビットから 512 ビットへ、署名スカラーを 62 ビットの情報へ引き上げました。
しかし、オンラインライセンス認証を考慮せずにキーを生成した場合でも、オペレーティングシステムのセットアップを通過できる有効なキーを生成することは可能でした。そして、まさにそれがこのコードの動作です。ランダムな 10 ビットの認証キーを生成します。今日では、ライセンス認証サーバーは停止しており、Server 2003 はアバンダンウェアとみなされているため、これはまったく問題になりません。このプロジェクト全体も同様に、海賊行為と見なされるべきではありません。
楕円曲線暗号 (ECC) は、公開鍵暗号システムの一種です。このクラスのシステムは、困難な「一方向」の数学的問題に依存しています。一方の方向への計算は簡単ですが、もう一方の方向への解決は困難です。これらは「トラップドア」関数と呼ばれることもあります。落ちるのは簡単でも、脱出するのは難しい関数です。[5]
ECC は次の形式の方程式を解くことに依存しています。 $$y^2 = x^3 + ax + b$$
一般に、暗号で利用される楕円曲線には 2 つの特殊なケースがあります。F2m と Fp です。両者はわずかに異なるだけです。両方の曲線は有限体上で定義され、Fp は 3 より大きい素数パラメータを使用し、F2m は $p = 2m$ を前提とします。Microsoft は後者をアルゴリズムで使用しました。
有限体 Fp 上の楕円曲線は、以下で構成されます:
F17 上の楕円曲線は次のようになります:

この曲線は、上の画像の青い点で構成されています。実際には、暗号で使用される「楕円曲線」は「正方行列内の点の集合」です。
上記の曲線は「学習用」です。これは非常に小さな鍵長 (4〜5 ビット) しか提供しません。実際の状況では、開発者は通常 256 ビット以上の曲線を使用します。
これは公開鍵暗号システムであるため、Microsoft は Windows XP のリリースに公開鍵を同梱し、入力されたプロダクトキーを照合できるようにする必要がありました。公開鍵は BINK リソースの形式で pidgen.dll 内に格納されています。最初の BINK データセットはリテールキーを検証するためのもので、2 番目はそれぞれ OEM キー用です。
Windows 98 および Windows XP の BINK リソースの構造は次のとおりです:
各セグメントは異なる色でマークされており、BINK ヘッダーの値は同じです。

Windows Server 2003 および Windows XP x64 では、異なる実装になっています:
そして、以下が BINK Reader 用に C で作成した構造体プロトタイプです:```c typedef struct _EC_BYTE_POINT { CHAR x[256]; // x-coordinate of the point on the elliptic curve. CHAR y[256]; // y-coordinate of the point on the elliptic curve. } EC_BYTE_POINT;
typedef struct _BINKHDR { // BINK version - not stored in the resource. ULONG32 dwVersion;
// Original BINK header.
ULONG32 dwID;
ULONG32 dwSize;
ULONG32 dwHeaderLength;
ULONG32 dwChecksum;
ULONG32 dwDate;
ULONG32 dwKeySizeInDWORDs;
ULONG32 dwHashLength;
ULONG32 dwSignatureLength;
// Extended BINK header. (Windows Server 2003+)
ULONG32 dwAuthCodeLength;
ULONG32 dwProductIDLength;
} BINKHDR;
typedef struct _BINKDATA { CHAR p[256]; // Finite Field order p. CHAR a[256]; // Elliptic Curve parameter a. CHAR b[256]; // Elliptic Curve parameter b.
EC_BYTE_POINT G; // Base point (Generator) G.
EC_BYTE_POINT K; // Public key K.
} BINKDATA;
typedef struct _BINKEY { BINKHDR header; BINKDATA data; } BINKEY;
さらに詳しく調べたい場合、`pidgen.dll` のソースコードとその全関数は、このリポジトリ内の "pidgen" フォルダにあります。
### 秘密鍵のリバース
Windows XP の有効なプロダクトキーを生成するには、`pidgen.dll` に付属する公開鍵を使って対応する秘密鍵を計算する必要があります。つまり、一方向性の ECC 問題を逆算して解かなければなりません。
BINK 内にある鍵から判断すると、曲線の位数は Windows XP では **384 ビット**、Server 2003 / XP x64 ではそれぞれ **512 ビット** の長さです。
最も効率的な Pollard's Rho アルゴリズム(漸近複雑度 $O(\sqrt{n})$)を用いた場合の計算難易度は、Windows XP では少なくとも $O(2^{168})$、Windows Server 2003 では $O(2^{256})$ になりますが、幸運なことに、
Microsoft は、一致するプロダクトキーの数を減らすために、Windows XP では署名の値を 55 ビットに、Windows Server 2003 では 62 ビットに制限したため、難易度ははるかに扱いやすい $O(2^{28})$ / $O(2^{31})$ に下がりました。
前述のとおり、現在のニーズを満たす公開ツールは Mr. HAANDI による ECDLP ソルバーのみです。<br>
秘密鍵を計算するには、BINK リソース内にある公開 ECC 値と、基点 `G(Gx; Gy)` の位数 `genOrder` をツールに与える必要があります。
基点の位数は SageMath を使って計算できます。
**Windows 98 の秘密鍵をリバースするために使用した基本的なアルゴリズムは次のとおりです。**
1. **SageMath** を使って基点の位数を計算します。SageMath で次のコマンドを実行してください。
1) `E = EllipticCurve(GF(p), [0, 0, 0, a, b])`。ここで `p`、`a`、`b` は BINK リソースから取得した楕円曲線パラメータの10進表現です。
2) `G = E(Gx, Gy)`。ここで `Gx` と `Gy` は BINK リソースから取得した基点座標の10進表現です。
3) `K = E(Kx, Ky)`。ここで `Kx` と `Ky` は BINK リソースから取得した公開鍵座標の10進表現です。
4) `n = G.order()`。`n` は計算された基点の位数になります。**最新のビルドでも計算に時間がかかる場合があります。**
5) `factor(n)` を使って位数を素因数分解します。Microsoft は点の位数に素数を使用しているため、結果がその数自体であってもまったく正常です。
6) 得られた位数の因数をどこかに保存します。
7) `-K` により、射影平面上の座標 `(x : y : z)` で公開鍵の逆元が得られます。`y` 座標をどこかに保存してください。正しい秘密鍵を生成するために必要です。
2. **ECDLP Solver v0.2a** を使って秘密鍵を計算します。
1) このツールにはテンプレートジョブ `job_template.txt` と ReadMe ファイルが同梱されています。使用するにはツールの動作を理解する必要があります。
2) BINK リソースから取得したすべての公開楕円曲線値を挿入します。**ただし `Ky` 座標は除きます。** 正しい秘密鍵を生成するには、**先ほど SageMath で計算した逆座標 `-Ky` を使用する必要があります。**
3) 基点の位数 `n` の因数を挿入し、因数の数を指定します。Microsoft は生成子の位数に主に素数を使用するため、ほぼ確実に `1` になります。
4) ツール `<arch> ECDLP Solver.exe <job_name>.txt` を実行し、秘密鍵 `k = %d` が計算されるのを待ちます。
**ECDLP ソルバーで正しい秘密鍵が得られる Windows XP 用ジョブ `job_xp.txt` の例を次に示します。**```pascal
GF := GF(22604814143135632990679956684344311209819952803216271952472204855524756275151440456421260165232069708317717961315241);
E := EllipticCurve([GF|1,0]);
G := E![10910744922206512781156913169071750153028386884676208947062808346072531411270489432930252839559606812441712224597826,19170993669917204517491618000619818679152109690172641868349612889930480365274675096509477191800826190959228181870174];
K := E![14399230353963643339712940015954061581064239835926823517419716769613937039346822269422480779920783799484349086780408,17120082747148185997450361756610881166187863099877353630300913555824935802439591336620545428308962346299700128114607];
/*
FactorCount:=1;
61760995553426173
*/
そして、そのためのECDLPソルバーの出力:

重要な注意点:
注意すべき点として、私がリバースエンジニアリングした秘密鍵を使って、通常の-Kyの代わりにKy座標を使っても、正しいWindows XP x64キーを生成できませんでした。
何らかの理由で、SageMathを使ってWindows Server 2003のベースポイントの位数を計算することもできませんでした。i7-12700K上で12時間計算させましたが、それでもまだ計算が詰まったままでした。
残りの作業は、このkeygenのコード内で行われます。
0x40000/0x62A32という正確な確率で有効なキーが生成され、その結果、正確に
0.64884、つまり約65%になりました。私の「3分の2」という見積もりは、考えられないほど正確でした。BBBセクションを640に設定し、CCCCCCセクションを0以外にすると、「より良い」キーを生成できる可能性が最も高くなります。今後のリリースで、参考文献にもっと良い読み物を追加する予定です。
Windows XPライセンス認証の基本を理解する:
楕円曲線暗号を理解する:
公開ディスカッション:
このソフトウェアを紹介またはフォークする場合は、Endermanch、z22、およびMSKeyへのクレジットを明記してください。
オープンソースであり続ける限り、お好みに合わせて自由に変更してください。GNU General Public License v3.0の下でライセンスされています。
貢献や質問はいつでも歓迎します。
| 桁 | 意味 |
|---|
| AAAAA | OS ファミリ定数 |
| BBB | チャネル ID |
| CCCCCC | シーケンス番号 |
| S | チェックディジット |
| DD | 公開鍵インデックス |
| EEE | ランダムな3桁の数字 |
| 容量 |
|---|
| データ |
|---|
| アップグレード | 1 bit | アップグレード版フラグ |
| シリアル | 30 bits | Raw Product Key (RPK) |
| ハッシュ | 28 bits | RPK ハッシュ |
| 署名 | 55 bits | RPK ハッシュの楕円曲線署名 |
| セグメント | 容量 | データ |
|---|
| アップグレード | 1 bit | アップグレード版フラグ |
| チャネル ID | 10 bits | RPK の BBB 部分 |
| ハッシュ | 31 bits | RPK ハッシュ |
| 署名 | 62 bits | RPK ハッシュの楕円曲線署名 |
| 認証キー | 10 bits | バックエンド認証値 |
| Offset | Value |
|---|
0x0000 | BINK ID |
0x0004 | BINKEY 構造体のサイズ(バイト単位)(実際には常に 0x16C) |
0x0008 | ヘッダー長(実際には常に 7) |
0x000C | チェックサム |
0x0010 | 数値エンコードされた日付 - BINKEY バージョン(実際には常に 19980206) |
0x0014 | ECC 曲線の位数サイズ(実際には常に 12) |
0x0018 | ハッシュ長(実際には常に 28) |
0x001C | 署名長(実際には常に 55) |
0x0020 | 有限体の位数 p |
0x005C | 曲線パラメータ a |
0x0098 | 曲線パラメータ b |
0x00D4 | ベースポイントの x 座標 Gx |
0x0110 | ベースポイントの y 座標 Gy |
0x014C | 公開鍵の x 座標 Kx |
0x0188 | 公開鍵の y 座標 Ky |
| Offset | Value |
|---|
0x0000 | BINK ID |
0x0004 | BINKEY 構造体のサイズ(バイト単位) |
0x0008 | ヘッダー長(実際には常に 9) |
0x000C | チェックサム |
0x0010 | 数値エンコードされた日付 - BINKEY バージョン(実際には常に 20020420) |
0x0014 | ECC 曲線の位数サイズ(実際には常に 16) |
0x0018 | ハッシュ長(実際には常に 31) |
0x001C | 署名長(実際には常に 62) |
0x0020 | バックエンド認証値の長さ(実際には常に 12) |
0x0024 | Product ID の長さ(実際には常に 20) |
0x0028 | 有限体の位数 p |
0x0068 | 曲線パラメータ a |
0x00A8 | 曲線パラメータ b |
0x00E8 | ベースポイントの x 座標 Gx |
0x0128 | ベースポイントの y 座標 Gy |
0x0168 | 公開鍵の x 座標 Kx |
0x01A8 | 公開鍵の y 座標 Ky |