Skip to content

Instantly share code, notes, and snippets.

@markekraus
Last active June 28, 2017 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markekraus/47c78dbbb106cc27558c435446aafd50 to your computer and use it in GitHub Desktop.
Save markekraus/47c78dbbb106cc27558c435446aafd50 to your computer and use it in GitHub Desktop.
Patch AD Computers for NotPetya. Supports multiple runs to skip previously patched machines and provides detailed logging objects.
#Requires -Modules PoshRSJob, ActiveDirectory
# create this file as read-Only before running script
$SourceFile = "C:\perfc"
$ServerFilter = {enabled -eq $True -and DnsHostName -like "*" -and operatingSystem -like "*windows*"}
$SearchBase = "dc=adatum,dc=com"
$LogFile = "C:\NotPetyaPatch.xml"
$Throttle = 40
$StartDate = Get-Date
$Results = [System.Collections.ArrayList]::new()
$Vaccinated = [System.Collections.ArrayList]::new()
$PreviousResults = Import-Clixml -Path $LogFile -ErrorAction SilentlyContinue
Foreach($PreviousResult in $PreviousResults){
if($PreviousResult.Vaccinated -eq $true){
$null = $Results.Add($PreviousResult)
$null = $Vaccinated.Add($PreviousResult.Server.SID.Value)
}
}
$Results | Select-Object ComputerName, Vaccinated, Date | Format-Table
$Servers = Get-ADComputer -filter $ServerFilter -SearchBase $SearchBase | Where-Object {$_.SID.Value -notin $Vaccinated}
$Servers | Start-RSJob -Name {$_.DnsHostName} -Throttle $Throttle -ScriptBlock {
$Server = $_
$ComputerName = $Server.DnsHostName
$SourceFile = $using:SourceFile
$AdminShare = '\\{0}\C$' -f $ComputerName
$DestinationFiles = @(
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc'
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc.dat'
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc.dll'
)
$Result = [PSCustomObject]@{
Server = $Server
ComputerName = $ComputerName
PathAvailable = $false
Vaccinated = "Unknown"
Errors = [System.Collections.ArrayList]::new()
CopyResults = [System.Collections.ArrayList]::new()
Date = Get-Date
}
if (-not (Test-Path -Path $AdminShare)) {
return $Result
}
$Result.PathAvailable = $True
foreach($DestinationFile in $DestinationFiles){
$DestinationResult = [PSCustomObject]@{
DestinationFile = $DestinationFile
FileAlreadyExists = $false
CopyAttempted = $false
CopySuccessful = $false
}
if (Test-Path -Path $DestinationFile) {
$DestinationResult.FileAlreadyExists = $true
$DestinationResult.CopySuccessful = $true
$null = $Result.CopyResults.Add($DestinationResult)
continue
}
try {
$DestinationResult.CopyAttempted = $True
$Null = Copy-Item -Path $SourceFile -destination $DestinationFile -ErrorAction Stop
}
catch {
$null = $Result.Errors.Add($_)
$null = $Result.CopyResults.Add($DestinationResult)
continue
}
if (Test-Path -Path $DestinationFile) {
$DestinationResult.CopySuccessful = $true
}
$null = $Result.CopyResults.Add($DestinationResult)
}
if($false -in $Result.CopyResults.CopySuccessful){
$Result.Vaccinated = $false
}
else{
$Result.Vaccinated = $true
}
return $Result
} | Wait-RSJob | Receive-RSJob | ForEach-Object {
$null = $Results.Add($_)
$_ | Select-Object ComputerName, Vaccinated
} | Format-Table
$VaccinatedTotal = $Results.Where({$_.vaccinated -eq $True}).Count
$VaccinatedThisRun = $VaccinatedTotal - $Vaccinated.Count
$EndDate = Get-Date
" "
"Results"
"---------------------------"
"Previously Vaccinated: {0}" -f $Vaccinated.Count
"Vaccinated This Run: {0}" -f $VaccinatedThisRun
"Vaccinated Total: {0}" -f $VaccinatedTotal
"Failed: {0}" -f $Results.Where({$_.vaccinated -eq $false}).Count
"Unknown: {0}" -f $Results.Where({$_.vaccinated -like "Unknown"}).Count
"Start Date: {0}" -f $StartDate
"End Date: {0}" -f $EndDate
"Run time: {0}" -f ($EndDate - $StartDate)
Get-RSJob | Remove-RSJob -Force
$Results | Export-Clixml -Path $LogFile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment