C# - 레지스트리에 등록된 마이크로소프트 제품의 DigitalProductId로부터 라이선스 키(Product Key)를 알아내는 방법
다음과 같은 글이 있군요. ^^
Decode DigitalProductId Registry Keys To Original Product Key with PowerShell
; https://chentiangemalc.wordpress.com/2021/02/23/decode-digitalproductid-registry-keys-to-original-product-key-with-powershell/
위의 내용은 PowerShell + C#으로 되어 있지만 이것을 C# 만으로 바꾸면 다음과 같습니다.
using Microsoft.Win32;
using RegUtils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
RegistryFinder regFinder = new RegUtils.RegistryFinder();
string searchTerm = "DigitalProductId";
RegistryKey baseKey = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
Microsoft.Win32.RegistryView.Registry64);
regFinder.FindRegValueNames(baseKey, searchTerm);
foreach (KeyValuePair<string, string> result in regFinder.Results)
{
byte [] keyData = Registry.GetValue(result.Key, "DigitalProductId", null) as byte [];
if (keyData == null)
{
Console.WriteLine(result.Key);
continue;
}
Console.WriteLine($"{result.Key}: {DecodeKey(keyData)}");
}
}
static string DecodeKey(byte[] key)
{
string KeyOutput = "";
int KeyOffset = 52;
if (key.Length < 66)
{
return "";
}
int dn = (int)System.Math.Truncate((double)key[66] / 6);
bool isWin8 = (bool)((dn & 1) == 1);
key[66] = (byte)((key[66] & 0xF7));
int i = 24;
string maps = "BCDFGHJKMPQRTVWXY2346789";
int last = 0;
do
{
int current = 0;
int j = 14;
do
{
current = current * 256;
current = key[j + KeyOffset] + current;
key[j + KeyOffset] = (byte)System.Math.Truncate((double)current / 24);
current = current % 24;
j--;
} while (j >= 0);
i--;
KeyOutput = maps.Substring(current, 1) + KeyOutput;
last = current;
} while (i >= 0);
if (isWin8 == true)
{
string keypart1 = KeyOutput.Substring(1, last);
if (string.IsNullOrEmpty(keypart1) == true)
{
return "";
}
string insert = "N";
KeyOutput = KeyOutput.Replace(keypart1, keypart1 + insert);
if (last == 0)
{
KeyOutput = insert + KeyOutput;
}
}
string result = "";
if (KeyOutput.Length == 26)
{
result = string.Format("{0}-{1}-{2}-{3}-{4}",
KeyOutput.Substring(1, 5),
KeyOutput.Substring(6, 5),
KeyOutput.Substring(11, 5),
KeyOutput.Substring(16, 5),
KeyOutput.Substring(21, 5));
}
else
{
Console.WriteLine(KeyOutput);
}
return result;
}
}
namespace RegUtils
{
public class RegistryFinder
{
public ConcurrentBag<KeyValuePair<string, string>> Results;
public RegistryFinder()
{
Results = new ConcurrentBag<KeyValuePair<string, string>>();
}
public void FindRegValueNames(RegistryKey SubKey, string pattern)
{
FindRegValueNames(SubKey, pattern, true);
}
private void FindRegValueNames(RegistryKey SubKey, string pattern, bool first)
{
try
{
Parallel.ForEach(SubKey.GetSubKeyNames(), sub =>
{
try
{
if (first)
{
foreach (var valueName in SubKey.GetValueNames())
{
if (string.Equals(valueName, pattern, StringComparison.OrdinalIgnoreCase) == true)
{
Results.Add(new KeyValuePair<string, string>(SubKey.Name, valueName));
}
}
}
RegistryKey local = SubKey.OpenSubKey(sub);
foreach (var valueName in local.GetValueNames())
{
if (string.Equals(valueName, pattern, StringComparison.OrdinalIgnoreCase) == true)
{
Results.Add(new KeyValuePair<string, string>(local.Name, valueName));
}
}
FindRegValueNames(local, pattern, false);
}
catch (System.Security.SecurityException)
{
}
});
}
catch { }
}
}
}
코드를 보면 알겠지만, 특정 DigitalProductId를 포함한 키를 지정하는 방식이 아닌, HKEY_LOCAL_MACHINE 하위에 DigitalProductId를 가진 모든 키를 찾아 해독하는 방법을 사용하고 있습니다. 대략 제 컴퓨터에서는 다음과 같은 형식의 출력이 나옵니다.
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\150\Tools\ClientSetup:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\140\Tools\ClientSetup:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\130\Tools\ClientSetup:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey2: J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey: AGVTT-V0H53-2CCHJ-W4FW5-7HV9Q
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion: J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MSSQLSERVER\Setup:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\150\Tools\ClientSetup:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Registration: J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 6/14/2019 23:54:49): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 6/11/2020 19:38:06): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 5/2/2018 21:12:54): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 2/15/2019 20:33:20): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 11/20/2017 09:45:21): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
HKEY_LOCAL_MACHINE\SYSTEM\Setup\Source OS (Updated on 11/11/2019 22:26:04): J5ANC-4J1BC-BDHV3-BDPH5-47JQT
보는 바와 같이 해독 가능한 DigitalProductId는 현재 "윈도우 운영체제"만 가능한 듯합니다. ^^
(
첨부 파일은 이 글의 예제 코드와
PowerShell 소스 코드입니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]