Saturday, February 07, 2009

Retrieveing the Windows Product Key

I was recently asked if I knew of a tool capable of retrieving the Product Key from an installed instance of Windows Vista. While there are several such tools available (use google), my solution - naturally - was to write a PowerShell script that can do just that.

The script below is based on information from "The Custodian" on Everything2: http://everything2.com/node/1058074

I've tested the function against Windows XP, Vista x64 and Windows 7 x64, as well as Windows Server 2003 and Windows Home Server. As long at the the user executing the script has sufficient privileges, and no firewall is blocking remote access to the registry/WMI the script appears to work fine.

function Get-WindowsKey {
    ## function to retrieve the Windows Product Key from any PC
    ## by Jakob Bindslet (jakob@bindslet.dk)
    param ($targets = ".")
    $hklm = 2147483650
    $regPath = "Software\Microsoft\Windows NT\CurrentVersion"
    $regValue = "DigitalProductId"
    Foreach ($target in $targets) {
        $productKey = $null
        $win32os = $null
        $wmi = [WMIClass]"\\$target\root\default:stdRegProv"
        $data = $wmi.GetBinaryValue($hklm,$regPath,$regValue)
        $binArray = ($data.uValue)[52..66]
        $charsArray = "B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9"
        ## decrypt base24 encoded binary data
        For ($i = 24; $i -ge 0; $i--) {
            $k = 0
            For ($j = 14; $j -ge 0; $j--) {
                $k = $k * 256 -bxor $binArray[$j]
                $binArray[$j] = [math]::truncate($k / 24)
                $k = $k % 24
            }
            $productKey = $charsArray[$k] + $productKey
            If (($i % 5 -eq 0) -and ($i -ne 0)) {
                $productKey = "-" + $productKey
            }
        }
        $win32os = Get-WmiObject Win32_OperatingSystem -computer $target
        $obj = New-Object Object
        $obj | Add-Member Noteproperty Computer -value $target
        $obj | Add-Member Noteproperty Caption -value $win32os.Caption
        $obj | Add-Member Noteproperty CSDVersion -value $win32os.CSDVersion
        $obj | Add-Member Noteproperty OSArch -value $win32os.OSArchitecture
        $obj | Add-Member Noteproperty BuildNumber -value $win32os.BuildNumber
        $obj | Add-Member Noteproperty RegisteredTo -value $win32os.RegisteredUser
        $obj | Add-Member Noteproperty ProductID -value $win32os.SerialNumber
        $obj | Add-Member Noteproperty ProductKey -value $productkey
        $obj
    }
}

Use the function to retrieve the Product Key from the local PC:

Get-WindowsKey

Or to retrieve the Product Key from one or more PCs (locally or remotely):

Get-WindowsKey "pc1", "pc2", "server999", "server777"

Remeber that the output from the function is a standard PowerShell object, so you can pipe into sort-object, format-table or mayby ConvertTo-HTML ...

41 comments:

travisb said...

First, thanks for posting this. It has helped me a lot.

I ran this script on 300 servers to get the product key and it worked on about half of them. The other half returned
"BBBBB-BBBBB-BBBBB-BBBBB-BBBBB" for the product key. I'm able to remote desktop to the servers and run Magic Jelly Bean Keyfinder to find the actual product key, but this will take forever. Any ideas?
Thanks,
Travis

Jakob Bindslet said...

The servers the script didn't works against, were they, by any chance, Windows 2008 servers or different in some other way from the rest of your server population?

travisb said...

They are mostly, if not all, 2003. The script did work on both virtual and physical and DMZ and internal servers. So, I'm not sure why they are not working.

I ran the script again on those that failed the first time and about 10 of the 150 came back with correct keys.

Jakob Bindslet said...

Very strange ... the only "problems" I can recreate are Windows 2008 based or due to limited access rights due to firewall, WMI restrictions or similar.

On the servers that fail, do you get other info, such as Buildnumber, correctly displayed?

Jakob Bindslet said...

If I run the function against a computer where access is blocked by a Firewall, the output looks like this:
Computer : 192.168.1.116
Caption :
CSDVersion :
OSArch :
BuildNumber :
RegisteredTo :
ProductID :
ProductKey : BBBBB-BBBBB-BBBBB-BBBBB-BBBBB

