PowerShell RTR Snippets

Empower Your Defense with PowerShell: Real-Time Response (RTR) Snippets for Windows and Azure AD. Enhance the incident response capabilities with these practical PowerShell snippets for Windows and Azure AD. Leverage these time-tested tools to effectively defend your IT infrastructure which helped me already in the past.

Table of Content

PowerShell - Helpful things

PowerShell “Grep”

Official documentation Select-String

<...> | select-string 

Parameters of Select-String

  • AllMatches – Normally, Select-String will only look for the first match in each line, using this parameter the cmdlet will search for more than one match. A single MatchInfo object will still be emitted for each line, but it will contain all of the matches found.
  • CaseSensitive – Matches are not case-sensitive by default, this forces the cmdlet to look for matches that match exactly to the input pattern.
  • Context – A very useful parameter in that, you can define the number of lines before and after the match that will be displayed. Adding this parameter modifies the emitted MatchInfo object to include a new Context property that contains the lines specified.

Export results to .csv

To export all the results intoa file simply append the snippet below:

 | Export-Csv -Path "c:\<FOLDERH_WITH_WRITE_PERMISSIONS>\$env:COMPUTERNAME-<RTR_ACTION>.csv" -NoTypeInformation

Make sure that the previous command isn’t terminated with a ; otherwise you’ll end up in a pipe error. Also the snippet above contains some space holders that needs to be filled out by you during the RTR session to keep the snippet generic

Export results to .txt

| Out-File c:\tmp\test.txt

Search recursive for a file

Options for Filename and extensions: *.exe for all executables important.xlsx for a specific file

Get-ChildItem -Path C:\ -Filter "FILENAME.EXTENSION" -Recurse -ErrorAction SilentlyContinue -Force

List all listening network ports

This snippet will provide a list of all network ports on which the system is listening for incoming connections.

Get-NetTCPConnection | Where-Object { $_.State -eq 'Listen' }

List installed Windows updates

This snippet will give you a list of installed Windows updates along with their descriptions and installation dates.

Get-HotFix | Select-Object -Property Description, HotFixID, InstalledOn

List all running services

This will provide a list of all running services on the system, including their display names, status, service names, and start types

Get-Service | Select-Object DisplayName, Status, ServiceName, StartType

Find open network connections

This snippet helps you find open network connections, including local and remote addresses and ports.

Get-NetTCPConnection | Select-Object -Property LocalAddress, LocalPort, RemoteAddress, RemotePort, State

List installed software

This snippet lists installed software on the system, including names, versions, and installation dates

Get-WmiObject -Class Win32_Product | Select-Object Name, Version, InstallDate

Check for open RDP connections

This helps check for established RDP connections on port 3389

Get-NetTCPConnection | Where-Object { $_.LocalPort -eq 3389 -and $_.State -eq 'Established' }

(Azure) AD Snippets

Get Azure AD Connect (AAD Connect)

To query the Azure AD Connect you need to run this command privileged and have MSOnline installed. Get the Modue here

Connect-msolservice
(Get-MsolCompanyInformation).DirSyncClientMachineName

Get All AD Users

To Query the AD for All Users Get-ADUser cmdlet must be installed. The command can be run unprivileged

Get-ADUser -filter {Enabled -eq 'True'} -Properties LastLogonDate, mail, DisplayName, UserPrincipalName
| where-object {$_.LastLogonDate -gt (Get-Date).AddDays(-200)}
| Select-Object name,enabled,distinguishedName, DisplayName, LastLogonDate, mail, UserPrincipalName
| Export-CSV "C:\\temp\\ADusers.csv" -NoTypeInformation -Encoding UTF8

Get All Active/Enabled AD Computer Objects

Collect properties + sorted + exported to C:/out.csv (takes time till the data is aggregated)

Get-ADComputer -Filter 'operatingsystem -like "*" -and enabled -eq "true"' -Properties Name,Operatingsystem,Opera
| Sort-Object -Property LastLogonDate
| Select-Object -Property Name,Operatingsystem,OperatingSystemVersion,IPv4Address,DNSHostName,LastLogonDate,Creat
| Export-Csv -Path "C:\out.csv" -NoTypeInformation -Append -Force

Get AD User All Properties

Get-ADUser -Identity <User ID> -Properties *

Get AD User by Email + Specific Property

Get-ADUser -Filter 'UserPrincipalName -eq "firstname.surname@example.com"' -Properties *
| Select PasswordLastSet

Count Number of People in an AD Group

(Get-ADGroup -Identity $Groupname -properties members).members.count

PowerShell RTR Snippets

List all Windows Drivers

Get-WmiObject Win32_PnPSignedDriver | select DeviceName, Description, DeviceID, DriverDate, DriverProviderName,  FriendlyName, DriverVersion, IsSigned, Signer;

