Recupera / decodifica la chiave del prodotto Windows 7 da Linux


19

Ho accidentalmente disconnesso il mio disco rigido mentre era ancora in esecuzione e ho danneggiato l'installazione di Windows 7; Ora non sono più in grado di avviare Windows. Ho provato di tutto per provare a riparare l'installazione: Windows Startup Repair, chkdsk / r, SFC / scannow, bootrec / rebuildbcd, ecc. E senza fortuna. Voglio solo eseguire una nuova installazione, ma il mio problema è che non ho la chiave del prodotto Windows scritta da nessuna parte e non riesco a utilizzare alcuno script o utilità per recuperarla dal registro perché non riesco ad avviare Windows.

Le chiavi del prodotto Windows 7 sono archiviate, crittografate, nel valore "DigitalProductId" della chiave di registro HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion. Sono stato in grado di montare la partizione di Windows danneggiata in sola lettura da un CD live di Ubuntu e copiare l'hive di registro Windows \ System32 \ config \ SOFTWARE, che contiene la chiave e il valore in questione, su un'unità flash, ma caricando questo alveare in regedit su un'installazione di Windows funzionante e quindi provare a utilizzare script o utility per decrittografare il valore "DigitalProductId" caricato restituisce solo la chiave del prodotto dell'installazione di Windows host, indipendentemente da quanto io abbia provato. Ho provato a contattare il supporto Microsoft e sono stati piuttosto inutili. Qualcuno sarebbe in grado di guidarmi ulteriormente? Forse se esiste un modo diverso di recuperare il codice Product Key da Linux?

Se qualcuno che ha più familiarità con lo scripting / crittografia sarebbe disposto a provare a seguire lo script di decrittazione per decrittografare manualmente la chiave del prodotto, potrei inviarti via e-mail il valore "DigitalProductId" esportato, l'alveare del registro SOFTWARE e lo script di decrittazione.


Questo non suona bene. Se hai acquistato una licenza dovresti avere la chiave. Ora, d'altra parte, se hai messo le mani su un'altra immagine di windows e vuoi estrarne la chiave, non è proprio questo il punto di questo sito.
JasonXA,

Ho comprato una licenza. Ho il DVD di installazione ma non riesco a trovare la chiave del prodotto fornita. Ma penso di aver trovato una soluzione qui: dagondesign.com/articles/windows-xp-product-key-recovery/…
sundiata

Sì, sembra funzionare. Usando il metodo sono riuscito a riprodurre la mia chiave.
JasonXA,

Se il firmware è basato su UEFI, la chiave di licenza viene effettivamente memorizzata nella tabella ACPI MSDM in modo che persista durante un riavvio. In tal caso, consultare blog.fpmurphy.com per i dettagli su come recuperarlo.
fpmurphy

Risposte:


30

C'è un ottimo strumento disponibile per Linux chiamato chntpw. Puoi scaricarlo facilmente su Debian / Ubuntu tramite:

sudo apt install chntpw

Per guardare nel file di registro pertinente montare il disco di Windows e aprirlo in questo modo:

chntpw -e /path/to/windisk/Windows/System32/config/software

Ora per ottenere il decodificato DigitalProductIdinserisci questo comando:

dpi \Microsoft\Windows NT\CurrentVersion\DigitalProductId

5
Il percorso del file di registro rilevante è in / path / to / windisk / Windows / System32 / config / RegBack / SOFTWARE
Mohamed EL HABIB

2
Questa è un'ottima risposta, l'ho citata su Ask Ubuntu askubuntu.com/a/953130/75060
Mark Kirby,

Grazie per questo. Si prega di prendere nota per verificare il caso della cartella e dei nomi dei file. Nel mio caso, ho dovuto usare le maiuscole SOFTWAREper il nome del file.
Paddy Landau,

In caso di problemi nella lettura della cartella system32, provare a fare una copia e fornire il percorso della copia a chntpw.
Markus von Broady,

2

Per coloro che non sono timidi fare un po 'di programmazione.

Ho trovato un algoritmo circa 10 anni fa e l'ho implementato in C # (vedi sotto)


Se vuoi solo eseguirlo su Windows

Mi sono preso la libertà di convertirlo in uno script PowerShell:

$dpid = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "DigitalProductId"

# Get the range we are interested in
$id = $dpid.DigitalProductId[52..(52+14)]

# Character table
$chars = "BCDFGHJKMPQRTVWXY2346789"

# Variable for the final product key
$pkey = ""