travisb said...

The list of servers I was given included many that have been retired.

I modified the script to ping the servers first and then scan for the product key if the server was up.

After removing the retired servers I was able to get the key from almost all of the servers. The rest of the servers I RDP'ed to and used another program to get the key locally.

Thanks for your help.

Jakob Bindslet said...

Thank you for the feedback Travisb - It good to know the script basically performs as it should.

Exotic Hadron said...

Hello Jakob!

Thanks for this nice script. I am experimenting with Windows Server 2008 R2 and since, for some reason, official public key did not work for me (banned?), I called techsupport and got the key from them. Since they just give you the set figures it's impossible to figure it out what will be the key. I tried your script and got

ProductKey : BBBBB-BBBBB-BBBBB-BBBBB-BBBBB

I wonder what privileges should be provided?
I even enabled
Set-ExecutionPolicy Unrestricted
Still no luck... Any clue?

Thank you!

Jakob Bindslet said...

The BBBB-BBB... indicates that it cannot read the registry, either due to the hostname being wrong or some rights lacking.

Try running this directly o nthe server in question:

$wmi = [WMIClass]"\\.\root\default:stdRegProv"
$data = $wmi.GetBinaryValue(2147483650,"Software\Microsoft\Windows NT\CurrentVersion","DigitalProductId")
$data.uValue

The output should be an array of numbers or maybe an error.

If the above doesn't work, you are welcome to contact me directly (my email is in my profile!)

Exotic Hadron said...

Thank you for your help! While I am not at work, I cannot test it, but I am sure I'll test it and let you known if it worked. What I am also thinking is if it could be possible to authenticate the thread before it invokes the WMI class. Possibly –authentication 6
can be used here? Or would it be better to use the get-credential commandlet? Which way would you recommend using it here to pre-authenticate on the remote computer (provided that ports 135, 137, 139 are opened on the remote PC). Thank you.

Exotic Hadron said...

Hello again, Jakob

I tested it on Windows Server 2008 x64. And here are the results.
Running 32-bit ISE non-elevated:
1. Get-Windowskey throws an error:
Cannot index into a null array.
and finally returns BBBB-BBBB
2. GetBinaryValue returns nothing.

Running 32-bit ISE elevated-elevated:
1. Ditto
2. Ditto

Running 64-bit ISE non-elevated
1. Immediately returns BBBB- without throwing an error.
2. Returns the array with no glitches

Running 64-bit ISE elevated
1. Same as with 64-bit non-elevated
2. Same as with 64-bit non-elevated

James Pool said...
This comment has been removed by the author.
James Pool said...
This comment has been removed by the author.
James Pool said...
This comment has been removed by the author.
James Pool said...

On my environment I ran against 200 computers. We do not have 2008 server here. I can confirm that anything with a 64bit OS would not return anything but Bs

In addition the real key was never returned for Dell boxes. I guess that must have something to do with the way that Dell Installs them using a Volume OEM key. I don't suppose there is anyway to get the actual key?

Unknown said...

I had a "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB" product key problem with
ProductID : 55041-011-1404685-86945
Microsoft Windows 7 Professional 32-bit build 7600
The reason is that Registry Path has changed.
Solution:
change regpath variable to
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"

Kipmix said...

I get this error on some machines

Cannot convert value "\\IT-05\root\default:stdRegProv" to type "System.Management.ManagementClass". Error: "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)"
At :line:11 char:25
+ $wmi = [WMIClass] <<<< "\\$target\root\default:stdRegProv"

Help?

Unknown said...

Great Job works with Win 7 x64

Anonymous said...

IMPORTANT!!!
When the product key is not stored in the Registry (like in volume licenses of Windows 7), ANY!!! Product Key Viewer will display BBBBB-BBBBB-BBBBB-BBBBB-BBBBB

Anonymous said...

First thanks a lot for this script

for users 2008 R2 with BBBBB problem

you have to change script
change Line 7
$regValue = "DigitalProductId"

to

$regValue = "DigitalProductId4"

and it will work like a charm....

thanks everyone...

Anonymous said...

sorry guyz about my last comment...

it do return a product key like thing...

but doesnt work....

r@c said...

