
Windows XP Keygen
Un générateur de clés VLK pour Windows XP / Windows Server 2003. Cet outil permet de générer des clés Windows XP valides à partir de la clé de produit brute (Raw Product Key), qui peut être aléatoire.
La clé de produit brute (RPK) est fournie sous la forme de 9 chiffres XXX-YYYYYY et n'est nécessaire que pour générer une clé Windows XP.

Rendez-vous dans l'onglet Releases et téléchargez-y la dernière version.
Ce projet n'est pas mort — je ferai de mon mieux pour le mener à bien.
En général, la seule chose qui nous sépare de la génération de clés Windows XP valides pour CHAQUE ÉDITION et CHAQUE VERSION est l'absence des clés privées respectives générées à partir de leurs homologues publiques dans pidgen.dll. Il n'existe pas de code pour la fonction de logarithme discret sur courbe elliptique largement disponible en ligne, seulement des informations vagues sur la façon de procéder.
Au fil du temps, le problème a été partiellement résolu.
La ressource BINK n'était encodée d'aucune manière et les données étaient simplement écrites séquentiellement dans la ressource. sk00ter a également entièrement expliqué le format BINK sur les forums MDL. En utilisant les connaissances communautaires antérieures sur le sujet, j'ai écrit un lecteur BINK en Python 3. Le fichier est public dans ce dépôt, cliquez ici pour voir le code source.
La solution du logarithme discret est le domaine de recherche le plus inexploré à la date du 28 mai 2023. Cependant, mon ami nephacks a tout de même trouvé cet outil insaisissable pour résoudre ce problème difficile dans les recoins les plus sombres d'Internet. Il s'appelle ECDLP (Elliptic Curve Discrete Logarithm Problem) Solver de Mr. HAANDI. Comme il était extrêmement frustrant de le trouver en ligne, je l'ai remis en ligne sur mon site Web. Vous pouvez télécharger l'outil ici.
Le fichier ReadMe fourni avec la version 0.2a du solveur est suffisant en soi, donc toute personne avec un minimum de jugeote saura configurer cet outil. Cependant, il n'est pas open-source, son intégration dans mon keygen s'avère donc impossible.
Dans le scénario idéal, le keygen vous demanderait une ressource BINK extraite de pidgen.dll, qu'il décomposerait ensuite dans les segments suivants :
pubX ; pubY)genX ; genY)a ; b)pEn connaissant ces segments, le keygen rechercherait par force brute l'ordre du générateur genOrder à l'aide de l'algorithme de Schoof, puis la clé privée privateKey, en exploitant le genOrder calculé pour utiliser l'algorithme de Pollard-Rho le plus optimal. Nul doute que nous pouvons casser n'importe quelle clé privée en une vingtaine de minutes avec la puissance de calcul moderne, à condition de disposer d'un algorithme fonctionnel.
Une fois que le keygen a fini de trouver par force brute la bonne clé privée, la tâche se résume à générer réellement une clé, ce que fait ce keygen. Pour vous donner une meilleure perspective, je peux vous fournir le déroulement du keygen idéal. Ce qui est barré correspond à ce que mon keygen implémente :
Nous devons utiliser une clé de produit brute aléatoire comme base pour générer un ID de produit sous la forme AAAAA-BBB-CCCCCCS-DDEEE.
La constante de famille d'OS AAAAA diffère pour chaque série de Windows XP. Par exemple, elle vaut 76487 pour SP3.
Les sections BBB et CCCCCC encodent essentiellement la clé de produit brute. Par exemple, si la première section est égale à XXX et la seconde à YYYYYY, la clé de produit brute sera encodée comme XXX-YYYYYY.
Le chiffre de contrôle S est choisi de sorte que la somme de tous les chiffres C, une fois S ajouté, forme un nombre divisible par 7.
L'index de clé publique DD nous permet de savoir quelle clé publique a été utilisée pour vérifier avec succès l'authenticité de notre clé de produit.
Par exemple, il est de 22 pour les clés Professional et de 23 pour les clés VLK.
Un nombre aléatoire EEE est utilisé pour générer un ID d'installation différent à chaque fois.
La clé de produit elle-même (à ne pas confondre avec la RPK) se présente sous la forme FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK, encodée en Base-24 avec
l'alphabet BCDFGHJKMPQRTVWXY2346789 afin d'exclure tout caractère pouvant être facilement confondu, comme I et 1 ou O et 0.
D'après la formule de capacité de l'alphabet, la clé peut contenir au plus 114 bits d'information. $$N = \log_2(24^{25}) \approx 114$$
Sur la base de ce calcul, nous décomposons la clé de produit de 114 bits en 4 segments ordonnés :
Par souci de simplicité, nous allons combiner les segments Upgrade et Serial en un seul segment appelé Data. Avec cette logique, nous pourrons extraire la RPK en
décalant Data vers la droite et la réintégrer en décalant les bits vers la gauche, car la plupart des clés de produit a priori valides que j'ai vérifiées avaient le bit Upgrade défini sur 1.
Microsoft a retravaillé son format de clé de produit avec Windows Server 2003 pour y inclure une clé d'authentification de serveur backend, ce qui constituait une approche réellement sécurisée de la validation de licence, car personne ne pouvait deviner quel algorithme de validation ils avaient utilisé sur leur serveur privé. Outre l'ajout du mécanisme de validation en ligne, ils ont également fait passer l'arithmétique globale de 384 à 512 bits, et le scalaire de la signature à 62 bits d'information.
Cependant, si nous générions une clé sans penser à l'activation en ligne, nous pourrions encore générer des clés valides qui nous permettraient de passer l'installation du système d'exploitation. Et c'est exactement ce que fait le code : il génère une clé d'authentification aléatoire de 10 bits. De nos jours, cela n'a plus aucune importance, car les serveurs d'activation sont hors service et Server 2003 est considéré comme un abandonware, tout comme ce projet dans son ensemble ne devrait pas être considéré comme du piratage.
La cryptographie à courbe elliptique (ECC) est un type de système cryptographique à clé publique. Cette classe de systèmes repose sur des problèmes mathématiques « unidirectionnels » difficiles : faciles à calculer dans un sens et impossibles à résoudre dans l'« autre » sens. On les appelle parfois fonctions « à trappe » : faciles à franchir, difficiles à contourner.[5]
L'ECC repose sur la résolution d'équations de la forme $$y^2 = x^3 + ax + b$$
En général, il existe 2 cas particuliers pour la courbe elliptique utilisée en cryptographie : F2m et Fp. Ils ne diffèrent que légèrement. Les deux courbes sont définies sur le corps fini ; Fp utilise un paramètre premier supérieur à 3, F2m suppose $p = 2m$. Microsoft a utilisé ce dernier dans son algorithme.
Une courbe elliptique sur le corps fini Fp se compose de :
Voici à quoi ressemblerait une courbe elliptique sur F17 :

