Can I recover my Windows product key from Ubuntu?
First recover your Ubuntu with going to recovery mode and running
sudo apt install --reinstall ubuntu-desktop
This answer is not written by me but by Thomas on Superuser, please vote there, if you vote here thanks
There is a great tool available for Linux called chntpw. You can get it easily on Debian/Ubuntu via:
sudo apt install chntpw
To look into the relevant registry file mount the Windows disk and open it like so:
chntpw -e /path/to/windisk/Windows/System32/config/SOFTWARE
Now to get the decoded DigitalProductId enter this command:
dpi \Microsoft\Windows NT\CurrentVersion\DigitalProductId
A comment from below says
The path to the relevant registry file is /path/to/windisk/Windows/System32/config/RegBack/SOFTWARE
So for anyone wondering how this actually works.
Essentially you'll have to grab the contents of the registry key
HKLM\Software\Microsoft\Windows NT\CurrentVersion\DigitalProductId
This is a so called REG_BINARY
. Meaning it's just a collection of bytes. You could dump them via chntpw
or copy them by hand.
Let's see what we have to do with those bytes in order to get our product key with the help of some pseudo code.
Once you have those in an Array, you need to extract the subset of bytes that encode the product id. In particular: the range between 52 and (52 + 14). That gives you 15 bytes.
EncodedId = DigitalProductId.Range(52, 52+14)
This is still a bunch of bytes, that don't at all resemble the product key. So let us decode it.
For that you need the collection of all the characters a product key can be made of:
Characters = "BCDFGHJKMPQRTVWXY2346789"
Yes this is not the whole alphabet. As it turns out a Windows product key doesn't use all of the alphanumerical symbols.
Now let's do the decoding. We'll need:
- A variable to hold the product key
- A loop over 0 to 24. For each character of our product key
- An inner loop over 0 to 14 (In reverse) For each byte in our encoded id
- Some bit fiddeling and arithmatic for the decoding process
ProductKey = ""
FOR i = 0 TO 24
c = 0
FOR j = 14 TO 0 STEP -1
# Shift the current contents of c to the left by 1 byte
# and xor it with the next byte of our id
c = (c * 256) XOR EncodedId[j]
# Put the result of the divison back into the array
EncodedId[j] = FLOOR(c / 24)
# Calculate remainder of c
c = c MOD 24
LOOP
# Take character at position c and prepend it to the ProductKey
ProductKey = Characters[c] + ProductKey
LOOP
Finally we insert the "-" character into the string at the appropriate places.
FOR i = 4 TO 1 STEP -1
ProductKey = ProductKey.Insert(i * 5, "-")
LOOP
And we're done!
... Almost:
PRINT(ProductKey)
Now!
Capabilities of our pseudo code
$array.Range($from, $to)
Get the contents of$array
from$from
to$to
$array.Insert($where, $what)
Insert$what
at$where
FOR $var = $start TO $stop [STEP $step]
loop the variable$var
from$start
to$stop
applying$step
on each iteration$a XOR $b
Calculate bit-wise exclusive or on the numbers$a
and$b
$a MOD $b
Calculate remainder of the division of$a
and$b
$array[$i]
Take only the element at position$i
from the array#bla bla
Is a comment and will be ignored- Strings are just char arrays.
You can see 3 actual implementations in C#, PowerShell and Python over at Super User