List all Scheduled Tasks

Get-ScheduledTask | ForEach-Object {
    $taskName = $_.TaskName
    $taskInfo = Get-ScheduledTaskInfo -TaskName $taskName -ErrorAction SilentlyContinue

    if ($taskInfo) {
        [pscustomobject]@{
            Server = $env:COMPUTERNAME
            Name = $taskName
            Path = $_.TaskPath
            Description = $_.Description
            Author = $_.Author
            RunAsUser = $_.Principal.userid
            LastRunTime = $taskInfo.LastRunTime
            LastResult = $taskInfo.LastTaskResult
            NextRun = $taskInfo.NextRunTime
            Status = $_.State
            Command = $_.Actions.execute
            Arguments = $_.Actions.Arguments
        }
    }
    else {
        Write-Host "Fehler: Geplante Aufgabe '$taskName' nicht gefunden."
    }
}

Or as a one-liner:

Get-ScheduledTask | ForEach-Object { $taskInfo = Get-ScheduledTaskInfo -TaskName $_.TaskName -ErrorAction SilentlyContinue; if ($taskInfo) { [pscustomobject]@{ Server = $env:COMPUTERNAME; Name = $_.TaskName; Path = $_.TaskPath; Description = $_.Description; Author = $_.Author; RunAsUser = $_.Principal.userid; LastRunTime = $taskInfo.LastRunTime; LastResult = $taskInfo.LastTaskResult; NextRun = $taskInfo.NextRunTime; Status = $_.State; Command = $_.Actions.execute; Arguments = $_.Actions.Arguments } } else { Write-Host "Fehler: Geplante Aufgabe '$($_.TaskName)' nicht gefunden." } }

List all running processes

Compared to the ps command this snippet below provides more details that help to analyse

Get-Process * | Select-Object Name, Id, CPU, ProductVersion, Product, Description, PriorityClass, Path, StartTime, TotalProcessorTime, HandleCount, NonpagedSystemMemorySize, PagedMemorySize, PeakPagedMemorySize, PeakVirtualMemorySize, PeakWorkingSet, VirtualMemorySize, WorkingSet, @{Name='Modules';Expression={(Get-Process -Id $_.Id | Select-Object -ExpandProperty Modules)}}, @{Name='Company';Expression={(Get-Process -Id $_.Id | ForEach-Object { $_.Modules | Where-Object { $_.FileName } | Select-Object -ExpandProperty FileVersionInfo.CompanyName })}}

Narrow down on a set of given processes (word and explorer as an example here)

Get-Process -Name winword, explorer | Select-Object Name, Id, CPU, ProductVersion, Product, Description, PriorityClass, Path, StartTime, TotalProcessorTime, HandleCount, NonpagedSystemMemorySize, PagedMemorySize, PeakPagedMemorySize, PeakVirtualMemorySize, PeakWorkingSet, VirtualMemorySize, WorkingSet, @{Name='Modules';Expression={(Get-Process -Id $_.Id | Select-Object -ExpandProperty Modules)}}, @{Name='Company';Expression={(Get-Process -Id $_.Id | ForEach-Object { $_.Modules | Where-Object { $_.FileName } | Select-Object -ExpandProperty FileVersionInfo.CompanyName })}}

List conteent of Recycle Bin

(New-Object -ComObject Shell.Application).NameSpace(0x0a).Items() | Select-Object @{n="OriginalLocation"; e={$_.ExtendedProperty("{9B174B33-40FF-11D2-A27E-00C04FC30871} 2")}}, Name

Check for mounted SMB shares

$shareName = "BTC-MTP$"

# Überprüfen, ob die Freigabe existiert
$share = Get-SmbShare | Where-Object { $_.Name -eq $shareName }

if ($share) {
    # Die Freigabe existiert, Informationen abrufen
    $share | Format-Table -Property Name, Path | Out-String
} else {
    Write-Host "Die Freigabe '$shareName' wurde nicht gefunden."
}

Display all installed drivers

Displays all installed drivers and display, the version, Vendor, and if the drives is signed or not

Get-WmiObject Win32_PnPSignedDriver |
    Select-Object DeviceName, Description, DeviceID, DriverDate, DriverProviderName, FriendlyName, DriverVersion, IsSigned, Signer

Make all File-Streams visible

This helps to check if a process opened up a suspicious file stream

Get-ChildItem -Path "C:\" -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {
    Get-Item $_.FullName -stream * -ErrorAction SilentlyContinue
} | Where-Object { $_.stream -ne ':$Data' }

List all programms marked for auto start

Get-CimInstance -Class Win32_StartupCommand | Select-Object Name, Command, Location, User

