This is purely because I had to spend time making/editing this when it should be widely available, so I'm providing it to everyone else.
The below script will Output a couple of CSV files to TEMP with the versions and vulnerability status of each machine in a selected (in the code) OU. You'll be able to remotely "security audit" an OU of machines.
Powershell 7.0 needed for the connection test line
RSAT needed to get the AD module
Visual Studio Code needed to get powershell 7.0 (on win7)
By the time you read this, the version list will probably be out of date within the file. Use this website
[To see links please register here]
to add newer dotnet entries. It's just a bunch of key values in "DotNet4Builds"
If within CompromisedCheck.csv a machine shows as =0, it's had it's security turned off manually, and you should raise whether the supplier did it, or a suspect employee.
I hope this helps someone searching for it for their business.
<#
Script Name : Get-DotNetVersions_Tweaked.ps1
Description : This script reports the various .NET Framework versions installed on the local or a remote set of computers
Author : Original by Martin Schvartzman - Edited by Mark Purnell
Reference :
[To see links please register here]
#>
$ErrorActionPreference = "Continue”
import-module ActiveDirectory
$searchOU = "OU=OU LEVEL 1,OU=OU LEVEL 2,OU=MACHINES,OU=OUR LAPTOPS,DC=PUT,DC=MY,DC=DOMAIN,DC=CONTROLLER,DC=HERE,DC=OK"
$computerList = Get-ADComputer -searchbase $searchOU -Filter *
function Get-DotNetFrameworkVersion($computerList)
{
$dotNetter = @()
$compromisedCheck = @()
$dotNetRoot = 'SOFTWARE\Microsoft\.NETFramework'
$dotNetRegistry = 'SOFTWARE\Microsoft\NET Framework Setup\NDP'
$dotNet4Registry = 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
$dotNet4Builds = @{
'30319' = @{ Version = [System.Version]'4.0' }
'378389' = @{ Version = [System.Version]'4.5' }
'378675' = @{ Version = [System.Version]'4.5.1' ; Comment = '(8.1/2012R2)' }
'378758' = @{ Version = [System.Version]'4.5.1' ; Comment = '(8/7 SP1/Vista SP2)' }
'379893' = @{ Version = [System.Version]'4.5.2' }
'380042' = @{ Version = [System.Version]'4.5' ; Comment = 'and later with KB3168275 rollup' }
'393295' = @{ Version = [System.Version]'4.6' ; Comment = '(Windows 10)' }
'393297' = @{ Version = [System.Version]'4.6' ; Comment = '(NON Windows 10)' }
'394254' = @{ Version = [System.Version]'4.6.1' ; Comment = '(Windows 10)' }
'394271' = @{ Version = [System.Version]'4.6.1' ; Comment = '(NON Windows 10)' }
'394802' = @{ Version = [System.Version]'4.6.2' ; Comment = '(Windows 10 Anniversary Update)' }
'394806' = @{ Version = [System.Version]'4.6.2' ; Comment = '(NON Windows 10)' }
'460798' = @{ Version = [System.Version]'4.7' ; Comment = '(Windows 10 Creators Update)' }
'460805' = @{ Version = [System.Version]'4.7' ; Comment = '(NON Windows 10)' }
'461308' = @{ Version = [System.Version]'4.7.1' ; Comment = '(Windows 10 Fall Creators Update)' }
'461310' = @{ Version = [System.Version]'4.7.1' ; Comment = '(NON Windows 10)' }
'461808' = @{ Version = [System.Version]'4.7.2' ; Comment = '(Windows 10 April & Winserver)' }
'461814' = @{ Version = [System.Version]'4.7.2' ; Comment = '(NON Windows 10)' }
'528040' = @{ Version = [System.Version]'4.8' ; Comment = '(Windows 10 May 2019 Update)' }
'528049' = @{ Version = [System.Version]'4.8' ; Comment = '(NON Windows 10)' }
}
foreach($computerObject in $computerList)
{
$computerName = $computerObject.DNSHostName
write-host("PCName is " + $computerName)
if(test-connection -TargetName $computerName -Quiet -TimeOutSeconds 1 -count 2){
if($regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computerName))
{
$os = (Get-WMIObject win32_operatingsystem -ComputerName SPL305350).Name
if(!$?){
write-host("wim not available")
$dotNetter += New-Object -TypeName PSObject -Property @{
'ComputerName' = $computerName
'OS' = "WIM not available"
'Build' = "WIM not available"
'Version' = "WIM not available"
'Comment' = "WIM not available"
}
}
else{
if ($netRegKey = $regKey.OpenSubKey("$dotNetRegistry"))
{
foreach ($versionKeyName in $netRegKey.GetSubKeyNames())
{
if ($versionKeyName -match '^v[123]') {
$versionKey = $netRegKey.OpenSubKey($versionKeyName)
$version = [System.Version]($versionKey.GetValue('Version', ''))
write-host("adding old dotnet")
$dotNetter += New-Object -TypeName PSObject -Property @{
ComputerName = $computerName
OS = $os
Build = $version.Build
Version = $version
Comment = ''
}
}
}
}
if ($net4RegKey = $regKey.OpenSubKey("$dotNet4Registry"))
{
if(-not ($net4Release = $net4RegKey.GetValue('Release')))
{
$net4Release = 30319
}
write-host("adding new dotnet")
$dotNetter += New-Object -TypeName PSObject -Property @{
'ComputerName' = $computerName
'OS' = $os
'Build' = $net4Release
'Version' = $dotNet4Builds["$net4Release"].Version
'Comment' = $dotNet4Builds["$net4Release"].Comment
}
}
if ($netRegKey = $regKey.OpenSubKey("$dotNetRoot")){
write-host("Checking for hacked keys")
foreach ($versionKeyName in $netRegKey.GetSubKeyNames())
{
if ($versionKeyName -match '^v[1234]') {
$versionKey = $netRegKey.OpenSubKey($versionKeyName)
write-host("versionKeyName is" + $versionKeyName)
write-host('ASPNetEnforceViewStateMac = ' + $versionKey.GetValue('ASPNetEnforceViewStateMac', ''))
$compromisedCheck += New-Object -TypeName PSObject -Property @{
'ComputerName' = $computerName
'version' = $versionKeyName
'compromisedCheck' = ('ASPNetEnforceViewStateMac = ' + $versionKey.GetValue('ASPNetEnforceViewStateMac', ''))
}
}
}
}
}
}
}
else{
write-host("could not connect to machine")
$dotNetter += New-Object -TypeName PSObject -Property @{
'ComputerName' = $computerName
'OS' = $os
'Build' = "Could not connect"
'Version' = "Could not connect"
'Comment' = "Could not connect"
}
}
}
$dotNetter | export-CSV c:\temp\DotNetVersions.csv
$compromisedCheck | export-CSV C:\temp\CompromisedCheck.csv
}
get-dotnetframeworkversion($computerList)