Inspect before changing
Start with read-only commands that show the current state. A command should answer a specific question before it modifies anything.
Windows 11 · Lesson 14
Use PowerShell to inventory Windows quickly, filter evidence, verify security state, and make small controlled changes without turning automation into blind hardening.
PowerShell is most valuable when it makes reasoning faster and more repeatable. The defensive pattern is simple: inspect, narrow, change carefully, re-query, test, and document.
Lesson Snapshot
Learning objectives
Explain where PowerShell is most useful during defensive Windows administration.
Use read-only inventory commands before making configuration changes.
Filter, sort, and select results so large system inventories become useful evidence.
Recognize the difference between inspection, controlled change, and bulk automation.
Use PowerShell to review users, services, firewall, Defender, updates, tasks, and event logs efficiently.
Verify the result of every meaningful administrative change instead of assuming the command worked as intended.
Core concept
The best commands answer a clear question and return structured objects that can be filtered, sorted, compared, and verified.
Automation warning
Bulk scripts can disable required services, remove valid users, or break network access before the team knows what changed.
Defensive PowerShell principles
Start with read-only commands that show the current state. A command should answer a specific question before it modifies anything.
Avoid commands that affect large groups of users, services, files, or rules unless the scope is fully understood.
Use names, properties, paths, states, and other filters so the command acts on the exact object you intend.
Capture relevant evidence before high-impact changes, especially for accounts, services, tasks, firewall rules, and event logs.
Small changes are easier to verify and troubleshoot than broad scripts that alter many controls at once.
The same command family used for inspection can often verify that the intended state actually exists afterward.
Pipeline basics
Retrieve objects from the system, such as users, services, firewall rules, scheduled tasks, or events.
Filter objects based on properties such as status, name, startup mode, profile, or account state.
Choose only the properties that matter so output is easier to read and compare.
Order results by properties such as time, state, display name, or install date.
Present selected output in a useful layout for review. Formatting changes presentation, not the underlying object.
Save structured inventory output for later comparison or documentation in an authorized practice environment.
High-value inventory commands
Get-LocalUserReview account names, enabled state, and password-related properties.
Get-LocalGroupMember -Group "Administrators"Review privileged local group membership.
Get-Service | Sort-Object Status, DisplayNameReview running and stopped services without changing them.
Get-CimInstance Win32_Service | Select-Object Name, DisplayName, State, StartMode, StartName, PathNameAdds startup type, account context, and executable path to service review.
Get-NetFirewallProfileReview Domain, Private, and Public firewall profile state.
Get-NetFirewallRule -Enabled True -Direction Inbound | Select-Object DisplayName, Action, ProfileBuild a quick view of active inbound firewall rules.
Get-MpComputerStatusReview Defender protection state and health information.
Get-MpPreferenceInspect Defender exclusions and protection-related preferences.
Filtering examples
Get-LocalUser | Where-Object {$_.Enabled -eq $false}Filters the local user inventory to accounts that are currently disabled.
Get-Service | Where-Object {$_.Status -eq 'Running'}Shows only services currently running.
Get-CimInstance Win32_Service | Where-Object {$_.StartMode -eq "Auto"}Shows services configured for automatic startup.
Get-NetFirewallRule | Where-Object {$_.Enabled -eq "True" -and $_.Direction -eq "Inbound" -and $_.Action -eq "Allow"}Narrows firewall review to active inbound allow rules.
Defensive administration map
Get-LocalUserGet-LocalGroupGet-LocalGroupMemberQuickly review authorized users, privileged groups, and unexpected membership.
Get-MpComputerStatusGet-MpPreferenceGet-NetFirewallProfileGet-NetFirewallRuleReview Defender and firewall posture from one console.
Get-ServiceGet-CimInstance Win32_ServiceGet-HotFixGet-ComputerInfoReview services, updates, Windows version, and core system state.
Get-ScheduledTaskGet-ScheduledTaskInfoGet-CimInstance Win32_StartupCommandReview recurring execution and startup behavior without opening multiple tools.
Get-WinEventGet-AclGet-ItemPropertyInspect logs, permissions, and configuration evidence with repeatable queries.
Controlled change examples
Change
Disable-LocalUser -Name "exampleuser"Use only after confirming the account is not required by the scenario or a service.
Verify
Get-LocalUser -Name "exampleuser"Change
Remove-LocalGroupMember -Group "Administrators" -Member "exampleuser"Confirm the user still needs the account but does not need administrative privilege.
Verify
Get-LocalGroupMember -Group "Administrators"Change
Start-Service -Name "Spooler"Use only when the service is required and its configuration is understood.
Verify
Get-Service -Name "Spooler"Change
Disable-ScheduledTask -TaskName "ExampleTask"Preserve task evidence first if the task may matter to forensics.
Verify
Get-ScheduledTask -TaskName "ExampleTask"Bulk-change risks
Stopped does not mean unnecessary. Many services start only when needed.
Some accounts may be required by the scenario or an application. Investigate first.
Legitimate applications often create their own tasks.
Required RDP, file sharing, management, or applications can depend on specific rules.
Some narrow exclusions may support required applications.
Bulk changes are difficult to attribute, troubleshoot, and verify during a timed competition.
Output techniques
Get-LocalUser | Select-Object Name, Enabled, PasswordRequired, PasswordExpiresRemoves visual noise and keeps the columns that answer the question.
Get-WinEvent -LogName System -MaxEvents 50 | Sort-Object TimeCreated -DescendingKeeps recent evidence easy to follow.
Get-Service | Select-Object Name, DisplayName, Status | Export-Csv ".\services-inventory.csv" -NoTypeInformationCreates a structured snapshot that can support documentation or before/after comparison.
Get-LocalGroupMember -Group "Administrators" | Out-File ".\admins-before.txt"Useful for preserving a small before-state record in an authorized lab.
Error handling
Confirm the cmdlet exists on the Windows version and edition you are using, and that the relevant module or feature is available.
Some administrative queries require an elevated PowerShell session. Do not assume lack of access means the object does not exist.
A filter may be too narrow or the object name may be wrong. Remove filters gradually and inspect the underlying object.
Different cmdlets return different object types. Use Get-Member or Format-List * in a lab to inspect available properties.
Verification pattern
01
Record the exact object and current state.
02
Change only the confirmed weakness.
03
Re-run a read-only inspection command to confirm the configuration state.
04
Verify the related user, service, application, network path, or security control still works.
05
Look for errors or expected evidence after high-impact changes.
06
Record what changed, why, and what verification proved.
Decision cases
PowerShell shows an unfamiliar account in the local Administrators group.
The finding is important, but the account must be compared with the scenario and service dependencies before removal.
Response
Inspect the account, document membership, identify purpose, then remove only the unnecessary privilege or disable the account if evidence supports it.
A service inventory shows an automatic service running from a user-profile directory.
The path is unusual enough to investigate, but the service may belong to a legitimate application.
Response
Review service name, account, executable, dependencies, installed software, and event evidence before making a change.
A filtered rule list shows a required service allowed inbound on all profiles.
The service may be required while the scope is excessive.
Response
Inspect the specific rule and remote scope, narrow only what is justified, then test the required service.
A task query shows a logon-triggered task that launches a script from an unusual user path.
This is an investigation lead, not automatic proof of malicious persistence.
Response
Preserve the task details, correlate with logs and file evidence, then disable or remove only when justified.
Fictional defensive lab
Step 01
Morgan is the authorized administrator. RDP, Defender, Windows Update, and a project share are required. One unknown local administrator and one unknown scheduled task need review.
Step 02
Use read-only commands to review local users, administrators, firewall profiles, Defender status, services, tasks, and recent events.
Step 03
Narrow the output to the unexpected administrator, the unusual task, and the specific services or rules related to required functionality.
Step 04
Save the relevant before-state output for the administrator group and the scheduled task before making any change.
Step 05
Remove only the confirmed unnecessary privilege and disable the suspicious task after evidence has been preserved.
Step 06
Re-query the administrator group and task state, then test RDP, Defender, firewall, and the required project share.
Common mistakes
PowerShell is fast enough to make mistakes quickly. Read the object state before changing it.
A script may assume a different Windows edition, network, scenario, or application set.
Wildcards can match far more objects than expected. Prefer explicit names and filters.
A command completing without an error does not prove the system is secure or functional.
Permissions, filters, or object types may explain empty output.
Gather and preserve evidence first, then remediate.
Reflection
Question 1
Why is PowerShell especially useful for defensive inventory?
Question 2
What is the difference between Get, Where-Object, and Select-Object?
Question 3
Why can a large hardening script be risky during a competition?
Question 4
What should happen before and after a destructive PowerShell command?
Question 5
Why should empty output not automatically be treated as proof that nothing exists?
Question 6
What makes a PowerShell workflow defensive rather than blind automation?
PowerShell checklist
Start with read-only inventory commands.
Use Select-Object to keep output focused.
Use Where-Object to narrow large result sets.
Use Sort-Object when order matters.
Preserve important before-state evidence.
Target one confirmed object at a time.
Avoid broad wildcards and bulk disable/remove commands.
Re-run inspection commands after every high-impact change.
Test the related user, service, application, or network path.
Check Event Viewer or Get-WinEvent when a change causes errors.
Document what changed and why.
Next Windows lesson
Next, learn how to preserve and correlate Windows evidence before remediation so forensic questions can be answered with defensible facts instead of assumptions.