3

Following on from this question (which asks how to retrieve a Windows Product Key), there seems to be conflicting information obtained from the various methods. This question asks why is there a difference when they should all return the same value?

These two methods ...

POWERSHELL

(Get-WmiObject -query ‘select * from SoftwareLicensingService’).OA3xOriginalProductKey

CMD

wmic path softwarelicensingservice get OA3xOriginalProductKey

return a different result to this VBS script ...

Set WshShell = CreateObject("WScript.Shell")
MsgBox ConvertToKey(WshShell.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId"))

Function ConvertToKey(Key)
    Const KeyOffset = 52
    i = 28
    Chars = "BCDFGHJKMPQRTVWXY2346789"
    Do
        Cur = 0
        x = 14
        Do
            Cur = Cur * 256
            Cur = Key(x + KeyOffset) + Cur
            Key(x + KeyOffset) = (Cur \ 24) And 255
            Cur = Cur Mod 24
            x = x - 1
        Loop While x >= 0
        i = i - 1
        KeyOutput = Mid(Chars, Cur + 1, 1) & KeyOutput
        If (((29 - i) Mod 6) = 0) And (i <> -1) Then
            i = i - 1
            KeyOutput = "-" & KeyOutput
        End If
    Loop While i >= 0
    ConvertToKey = KeyOutput
End Function

POWERSHELL and CMD agree with each other, but the VBS script shows a different value.

Any ideas why this might be?


UPDATE - Nearly there!!

The following PowerShell script gets the same product key as the PowerShell and Cmd commands. It appears that something has changed in the way the values are encoded (I've not had time to ascertain what that change is yet)

function Get-ProductKey {
     <#
    .SYNOPSIS
        Retrieves the product key and OS information from a local or remote system/s.

    .Description
        Retrieves the product key and OS information from a local or remote system/s. Queries of 64bit OS from a 32bit OS will result in
        inaccurate data being returned for the Product Key. You must query a 64bit OS from a system running a 64bit OS.

    .Parameter ComputerName
        Name of the local or remote system/s.

    .Notes
Author:             Boe Prox
        Version: 1.1
            -Update of function from http://powershell.com/cs/blogs/tips/archive/2012/04/30/getting-windows-product-key.aspx
            -Added capability to query more than one system
            -Supports remote system query
            -Supports querying 64bit OSes
            -Shows OS description and Version in output object
            -Error Handling

    .EXAMPLE
     Get-ProductKey -Computername Server1

    OSDescription                                           Computername OSVersion ProductKey
    -------------                                           ------------ --------- ----------
    Microsoft(R) Windows(R) Server 2003, Enterprise Edition Server1       5.2.3790  bcdfg-hjklm-pqrtt-vwxyy-12345

        Description
        -----------
        Retrieves the product key information from 'Server1'
    #>
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipeLine=$True,ValueFromPipeLineByPropertyName=$True)]
        [Alias("CN","__Server","IPAddress","Server")]
        [string[]]$Computername = $Env:Computername
    )
    Begin {
        $map="BCDFGHJKMPQRTVWXY2346789"
    }
    Process {
        ForEach ($Computer in $Computername) {
            Write-Verbose ("{0}: Checking network availability" -f $Computer)
            If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {
                Try {
                    Write-Verbose ("{0}: Retrieving WMI OS information" -f $Computer)
                    $OS = Get-WmiObject -ComputerName $Computer Win32_OperatingSystem -ErrorAction Stop
                } Catch {
                    $OS = New-Object PSObject -Property @{
                        Caption = $_.Exception.Message
                        Version = $_.Exception.Message
                    }
                }
                Try {
            Write-Verbose ("{0}: Attempting remote registry access" -f $Computer)
            $remoteReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer)
            $value = $remoteReg.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue('DigitalProductId')[0x34..0x42]
            $isWin8OrNewer = [math]::Floor(($value[14] / 6)) -band 1
            $value[14] = ($value[14] -band 0xF7) -bor (($isWin8OrNewer -band 2) * 4)
            $ProductKey = ""
            Write-Verbose ("{0}: Translating data into product key" -f $Computer)
            for ($i = 24; $i -ge 0; $i--) {
              $r = 0
              for ($j = 14; $j -ge 0; $j--) {
                $r = ($r * 256) -bxor $value[$j]
                $value[$j] = [math]::Floor([double]($r/24))
                $r = $r % 24
              }
              $ProductKey = $map[$r] + $ProductKey
            }
        } Catch {
            $ProductKey = $_.Exception.Message
        }

        if ($isWin8OrNewer){
            $ProductKey = $ProductKey.Remove(0, 1)
            $ProductKey = $ProductKey.Insert($r, 'N')
        }

        #insert dashes to make key more readable
        for($i = 5; $i -lt 29; $i = $i + 6){
            $ProductKey = $ProductKey.Insert($i, '-')
        }
                $object = New-Object PSObject -Property @{
                    Computername = $Computer
                    ProductKey = $ProductKey
                    OSDescription = $os.Caption
                    OSVersion = $os.Version
                }
                $object.pstypenames.insert(0,'ProductKey.Info')
                $object
            } Else {
                $object = New-Object PSObject -Property @{
                    Computername = $Computer
                    ProductKey = 'Unreachable'
                    OSDescription = 'Unreachable'
                    OSVersion = 'Unreachable'
                }
                $object.pstypenames.insert(0,'ProductKey.Info')
                $object
            }
        }
    }
}

The above script was taken from here, but takes into account the change suggested by TJ in the comments at the bottom, dated Feb 5th 2016. That guy is a legend! Well, the original author too, clearly!

I will post the VB version when I have created it, assuming this question doesn't get closed (only 3 more votes required so act quickly people) /sarcasm.

Community
  • 1
  • 1
  • 1
    Because both methods are using different locations to find the key. You've [already posted about this](http://stackoverflow.com/q/39530254/692942) why create a new question? – user692942 Sep 19 '16 at 12:50
  • I wrote update 3 :0) Surely there is only one windows product key per copy of windows, hence my confusion as to why I'm getting different answers!! The VBS script has been heralded, nay lauded as retrieving valid Windows Product keys in the past, so why should it have stopped working now? – 3-14159265358979323846264 Sep 19 '16 at 12:55
  • It's a separate question, clearly! Oh you've changed your comment now you see I was the author of the other question. My first question was about retrieving the product key, this question is why do i get different results. – 3-14159265358979323846264 Sep 19 '16 at 12:56
  • Probably because they changed the algorithm for generating them with later versions? I don't know, but wouldn't trust the VBScript approach. – user692942 Sep 19 '16 at 12:56
  • Lol. I agree, but unfortunately older versions of windows, and those that weren't OEM installs don't work with the POWERSHELL/CMD version. – 3-14159265358979323846264 Sep 19 '16 at 12:57
  • 1
    Indeed they won't welcome to the world of Microsoft! – user692942 Sep 19 '16 at 12:58
  • 1
    If I had made that into two questions, someone else would have complained that I should start another question. So I put the extra effort into to asking a distinctly different question. Why does this happen is very different to how do i do this? I hope you appreciate my awkward position! Because I appreciate your input ;0) – 3-14159265358979323846264 Sep 19 '16 at 13:06
  • Fair enough. However just note [the article](http://www.thewindowsclub.com/find-windows-10-product-key-using-vb-script) referenced in the [linked question](http://stackoverflow.com/a/39530505/692942) where the VBScript comes from is full of comments of people complaining the keys they get back are wrong / different. – user692942 Sep 19 '16 at 13:11

2 Answers2

1

On the Windows 7 and Windows 10 systems that I tested, this key does not exist: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId
But the vbscript will still output a value rather than throw an error.

You might be looking for this value instead on Windows 7:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey\DigitalProductId
(Note: it doesn't exist on Windows 10)

BenH
  • 9,766
  • 1
  • 22
  • 35
0

According to this article the WMI query will return an OEM key that was stored in the BIOS or UEFI firmware by the manufacturer. The VBScript method reading from the registry will return a retail product key that was entered during (or after) setup by the user.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • I haven't entered a different key on my machine! I would therefore expect the same result from all three methods ... perhaps it has something to do with 64 bit key values, and the VBS method is working with 32 bit values?! I really have no idea and information seems a bit scarce. – 3-14159265358979323846264 Sep 23 '16 at 12:59
  • This answer answers part of the question, but the other unanswered question is why the VBScript returns a different product key compared with the Powershell script. I believe the answer is that, although the product key is stored in the same registry value across all Windows versions, for Win8+ it is encoded differently, as the OP alludes to. This is reflected in the Powershell script where you have `$isWin8OrNewer`. See also this VBScript which works on all Windows versions: https://github.com/foerl/Windows-10-Key-Extract-VBS/blob/master/extract.vbs – Jimadine Nov 01 '20 at 13:26