La courbe est constituée des points bleus de l'image ci-dessus. En pratique, les « courbes elliptiques » utilisées en cryptographie sont des « ensembles de points dans une matrice carrée ».
La courbe ci-dessus est « pédagogique ». Elle offre une très petite longueur de clé (4 à 5 bits). Dans les situations réelles, les développeurs utilisent généralement des courbes de 256 bits ou plus.
Puisqu'il s'agit d'un système cryptographique à clé publique, Microsoft devait partager la clé publique avec sa version de Windows XP afin de vérifier les clés de produit saisies.
Elle est stockée dans pidgen.dll sous la forme d'une ressource BINK. Le premier ensemble de données BINK sert à valider les clés retail, le second est respectivement destiné aux
clés OEM.
La structure de la ressource BINK pour Windows 98 et Windows XP est la suivante :
Chaque segment est marqué d'une couleur différente ; les valeurs de l'en-tête BINK sont les mêmes.

Windows Server 2003 et Windows XP x64 l'implémentent différemment :
Et voici mes prototypes de structure réalisés pour le lecteur 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 cas d'exploration plus approfondie, le code source de `pidgen.dll` et de toutes ses fonctions est disponible dans ce dépôt, dans le dossier « pidgen ».
### Inversion de la clé privée
Si nous voulons générer des clés de produit valides pour Windows XP, nous devons calculer la clé privée correspondante à l'aide de la clé publique fournie avec `pidgen.dll`,
ce qui signifie que nous devons résoudre à l'envers la tâche ECC à sens unique.
À en juger par la clé située dans BINK, l'ordre de la courbe est de **384 bits** sous Windows XP et de **512 bits** sous Server 2003 / XP x64 respectivement.
La difficulté de calcul avec l'algorithme le plus efficace de Pollard Rho, de complexité asymptotique $O(\sqrt{n})$, serait d'au moins $O(2^{168})$ pour Windows XP et $O(2^{256})$ pour Windows Server 2003, mais par chance,
Microsoft a limité la valeur de la signature à 55 bits sous Windows XP et à 62 bits sous Windows Server 2003 afin de réduire le nombre de clés de produit correspondantes, ramenant la difficulté à un niveau bien plus gérable de $O(2^{28})$ / $O(2^{31})$.
Comme mentionné précédemment, il n'existe qu'un seul outil public qui réponde à nos besoins actuels : le solveur ECDLP de M. HAANDI.<br>
Pour calculer la clé privée, nous devrons fournir à l'outil les valeurs ECC publiques situées dans la ressource BINK, ainsi que l'ordre `genOrder` du point de base `G(Gx; Gy)`.
L'ordre du point de base peut être calculé avec SageMath.
**Voici l'algorithme de base que j'ai utilisé pour inverser la clé privée de Windows 98 :**
1. Calculer l'ordre du point de base avec **SageMath**. Dans SageMath, exécuter les commandes suivantes :
1) `E = EllipticCurve(GF(p), [0, 0, 0, a, b])`, où `p`, `a` et `b` sont les paramètres de la courbe elliptique en représentation décimale issus de la ressource BINK.
2) `G = E(Gx, Gy)`, où `Gx` et `Gy` sont les coordonnées du point de base en représentation décimale issues de la ressource BINK.
3) `K = E(Kx, Ky)`, où `Kx` et `Ky` sont les coordonnées de la clé publique en représentation décimale issues de la ressource BINK.
4) `n = G.order()`, `n` sera l'ordre calculé du point de base. **Le calcul peut prendre du temps, même sur les builds les plus récents.**
5) Factoriser l'ordre avec `factor(n)`. Microsoft a utilisé des nombres premiers pour les ordres des points ; donc si la fonction renvoie le nombre lui-même, c'est tout à fait normal.
6) Enregistrer les facteurs résultants de l'ordre quelque part.
7) `-K` donnera l'inverse de la clé publique dans un plan projectif avec les coordonnées `(x : y : z)`. Enregistrer la coordonnée `y` quelque part, elle est nécessaire pour générer une clé privée correcte.
2. Calculer la clé privée avec **ECDLP Solver v0.2a**.
1) L'outil est fourni avec un modèle de tâche `job_template.txt` et un fichier ReadMe. Il est nécessaire de comprendre le fonctionnement de l'outil pour l'utiliser.
2) Insérer toutes les valeurs publiques de la courbe elliptique issues de la ressource BINK, **à l'exception de la coordonnée `Ky`**. Pour générer une clé privée correcte, **vous devez utiliser la coordonnée inverse `-Ky` que vous avez calculée plus tôt dans SageMath.**
3) Insérer les facteurs de l'ordre `n` du point de base et préciser le nombre de facteurs. Il y a de très fortes chances que ce soit `1`, car Microsoft utilise principalement des nombres premiers pour les ordres de leurs générateurs.
4) Exécuter l'outil `<arch> ECDLP Solver.exe <job_name>.txt` et attendre qu'il calcule la clé privée `k = %d` pour vous.
**Voici un exemple de tâche Windows XP `job_xp.txt` qui produit la clé privée correcte pour l'ECDLP Solver.**```pascal
GF := GF(22604814143135632990679956684344311209819952803216271952472204855524756275151440456421260165232069708317717961315241);
E := EllipticCurve([GF|1,0]);
G := E![10910744922206512781156913169071750153028386884676208947062808346072531411270489432930252839559606812441712224597826,19170993669917204517491618000619818679152109690172641868349612889930480365274675096509477191800826190959228181870174];
K := E![14399230353963643339712940015954061581064239835926823517419716769613937039346822269422480779920783799484349086780408,17120082747148185997450361756610881166187863099877353630300913555824935802439591336620545428308962346299700128114607];
/*
FactorCount:=1;
61760995553426173
*/
Et la sortie du solveur ECDLP pour cela :

