Microsoft Authenticator for M365 users
Synopsis: Microsoft will turn on number matching on 2/27/2023 which will undoubtedly cause chaos if you have users who are not smart enough to use mobile devices that are patchable and updated automatically.
Reference: https://learn.microsoft.com/en-us/azure/active-directory/authentication/how-to-mfa-number-match.
Date of change: March 2023
_______
DCOM changes
Synopsis: Changes to the security posture of DCOM (first released in June of 2021) become enforced.
References: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-26414 and https://support.microsoft.com/en-us/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c.
Date of change: 03-14-2023
_______
AD Connect 2.0.x
Synopsis: AD Connect 2.0.x versions are going end-of-life for those syncing with M365.
Reference: https://learn.microsoft.com/en-us/azure/active-directory/hybrid/reference-connect-version-history
Date of change: April 2023
_______
AD Permissions issue becomes enforced
Synopsis: To address an Active Directory Domain Services Elevation of Privilege Vulnerability and AD audit mode will become enforced.
References: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42291 and https://support.microsoft.com/en-us/topic/kb5008383-active-directory-permissions-updates-cve-2021-42291-536d5555-ffba-4248-a60e-d6cbc849cde1
Date of change: 04-11-2023
_______
NetLogon RPC becomes enforced
Synopsis: Windows domain controllers will require that Netlogon clients use RPC seal if they are running Windows, or if they are acting as either domain controllers or as trust accounts.
References: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-38023 and https://support.microsoft.com/en-us/topic/kb5021130-how-to-manage-the-netlogon-protocol-changes-related-to-cve-2022-38023-46ea3067-3989-4d40-963c-680fd9e8ee25
Date of Change: 04-11-2023
_______
Kerberos Protocol Changes
Synopsis: Enforcement mode will be enabled on all Windows domain controllers and will block vulnerable connections from non-compliant devices (aka those using weak RC4-HMAC for negotiation).
References: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-37966 , https://support.microsoft.com/en-us/topic/kb5021131-how-to-manage-the-kerberos-protocol-changes-related-to-cve-2022-37966-fd837ac3-cdec-4e76-a6ec-86e67501407d , https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-37967 , and https://support.microsoft.com/en-us/topic/kb5020805-how-to-manage-kerberos-protocol-changes-related-to-cve-2022-37967-997e9acc-67c5-48e1-8d0d-190269bf4efb#timing
Date of change: 07-11-2023
_______
Office 2016/2019 dropped from being able to connect to M365 services
Synopsis: Office 2016/2019 dropped from being able to connect to M365 services due to end-of-support.
References: https://learn.microsoft.com/en-us/deployoffice/endofsupport/microsoft-365-services-connectivity
Date of Change: 10-10-2023
_______
Kerberos/Certificate-based authentication on DCs becomes enforced
Synopsis: Kerberos/Certificate-based authentication on DCs becomes enforced. By 11-14-2023, or later, all devices will be updated to Full Enforcement mode. In this mode, if a certificate fails the strong (secure) mapping criteria, authentication will be denied.
References: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-26931 and https://support.microsoft.com/en-us/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16
Date of change: 11-14-2023
PowerShell Move Mouse every 10-seconds
Add-Type -AssemblyName System.Windows.Forms
while ($true)
{
$Pos = [System.Windows.Forms.Cursor]::Position
$x = ($pos.X % 500) + 1
$y = ($pos.Y % 500) + 1
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)
Start-Sleep -Seconds 10
}
InfraGard Data Breach
VMware PowerCLI Cheat Sheet
SolarWinds SQL Correlate WMI Credential to Node
USE SolarWindsOrion
SELECT
NodesData.NodeID,
NodesData.Caption,
NodeSettings.SettingName,
NodeSettings.SettingValue,
Credential.Name
from dbo.NodesData
join dbo.NodeSettings on NodesData.NodeID = NodeSettings.NodeID
join Credential on NodeSettings.SettingValue = Credential.ID
where NodesData.ObjectSubType = 'WMI'
and nodesettings.SettingName = 'WMICredential'
PowerShell Split File
function Split-File
{
<#
.SYNOPSIS
Splits a file into multiple parts
.DESCRIPTION
Splits a file into smaller parts. The maximum size of the part files can be specified. The number of parts required is calculated.
.EXAMPLE
Split-File -Path 'c:\test.zip' -PartSizeBytes 2.5MB
Splits the file c:\test.zip in as many parts as necessary. Each part file is no larger than 2.5MB
.EXAMPLE
Split-File -Path 'c:\test.zip' -PartSizeBytes 2.5MB -AddSelfExtractor
Splits the file c:\test.zip in as many parts as necessary. Each part file is no larger than 2.5MB
Adds a powershell script that joins the parts when run, and adds a shortcut file to
run the PowerShell extractor script on double-click, essentially adding a self-extractor
#>
param
(
# Path to the file you want to split
[Parameter(Mandatory,HelpMessage='Path to the file you want to split')]
[String]
$Path,
# maximum size of file chunks (in bytes)
[int]
$PartSizeBytes = 1MB,
# when specified, add a an extractor script and link file to easily convert
# chunks back into the original file
[Switch]
$AddSelfExtractor
)
try
{
# get the path parts to construct the individual part
# file names:
$fullBaseName = [IO.Path]::GetFileName($Path)
$baseName = [IO.Path]::GetFileNameWithoutExtension($Path)
$parentFolder = [IO.Path]::GetDirectoryName($Path)
$extension = [IO.Path]::GetExtension($Path)
# get the original file size and calculate the
# number of required parts:
$originalFile = New-Object -TypeName System.IO.FileInfo -ArgumentList ($Path)
$totalChunks = [int]($originalFile.Length / $PartSizeBytes) + 1
$digitCount = [int][Math]::Log10($totalChunks) + 1
# read the original file and split into chunks:
$reader = [IO.File]::OpenRead($Path)
$count = 0
$buffer = New-Object -TypeName Byte[] -ArgumentList $PartSizeBytes
$moreData = $true
# read chunks until there is no more data
while($moreData)
{
# read a chunk
$bytesRead = $reader.Read($buffer, 0, $buffer.Length)
# create the filename for the chunk file
$chunkFileName = "$parentFolder\$fullBaseName.{0:D$digitCount}.part" -f $count
Write-Verbose -Message "saving to $chunkFileName..."
$output = $buffer
# did we read less than the expected bytes?
if ($bytesRead -ne $buffer.Length)
{
# yes, so there is no more data
$moreData = $false
# shrink the output array to the number of bytes
# actually read:
$output = New-Object -TypeName Byte[] -ArgumentList $bytesRead
[Array]::Copy($buffer, $output, $bytesRead)
}
# save the read bytes in a new part file
[IO.File]::WriteAllBytes($chunkFileName, $output)
# increment the part counter
++$count
}
# done, close reader
$reader.Close()
# add self-extractor
if ($AddSelfExtractor)
{
Write-Verbose -Message "Adding extractor scripts..."
# define the self-extractor powershell script:
$extractorName = "${fullBaseName}.{0:D$digitCount}.part.ps1" -f $count
$extractorPath = Join-Path -Path $parentFolder -ChildPath $extractorName
$filePath = '$PSScriptRoot\' + "$baseName$extension"
# define the self-extractor shortcut file that launches
# the powershell script on double-click:
$linkName = "Extract ${fullBaseName}.lnk"
$linkPath = Join-Path -Path $parentFolder -ChildPath $linkName
# this will be used inside the extractor script to find the
# part files via relative path:
$currentFile = '"$PSCommandPath"'
$currentFolder = '"$PSScriptRoot"'
# write the extractor script source code to file:
"
# copy the join-file source code into the extractor script:
function Join-File {
${function:Join-File}
}
# join the part files and delete the part files after joining:
Join-File -Path ""$filePath"" -Verbose -DeletePartFiles
# remove both extractor scripts:
(Join-Path -Path $currentFolder -ChildPath '$linkName') | Remove-Item
Remove-Item -Path $currentFile
# open the extracted file in windows explorer
explorer.exe ""/select,""""$filepath""""""
" | Set-Content -Path $extractorPath
# create a shortcut file that launches the extractor script
# when it is double-clicked:
$shell = New-Object -ComObject WScript.Shell
$scut = $shell.CreateShortcut($linkPath)
$scut.TargetPath = "powershell.exe"
$scut.Arguments = "-nop -executionpolicy bypass -file ""$extractorPath"""
$scut.WorkingDirectory = ""
$scut.IconLocation = "$env:windir\system32\shell32.dll,162"
$scut.Save()
}
}
catch
{
throw "Unable to split file ${Path}: $_"
}
}
New Windows ‘LockSmith’ PowerToy lets you free locked files
Force Halt VMware VM w/PowerCLI
# Get list of VMs on ESXi host
esxcli vm process list
## Note the WorldID of the machine you want to kill
# Kill one of them
esxcli vm process kill --type=soft -w=WhateverWorldID
PowerShell Port Scanner
#######################################################################################
# Language : PowerShell 4.0
# Filename : PortScan.ps1
# Autor : Brandon Lanczak
# Description : Asynchronus IPv4 Port Scanner
#######################################################################################
<#
.SYNOPSIS
Asynchronus IPv4 Port Scanner
.DESCRIPTION
This asynchronus IPv4 Port Scanner allows you to scan every Port-Range you want (500 to 2600 would work). Only TCP-Ports are scanned.
The result will contain the Port number, Protocol, Service name, Description and the Status.
.EXAMPLE
.\IPv4PortScan.ps1 -ComputerName rubbish.com -EndPort 500
Port Protocol ServiceName ServiceDescription Status
---- -------- ----------- ------------------ ------
53 tcp domain Domain Name Server open
80 tcp http World Wide Web HTTP open
#>
[CmdletBinding()]
param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage='ComputerName or IPv4-Address of the device which you want to scan')]
[String]$ComputerName,
[Parameter(
Position=1,
HelpMessage='First port which should be scanned (Default=1)')]
[ValidateRange(1,65535)]
[Int32]$StartPort=1,
[Parameter(
Position=2,
HelpMessage='Last port which should be scanned (Default=65535)')]
[ValidateRange(1,65535)]
[ValidateScript({
if($_ -lt $StartPort)
{
throw "Invalid Port-Range!"
}
else
{
return $true
}
})]
[Int32]$EndPort=65535,
[Parameter(
Position=3,
HelpMessage='Maximum number of threads at the same time (Default=500)')]
[Int32]$Threads=10,
[Parameter(
Position=4,
HelpMessage='Execute script without user interaction')]
[switch]$Force
)
Begin{
Write-Verbose -Message "Script started at $(Get-Date)"
$PortList_Path = "$PSScriptRoot\Resources\ports.txt"
}
Process{
if(Test-Path -Path $PortList_Path -PathType Leaf)
{
$PortsHashTable = @{ }
Write-Verbose -Message "Read ports.txt and fill hash table..."
foreach($Line in Get-Content -Path $PortList_Path)
{
if(-not([String]::IsNullOrEmpty($Line)))
{
try{
$HashTableData = $Line.Split('|')
if($HashTableData[1] -eq "tcp")
{
$PortsHashTable.Add([int]$HashTableData[0], [String]::Format("{0}|{1}",$HashTableData[2],$HashTableData[3]))
}
}
catch [System.ArgumentException] { } # Catch if port is already added to hash table
}
}
$AssignServiceWithPort = $true
}
else
{
$AssignServiceWithPort = $false
Write-Warning -Message "No port-file to assign service with port found! Execute the script ""Create-PortListFromWeb.ps1"" to download the latest version.. This warning doesn`t affect the scanning procedure."
}
# Check if host is reachable
Write-Verbose -Message "Test if host is reachable..."
if(-not(Test-Connection -ComputerName $ComputerName -Count 2 -Quiet))
{
Write-Warning -Message "$ComputerName is not reachable!"
if($Force -eq $false)
{
$Title = "Continue"
$Info = "Would you like to continue? (perhaps only ICMP is blocked)"
$Options = [System.Management.Automation.Host.ChoiceDescription[]] @("&Yes", "&No")
[int]$DefaultChoice = 0
$Opt = $host.UI.PromptForChoice($Title , $Info, $Options, $DefaultChoice)
switch($Opt)
{
1 {
return
}
}
}
}
$PortsToScan = ($EndPort - $StartPort)
Write-Verbose -Message "Scanning range from $StartPort to $EndPort ($PortsToScan Ports)"
Write-Verbose -Message "Running with max $Threads threads"
# Check if ComputerName is already an IPv4-Address, if not... try to resolve it
$IPv4Address = [String]::Empty
if([bool]($ComputerName -as [IPAddress]))
{
$IPv4Address = $ComputerName
}
else
{
# Get IP from Hostname (IPv4 only)
try{
$AddressList = @(([System.Net.Dns]::GetHostEntry($ComputerName)).AddressList)
foreach($Address in $AddressList)
{
if($Address.AddressFamily -eq "InterNetwork")
{
$IPv4Address = $Address.IPAddressToString
break
}
}
}
catch{ } # Can't get IPAddressList
if([String]::IsNullOrEmpty($IPv4Address))
{
throw "Could not get IPv4-Address for $ComputerName. (Try to enter an IPv4-Address instead of the Hostname)"
}
}
# Scriptblock --> will run in runspaces (threads)...
[System.Management.Automation.ScriptBlock]$ScriptBlock = {
Param(
$IPv4Address,
$Port
)
try{
$Socket = New-Object System.Net.Sockets.TcpClient($IPv4Address,$Port)
if($Socket.Connected)
{
$Status = "Open"
$Socket.Close()
}
else
{
$Status = "Closed"
}
}
catch{
$Status = "Closed"
}
if($Status -eq "Open")
{
[pscustomobject] @{
Port = $Port
Protocol = "tcp"
Status = $Status
}
}
}
Write-Verbose -Message "Setting up RunspacePool..."
# Create RunspacePool and Jobs
$RunspacePool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1, $Threads, $Host)
$RunspacePool.Open()
[System.Collections.ArrayList]$Jobs = @()
Write-Verbose -Message "Setting up Jobs..."
#Set up job for each port...
foreach($Port in $StartPort..$EndPort)
{
$ScriptParams =@{
IPv4Address = $IPv4Address
Port = $Port
}
# Catch when trying to divide through zero
try {
$Progress_Percent = (($Port - $StartPort) / $PortsToScan) * 100
}
catch {
$Progress_Percent = 100
}
Write-Progress -Activity "Setting up jobs..." -Id 1 -Status "Current Port: $Port" -PercentComplete ($Progress_Percent)
# Create mew job
$Job = [System.Management.Automation.PowerShell]::Create().AddScript($ScriptBlock).AddParameters($ScriptParams)
$Job.RunspacePool = $RunspacePool
$JobObj = [pscustomobject] @{
RunNum = $Port - $StartPort
Pipe = $Job
Result = $Job.BeginInvoke()
}
# Add job to collection
[void]$Jobs.Add($JobObj)
}
Write-Verbose -Message "Waiting for jobs to complete & starting to process results..."
# Total jobs to calculate percent complete, because jobs are removed after they are processed
$Jobs_Total = $Jobs.Count
# Process results, while waiting for other jobs
Do {
# Get all jobs, which are completed
$Jobs_ToProcess = $Jobs | Where-Object -FilterScript {$_.Result.IsCompleted}
# If no jobs finished yet, wait 500 ms and try again
if($null -eq $Jobs_ToProcess)
{
Write-Verbose -Message "No jobs completed, wait 500ms..."
Start-Sleep -Milliseconds 500
continue
}
# Get jobs, which are not complete yet
$Jobs_Remaining = ($Jobs | Where-Object -FilterScript {$_.Result.IsCompleted -eq $false}).Count
# Catch when trying to divide through zero
try {
$Progress_Percent = 100 - (($Jobs_Remaining / $Jobs_Total) * 100)
}
catch {
$Progress_Percent = 100
}
Write-Progress -Activity "Waiting for jobs to complete... ($($Threads - $($RunspacePool.GetAvailableRunspaces())) of $Threads threads running)" -Id 1 -PercentComplete $Progress_Percent -Status "$Jobs_Remaining remaining..."
Write-Verbose -Message "Processing $(if($null -eq $Jobs_ToProcess.Count){"1"}else{$Jobs_ToProcess.Count}) job(s)..."
# Processing completed jobs
foreach($Job in $Jobs_ToProcess)
{
# Get the result...
$Job_Result = $Job.Pipe.EndInvoke($Job.Result)
$Job.Pipe.Dispose()
# Remove job from collection
$Jobs.Remove($Job)
# Check if result is null --> if not, return it
if($Job_Result.Status)
{
if($AssignServiceWithPort)
{
$Service = [String]::Empty
$Service = $PortsHashTable.Get_Item($Job_Result.Port).Split('|')
[pscustomobject] @{
Port = $Job_Result.Port
Protocol = $Job_Result.Protocol
ServiceName = $Service[0]
ServiceDescription = $Service[1]
Status = $Job_Result.Status
}
}
else
{
$Job_Result
}
}
}
} While ($Jobs.Count -gt 0)
Write-Verbose -Message "Closing RunspacePool and free resources..."
# Close the RunspacePool and free resources
$RunspacePool.Close()
$RunspacePool.Dispose()
Write-Verbose -Message "Script finished at $(Get-Date)"
}
End{
}
# Create Ports hash file
#[xml]$LatestPorts = Get-Content -Path "$PSScriptRoot\Service Name and Transport Protocol Port Number Registry.xml"
[xml]$LatestPorts = (Invoke-WebRequest -Uri "https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml").Content
$Output = ""
foreach($record in $LatestPorts.ChildNodes.record)
{
if([string]::IsNullOrEmpty($record.number) -or ([string]::IsNullOrEmpty($record.protocol)))
{
continue
}
$Description = ($record.description -replace '`n','') -replace '\s+',' '
$Number = $record.number
if($Number -like "*-*")
{
$NumberArr = $Number.Split('-')
foreach($Number1 in $NumberArr[0]..$NumberArr[1])
{
$Output += "$Number1|$($record.protocol)|$($record.name)|$Description`n"
}
}
else
{
$Output += "$Number|$($record.protocol)|$($record.name)|$Description`n"
}
}
Out-File -InputObject $Output -FilePath "$PSScriptRoot\Resources\ports.txt"
PowerShell Constant Attention
# Time for loop to run
param($minutes = 920)
# Loop
$myshell = New-Object -com "Wscript.Shell"
for ($i = 0; $i -lt $minutes; $i++) {
$myshell.sendkeys("{SCROLLLOCK}")
Get-Date -Format "dddd MM/dd/yyyy HH:mm K" | Write-Host
Start-Sleep -Milliseconds 100
$myshell.sendkeys("{SCROLLLOCK}")
Echo $i
Start-Sleep -Seconds 60
}