14

My new laptop came preinstalled with Windows 8. Naively, as I am, I just formatted the harddrive and installed fine old Ubuntu. Now I want to install Windows 8 for dual boot again, but I have no DVD and do download the ISO one needs a product key. That key is not on the back of the laptop anymore but somewhere on the mainboard.

Is there any way to recover the product key from the mainboard using Ubuntu?

17

Usually, OEM manufacturers have preloaded a key electronically on a ROM. Windows will identify this and automatically activate your installation. So, usually, you don't need to know this code. However, you may see some trace of this using

sudo dmidecode

listed as OEM-specific Types, encoded/encrypted, which may hold it. Major OEMs like HP and Dell use this. Ask on Windows websites for more details; this is the wrong place. The only detail I remember is that one needs an OEM version of the Windows installation disc (i.e. non-retail).

1
  • I remember using dmidecode on a Lenovo Thinkpad in the past, but it seems that on this Lenovo Ideapad it does not contain the license key anywhere. Eventually I found it in /sys/firmware/acpi/tables/MSDM as mentioned by Chuck R in the other answer below. – Luc Jul 6 '19 at 9:55
25

Another way that doesn't require looking through a ton of output is:

sudo acpidump -b -t MSDM | dd bs=1 skip=56 2>/dev/null;echo

acpidump dumps the table (default in hexdump format), but the -b options tells it to output the raw data. Since we only need the last part of the table, pipe the output into dd, but but skip the unnecessary junk. Finally, add an echo at the end to make it terminal-friendly =D

acpidump -t MSDM will work as well, but the key is broken over multiple lines, making it hard to copy.


Update thanks to Lekensteyn:

New versions of acpidump shipped with Ubuntu work differently than described above. The -b flag causes acpidump to write to a file under all circumstances, so an alternative method is to use the command

sudo tail -c+57 /sys/firmware/acpi/tables/MSDM

A legitimate Windows 8 installer should automatically detect the key in the ACPI and continue installing with the built-in key.

It should be noted, however, that I used this method to try to install Win8 in a VM using my own product key, but it automatically deactivated saying that the product key was in use. So, it's of little use in all reality. Since Win8 OEM keys are designed to be tied to that specific computer, you'll hit a brick wall if you ask Microsoft to unregister the key so you can use it in a VM, let alone another computer.

The only way you could use the key is if you had never booted into Win8 to begin with or weren't connected to a network when you did. Even so, if your VM/new computer is ever allowed to connect to the network, it will automatically register the key making your actual installation unusable.

5
  • Was just trying this out, and the command above cut off one of the characters. I used sudo acpidump -b -t MSDM | dd bs=1 skip=56 2>/dev/null;echo and I got the full key out. – Andrew C Aug 29 '13 at 5:49
  • You are correct, sorry about that. Updating my answer. – Chuck R Sep 5 '13 at 22:31
  • 1
    The -b option is specific to the acpidump tool included with the kernel tree. Newer Ubuntu versions ship with a different acpidump tool (from iasl) which have different options. I could not test this command, but it should work: sudo acpidump -n HPET | tail -n+2 | xxd -r | head -c+57. Alternative method: sudo tail -c+57 /sys/firmware/acpi/tables/MSDM – Lekensteyn Jul 1 '14 at 16:34
  • @Lekensteyn I noticed that recently too when I was on the phone with MS. If you do the -b option, it defaults to bumping to a file now for some reason. I wonder if there is a way to flag that a pipe be destroyed when there's no more data left on it... another topic for another day though. Your first command didn't work for me, however the second one was just fine. I'll update my answer to include it =) – Chuck R Jul 6 '14 at 23:32
  • 1
    Used the updated version for Ubuntu 16.04 LTS: "sudo tail -c+57 /sys/firmware/acpi/tables/MSDM" Can confirm I got my Windows key from a Samsung laptop just fine =) – Valross.nu Sep 30 '16 at 10:29
13
 sudo tail -c+57 /sys/firmware/acpi/tables/MSDM

This got me the Product Key of my OEM Windows 8 on MSI laptop.

3

You can all so use this code that works as well if the ones above don't work for you or you just want to see the hex output with your key. It's similar to bless hex binary editor. Windows will have their key in the usual format HAN50-0L00M-4D31T-CR4ZY. 5 letters or numbers in 5 groups.

$ ls /sys/firmware/acpi/tables
$ sudo hd /sys/firmware/acpi/tables/MSDM