Remarque importante :
Sachez que je n'ai pas pu générer de clé Windows XP x64 valide avec la clé privée que j'ai rétroconçue, même en utilisant la coordonnée Ky au lieu de la coordonnée -Ky habituelle.
Pour une raison inconnue, je n'ai pas non plus réussi à calculer l'ordre du point de base de Windows Server 2003 avec SageMath. Je lui ai laissé 12 heures de calcul sur mon i7-12700K, mais il était toujours bloqué sur le calcul.
Le reste du travail est effectué dans le code de ce keygen.
0x40000/0x62A32, ce qui donnait exactement
0.64884, soit environ 65 %. Mon estimation de « 2 sur 3 » était incroyablement précise.BBB définie sur 640 et la section CCCCCC non nulle.J'ajouterai d'autres lectures intéressantes à la bibliographie dans les prochaines versions.
Comprendre les bases de l'activation de Windows XP :
Comprendre la cryptographie à courbes elliptiques :
Discussions publiques :
Si vous comptez présenter ou forker ce logiciel, merci de créditer Endermanch, z22 et MSKey.
N'hésitez pas à le modifier à votre guise, tant que vous le laissez en open source. Sous licence GNU General Public License v3.0.
Toute contribution ou question est la bienvenue.
genOrder, privateKey)| Chiffres | Signification |
|---|
| AAAAA | Constante de famille d'OS |
| BBB | ID de canal |
| CCCCCC | Numéro de séquence |
| S | Chiffre de contrôle |
| DD | Index de clé publique |
| EEE | Nombre aléatoire à 3 chiffres |
| Segment | Capacité | Données |
|---|
| Upgrade | 1 bit | Indicateur de version Upgrade |
| Serial | 30 bits | Clé de produit brute (RPK) |
| Hash | 28 bits | Hash RPK |
| Signature | 55 bits | Signature à courbe elliptique pour le hash RPK |
| Segment | Capacité | Données |
|---|
| Upgrade | 1 bit | Indicateur de version Upgrade |
| Channel ID | 10 bits | La partie BBB de la RPK |
| Hash | 31 bits | Hash RPK |
| Signature | 62 bits | Signature à courbe elliptique pour le hash RPK |
| Auth Key | 10 bits | Valeur d'authentification backend |
| Offset | Valeur |
|---|
0x0000 | ID BINK |
0x0004 | Taille de la structure BINKEY en octets (toujours 0x16C en pratique) |
0x0008 | Longueur de l'en-tête (toujours 7 en pratique) |
0x000C | Somme de contrôle |
0x0010 | Date encodée numériquement - version BINKEY (toujours 19980206 en pratique) |
0x0014 | Taille de l'ordre de la courbe ECC (toujours 12 en pratique) |
0x0018 | Longueur du hash (toujours 28 en pratique) |
0x001C | Longueur de la signature (toujours 55 en pratique) |
0x0020 | Ordre du corps fini p |
0x005C | Paramètre de courbe a |
0x0098 | Paramètre de courbe b |
0x00D4 | Coordonnée x du point de base Gx |
0x0110 | Coordonnée y du point de base Gy |
0x014C | Coordonnée x de la clé publique Kx |
0x0188 | Coordonnée y de la clé publique Ky |
| Offset | Valeur |
|---|
0x0000 | ID BINK |
0x0004 | Taille de la structure BINKEY en octets |
0x0008 | Longueur de l'en-tête (toujours 9 en pratique) |
0x000C | Somme de contrôle |
0x0010 | Date encodée numériquement - version BINKEY (toujours 20020420 en pratique) |
0x0014 | Taille de l'ordre de la courbe ECC (toujours 16 en pratique) |
0x0018 | Longueur du hash (toujours 31 en pratique) |
0x001C | Longueur de la signature (toujours 62 en pratique) |
0x0020 | Longueur de la valeur d'authentification backend (toujours 12 en pratique) |
0x0024 | Longueur de l'ID de produit (toujours 20 en pratique) |
0x0028 | Ordre du corps fini p |
0x0068 | Paramètre de courbe a |
0x00A8 | Paramètre de courbe b |
0x00E8 | Coordonnée x du point de base Gx |
0x0128 | Coordonnée y du point de base Gy |
0x0168 | Coordonnée x de la clé publique Kx |
0x01A8 | Coordonnée y de la clé publique Ky |