# Calculate the product key
for ($i=0; $i -le 24; $i++) {
    $c = 0

    for($j=14; $j -ge 0; $j--) {
        $c = ($c -shl 8) -bxor $id[$j]

        $id[$j] = [Math]::Floor($c / 24) -band 255

        $c = $c % 24
    }
    $pkey = $chars[$c] + $pkey
}
# Insert some dashes
for($i = 4; $i -gt 0; $i--) {
    $pkey = $pkey.Insert($i * 5, "-")
}
$pkey

Esegui questo e ottieni la chiave del prodotto. (Quindi nessuna codifica per te dopo tutto)


Posta originale

Quindi questo è l'attuale codice C # che ho scavato e commentato.

public static string ConvertDigitalProductID(string regPath, string searchKey = "DigitalProductID") {
    // Open the sub key i.E.: "Software\Microsoft\Windows NT\CurrentVersion"
    var regkey = Registry.LocalMachine.OpenSubKey(regPath, false);
    // Retreive the value of "DigitalProductId"
    var dpid = (byte[])regkey.GetValue(searchKey);
    // Prepare an array for the relevant parts
    var idpart = new byte[15];

    // Copy the relevant parts of the array
    Array.Copy(dpid, 52, idpart, 0, 15);

    // Prepare the chars that will make up the key
    var charStore = "BCDFGHJKMPQRTVWXY2346789";

    // Prepare a string for the result
    string productkey = "";

    // We need 24 iterations (one for each character)
    for(int i = 0; i < 25; i++) {

        int c = 0;
        // Go through each of the 15 bytes of our dpid
        for(int j = 14; j >= 0; j--) {
            // Shift the current byte to the left and xor in the next byte
            c = (c << 8) ^ idpart[j];

            // Leave the result of the division in the current position
            idpart[j] = (byte)(c / 24);

            // Take the rest of the division forward to the next round
            c %= 24;
        }
        // After each round, add a character from the charStore to our key
        productkey = charStore[c] + productkey;
    }

    // Insert the dashes
    for(int i = 4; i > 0; i--) {
        productkey = productkey.Insert(i * 5, "-");
    }

    return productkey;
}

Dovrai passarlo Software\Microsoft\Windows NT\CurrentVersioncome chiave, dove troveràDigitalProductId

A quel tempo MS Office Products utilizzava lo stesso algoritmo, quindi fornendo alla funzione la chiave di registro pertinente poteva calcolare anche quelle chiavi del prodotto.

Ovviamente puoi refactorizzare la funzione in modo che prenda un array di byte come input.

Per oggi L'ho appena testato sul mio computer Windows 10 e funziona ancora.


Questa è una buona risposta, ma la domanda è molto vecchia e potrebbe non ricevere molte opinioni. Dato che sei un membro, ti preghiamo di considerare di aggiungere la tua risposta al nostro attuale post di Ask Ubuntu askubuntu.com/questions/953126/…
Mark Kirby,

Grazie. Ma credo che sarebbe fuori tema laggiù. Potrei dare uno schiaffo all'implementazione di uno pseudo codice. E fare riferimento a questo post come un'implementazione effettiva.
Mr Paul Paul,

Nessun problema, fai quello che pensi sia il migliore
Mark Kirby,

2

Ecco una porta Python dell'altra risposta (adattata per Windows 8.1). Il vantaggio di questo chntpwè che funzionerà anche con le unità in stato di sola lettura.

Requisiti:

pip install python-registry

Codice:

#!/usr/bin/env python
import sys
from Registry import Registry
reg = Registry.Registry("/path/to/drive/Windows/System32/config/RegBack/SOFTWARE")
# Uncomment for registry location for Windows 7 and below:
#reg = Registry.Registry("/path/to/drive/Windows/system32/config/software")
key = reg.open("Microsoft\Windows NT\CurrentVersion")
did = bytearray([v.value() for v in key.values() if v.name() == "DigitalProductId"][0])
idpart = did[52:52+15]
charStore = "BCDFGHJKMPQRTVWXY2346789";
productkey = "";
for i in range(25):
  c = 0
  for j in range(14, -1, -1):
    c = (c << 8) ^ idpart[j]
    idpart[j] = c // 24
    c %= 24
  productkey = charStore[c] + productkey
print('-'.join([productkey[i * 5:i * 5 + 5] for i in range(5)]))

Il ciclo interno era un'iterazione troppo breve. Dovrebbe funzionare ora.
Lenar Hoyt,

0

