我能在Ubuntu上恢复我的Windows产品密钥吗?

我现在正在使用Ubuntu遇到一些困难,希望能得到一些帮助。
目前我是通过USB闪存驱动器运行Ubuntu,因为Windows 7不知怎么的就消失了。
我该如何在Ubuntu中找到我的笔记本硬盘上的Windows产品密钥呢?

2获取Windows密钥与Ubuntu无关。您可以在superuser.com上提问。 - user692175
如果这是预装的Windows系统,你可以在底部(笔记本电脑)或背面(台式电脑)的贴纸上找到产品密钥。 - Mark Kirby
谢谢MichealBay,我也会在那里问的,但问题与Ubuntu有关,因为我正在使用Ubuntu。而且Mark Kirby,贴纸磨损了!! - frugge
19尝试使用sudo cat /sys/firmware/acpi/tables/MSDM - Charles Green
查尔斯·格林,它显示“没有这样的文件或目录”。无论如何,谢谢! - frugge
2我把你的问题进行了大量编辑,因为下面的答案已经被确认有效。由于这是一个相当普遍的问题,而且很少有人知道解决方法,所以我进行了编辑,使其尽可能清晰,让更多的人能够找到它并得到帮助。 - Mark Kirby
1在我看来,最好考虑这个问题是否属于主题范围。这并不是已经确立的政策——我认为我们对此没有一个明确的政策——只是我的观点而已。这基本上与从主板中检索Windows 8产品密钥的问题相同。回答中涉及到读取固件存储和Windows注册表的方法不同,但总体问题是一样的。我建议我们将其中一个关闭,并可能请管理员合并回答。 - Eliah Kagan
2@MichaelBay 但是从Ubuntu中获取Windows密钥是一件有趣的事情 ;) - Rinzwind
@EliahKagan 我同意,将所有这些答案整合到一个清晰的问题下是一件好事,可以将其带到元社区进行投票,我会支持合并。 - Mark Kirby
至少根据我安装的Windows 8.1来看,这会产生与此其他解决方案所生成的密钥不同。 - caw
2个回答

首先,通过进入恢复模式并运行以下命令来恢复您的Ubuntu。
sudo apt install --reinstall ubuntu-desktop

这个答案不是我写的,而是由ThomasSuperuser上写的,请在那里投票,如果你在这里投票,谢谢。

Linux有一个很棒的工具叫做chntpw。你可以通过以下方式轻松地在Debian/Ubuntu上获取它:

sudo apt install chntpw

要查看相关的注册表文件,请挂载Windows磁盘并像这样打开它:

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

现在,要获取解码后的DigitalProductId,请输入以下命令:

dpi \Microsoft\Windows NT\CurrentVersion\DigitalProductId

下面的评论说:

相关注册表文件的路径是/path/to/windisk/Windows/System32/config/RegBack/SOFTWARE


6挺酷的!我刚在家里的系统上测试了一下,下面的评论对我的家用系统来说是正确的。那个系统是运行Windows 10的。我喜欢这个!+1 - Terrance
7检查文件夹和文件名的大小写是很重要的。在我的Windows 10电脑上,该文件并不存在;我不得不使用大写的SOFTWARE作为文件名。 - Paddy Landau
2哇,这个chntpw的功能真是太棒了。 - dhaupin
很遗憾,在Windows 10磁盘上出现了“文件太小;预期为72字节或更多,实际为0字节”的错误。 - amenthes
1在Windows 7分区上工作,ubuntu 18.04。无法在只读挂载上工作。必须重新挂载为可写。路径中的大写字母不同 chntpw -e /media/sdb1/WINDOWS/system32/config/software - rickfoosusa
我的Windows10 1803上不存在文件Windows/system32/config/software - TekTimmy
如果你在读取system32文件夹时遇到问题,尝试复制一份并将复制的路径提供给chntpw工具。 - Markus von Broady
在“Windows NT”之间应该有一个空格。不知道如何使糟糕的Markdown保持这个空格。 - Jan Kyu Peblik
磁盘必须以读写方式挂载:mount -t ntfs-3g /dev/<device> /mnt -o remove_hiberfile - shrimpwagon
1在Ubuntu 22.04和Windows 10上都能正常工作,非常感谢你。 - rjmacarthy

对于任何想知道this如何工作的人来说。
基本上,你需要获取注册表键的内容。
HKLM\Software\Microsoft\Windows NT\CurrentVersion\DigitalProductId

这是一个所谓的REG_BINARY。意思是它只是一组字节。你可以通过chntpw转储它们,或者手动复制它们。
让我们看看我们需要如何处理这些字节,以便通过一些伪代码来获取我们的产品密钥。
一旦你将它们放入一个数组中,你需要提取编码产品ID的字节子集。特别是:范围在52到(52 + 14)之间。这给你15个字节。
EncodedId = DigitalProductId.Range(52, 52+14)

这仍然是一堆字节,根本不像产品密钥。所以让我们解码它。
为此,您需要包含所有可能构成产品密钥的字符集合:
Characters = "BCDFGHJKMPQRTVWXY2346789"

是的,这并不是完整的字母表。事实证明,Windows产品密钥并没有使用所有的字母数字符号。
现在让我们来解码。 我们需要:
- 一个变量来保存产品密钥 - 一个循环从0到24。对于我们产品密钥的每个字符 - 一个内部循环从0到14(逆序)。对于我们编码的ID中的每个字节 - 一些位操作和算术运算用于解码过程
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

最后,我们将"-"字符插入到字符串的适当位置。
FOR i = 4 TO 1 STEP -1
    ProductKey = ProductKey.Insert(i * 5, "-")
LOOP

我们完成了!
差一点点:
PRINT(ProductKey)

立刻!
我们的伪代码的功能
- `$array.Range($from, $to)`: 获取`$array`从`$from`到`$to`的内容 - `$array.Insert($where, $what)`: 在`$where`位置插入`$what` - `FOR $var = $start TO $stop [STEP $step]`: 循环变量`$var`从`$start`到`$stop`,每次迭代应用`$step` - `$a XOR $b`: 对数字`$a`和`$b`进行位异或运算 - `$a MOD $b`: 计算`$a`除以`$b`的余数 - `$array[$i]`: 仅获取数组中位置为`$i`的元素 - `#bla bla`: 是注释,将被忽略 - 字符串只是字符数组。
你可以在Super User上看到C#,PowerShell和Python的3个实际实现。

好的,快速提示!假设你想从你的机器上获取Windows许可密钥,而你正在运行Linux。只需打开终端并运行以下命令。sudo hexdump -s 56 -e '"MSDM key: " /29 "%s\n"' /sys/firmware/acpi/tables/MSDM - dilshad
/sys/firmware/acpi/tables/MSDM 只适用于原始设备制造商(OEM)许可证吗? - King Midas