
Windows XP Keygen
Un generador de claves VLK para Windows XP / Windows Server 2003. Esta herramienta te permite generar claves válidas de Windows XP basadas en la Raw Product Key (Clave de Producto sin procesar), que puede ser aleatoria.
La Raw Product Key (RPK) se proporciona en forma de 9 dígitos XXX-YYYYYY y solo es necesaria para generar una clave de Windows XP.

Ve a la pestaña de Releases y descarga la última versión desde allí.
Este proyecto no está muerto — haré todo lo posible por llevarlo a buen término.
En general, lo único que nos separa de generar claves válidas de Windows XP para CADA EDICIÓN y CADA COMPILACIÓN es la falta de las respectivas claves privadas generadas a partir de sus contrapartes públicas dentro de pidgen.dll. No hay código disponible en línea para la función de logaritmo discreto de curva elíptica, solo hay información vaga sobre cómo hacerlo.
Con el tiempo, el problema se ha resuelto parcialmente.
El recurso BINK no estaba codificado de ninguna manera y los datos simplemente se escribían secuencialmente en el recurso. sk00ter también explicó por completo el formato BINK en los foros de MDL. Aprovechando el conocimiento previo de la comunidad sobre el tema, escribí un lector BINK en Python 3. El archivo es público en este repositorio, haz clic aquí para ver el código fuente.
La solución del logaritmo discreto es el área de investigación más inexplorada a día de 28 de mayo de 2023. Sin embargo, mi amigo nephacks encontró esa escurridiza herramienta para resolver ese difícil problema en los rincones más oscuros de internet. Se llama ECDLP (Problema del Logaritmo Discreto de Curva Elíptica) Solver, de Mr. HAANDI. Como era extremadamente frustrante encontrarla en línea, la volví a subir a mi sitio web. Puedes descargar la herramienta aquí.
El archivo ReadMe que viene con la versión 0.2a del solucionador es suficientemente bueno por sí solo, así que cualquiera con un poco de criterio podrá configurar esa herramienta. Sin embargo, no es de código abierto, por lo que integrarlo en mi keygen resulta imposible.
En el escenario ideal, el keygen te pediría un recurso BINK extraído de pidgen.dll, que luego descompondría en los siguientes segmentos:
pubX; pubY)genX; genY)a; b)pConociendo estos segmentos, el keygen forzaría por fuerza bruta el orden del generador genOrder usando el algoritmo de Schoof, seguido de la clave privada privateKey, aprovechando el genOrder calculado para usar el algoritmo más óptimo de Pollard Rho. No hay duda de que podemos descifrar cualquier clave privada en cuestión de 20 minutos usando poder computacional moderno, siempre que tengamos el algoritmo funcional.
Una vez que el keygen termina de forzar por fuerza bruta la clave privada correcta, la tarea se reduce a generar realmente una clave, que es lo que hace este keygen. Para darte una mejor perspectiva, puedo proporcionarte el flujo del keygen ideal. Lo que está tachado es lo que implementa mi keygen:
Necesitamos usar una Raw Product Key aleatoria como base para generar un ID de producto con la forma AAAAA-BBB-CCCCCCS-DDEEE.
La constante de familia de SO AAAAA es diferente para cada serie de Windows XP. Por ejemplo, es 76487 para SP3.
Las secciones BBB y CCCCCC esencialmente codifican la Raw Product Key. Por ejemplo, si la primera sección es igual a XXX y la segunda sección es igual a YYYYYY, la Raw Product Key se codificará como XXX-YYYYYY.
El dígito de comprobación S se elige de modo que la suma de todos los dígitos C más él dé un número divisible por 7.
El índice de clave pública DD nos permite saber qué clave pública se usó para verificar con éxito la autenticidad de nuestra Clave de Producto.
Por ejemplo, es 22 para claves Professional y 23 para claves VLK.
Se usa un número aleatorio EEE para generar un ID de instalación diferente cada vez.
La Clave de Producto en sí (no confundir con la RPK) tiene la forma FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK, codificada en Base-24 con
el alfabeto BCDFGHJKMPQRTVWXY2346789 para excluir cualquier carácter que pueda confundirse fácilmente, como I y 1 u O y 0.
Según la fórmula de capacidad del alfabeto, la clave puede contener como máximo 114 bits de información. $$N = \log_2(24^{25}) \approx 114$$
Con base en ese cálculo, descomponemos la Clave de Producto de 114 bits en 4 segmentos ordenados:
Por simplicidad, combinaremos los segmentos Upgrade y Serial en un solo segmento llamado Data. Con esa lógica podremos extraer la RPK desplazando Data a la derecha y volver a empaquetarla desplazando los bits a la izquierda, porque la mayoría de las claves de producto a priori válidas que he comprobado tenían el bit de actualización establecido en 1.
Microsoft rehizo el formato de su Clave de Producto con Windows Server 2003 para incluir una clave de autenticación de servidor backend, que era un enfoque realmente seguro para la validación de licencias, ya que nadie podía adivinar qué algoritmo de validación habían empleado en su servidor privado. Además de añadir el mecanismo de validación en línea, también aumentaron la aritmética general de 384 a 512 bits y el escalar de la firma a 62 bits de información.
Sin embargo, si generábamos una clave sin tener en cuenta la activación en línea, aún podíamos generar claves válidas que nos permitieran pasar la instalación del sistema operativo. Y eso es exactamente lo que hace el código: genera una clave de autenticación aleatoria de 10 bits. Hoy en día no importa en absoluto, ya que los servidores de activación están caídos y Server 2003 se considera abandonware, del mismo modo que todo este proyecto no debería considerarse piratería.
La criptografía de curva elíptica (ECC) es un tipo de sistema criptográfico de clave pública. Esta clase de sistemas se basa en problemas matemáticos "unidireccionales" difíciles: fáciles de calcular en un sentido e intratables de resolver en el "otro". A veces se les llama funciones "trampa": fáciles de caer en ellas, complicadas de escapar.[5]
ECC se basa en resolver ecuaciones de la forma $$y^2 = x^3 + ax + b$$
En general, hay 2 casos especiales para la curva elíptica utilizada en criptografía: F2m y Fp. Se diferencian solo ligeramente. Ambas curvas están definidas sobre el campo finito; Fp usa un parámetro primo mayor que 3, F2m asume $p = 2m$. Microsoft usó este último en su algoritmo.
Una curva elíptica sobre el campo finito Fp consiste en:
Una curva elíptica sobre F17 se vería así:

