Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Product.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;

namespace VSKeyExtractor;

/// <summary>
/// Represents a product entry with its display name, GUID, and MPC value.
/// </summary>
/// <param name="Name"> Gets the product name. </param>
/// <param name="GUID"> Gets the product GUID. </param>
/// <param name="MPC"> Gets the product MPC value. </param>
internal record struct Product(string Name, Guid GUID, string MPC)
{
/// <summary>
/// Gets the product name.
/// </summary>
public string Name { get; } = Name;

/// <summary>
/// Gets the product GUID.
/// </summary>
public Guid GUID { get; } = GUID;

/// <summary>
/// Gets the product MPC value.
/// </summary>
public string MPC { get; } = MPC;
}
140 changes: 79 additions & 61 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,99 @@
using System.Text;
using System.Text.RegularExpressions;

namespace VSKeyExtractor
{
internal struct Product
{
public string Name { get; }
public Guid GUID { get; }
public string MPC { get; }
public Product(string name, Guid guid, string mpc)
{
Name = name;
GUID = guid;
MPC = mpc;
}
}
namespace VSKeyExtractor;

class Program
{
private static readonly IReadOnlyList<Product> Products = new List<Product>()
{
new Product("Visual Studio Express 2012 for Windows Phone" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04937"),
new Product("Visual Studio Professional 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04938"),
new Product("Visual Studio Ultimate 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04940"),
new Product("Visual Studio Premium 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04941"),
new Product("Visual Studio Test Professional 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04942"),
new Product("Visual Studio Express 2012 for Windows Desktop", new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "05695"),
/// <summary>
/// Console entry point for extracting Visual Studio product license keys from the Windows registry.
/// </summary>
class Program
{
/// <summary>
/// Known Visual Studio product names, registry product codes, and license identifiers.
/// The application iterates over this list and tries to locate a matching encrypted license entry
/// under the registry path used by Visual Studio installations.
/// </summary>
private static readonly IReadOnlyList<Product> Products =
[
// Visual Studio 2012 family.
new Product("Visual Studio Express 2012 for Windows Phone" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04937"),
new Product("Visual Studio Professional 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04938"),
new Product("Visual Studio Ultimate 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04940"),
new Product("Visual Studio Premium 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04941"),
new Product("Visual Studio Test Professional 2012" , new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "04942"),
new Product("Visual Studio Express 2012 for Windows Desktop", new Guid("77550D6B-6352-4E77-9DA3-537419DF564B"), "05695"),

new Product("Visual Studio 2013 Professional" , new Guid("E79B3F9C-6543-4897-BBA5-5BFB0A02BB5C"), "06177"),
new Product("Visual Studio 2013 Ultimate" , new Guid("E79B3F9C-6543-4897-BBA5-5BFB0A02BB5C"), "06181"),
// Visual Studio 2013 family.
new Product("Visual Studio 2013 Professional" , new Guid("E79B3F9C-6543-4897-BBA5-5BFB0A02BB5C"), "06177"),
new Product("Visual Studio 2013 Ultimate" , new Guid("E79B3F9C-6543-4897-BBA5-5BFB0A02BB5C"), "06181"),

new Product("Visual Studio 2015 Enterprise" , new Guid("4D8CFBCB-2F6A-4AD2-BABF-10E28F6F2C8F"), "07060"),
new Product("Visual Studio 2015 Professional" , new Guid("4D8CFBCB-2F6A-4AD2-BABF-10E28F6F2C8F"), "07062"),
// Visual Studio 2015 family.
new Product("Visual Studio 2015 Enterprise" , new Guid("4D8CFBCB-2F6A-4AD2-BABF-10E28F6F2C8F"), "07060"),
new Product("Visual Studio 2015 Professional" , new Guid("4D8CFBCB-2F6A-4AD2-BABF-10E28F6F2C8F"), "07062"),

new Product("Visual Studio 2017 Enterprise" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08860"),
new Product("Visual Studio 2017 Professional" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08862"),
new Product("Visual Studio 2017 Test Professional" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08866"),
// Visual Studio 2017 family.
new Product("Visual Studio 2017 Enterprise" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08860"),
new Product("Visual Studio 2017 Professional" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08862"),
new Product("Visual Studio 2017 Test Professional" , new Guid("5C505A59-E312-4B89-9508-E162F8150517"), "08866"),

new Product("Visual Studio 2019 Enterprise" , new Guid("41717607-F34E-432C-A138-A3CFD7E25CDA"), "09260"),
new Product("Visual Studio 2019 Professional" , new Guid("41717607-F34E-432C-A138-A3CFD7E25CDA"), "09262"),
// Visual Studio 2019 family.
new Product("Visual Studio 2019 Enterprise" , new Guid("41717607-F34E-432C-A138-A3CFD7E25CDA"), "09260"),
new Product("Visual Studio 2019 Professional" , new Guid("41717607-F34E-432C-A138-A3CFD7E25CDA"), "09262"),

new Product("Visual Studio 2022 Enterprise" , new Guid("1299B4B9-DFCC-476D-98F0-F65A2B46C96D"), "09660"),
new Product("Visual Studio 2022 Professional" , new Guid("1299B4B9-DFCC-476D-98F0-F65A2B46C96D"), "09662"),
// Visual Studio 2022 family.
new Product("Visual Studio 2022 Enterprise" , new Guid("1299B4B9-DFCC-476D-98F0-F65A2B46C96D"), "09660"),
new Product("Visual Studio 2022 Professional" , new Guid("1299B4B9-DFCC-476D-98F0-F65A2B46C96D"), "09662"),

new Product("Visual Studio 2026 Enterprise Insider" , new Guid("0EB1B2EC-090C-4540-B219-F529C658360C"), "09760"),
new Product("Visual Studio 2026 Professional Insider" , new Guid("0EB1B2EC-090C-4540-B219-F529C658360C"), "09762"),
// Visual Studio 2026 Insider builds.
new Product("Visual Studio 2026 Enterprise Insider" , new Guid("0EB1B2EC-090C-4540-B219-F529C658360C"), "09760"),
new Product("Visual Studio 2026 Professional Insider" , new Guid("0EB1B2EC-090C-4540-B219-F529C658360C"), "09762"),

new Product("Visual Studio 2026 Enterprise" , new Guid("97372B8F-5B80-4DA7-8476-FF55D6368CBD"), "09860"),
new Product("Visual Studio 2026 Professional" , new Guid("97372B8F-5B80-4DA7-8476-FF55D6368CBD"), "09862"),
// Visual Studio 2026 release builds.
new Product("Visual Studio 2026 Enterprise" , new Guid("97372B8F-5B80-4DA7-8476-FF55D6368CBD"), "09860"),
new Product("Visual Studio 2026 Professional" , new Guid("97372B8F-5B80-4DA7-8476-FF55D6368CBD"), "09862"),

};
];

static void Main()
{
foreach (var product in Products) ExtractLicense(product);
}
/// <summary>
/// Starts the extraction process for every known product in the static product list.
/// </summary>
static void Main()
{
foreach (var product in Products) ExtractLicense(product);
}

private static void ExtractLicense(Product product)
/// <summary>
/// Reads the encrypted license blob for a specific product from the registry, decrypts it,
/// and searches the decrypted text for a key formatted as five groups of five alphanumeric
/// characters separated by hyphens.
/// </summary>
/// <param name="product">The product metadata used to locate the registry entry.</param>
private static void ExtractLicense(Product product)
{
// Visual Studio stores encrypted license data beneath this registry path.
var encrypted = Registry.GetValue($"HKEY_CLASSES_ROOT\\Licenses\\{product.GUID}\\{product.MPC}", "", null);
if (encrypted == null) return;
try
{
var encrypted = Registry.GetValue($"HKEY_CLASSES_ROOT\\Licenses\\{product.GUID}\\{product.MPC}", "", null);
if (encrypted == null) return;
try
{
var secret = ProtectedData.Unprotect((byte[])encrypted, null, DataProtectionScope.CurrentUser);
var str = Encoding.Unicode.GetString(secret);
foreach (var sub in str.Split('\0'))
if (!string.IsNullOrWhiteSpace(sub))
// Decrypt the protected blob using the current user's DPAPI context.
var secret = ProtectedData.Unprotect((byte[])encrypted, null, DataProtectionScope.CurrentUser);
// Convert the decrypted binary data into a Unicode string for token scanning.
var str = Encoding.Unicode.GetString(secret);
foreach (var sub in str.Split('\0'))
if (!string.IsNullOrWhiteSpace(sub))
{
Debug.WriteLine($"sub: {sub}");
// Search each token for a license-key-shaped value.
var match = Regex.Match(sub, @"\w{5}-\w{5}-\w{5}-\w{5}-\w{5}");
if (match.Success)
{
Debug.WriteLine($"sub: {sub}");
var match = Regex.Match(sub, @"\w{5}-\w{5}-\w{5}-\w{5}-\w{5}");
if (match.Success)
{
Console.WriteLine($"Found key for {product.Name}: {match.Captures[0]}");
}
Console.WriteLine($"Found key for {product.Name}: {match.Captures[0]}");
}
}
catch (Exception) {/*just void em*/}
}
}
catch (Exception)
{
// Ignore malformed or inaccessible registry entries and continue with the next product.
}
}
}
68 changes: 68 additions & 0 deletions README.de.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# VSKeyExtractor

VSKeyExtractor ist ein kleines Kommandozeilenwerkzeug, das versucht, den Lizenzschlüssel aus einer lokalen Visual Studio-Installation zu extrahieren.

Es durchsucht bekannte Visual Studio-Produkt-Einträge, liest die verschlüsselten Lizenzdaten aus der Windows-Registrierung, entschlüsselt sie im Kontext des aktuellen Benutzers und sucht nach einem Schlüssel im Format `AAAAA-BBBBB-CCCCC-DDDDD-EEEEE`.

## Funktionen

- Liest Visual-Studio-Lizenzdaten aus der Windows-Registrierung
- Unterstützt mehrere Visual-Studio-Produktgenerationen
- Versucht, geschützte Lizenzdaten mit dem aktuellen Benutzerprofil zu entschlüsseln
- Gibt gefundene schlüsselartige Werte in der Konsole aus

## Voraussetzungen

- Windows
- Eine Visual-Studio-Installation mit vorhandenen lokalen Lizenzdaten
- Die benötigte .NET-Runtime für das jeweilige Projekt

## Funktionsweise

Das Tool prüft Registrierungswerte an den bekannten Visual-Studio-Lizenzpfaden und versucht anschließend, die gespeicherten Daten zu entschlüsseln. Wenn im entschlüsselten Text ein passender Schlüssel gefunden wird, wird er in die Standardausgabe geschrieben.

Falls kein Schlüssel gefunden wird, fährt das Tool einfach mit dem nächsten bekannten Produkt-Eintrag fort.

## Anwendung starten

Du kannst das Projekt direkt mit `dotnet run` starten.

### .NET Framework / Windows-Target

```powershell
dotnet run --project .\VSKeyExtractor.csproj
```

### SDK-style-Projekt

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj
```

### Bestimmtes Target Framework ausführen

Wenn du das SDK-style-Projekt verwendest und ein bestimmtes Framework starten möchtest, kannst du Folgendes nutzen:

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj -f net8.0-windows
```

Weitere unterstützte Target Frameworks können `net9.0-windows` oder `net10.0-windows` sein, abhängig vom installierten .NET SDK.

## Beispielausgabe

```text
Found key for Visual Studio 2022 Professional: ABCDE-FGHIJ-KLMNO-PQRST-UVWXY
```

## Hinweise

- Führe das Tool auf dem Rechner aus, auf dem Visual Studio aktiviert wurde.
- Das Tool kann nur Daten lesen, die für das aktuelle Benutzerprofil verfügbar sind.
- Einige Einträge können nicht verfügbar, fehlerhaft oder geschützt sein; das ist erwartbar.

## Übersetzungen

- [English](README.md)
- [Français](README.fr.md)
- [Español](README.es.md)
68 changes: 68 additions & 0 deletions README.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# VSKeyExtractor

VSKeyExtractor es una pequeña herramienta de línea de comandos que intenta extraer la clave de licencia utilizada para activar una instalación local de Visual Studio.

Recorre entradas conocidas de productos de Visual Studio, lee los datos de licencia cifrados del registro de Windows, los descifra en el contexto del usuario actual y busca una clave con formato `AAAAA-BBBBB-CCCCC-DDDDD-EEEEE`.

## Características

- Lee datos de licencia de Visual Studio desde el registro de Windows
- Admite varias generaciones de productos de Visual Studio
- Intenta descifrar blobs de licencia protegidos con el perfil del usuario actual
- Muestra en la consola cualquier valor que parezca una clave

## Requisitos

- Windows
- Una instalación de Visual Studio con datos de licencia locales disponibles
- El runtime de .NET necesario para el proyecto que quieras ejecutar

## Cómo funciona

La herramienta comprueba valores del registro en las rutas de licencia conocidas de Visual Studio y después intenta descifrar los datos almacenados. Si encuentra una clave coincidente en el texto descifrado, la escribe en la salida estándar.

Si no encuentra ninguna clave, simplemente continúa con la siguiente entrada de producto conocida.

## Ejecutar la aplicación

Puedes ejecutar el proyecto directamente con `dotnet run`.

### Destino .NET Framework / Windows

```powershell
dotnet run --project .\VSKeyExtractor.csproj
```

### Proyecto estilo SDK

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj
```

### Ejecutar un framework de destino específico

Si usas el proyecto estilo SDK y quieres apuntar a un framework concreto, puedes usar:

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj -f net8.0-windows
```

Otros frameworks de destino admitidos pueden incluir `net9.0-windows` o `net10.0-windows`, según el SDK de .NET instalado.

## Ejemplo de salida

```text
Found key for Visual Studio 2022 Professional: ABCDE-FGHIJ-KLMNO-PQRST-UVWXY
```

## Notas

- Ejecuta la herramienta en el equipo donde se activó Visual Studio.
- La herramienta solo puede leer datos disponibles para el perfil de usuario actual.
- Algunas entradas pueden no estar disponibles, estar dañadas o protegidas; esto es esperable.

## Traducciones

- [English](README.md)
- [Deutsch](README.de.md)
- [Français](README.fr.md)
68 changes: 68 additions & 0 deletions README.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# VSKeyExtractor

VSKeyExtractor est un petit outil en ligne de commande qui tente d’extraire la clé de licence utilisée pour activer une installation locale de Visual Studio.

Il parcourt les entrées connues des produits Visual Studio, lit les données de licence chiffrées dans le registre Windows, les déchiffre dans le contexte de l’utilisateur actuel et recherche une clé au format `AAAAA-BBBBB-CCCCC-DDDDD-EEEEE`.

## Fonctionnalités

- Lit les données de licence Visual Studio depuis le registre Windows
- Prend en charge plusieurs générations de produits Visual Studio
- Tente de déchiffrer les blobs de licence protégés avec le profil de l’utilisateur actuel
- Affiche dans la console toute valeur ressemblant à une clé

## Prérequis

- Windows
- Une installation de Visual Studio avec des données de licence locales présentes
- Le runtime .NET requis pour le projet que vous souhaitez exécuter

## Fonctionnement

L’outil vérifie les valeurs du registre aux emplacements de licence connus de Visual Studio, puis tente de déchiffrer les données stockées. Si une clé correspondante est trouvée dans le texte déchiffré, elle est écrite dans la sortie standard.

Si aucune clé n’est trouvée, l’outil passe simplement à l’entrée de produit suivante.

## Exécuter l’application

Vous pouvez exécuter le projet directement avec `dotnet run`.

### Cible .NET Framework / Windows

```powershell
dotnet run --project .\VSKeyExtractor.csproj
```

### Projet de style SDK

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj
```

### Exécuter un framework cible spécifique

Si vous utilisez le projet de style SDK et souhaitez cibler un framework particulier, vous pouvez utiliser :

```powershell
dotnet run --project .\VSKeyExtractor_net.csproj -f net8.0-windows
```

D’autres frameworks cibles pris en charge peuvent inclure `net9.0-windows` ou `net10.0-windows`, selon le SDK .NET installé.

## Exemple de sortie

```text
Found key for Visual Studio 2022 Professional: ABCDE-FGHIJ-KLMNO-PQRST-UVWXY
```

## Remarques

- Exécutez l’outil sur la machine où Visual Studio a été activé.
- L’outil ne peut lire que les données disponibles pour le profil utilisateur actuel.
- Certaines entrées peuvent être indisponibles, endommagées ou protégées ; c’est normal.

## Traductions

- [English](README.md)
- [Deutsch](README.de.md)
- [Español](README.es.md)
Loading