一个 Windows XP / Windows Server 2003 VLK 密钥生成器。该工具允许你基于 Raw Product Key 生成 有效的 Windows XP 密钥,而 Raw Product Key 可以是随机的。
Raw Product Key (RPK) 以 9 位数字 XXX-YYYYYY 的形式提供,并且仅在生成 Windows XP 密钥时才需要。

前往 Releases 标签页,从那里下载最新版本。
这个项目还没有死——我会尽我所能把它做出来。
一般来说,阻碍我们为每个版本(EVERY EDITION)和每个构建(EVERY BUILD)生成有效的 Windows XP 密钥的唯一因素,是缺少从 pidgen.dll 中的公钥对应生成的私钥。网上没有广泛可用的椭圆曲线离散对数函数代码,只有关于如何实现它的模糊信息。
随着时间推移,这个问题已经_部分_解决了。
BINK 资源没有以任何方式编码,数据只是按顺序写入资源。sk00ter 还在 MDL 论坛上完整解释了 BINK 格式。 利用社区先前关于这个主题的知识,我用 Python 3 编写了一个 BINK Reader。该文件在本仓库中公开,点击这里查看源代码。
截至 2023 年 5 月 28 日,离散对数求解仍是研究中最少被探索的领域。然而,我的朋友 nephacks 确实在互联网最黑暗的角落找到了那个难以捉摸的工具来解决这个难题。 它叫 ECDLP(椭圆曲线离散对数问题)Solver,作者是 Mr. HAANDI。由于在网上找它极其令人沮丧,我将其重新上传到了我的网站。你可以在此下载该工具。
该求解器 0.2a 版本自带的 ReadMe 文件本身已经足够好,所以任何有脑子的人都能把它配置好。然而,它不是开源的,因此将其集成到我的 keygen 中被证明是不可能的。
在理想情况下,keygen 会要求你提供从 pidgen.dll 中提取的 BINK 资源,然后将其解包为以下部分:
pubX; pubY)genX; genY)a; b)p知道这些部分后,keygen 将使用 Schoof 算法暴力破解生成元阶 genOrder,然后求解私钥 privateKey,并利用计算出的 genOrder 来使用最优的 Pollard's Rho 算法。毫无疑问,只要我们有可用的算法,借助现代计算能力,我们可以在 20 分钟内破解任何私钥。
一旦 keygen 完成对正确私钥的暴力破解,任务就归结为实际生成密钥,而这正是这个 keygen 所做的。 为了让你有更清晰的认识,我可以提供理想 keygen 的流程。被划掉的是我的 keygen 已经实现的部分:
genOrder, privateKey)我们需要使用一个随机的 Raw Product Key 作为基础,生成形式为 AAAAA-BBB-CCCCCCS-DDEEE 的 Product ID。
| 位数 | 含义 |
|---|---|
| AAAAA | 操作系统系列常量 |
| BBB | 渠道 ID |
| CCCCCC | 序列号 |
| S | 校验位 |
| DD | 公钥索引 |
| EEE | 随机三位数 |
操作系统系列常量 AAAAA 对于每个 Windows XP 系列都不同。例如,SP3 的该值为 76487。
BBB 和 CCCCCC 部分本质上对 Raw Product Key 进行编码。例如,如果第一部分等于 XXX,第二部分等于 YYYYYY,则 Raw Product Key 将被编码为 XXX-YYYYYY。
选择校验位 S 是为了让所有 C 位数之和加上它后成为一个能被 7 整除的数。
公钥索引 DD 让我们知道哪个公钥被用于成功验证产品密钥的真实性。
例如,Professional 密钥为 22,VLK 密钥为 23。
每次都会使用一个随机数 EEE 来生成不同的安装 ID。
产品密钥本身(不要与 RPK 混淆)的形式为 FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK,使用 Base-24 编码,字母表为 BCDFGHJKMPQRTVWXY2346789,以排除任何容易混淆的字符,例如 I 和 1 或 O 和 0。
根据字母表容量公式,密钥最多可以包含 114 位信息。 $$N = \log_2(24^{25}) \approx 114$$
基于该计算,我们将 114 位的产品密钥解包为 4 个有序分段:
| Segment | 容量 | 数据 |
|---|---|---|
| Upgrade | 1 bit | 升级版本标志 |
| Serial | 30 bits | Raw Product Key (RPK) |
| Hash | 28 bits | RPK 哈希 |
| Signature | 55 bits | 针对 RPK 哈希的椭圆曲线签名 |
为简单起见,我们将 Upgrade 和 Serial 分段合并为一个名为 Data 的分段。按照这种逻辑,我们将能够通过将 Data 右移来提取 RPK,并通过左移位来将其装回,因为我检查过的大多数先验有效的产品密钥的 Upgrade 位都设置为 1。
微软在 Windows Server 2003 中重新设计了产品密钥格式,加入了一个后端服务器认证密钥,这实际上是一种安全的许可证验证方法,因为没有人能够猜到他们在私有服务器上使用了哪种验证算法。除了增加在线验证机制外,他们还将整体运算从 384 位提高到 512 位,并将签名标量提高到 62 位信息。
| Segment | 容量 | 数据 |
|---|---|---|
| Upgrade | 1 bit | 升级版本标志 |
| Channel ID | 10 bits | RPK 的 BBB 部分 |
| Hash | 31 bits | RPK 哈希 |
| Signature | 62 bits | 针对 RPK 哈希的椭圆曲线签名 |
| Auth Key | 10 bits | 后端认证值 |
然而,如果我们在生成密钥时不考虑在线激活,我们仍然可以生成有效的密钥,从而通过操作系统的安装过程。这正是代码所做的——它生成一个随机的 10 位认证密钥。如今这已经完全不重要了,因为激活服务器已经关闭,Server 2003 被视为废弃软件(abandonware),正如整个项目不应被视为盗版一样。
椭圆曲线密码学(ECC)是一种公钥密码系统。这类系统依赖于具有挑战性的“单向”数学问题——一个方向容易计算,而“另一个”方向难以求解。它们有时被称为“陷门”函数——容易掉进去,却难以逃出来。[5]
ECC 依赖于求解以下形式的方程 $$y^2 = x^3 + ax + b$$
一般来说,密码学中利用的椭圆曲线有两种特殊情况——F2m 和 Fp。它们只有细微差别。两条曲线都定义在有限域上,Fp 使用一个大于 3 的素数参数,F2m 假定 $p = 2m$。微软在其算法中使用了后者。
有限域 Fp 上的椭圆曲线由以下部分组成:
F17 上的椭圆曲线看起来像这样:

该曲线由上图蓝色点组成。在实践中,密码学中使用的“椭圆曲线”是“方形矩阵中的点集”。
上述曲线是“教学用”的。它提供的密钥长度非常小(4-5 位)。在现实世界中,开发人员通常使用 256 位或更长的曲线。
由于这是一个公钥密码系统,微软必须在其 Windows XP 版本中共享公钥,用于校验输入的产品密钥。它存储在 pidgen.dll 中,以 BINK 资源的形式存在。第一组 BINK 数据用于验证零售密钥,第二组分别用于 OEM 密钥。
适用于 Windows 98 和 Windows XP 的 BINK 资源结构如下:
| 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 |
每个分段都用不同的颜色标记,BINK 头部值是相同的。

Windows Server 2003 和 Windows XP x64 的实现方式有所不同:
| 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 |