00000000  ha ns oo lo oe at es ap  pl le sa uc ef or li fe  |Key in area|
00000010  cu si ca nb ro ha ms am  cu si ca nb ro ha ms am  |In key area|
00000020  it sj us ho wz ir ol lz  it sj us ho wz ir ol lz  |Area in key|
00000000  ha ns oo lo oe at es ap  pl le sa uc ef or li fe  |It is 5 x 5|
00000010  cu si ca nb ro ha ms am  cu si ca nb ro ha ms am  |Key in area|
00000020  it sj us ho wz ir ol lz  it sj us ho wz ir ol lz  |In key area|
00000050  ha ns oo lo ow az he re                           |Area in key|
00000055                                                    |It is 5 x 5|

Running the following command will dump the product key in its standard Microsoft format.

sudo hexdump -s 56 -e '"MSDM key: " /29 "%s\n"' /sys/firmware/acpi/tables/MSDM
0

so I saw the other answers on here and needed to chime in. found

strings /sys/firmware/acpi/tables/MSDM

works great if the original key is what is still being used. However I have some systems that came with the home addition and you need to get the current key from the registry.

winmount=/mnt
echo "hex \\Microsoft\\Windows NT\\CurrentVersion\\DigitalProductId\nq\nq" | chntpw -e ${winmount}/Windows/System32/config/SOFTWARE

then we will need to run it through an algorithm to get the key.

I found some code from https://github.com/mrpeardotnet/WinProdKeyFinder/blob/master/WinProdKeyFind/KeyDecoder.cs

    /// <summary>
    /// Decodes Windows Product Key from the DigitalProductId. 
    /// This method applies to DigitalProductId from Windows 7 or lower versions of Windows.
    /// </summary>
    /// <param name="digitalProductId">DigitalProductId to decode</param>
    /// <returns>Decoded Windows Product Key as a string</returns>
    private static string DecodeProductKey(byte[] digitalProductId)
    {
        const int keyStartIndex = 52;
        const int keyEndIndex = keyStartIndex + 15;
        var digits = new[]
        {
            'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R',
            'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
        };
        const int decodeLength = 29;
        const int decodeStringLength = 15;
        var decodedChars = new char[decodeLength];
        var hexPid = new ArrayList();
        for (var i = keyStartIndex; i <= keyEndIndex; i++)
        {
            hexPid.Add(digitalProductId[i]);
        }
        for (var i = decodeLength - 1; i >= 0; i--)
        {
            // Every sixth char is a separator.
            if ((i + 1) % 6 == 0)
            {
                decodedChars[i] = '-';
            }
            else
            {
                // Do the actual decoding.
                var digitMapIndex = 0;
                for (var j = decodeStringLength - 1; j >= 0; j--)
                {
                    var byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
                    hexPid[j] = (byte)(byteValue / 24);
                    digitMapIndex = byteValue % 24;
                    decodedChars[i] = digits[digitMapIndex];
                }
            }
        }
        return new string(decodedChars);
    }

    /// <summary>
    /// Decodes Windows Product Key from the DigitalProductId. 
    /// This method applies to DigitalProductId from Windows 8 or newer versions of Windows.
    /// </summary>
    /// <param name="digitalProductId">DigitalProductId to decode</param>
    /// <returns>Decoded Windows Product Key as a string</returns>
    public static string DecodeProductKeyWin8AndUp(byte[] digitalProductId)
    {
        var key = String.Empty;
        const int keyOffset = 52;
        var isWin8 = (byte)((digitalProductId[66] / 6) & 1);
        digitalProductId[66] = (byte)((digitalProductId[66] & 0xf7) | (isWin8 & 2) * 4);

        const string digits = "BCDFGHJKMPQRTVWXY2346789";
        var last = 0;
        for (var i = 24; i >= 0; i--)
        {
            var current = 0;
            for (var j = 14; j >= 0; j--)
            {
                current = current*256;
                current = digitalProductId[j + keyOffset] + current;
                digitalProductId[j + keyOffset] = (byte)(current/24);
                current = current%24;
                last = current;
            }
            key = digits[current] + key;
        }

        var keypart1 = key.Substring(1, last);
        var keypart2 = key.Substring(last + 1, key.Length - (last + 1));
        key = keypart1 + "N" + keypart2;

        for (var i = 5; i < key.Length; i += 6)
        {
            key = key.Insert(i, "-");
        }

        return key;
    }

I'm going to try and decode the algorithm and write it in bash. The dmi output seems to be the older algorithm (<win8) for decoding the key. I have not found an option for using the new algorithm (>win7).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.