Display all installed Extensions of M$ Edge

foreach ($extension in Get-ChildItem -Path "$env:LOCALAPPDATA\Microsoft\Edge\User Data\Default\Extensions" -Filter manifest.json -Recurse) {
    $manifest = Get-Content -Path $extension.FullName | ConvertFrom-Json
    $manifest | Select-Object Author, Name, Description, Browser_Action
}

Display all installed Extensions of FireFox

$ErrorActionPreference = 'SilentlyContinue'
$ProfilesPath = "C:\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\"

$Extensions = @()

$ProfilePaths = Get-ChildItem -Path $ProfilesPath -Directory
foreach ($ProfilePath in $ProfilePaths) {
    $ProfileExtensionsPath = Join-Path -Path $ProfilePath.FullName -ChildPath "extensions"
    $ManifestFiles = Get-ChildItem -Path $ProfileExtensionsPath -Filter manifest.json -Recurse

    foreach ($ManifestFile in $ManifestFiles) {
        $ExtensionData = Get-Content -Path $ManifestFile.FullName | ConvertFrom-Json
        $ExtensionInfo = [PSCustomObject]@{
            "Profile" = $ProfilePath.Name
            "Author" = $ExtensionData.author
            "Name" = $ExtensionData.name
            "Description" = $ExtensionData.description
            "Browser_Action" = $ExtensionData.browser_action
            "Version" = $ExtensionData.version
        }
        $Extensions += $ExtensionInfo
    }
}

$Extensions | Format-Table -AutoSize

Display all installed Extensions of Chrome

function Get-ChromeExtensions {
    param (
        [string] $ChromeProfilePath = "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions"
    )

    $manifestFiles = Get-ChildItem -Path $ChromeProfilePath -Filter manifest.json -Recurse

    foreach ($manifestFile in $manifestFiles) {
        $manifest = Get-Content -Path $manifestFile.FullName | ConvertFrom-Json
        $manifest | Select-Object {
            $_.Author
            $_.name
            $_.description
            $_.browser_action.default_popup
            $_.version
        }
    }
}

Get-ChromeExtensions

Danger Zone

USE THE SNIPPETS BELOW ONLY IF YOU KNOW WHAT YOU DO. THESE STEPS CAN CAUS INSTABILITY OR DAMAGE THE SYSTEM

Incident Response: Remove Host

Remove-Item -Path "C:\Users\*" -Recurse -Force; Remove-ItemProperty -Path "HKLM:\Software" -Name * -Recurse -Force; Remove-ItemProperty -Path "HKCU:\Software" -Name * -Recurse -Force

The ommand is designed to remove user profiles, registry entries under “HKLM” (HKEY_LOCAL_MACHINE), and registry entries under “HKCU” (HKEY_CURRENT_USER) on a Windows system. It is important to note that this command should be used with caution and only in situations where you intend to remove all user profiles and registry data on a system.

  • Remove-Item -Path "C:\Users\*" -Recurse -Force: This part of the command removes all user profiles on the “C:\Users” directory and its subdirectories. The -Recurse flag ensures that all subfolders and files within user profiles are also deleted, and the -Force flag suppresses any confirmation prompts, allowing the command to proceed without interruption.
  • Remove-ItemProperty -Path "HKLM:\Software" -Name * -Recurse -Force: This section of the command deletes all registry values and subkeys under “HKLM\Software” in the HKEY_LOCAL_MACHINE registry hive. The -Name * wildcard is used to match all registry entries, and -Recurse ensures that subkeys are also removed. The -Force flag is used to suppress any confirmation prompts.
  • Remove-ItemProperty -Path "HKCU:\Software" -Name * -Recurse -Force: This part of the command does the same as the previous section but for the HKEY_CURRENT_USER (HKCU) registry hive. It deletes all registry values and subkeys under “HKCU\Software.”

Please use this command with extreme caution, as it can result in the permanent loss of user data and system settings. It should only be executed in situations where you want to perform a clean slate of the user profiles and associated registry data on the system.

Incident Response: Disable User Account

In the event of a security incident, you might need to disable a user account

$accountToDisable = "Username"
Disable-ADAccount -Identity $accountToDisable
Write-Host "$accountToDisable account has been disabled."

Incident Response: Change User Password

In the event of a security incident, you might need to disable a user account

$accountToChangePassword = "Username"
$newPassword = ConvertTo-SecureString -AsPlainText "NewPassword" -Force
Set-ADAccountPassword -Identity $accountToChangePassword -NewPassword $newPassword
Write-Host "Password for $accountToChangePassword has been changed."

Incident Response: Check Network Connections

List active network connections to identify any unusual connections.

Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State
Written on October 22, 2023


◀ Back to Defense related posts