Welcome › Forums › General PowerShell Q&A › observation / Going from good to brilliant at powershell
This topic contains 3 replies, has 4 voices, and was last updated by
-
AuthorPosts
-
October 19, 2015 at 1:31 am #31008
I came across this script that allows you to get the product key from your windows OS. I looked at this script as was amazed at the brilliance of it. I would say this is another level of PowerShell skill, how do you get to write scripts on the level ? This maybe a daft question and hard to answer but wanted to share my thoughts !
function Get-WindowsKey { ## function to retrieve the Windows Product Key from any PC 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 } }
-
October 19, 2015 at 2:27 am #31010
This would've taken time and research, however, If I'm honest, If you have watched Don Jones' Ultimate PowerShell Training cover to cover, this gives you the skills you would need to apply your research.
I imagine it took quite some trial and error too! Kudos to whoever made this, I like how it utilises a range of different areas of PowerShell 🙂
-
October 19, 2015 at 9:46 am #31032
If you break down the script there are 4 main tasks:
1. get the binary value of the product key from the registry
2. decode the product key
3. get the operating system data via WMI
4. create an output objectFrom the look of the code it was written around the time of PowerShell 1.0 when using [WMICLASS] accelerator was the only way to access the WMI registry provider methods.
Using a lot of Add-Member statements is also a techniques that is effectively obsolete. New-Object provides a better approach.
I've brought the script up to date
function Get-WindowsKey { ## function to retrieve the Windows Product Key from any PC [CmdletBinding()] param ( [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String[]]$computername = "$env:COMPUTERNAME" ) PROCESS { Foreach ($computer in $computername) { $productKey = $null $win32os = $null try { $data = Invoke-CimMethod -ClassName StDRegProv -ComputerName $computer ` -MethodName GetBinaryValue -ErrorAction Stop -Arguments @{ hDefKey = [uint32]2147483650 sSubKeyName = 'Software\Microsoft\Windows NT\CurrentVersion' sValueName = 'DigitalProductId' } } catch { Throw 'Error retreiving product Id' } $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 } } try { $win32os = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $computer -ErrorAction Stop } catch { Throw 'Error OS data' } $props = @{ Computer = $computer Caption = $win32os.Caption CSDVersion = $win32os.CSDVersion OSArchitecture = $win32os.OSArchitecture BuildNumber = $win32os.BuildNumber RegisteredTo = $win32os.RegisteredUser ProductID = $win32os.SerialNumber ProductKey = $productkey } New-Object -TypeName PSObject -Property $props } } }
I've added the ability to use on the pipeline and try/catch error handling round the wmi calls. I've also renamed the parameter to computername which fits with the standard powershell parameter name.
AS to how you get to be able to write scripts like the original – its a fairly simple process:
1. Understand basic PowerShell
2. Define the task you need to perform
3. Work out the PowerShell to do the task
4. Put the script together
5. Test and fix until it works the way you want.By the way – I'm not convinced the productid decode is giving the correct answer. The result on my Windows 10 machine doesn't match any product key I've used
-
October 19, 2015 at 12:59 pm #31036
Thank you Richard. On the front it looks impressive, but as you said, breaking it down really makes a difference. Your rework is impressive mind you ! 🙂
-
AuthorPosts
The topic ‘observation / Going from good to brilliant at powershell’ is closed to new replies.