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 ...
Saturday, February 07, 2009
Subscribe to:
Post Comments (Atom)
40 comments:
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
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?
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.
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?
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
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.
Thank you for the feedback Travisb - It good to know the script basically performs as it should.
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!
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!)
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.
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
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?
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"
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?
Great Job works with Win 7 x64
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
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...
sorry guyz about my last comment...
it do return a product key like thing...
but doesnt work....
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
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.
"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 :)
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.
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.
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.
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
This script was updated long ago - look on the blog for at post named "- update"
This script was updated long ago - look on the blog for at post named "- update"
This script was updated long ago - look on the blog for at post named "- update"
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
Thanks for sharing! For Windows/Office product keys any editions, you can find some great ones here: www.motionkeys.com.
For legit any kind of product keys, check this out: www.gankings.com. 100% working!
You guys can try this site to get a valid Product Key all editions: www.cdekey.com.
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?
Post a Comment