I ran ALL the available softwares for the product key, and kept getting BBBBB-BBBBB-BBBBB-BBBBB-BBBBB.

This script with the change in registry path, saved me a shit load of cash!

Thanks a LOT

r@c said...
This comment has been removed by the author.
Anonymous said...

As j said ...

I had a "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB" product key problem with
ProductID : 55041-011-1404685-86945
Microsoft Windows 7 Professional 32-bit build 7600
The reason is that Registry Path has changed.
Solution:
change regpath variable to
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"

Works on win7 x64.

Omega84 said...

"I had a "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB" product key problem with
ProductID : 55041-011-1404685-86945
Microsoft Windows 7 Professional 32-bit build 7600
The reason is that Registry Path has changed.
Solution:
change regpath variable to
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"

Can someone please tell me how to change the regpath so I can do this. I opened the HKEY path and saw that in default product key it isnt defined. Please help someone :)

BLACKHART THE REMIXOLOGIST said...

Can someone pleaseeeeee explain how to change the registry in Windows 7 professional as suggested here???

Solution:
change regpath variable to
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"
Thanks.

Logan said...

Thanks for publishing this script.
I don't know if you're still watching for questions in the comments on this post, but will try.
The script does run in my server environment and provides what looks like the proper output but all of the "ProductKey" fields are the default installation keys from the "Products.ini" file, not the keys used for license activation. Is this expected behaviour? Is there another way to retrieve the activation keys?
Thanks again.

Logan said...
This comment has been removed by the author.
Unknown said...

So Im a nO_ob, but from my understanding, i need to paste this exact script in a notepad and save as a .ps1 file. Then, run Powershell and type the full filepath to run the script... except it isnt working that way... Jakob, any chance you have the working ps1 file handy that you would like to share? Am I missing something?

I too suffer from the BBBB Key syndrome and I am trying to retrieve my Win 7 x64 Pro Key but the applications out there are giving me a BBBB

Jakob Bindslet said...

If anyone get a "BBBBB-.." code returned it is due to access being blocked.

Access can be blocked through a network firewall, a firewall on the server you are trying to access or by insufficient privileges on the server.

You need to have administrative rights on the server to extract the registration key.

The firewall problems can be bypassed by running the script locally on the server.

The rights issue need to be resolved by you or your administrator.

Blogger Here!!! said...

Got something displayed as a "Product Key". I'm using Win 7 Ent Edition installed with MAK.

Got 'B' as the key till I changed that line

$regValue = "DigitalProductId"

to

$regValue = "DigitalProductId4"

Also, changing
$regPath = "Software\Microsoft\Windows NT\CurrentVersion"

to
$regPath = "Software\Microsoft\Windows NT\CurrentVersion\DefaultProductKey"

gives a completely different key.

None of the three generated keys matches the partial key displayed by running slmgr.vbs /dli. I'm not able to find a problem with the script either. :-\

$wmi = [WMIClass]"\\.\root\default:stdRegProv"
$data = $wmi.GetBinaryValue(2147483650,"Software\Microsoft\Windows NT\CurrentVersion","DigitalProductId")
$data.uValue

This one indeed gave an array of numbers though

Jakob Bindslet said...

This script was updated long ago - look on the blog for at post named "- update"

Jakob Bindslet said...

This script was updated long ago - look on the blog for at post named "- update"

Jakob Bindslet said...

This script was updated long ago - look on the blog for at post named "- update"

Unknown said...
This comment has been removed by a blog administrator.
Unknown said...

http://goo.gl/xjU3jn

As far as I know, you can buy it from the authorized vendor online http://goo.gl/xjU3jn . You can count on them 100% as this site is the partner vendor of Microsoft. This is the biggest competitive point.

http://goo.gl/xjU3jn

Unknown said...

Thanks for sharing! For Windows/Office product keys any editions, you can find some great ones here: www.motionkeys.com.

Unknown said...

For legit any kind of product keys, check this out: www.gankings.com. 100% working!

Unknown said...
This comment has been removed by the author.
Unknown said...

You guys can try this site to get a valid Product Key all editions: www.cdekey.com.

Caio K. said...

Hi there

Does this script work for MAK licenses of Windows 7? Is there anywhere I can get something to retrieve these kinds of licenses?