La curva consiste en los puntos azules de la imagen anterior. En la práctica, las "curvas elípticas" utilizadas en criptografía son "conjuntos de puntos en una matriz cuadrada".
La curva anterior es "educativa". Proporciona una longitud de clave muy pequeña (4-5 bits). En situaciones del mundo real, los desarrolladores suelen usar curvas de 256 bits o más.
Dado que es un sistema criptográfico de clave pública, Microsoft tuvo que compartir la clave pública con su versión de Windows XP para verificar las claves de producto introducidas.
Se almacena dentro de pidgen.dll en forma de un recurso BINK. El primer conjunto de datos BINK está ahí para validar claves minoristas, el segundo es para las
claves OEM respectivamente.
La estructura del recurso BINK para Windows 98 y Windows XP es la siguiente:
Cada segmento está marcado con un color diferente; los valores de la cabecera BINK son los mismos.

Windows Server 2003 y Windows XP x64 lo implementan de manera diferente:
Y estos son mis prototipos de estructura creados para el lector BINK en 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;
En caso de que quieras explorar más a fondo, el código fuente de `pidgen.dll` y todas sus funciones está disponible dentro de este repositorio, en la carpeta "pidgen".
### Reversing de la clave privada
Si queremos generar claves de producto válidas para Windows XP, debemos calcular la clave privada correspondiente usando la clave pública suministrada con `pidgen.dll`,
lo que significa que tenemos que resolver en sentido inverso la tarea ECC unidireccional.
A juzgar por la clave ubicada en BINK, el orden de la curva es de **384 bits** en Windows XP y de **512 bits** en Server 2003 / XP x64, respectivamente.
La dificultad de cómputo usando el algoritmo Rho de Pollard más eficiente con complejidad asintótica $O(\sqrt{n})$ sería de al menos $O(2^{168})$ para Windows XP, y $O(2^{256})$ para Windows Server 2003, pero para nuestra suerte,
Microsoft limitó el valor de la firma a 55 bits en Windows XP y a 62 bits en Windows Server 2003 para reducir la cantidad de claves de producto coincidentes, reduciendo la dificultad a un mucho más manejable $O(2^{28})$ / $O(2^{31})$.
Como se mencionó antes, solo hay una herramienta pública que satisface nuestras necesidades actuales, que es el solucionador ECDLP de Mr. HAANDI.<br>
Para calcular la clave privada, necesitaremos proporcionar a la herramienta los valores públicos ECC ubicados en el recurso BINK, así como el orden `genOrder` del punto base `G(Gx; Gy)`.
El orden del punto base se puede calcular usando SageMath.
**Este es el algoritmo básico que usé para hacer ingeniería inversa de la clave privada de Windows 98:**
1. Calcula el orden del punto base usando **SageMath**. En SageMath, ejecuta los siguientes comandos:
1) `E = EllipticCurve(GF(p), [0, 0, 0, a, b])`, donde `p`, `a` y `b` son parámetros de curva elíptica representados en decimal del recurso BINK.
2) `G = E(Gx, Gy)`, donde `Gx` y `Gy` son coordenadas del punto base representadas en decimal del recurso BINK.
3) `K = E(Kx, Ky)`, donde `Kx` y `Ky` son coordenadas de clave pública representadas en decimal del recurso BINK.
4) `n = G.order()`, `n` será el orden calculado del punto base. **Puede tardar un tiempo en calcularse, incluso en las compilaciones más recientes.**
5) Factoriza el orden usando `factor(n)`. Microsoft usó números primos para los órdenes de los puntos, así que si devuelve el número en sí, es completamente normal.
6) Guarda los factores resultantes del orden en algún lugar.
7) `-K` te dará la inversa de la clave pública en un plano proyectivo con coordenadas `(x : y : z)`. Guarda la coordenada `y` en algún lugar; se requiere para generar una clave privada correcta.
2. Calcula la clave privada usando **ECDLP Solver v0.2a**.
1) La herramienta incluye una plantilla de trabajo `job_template.txt` y un archivo ReadMe. Es necesario entender cómo funciona la herramienta para usarla.
2) Inserta todos los valores públicos de la curva elíptica del recurso BINK, **excepto la coordenada `Ky`**. Para generar una clave privada correcta, **debes usar la coordenada inversa `-Ky` que calculaste antes en SageMath.**
3) Inserta los factores del orden del punto base `n` y especifica el número de factores. Muy probablemente será `1`, ya que Microsoft usa principalmente números primos para sus órdenes de generador.
4) Ejecuta la herramienta `<arch> ECDLP Solver.exe <job_name>.txt` y espera a que calcule la clave privada `k = %d` para ti.
**Aquí tienes un ejemplo del archivo de trabajo de Windows XP `job_xp.txt` que produce la clave privada correcta para el ECDLP Solver.**```pascal
GF := GF(22604814143135632990679956684344311209819952803216271952472204855524756275151440456421260165232069708317717961315241);
E := EllipticCurve([GF|1,0]);
G := E![10910744922206512781156913169071750153028386884676208947062808346072531411270489432930252839559606812441712224597826,19170993669917204517491618000619818679152109690172641868349612889930480365274675096509477191800826190959228181870174];
K := E![14399230353963643339712940015954061581064239835926823517419716769613937039346822269422480779920783799484349086780408,17120082747148185997450361756610881166187863099877353630300913555824935802439591336620545428308962346299700128114607];
/*
FactorCount:=1;
61760995553426173
*/
Y la salida del ECDLP Solver para ello:

Nota importante:
Ten en cuenta que no pude generar una clave correcta de Windows XP x64 usando la clave privada que he obtenido mediante ingeniería inversa, incluso usando la coordenada Ky en lugar de la habitual -Ky.
Por alguna razón, tampoco pude calcular el orden del punto base de Windows Server 2003 con SageMath. Le di 12 horas para que lo calculara en mi i7-12700K, pero seguía atascado en el cálculo.
El resto del trabajo se realiza dentro del código de este keygen.
0x40000/0x62A32, lo que resultaba en exactamente
0.64884, o alrededor del 65%. Mi estimación de "2 de cada 3" fue asombrosamente precisa.BBB establecida en 640 y la sección CCCCCC distinta de cero.Añadiré más lecturas interesantes a la bibliografía en versiones posteriores.
Entendiendo los conceptos básicos de la activación de Windows XP:
Entendiendo la criptografía de curva elíptica:
Discusiones públicas:
Si vas a mostrar este software o hacer un fork, por favor da crédito a Endermanch, z22 y MSKey.
Siéntete libre de modificarlo a tu gusto, siempre y cuando lo mantengas como código abierto. Licenciado bajo la GNU General Public License v3.0.
Cualquier contribución o pregunta es bienvenida.
genOrder, privateKey)| Dígitos | Significado |
|---|
| AAAAA | Constante de familia de SO |
| BBB | ID de canal |
| CCCCCC | Número de secuencia |
| S | Dígito de comprobación |
| DD | Índice de clave pública |
| EEE | Número aleatorio de 3 dígitos |
| Segment | Capacity | Data |
|---|
| Upgrade | 1 bit | Indicador de versión de actualización |
| Serial | 30 bits | Raw Product Key (RPK) |
| Hash | 28 bits | Hash de la RPK |
| Signature | 55 bits | Firma de curva elíptica para el hash de la RPK |
| Segment | Capacity | Data |
|---|
| Upgrade | 1 bit | Indicador de versión de actualización |
| Channel ID | 10 bits | La parte BBB de la RPK |
| Hash | 31 bits | Hash de la RPK |
| Signature | 62 bits | Firma de curva elíptica para el hash de la RPK |
| Auth Key | 10 bits | Valor de autenticación backend |
| Offset | Value |
|---|
0x0000 | ID de BINK |
0x0004 | Tamaño de la estructura BINKEY en bytes (siempre 0x16C en la práctica) |
0x0008 | Longitud de cabecera (siempre 7 en la práctica) |
0x000C | Suma de comprobación |
0x0010 | Fecha codificada numéricamente - versión de BINKEY (siempre 19980206 en la práctica) |
0x0014 | Tamaño del orden de la curva ECC (siempre 12 en la práctica) |
0x0018 | Longitud de hash (siempre 28 en la práctica) |
0x001C | Longitud de firma (siempre 55 en la práctica) |
0x0020 | Orden del campo finito p |
0x005C | Parámetro de curva a |
0x0098 | Parámetro de curva b |
0x00D4 | Coordenada x del punto base Gx |
0x0110 | Coordenada y del punto base Gy |
0x014C | Coordenada x de la clave pública Kx |
0x0188 | Coordenada y de la clave pública Ky |
| Offset | Value |
|---|
0x0000 | ID de BINK |
0x0004 | Tamaño de la estructura BINKEY en bytes |
0x0008 | Longitud de cabecera (siempre 9 en la práctica) |
0x000C | Suma de comprobación |
0x0010 | Fecha codificada numéricamente - versión de BINKEY (siempre 20020420 en la práctica) |
0x0014 | Tamaño del orden de la curva ECC (siempre 16 en la práctica) |
0x0018 | Longitud de hash (siempre 31 en la práctica) |
0x001C | Longitud de firma (siempre 62 en la práctica) |
0x0020 | Longitud del valor de autenticación backend (siempre 12 en la práctica) |
0x0024 | Longitud del ID de producto (siempre 20 en la práctica) |
0x0028 | Orden del campo finito p |
0x0068 | Parámetro de curva a |
0x00A8 | Parámetro de curva b |
0x00E8 | Coordenada x del punto base Gx |
0x0128 | Coordenada y del punto base Gy |
0x0168 | Coordenada x de la clave pública Kx |
0x01A8 | Coordenada y de la clave pública Ky |