Ecco la mia implementazione bash. Lo chiamo get_windows_key.sh funziona bene da clonezilla. Inizialmente l'ho pubblicato qui https://sourceforge.net/p/clonezilla/discussion/Open_discussion/thread/979f335385/

#!/bin/bash
# written by Jeff Sadowski
# credit
###################################################
# Pavel Hruška, Scott Skahht, and Philip M for writting
# https://github.com/mrpeardotnet/WinProdKeyFinder/blob/master/WinProdKeyFind/KeyDecoder.cs
# that I got my conversion code from
#
# I used the comments on the sudo code from
# /ubuntu/953126/can-i-recover-my-windows-product-key- from-ubuntu
# by MrPaulch
#
# and the creator of chntpw
#
# Petter Nordahl-Hagen
# without which I would not be able to get the key in linux
#
# also the creators of ntfs-3g, linux and bash

parted -l 2>/dev/null |grep -e ntfs -e fat -e Disk|grep -v Flags
#get the first mac address that isn't a loopback address
# loopback will have all zeros
MAC=$(cat /sys/class/net/*/address|grep -v 00:00:00:00:00:00|head -n 1|sed "s/:/-/g")
if [ "$1" = "" ];then
 echo "mount the Windows share then give this script the path where you mounted it"
 exit
fi
cd $1
#
# This way will work no matter what the capitalization is
next=$(find ./ -maxdepth 1 -iname windows);cd ${next}
next=$(find ./ -maxdepth 1 -iname system32);cd ${next}
next=$(find ./ -maxdepth 1 -iname config);cd ${next}
file=$(find ./ -maxdepth 1 -iname software)
#echo $(pwd)${file:1}
#Get the necissary keys
#get the version key
VERSION=$((16#$(echo -e "cat \\Microsoft\\Windows NT\\CurrentVersion\\CurrentMajorVersionNumber\nq\n" | chntpw -e ${file}|grep "^0x"|cut -dx -f2)))
hexPid_csv_full=$(echo $(echo -e "hex \\Microsoft\\Windows NT\\CurrentVersion\\DigitalProductId\nq\n" | chntpw -e ${file}|grep "^:"|cut -b 9-55)|sed 's/ /,/g' | tr '[:u>
# get the subset 53 to 68 of the registry entry
hexPid_csv=$(echo $(echo -e "hex \\Microsoft\\Windows NT\\CurrentVersion\\DigitalProductId\nq\n" | chntpw -e ${file}|grep "^:"|cut -b 9-55)|sed 's/ /,/g' | tr '[:upper:>
echo "${hexPid_csv_full}" > /custom/DigitalProductId_${MAC}.txt
#formatted output
spread()
{
 key=$1
 echo ${key:0:5}-${key:5:5}-${key:10:5}-${key:15:5}-${key:20:5}
}
# almost a direct conversion of c# code from
# https://github.com/mrpeardotnet/WinProdKeyFinder/blob/master/WinProdKeyFind/KeyDecoder.cs
# however most of this looks similar to sudo code I found
# /ubuntu/953126/can-i-recover-my-windows-product-key-from-ubuntu
DecodeProductKey()
{
digits=(B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9)
for j in {0..15};do
#Populate the Pid array from the values found in the registry
 Pid[$j]=$((16#$(echo ${hexPid_csv}|cut -d, -f $(($j+1)))))
done
if [ "$1" = "8+" ];then
# modifications needed for getting the windows 8+ key
 isWin8=$(($((${Pid[14]}/6))&1))
 Pid[14]=$(( $(( ${Pid[14]}&247 )) | $(( $(( ${isWin8} & 2 )) * 4 )) ))
fi
key=""
last=0
for i in {24..0};do
 current=0
 for j in {14..0};do
  # Shift the current contents of c to the left by 1 byte 
  # and add it with the next byte of our id
  current=$((${current}*256))
  current=$((${Pid[$j]} + current))
  # Put the result of the divison back into the array
  Pid[$j]=$((${current}/24))
  # Calculate remainder of c
  current=$((${current}%24))
  last=${current}
 done
 # Take character at position c and prepend it to the ProductKey
 key="${digits[${current}]}${key}"
done
if [ "$1" = "8+" ];then
# another modification needed for a windows 8+ key
 key="${key:1:${last}}N${key:$((${last}+1)):24}"
 echo -n "Windows 8+ key: "
else
 echo -n "Windows 7- key: "
fi
spread "${key}"
}
if [ "$VERSION" -gt "7" ];then
 DecodeProductKey 8+
else
 DecodeProductKey
fi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.