Master Checklists

windowsClient Windows Client Master Checklist

Windows 10/11 workstation hardening — accounts, policy, firewall, services, persistence hunting, and 25 sections deep.

0 / 0 checked

A comprehensive, competition-ready reference for hardening a Windows 7/8/8.1/10/11 client/workstation image in CyberPatriot. Merged and reorganized from "In-Depth Windows Checklist," "The Ultimate Windows Checklist," and an internal hardening script, plus general CyberPatriot community knowledge.

Golden Rule: The README on the Desktop (and any scenario/forensics documents) always overrides generic values in this checklist. If the README says a user must exist, must be an admin, or a service must run — that beats every table below. When in doubt: README > forensics questions > common sense > this document.

Do not blindly run every script/command in this document top to bottom. This is a reference, not a single automated fix-it script. Read the README first, understand what's on the box, then apply the relevant sections. Blind automation can delete a required user, kill a required service, or uninstall required software — all of which cost points.


Table of Contents#

0. How to Use This Document#

  • Read this whole table of contents once so you know what exists before you start clicking randomly.
  • Work as a team — divide sections (accounts, firewall/services, policy, malware/files) so nobody duplicates effort.
  • Re-check the scoring report after every few changes. If points drop, undo your last change first — you likely broke something required.
  • Keep a scratch notes file (Notepad on the desktop, or paper) listing: required users, required admins, required software, forensics answers, and anything the README calls out as "leave alone."

Tip: Screenshot or write down the starting scoring report state and the README text verbatim before you change anything. If the round disconnects or the VM has to be reset, you don't want to re-derive everything from memory.


1. Initial Recon & README#

  • Open the README on the Desktop (or wherever the competition places it) and read the entire thing before touching anything else.
  • Note the OS version (winver, or Settings > System > About) — Windows 7/8/8.1/10/11 behave differently for several steps below.
  • Identify and write down:
    • Authorized/required user accounts (and which ones must be Administrators)
    • Users who are explicitly not authorized (candidates for disabling)
    • Required installed software / services (don't remove or disable these!)
    • Any specific policy values the README overrides (e.g., "minimum password length must be 10" instead of a generic 14)
    • The competition's rules about internet access on the scored image (many rounds have no internet access once scoring starts — plan tool usage accordingly)
  • Open the scoring report (usually a browser bookmark, tray icon, or desktop shortcut) and note the starting score and any visible categories/vulnerabilities it lists.
  • Make a System Restore Point / snapshot now, before hardening, so you have a rollback point if something breaks badly.
powershell
# Quick system info dump
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
Get-ComputerInfo | Select WindowsProductName, WindowsVersion, OsHardwareAbstractionLayer
Expected result:
  • Two or three lines of text naming the OS (e.g. "OS Name: Microsoft Windows 10 Pro") and a build number.
  • Get-ComputerInfo prints a small object with WindowsProductName/WindowsVersion fields filled in.
If it fails:
  • systeminfo can take 10-20+ seconds to run (it's slow by design, not broken) — wait before assuming it hung.
  • If findstr returns nothing, the OS name string may be localized/different — just run bare systeminfo and read the top of the output.
  • If Get-ComputerInfo errors with "not recognized," you're on an old PowerShell version (pre-5.1, common on Windows 7) — use systeminfo alone instead, it's older and universally available.
cmd
:: Create a manual restore point (requires System Protection enabled - see Section 16-adjacent GUI steps)
wmic.exe /Namespace:\\root\default Path SystemRestore Call CreateRestorePoint "CP Baseline", 100, 7
Expected result:
  • Output ending in ReturnValue = 0; — that's success.
  • A new restore point appears in rstrui.exe (System Restore) afterward.
If it fails:
  • ReturnValue nonzero, or "System Restore is disabled on this drive" — System Protection is off for the C: drive.
  • Turn it on first: Control Panel → System → System Protection → Configure → Turn on system protection, then re-run the command.
  • If wmic itself says "not recognized" (Windows 11 24H2+ removed it by default), use the GUI instead (sysdm.cpl → System Protection tab → Create), or fall back to the hypervisor snapshot mentioned just above this section — that's the more reliable safety net anyway and doesn't depend on wmic existing.

Things to try / extra points#

Tip: Do the Forensics Questions before hardening. Many answers (a suspicious file's timestamp, a specific user's last logon, a weird registry value) can be erased by your own hardening work — e.g., deleting the malicious user before you've recorded their name, or wiping event logs before you've read the entry the question is asking about.

Tip: Take a "before" and "after" screenshot of the scoring report each session — this helps you see exactly which category(ies) changed and reverse-engineer what you fixed vs. broke.

  • Get-ComputerInfo, Get-HotFix, and Get-Service are useful quick first looks that don't change anything on the system yet — safe to run immediately.

  • If the README is a physical printout or a locked/read-only file, you can still grab a digital copy of anything on-disk from PowerShell to paste into your notes without retyping it:

powershell
Get-Content "C:\Users\Public\Desktop\README.txt" -ErrorAction SilentlyContinue
Get-ChildItem -Path "$env:USERPROFILE\Desktop","C:\Users\Public\Desktop" -Filter "*.txt","*.rtf","*.docx" -ErrorAction SilentlyContinue
Expected result:The README's text printed to console, or (second line) a file listing showing README/other text files on either desktop.
If it fails:
  • Empty output with no error usually just means the filename/extension doesn't match (.docx won't be caught by a .txt filter, and Filter only accepts one pattern at a time in older PowerShell — if the second command shows nothing, try each extension separately: -Filter "*.txt", then -Filter "*.docx").
  • If the path itself is wrong, run Get-ChildItem "$env:USERPROFILE\Desktop" with no filter to see everything that's actually there.
  • Check whoami /all early — it shows your current username, SID, group memberships, and privileges in one shot, which is useful both for confirming you're logged in as the account you think you are, and as a baseline to compare against later if you suspect your own session got tampered with.
cmd
whoami /all
Expected result:Three sections — User Information (your username + SID), Group Information (every group you belong to, with SIDs), and Privilege Information (a table of enabled/disabled privileges like SeDebugPrivilege).
If it fails:
  • "Access is denied" is unusual for this specific command since it reads your own token — if you see it, your session itself may be broken/restricted; log off and back on.
  • If group names show as raw SIDs instead of readable names, the machine can't resolve them locally (harmless, common on isolated/offline images) — the SIDs are still usable for comparison purposes.
  • Note the current date/time and timezone (Get-Date, or the clock in the taskbar) against what you'd expect — a wildly wrong system clock can itself be a scored vulnerability and will also make event log timestamps confusing later when you're doing forensics.

  • If your team has more than one person on this box, agree on a simple "claim" system before splitting up sections (e.g., a shared notes doc with initials next to each section) — working the same section twice wastes time, and working conflicting sections simultaneously (e.g., one person disables a service another person just re-enabled) wastes more.

Snapshot Checkpoint — take one right now, before anything else: CyberPatriot images almost always run as a local virtual machine (VirtualBox, VMware, or Hyper-V), and that hypervisor's snapshot feature is your real safety net — separate from, and more powerful than, Windows' own System Restore mentioned above. Take a full snapshot before you change a single setting: VirtualBox = Machine → Take Snapshot; VMware Workstation/Player = VM → Snapshot → Take Snapshot; Hyper-V = right-click the VM in Hyper-V Manager → Checkpoint. If you only take one snapshot all round, make it this one — it can undo a mistake even if Windows itself won't boot or log in anymore.


2. Forensics Questions#

CyberPatriot images frequently include short-answer questions (often as a text file or a form in the README/scoring interface) worth points independent of the scored checklist items. Common categories:

  • Identify malware / suspicious files — name of a file, its location, a hash, or which user's profile it lives in.
  • Log analysis — "Who logged on at X time?", "What account failed to log in the most?", "When was a specific service installed/started?"
  • Hidden/unauthorized user accounts — "How many local user accounts exist?", "Which account should not be here?"
  • File permissions / ownership — "Who has access to folder X?", "What permission does user Y have on file Z?"
  • System configuration facts — installed OS build, number of CPU cores, installed RAM, disk size, computer name, current IP configuration.
  • Policy state facts — "What is the current password policy minimum length?", "Is the firewall currently on?"
  • Media/prohibited file identification — "How many mp3 files are on this system?", "What is the name of the pirated software installed?"

Things to try / extra points#

powershell
# Who's logged on / logon history without touching anything
query user
Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624 or EventID=4625)]]" -MaxEvents 50 |
    Select TimeCreated, Id, Message

# List all local accounts and last logon (answers "how many accounts / who logged on last")
Get-LocalUser | Select Name, Enabled, LastLogon

# File count / size questions
Get-ChildItem -Path C:\Users -Recurse -Include *.mp3,*.mp4,*.avi,*.mkv -ErrorAction SilentlyContinue | Measure-Object

# Ownership / permissions on a specific file or folder
icacls "C:\path\to\file_or_folder"
Get-Acl "C:\path\to\file_or_folder" | Format-List
Expected result:
  • query user lists currently logged-on sessions (username, session name, state).
  • The Get-WinEvent line prints up to 50 rows of logon/logon-failure events with timestamps — Event ID 4624 = successful logon, 4625 = failed.
  • Get-LocalUser lists every local account with its enabled state and last logon time.
  • The Measure-Object line prints a Count (and if you add -Sum with -Property Length, a total size).
  • icacls/Get-Acl print the permission entries (account + rights) on that path.
If it fails:
  • query user saying "No User exists..." just means nobody else is logged on right now — not an error.
  • Get-WinEvent returning nothing usually means the Security log's audit policy isn't logging logon events yet (fix that first in Section 5, then re-run) or the log has rolled over past your event — check log size/retention via Get-WinEvent -ListLog Security.
  • Get-LocalUser showing blank LastLogon for an account just means it has genuinely never logged on.
  • Get-ChildItem -Recurse over all of C:\Users can take a couple of minutes on a full disk — that's normal, not a hang; -ErrorAction SilentlyContinue is already suppressing the inevitable "access denied" noise from other users' protected folders.
  • icacls/Get-Acl on a path that doesn't exist just errors "cannot find path" — double check the exact path/spelling first with Test-Path.

Tip: If a forensics question asks about something you're about to fix (a malicious user, a bad registry key, a rogue file), answer the question first, or at minimum copy the exact name/path/value into your notes before remediating.

Tip: "Number of administrator accounts," "number of user accounts," and "which services are running" are extremely common forensic-style asks — the commands in Section 3 and Section 9 answer these directly and quickly.

Answer forensics questions using facts you can verify with a command shown above — don't guess. If unsure, re-run the command rather than trusting a earlier note that may now be stale.

  • For "which files were recently modified/created" style questions, sort by timestamp instead of scrolling folders by eye:
powershell
Get-ChildItem -Path C:\Users -Recurse -File -ErrorAction SilentlyContinue |
    Sort-Object LastWriteTime -Descending | Select-Object -First 25 FullName, LastWriteTime
Expected result:A table of the 25 most-recently-modified files anywhere under C:\Users, newest first.
If it fails:
  • Takes a while on a full profile — that's expected, not a hang.
  • If you only care about one user's files, narrow the -Path to that profile folder to speed it up.
  • An empty result with no error means C:\Users itself is unreadable from your account — confirm you're running as Administrator.
  • For "what is this file's hash / can you prove it's the same file" style questions, generate a hash rather than eyeballing size/name:
powershell
Get-FileHash -Algorithm SHA256 "C:\path\to\file.exe"
Expected result:One line with Algorithm, Hash (a 64-character hex string for SHA256), and Path.
If it fails:
  • "Cannot find path" — check the exact path/spelling with Test-Path "C:\path\to\file.exe" first (tab-completion in the console helps avoid typos).
  • If you need to match a hash given in MD5 instead of SHA256, add -Algorithm MD5 (or SHA1) — the algorithm must match what the question/answer key used or the hashes will never agree even for identical files.
  • For "what did this user open/run recently" style questions, Windows keeps Most-Recently-Used (MRU) lists per user — useful even if the file itself has since been deleted:
powershell
Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs" -ErrorAction SilentlyContinue
Get-ChildItem "$env:APPDATA\Microsoft\Windows\Recent" -ErrorAction SilentlyContinue | Select Name, LastWriteTime
Expected result:The first line prints raw binary-ish registry property data (not very readable directly — the useful part is the property names, which are often filenames); the second lists shortcut (.lnk) files in the Recent folder with real filenames and timestamps — usually the more readable of the two.
If it fails:
  • HKCU only shows the currently logged-on user's MRU — to check a different user's history you must load their hive first (reg load HKU\TempHive C:\Users\<user>\NTUSER.DAT, browse under HKU:\TempHive\..., then reg unload HKU\TempHive when done) or log on as that user directly.
  • An empty Recent folder just means nothing's been opened recently, or the user cleared it — not an error.
  • For "how many programs are installed" style questions, count rather than scroll-and-tally in Control Panel:
powershell
(Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue | Where-Object DisplayName).Count
Expected result:A single integer.
If it fails:
  • The number looks too low compared to Control Panel's "Programs and Features" — 64-bit Windows keeps a separate 32-bit uninstall key; also check HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* and add its count, and HKCU:\...\Uninstall\* for per-user installs.
  • If it returns 0, confirm you didn't typo the registry path — a bad path silently returns nothing rather than erroring.
  • For network-configuration questions ("what's this machine's IP/MAC/DNS server"), ipconfig /all gives everything in one place rather than hunting through several GUI panes:
cmd
ipconfig /all
Expected result:A block per network adapter showing IPv4/IPv6 address, subnet mask, default gateway, DNS servers, and MAC ("Physical Address").
If it fails:
  • Adapter shows "Media disconnected" — that NIC has no cable/link, look at the other listed adapters instead.
  • If nothing at all is listed, the machine may have all adapters disabled — check Get-NetAdapter (PowerShell) to see adapter state regardless of connection.

Tip: If a question's answer depends on something you might change later (an IP address, a running process, a registry value), take the habit of writing the exact command output into your notes verbatim rather than paraphrasing — a paraphrase like "it was some Python thing" is much less useful when you go to fill in the answer sheet than a copy-pasted process name and path.

Encoded / Obfuscated Data#

A recurring forensics pattern — a real CyberPatriot practice round included a message on the desktop encoded in base64 — is a text file, filename, or note that isn't in plain English because it's been encoded or lightly "encrypted." Recognize the pattern first, then decode:

Looks like Likely encoding Tell
SGVsbG8gV29ybGQh Base64 Only letters/digits/+//, often padded with = or == at the end, length a multiple of 4
48656c6c6f20576f726c6421 Hex Only 0-9 and a-f, always an even number of characters
01001000 01100101 Binary Only 0s and 1s, usually in 8-character groups
Uryyb Jbeyq ROT13 / Caesar shift Looks like garbled English but word lengths, spacing, and punctuation all match real text
Hello%20World%21 URL encoding % followed by two hex digits
powershell
# Base64 decode — works fully offline, no internet needed
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("SGVsbG8gV29ybGQh"))

# Base64 decode from/to a file using certutil (built into every Windows install, no PowerShell needed)
certutil -decode input.b64 output.txt

# Base64 ENCODE (useful if a question asks you to encode an answer, not just decode one)
[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("plain text here"))

# Hex decode
-join (("48656c6c6f20576f726c6421") -split '(?<=\G..)(?!$)' | ForEach-Object { [char][Convert]::ToInt32($_,16) })

# ROT13 decode (self-inverse — running it again re-encodes)
function Decode-Rot13($s) {
    -join ($s.ToCharArray() | ForEach-Object {
        if ($_ -cmatch '[a-z]') { [char]((([int][char]$_ - 97 + 13) % 26) + 97) }
        elseif ($_ -cmatch '[A-Z]') { [char]((([int][char]$_ - 65 + 13) % 26) + 65) }
        else { $_ }
    })
}
Decode-Rot13 "Uryyb Jbeyq"
Expected result:
  • Each line prints the decoded/encoded plain text directly to the console (e.g. "Hello World!" for the base64 example).
  • certutil -decode prints CertUtil: -decode command completed successfully. and writes output.txt to the current directory.
If it fails:
  • FromBase64String throwing "Invalid length for a Base-64 char array" means the string isn't valid base64 (wrong data, or you copied it with extra whitespace/line breaks — strip those first: $s -replace '\s','').
  • certutil -decode failing with a similar complaint has the same cause.
  • The hex-decode one-liner throws if the string has an odd number of characters or non-hex characters — recheck you copied the whole string.
  • If Decode-Rot13 prints gibberish instead of readable English, you're not actually looking at ROT13 (try comparing letter/word patterns against the table above again, or just try ROT13 on it anyway since it's low-cost to test and self-inverse).
  • Where to look for encoded content: desktop .txt/.docx files with odd names, a suspiciously long "comment" or "description" field, image file metadata/EXIF (Get-ItemProperty won't show this — use the file's Properties → Details tab in Explorer), browser bookmarks/saved pages, and recently-modified files (see the timestamp-sort command above).
  • Steganography (data hidden inside an image) is rarer but does show up — a loose tell is an image file that's unusually large for what it visually shows. Check Properties → Details for hidden metadata first; dedicated stego-detection tools generally aren't pre-installed and may not be available if the round is offline, so don't sink much time here unless a question explicitly points at a specific image.
  • If you're not sure which encoding you're looking at, try base64 first — it's by far the most common in practice, and a failed decode attempt is instant feedback that you're looking at something else.

3. User & Group Account Auditing#

GUI Method#

  • Open Start → type lusrmgr.msc (or via StartRunMMCFileAdd/Remove Snap-inLocal Users and Groups on editions without lusrmgr.msc, e.g. Home editions).
  • Under Users, cross-reference every listed account against the README's authorized list.
    • Never delete an account you're unsure about — disable it instead. Deleted local accounts (and their SIDs/profile data) generally cannot be un-deleted.
    • Disable any account not listed as authorized (right-click → Disable Account).
    • Set/confirm a strong password on every account that should remain enabled.
    • Confirm the Guest account is disabled.
    • Rename the built-in Administrator account unless you are currently logged on as it — if you rename the account you're using, you may lock yourself out mid-session on some builds. If the README specifically says to leave it named "Administrator," follow the README.
  • Under Groups, open Administrators and confirm membership matches exactly what the README authorizes. Remove (don't delete the underlying account — just remove group membership) any unauthorized member from the Administrators group.
  • Check other privileged/interesting groups too: Remote Desktop Users, Backup Operators, Power Users.

Command-Line Method (fast triage)#

cmd
net user
net user <username>
net localgroup administrators
net localgroup "Remote Desktop Users"
Expected result:
  • net user (no args) lists all local account names in columns.
  • net user <username> shows that account's full detail (full name, enabled state, password last set, group memberships, etc).
  • net localgroup <name> lists the members of that group.
If it fails:"The user name could not be found" means a typo in <username> — re-run bare net user to get exact names/casing. "The group name could not be found" for Remote Desktop Users usually means it genuinely doesn't exist on this SKU (rare) or you mistyped the quotes — group names with spaces need the quotes exactly as shown.
powershell
Get-LocalUser | Select-Object Name, Enabled, AccountExpires, LastLogon, PasswordRequired, PasswordLastSet
Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember -Group "Remote Desktop Users"
wmic useraccount get name,sid,disabled,lockout
Expected result:A table of all local users with the requested columns; then two membership lists; then a wmic table of name/SID/disabled/lockout flags.
If it fails:
  • Get-LocalUser/Get-LocalGroupMember say "not recognized" on some older Windows 7/8 boxes — these cmdlets need the Microsoft.PowerShell.LocalAccounts module (PowerShell 5.1+); fall back to the net user/net localgroup commands above instead, they're older and always available.
  • wmic itself is removed by default starting Windows 11 24H2 — if "not recognized," use Get-CimInstance Win32_UserAccount | Select Name,SID,Disabled,Lockout as the direct PowerShell equivalent.
cmd
:: Disable (do NOT delete) unauthorized default/unknown accounts
net user Guest /active:no
net user DefaultAccount /active:no
net user <unauthorized_user> /active:no

:: Set a strong password for a required user
net user <username> "NewC0mplex!Passw0rd_2026"

:: Rename the built-in Administrator (only if not currently using it / README allows)
wmic useraccount where name='Administrator' call rename name='RenamedAdmin'
Expected result:Each net user ... /active:no prints "The command completed successfully." Re-run net user <name> afterward and confirm "Account active" now says No. The password-set command prints the same success line; the rename command's success shows as ReturnValue = 0; in its output block.
If it fails:
  • "Access is denied" on any of these means your shell isn't elevated — right-click Command Prompt/PowerShell → Run as administrator and retry. "System error 2224 has occurred.
  • The password does not meet the password policy requirements" means your chosen password fails the complexity/length policy you (or the README) set — pick a longer password mixing case, digits, and symbols.
  • Don't disable an account you're not certain is unauthorized — cross-check the README's list again first.
powershell
# Same rename via PowerShell/WMI object
(Get-WmiObject -Class Win32_UserAccount -Filter "Name='Administrator'").Rename("RenamedAdmin")

# Remove a user from Administrators without touching the account itself
Remove-LocalGroupMember -Group "Administrators" -Member "SuspiciousUser"
Expected result:No output on success (PowerShell cmdlets here are silent by default when they succeed) — verify with net user RenamedAdmin and Get-LocalGroupMember -Group Administrators afterward.
If it fails:
  • Get-WmiObject is deprecated/removed in PowerShell 7+ ("not recognized") — use the wmic or net user rename method above instead on newer systems, or Get-CimInstance as the modern replacement.
  • Remove-LocalGroupMember erroring "member does not exist in this group" just means that account wasn't actually in Administrators — double-check membership first with Get-LocalGroupMember -Group Administrators rather than assuming the removal command's phrasing is wrong.

Things to try / extra points#

Tip: net user and Get-LocalUser sometimes disagree with what Control Panel shows for accounts hidden from the welcome/login screen via the registry SpecialAccounts\UserList key. Always trust the command-line/registry truth over the GUI login screen.

powershell
# Reveal accounts hidden from the Windows logon screen
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" -ErrorAction SilentlyContinue
  • Check net accounts to see the currently active password/lockout policy in one shot — useful both for forensics questions and for verifying your policy changes actually applied:
cmd
net accounts
  • Compare Get-LocalUser output against the SAM registry hive count if you suspect an account is being hidden from normal enumeration (rare, but seen in harder images):
powershell
Get-ChildItem "HKLM:\SAM\SAM\Domains\Account\Users\Names" -ErrorAction SilentlyContinue

This key is normally locked down to SYSTEM; if you can't read it as Administrator, that itself can be a forensics-question answer ("why can't you view this key").

  • Double- and triple-check before deleting: if you truly must recreate a required user because it was wrongly deleted, use net user <name> <password> /add and re-add to the correct groups — but understand the new SID means file ownership/permissions tied to the old account are gone. Prevention (disable, don't delete) is far better than recovery.

  • Check for accounts where the password is set to never expire — a common lingering-access trick, especially on an account that also has no lockout/complexity applied to it:

powershell
Get-LocalUser | Select Name, Enabled, PasswordExpires, PasswordLastSet
Get-CimInstance Win32_UserAccount | Where-Object { $_.PasswordExpires -eq $false } | Select Name, Disabled
  • List every local group, not just Administrators — a vulnerable image can plant an unauthorized account in a less-obvious group (Backup Operators and Power Users both carry real privileges most competitors forget to check):
powershell
Get-LocalGroup
net localgroup
powershell
foreach ($g in (Get-LocalGroup).Name) { Write-Host "`n== $g ==" ; Get-LocalGroupMember -Group $g -ErrorAction SilentlyContinue }
  • On Windows 10/11, netplwiz (Start → Run → netplwiz) is a faster GUI alternative to lusrmgr.msc for a quick pass on account list + group membership + "require password to log on," if the full Local Users and Groups snap-in feels slow to navigate.

  • Verify a rename or password change actually stuck by reading it back immediately rather than assuming the dialog box succeeding means it worked:

powershell
Get-LocalUser | Select Name, Enabled, PasswordLastSet

Snapshot Checkpoint: You're about to start mass-editing Local Security Policy (Sections 4–6) using secpol.msc and secedit import/export. A bad secedit import or an overly aggressive lockout/rights change can lock accounts out or break logon entirely, and it's not always obvious which line caused it. Take a fresh snapshot now if you don't already have one from the last few minutes — it's much faster than troubleshooting a locked-out box afterward.


4. Password & Account Lockout Policy#

Configure via secpol.mscAccount PoliciesPassword Policy / Account Lockout Policy, or via net accounts, or via secedit export/import for scripted changes.

Setting Suggested Value*
Enforce Password History 24 (source table used 8; many CyberPatriot guides recommend higher, e.g. 24)
Maximum Password Age 30 days (or per README; do not set to 0/never)
Minimum Password Age 1 day
Minimum Password Length 8–14 characters (higher is generally safer; follow README if specified)
Password Must Meet Complexity Requirements Enabled
Store Passwords Using Reversible Encryption Disabled
Account Lockout Duration 15–30 minutes
Account Lockout Threshold 3–5 invalid attempts
Reset Account Lockout Counter After 10–15 minutes

*Two sources disagreed slightly on exact numbers (e.g., 8 vs. 24 for history, 7 vs. 5 for lockout threshold). There is no single "official" CyberPatriot number — use reasonable, defensible values in this range unless the README specifies exact numbers, in which case follow the README exactly.

GUI Method#

  • secpol.mscSecurity SettingsAccount PoliciesPassword Policy — set each value above.
  • Account PoliciesAccount Lockout Policy — set each value above.

Command-Line / Scripted Method#

  • Step 1 — check current policy. This is read-only and safe to run any time:
cmd
net accounts
Expected result:A short list of current policy values (Force user logoff, password age min/max, min password length, lockout threshold, etc.) as currently applied.
If it fails:This command essentially never fails on a working system; if it prints nothing useful, confirm you're not accidentally running it as a non-elevated/restricted user.

The secedit export/edit/import pattern below does the same job as the GUI method above, but scripted — useful if you're applying the same values across multiple machines, or just prefer text-editing to clicking through dialogs. It's four distinct steps; don't skip the "verify" step at the end.

  • Step 2 — export the current policy to a text file. This creates C:\secpol.cfg, a plain-text snapshot of every current Local Security Policy setting:
cmd
secedit /export /cfg C:\secpol.cfg
Expected result:The task has completed successfully. and C:\secpol.cfg now exists (confirm with dir C:\secpol.cfg).
If it fails:"Access is denied" writing to C:\ — some lockdown images restrict writing to the drive root; export to C:\Users\Public\secpol.cfg instead (adjust every later step's path to match). "The task has completed with one or more errors" alongside a mostly-fine-looking file is usually still safe to proceed with — open the file and confirm the [System Access] section is present and readable before continuing.
  • Step 3 — edit the exported file. Open C:\secpol.cfg in Notepad, find the [System Access] section, and change (or add, if missing) these specific lines to the values below — leave every other line in the file untouched:
ini
MinimumPasswordAge = 1
MaximumPasswordAge = 30
MinimumPasswordLength = 14
PasswordComplexity = 1
PasswordHistorySize = 24
LockoutBadCount = 5
ResetLockoutCount = 15
LockoutDuration = 30
RequireLogonToChangePassword = 1

Save the file when done. Expected result: Notepad saves without complaint; the file still opens and looks like normal .ini-style text. If it fails: If Notepad refuses to save citing "Access is denied," you edited a copy outside your own write permissions (e.g. C:\ root with a restrictive image) — save as a copy to C:\Users\Public\ instead and use that path in Step 4. If a line you need (e.g. PasswordHistorySize) simply doesn't exist in the exported file, add it as a new line under [System Access] exactly as shown — secedit accepts added lines as long as they're valid keys in the right section.

  • Step 4 — re-import the edited file to apply it. This is the step that actually changes the running system's policy:
cmd
secedit /configure /db C:\Windows\security\local.sdb /cfg C:\secpol.cfg /areas SECURITYPOLICY
Expected result:The task has completed successfully. A log is written to %windir%\security\logs\scesrv.log if you need to double check details.
If it fails:
  • "The task has completed with one or more errors" here (unlike the export step) usually DOES mean a line in your edited .cfg is malformed — open scesrv.log (path above) and look for the specific line/key it choked on; a common cause is a typo'd key name or a value outside the valid range (e.g. MinimumPasswordLength = 30 — max is 14 on most builds).
  • Fix the offending line in secpol.cfg and re-run this command; it's safe to re-run.
  • Step 5 — verify it took effect. Re-run net accounts and confirm the numbers match what you just set — secedit fails silently on a malformed line, so this step isn't optional:
cmd
net accounts
Expected result:The printed numbers now match what you set in secpol.cfg (e.g. minimum password length shows 14, not the old default).
If it fails:Values unchanged after a "successful" import means one of two things: either the /db path you configured against isn't the one actually governing local policy (rare — stick to the exact path shown), or a domain GPO is overriding your local setting (see the gpresult /r tip further down this section) — a domain-joined machine's local policy can be silently beaten by Group Policy, and no error will tell you that's happening.

Prefer to skip manual Notepad editing? The block below automates Steps 2–4 as one script — same net effect, no Notepad required:

powershell
secedit /export /cfg C:\secpol.cfg
(Get-Content C:\secpol.cfg) | ForEach-Object {
    if ($_ -match "MinimumPasswordAge")            { "MinimumPasswordAge = 1" }
    elseif ($_ -match "MaximumPasswordAge")        { "MaximumPasswordAge = 30" }
    elseif ($_ -match "MinimumPasswordLength")     { "MinimumPasswordLength = 14" }
    elseif ($_ -match "PasswordComplexity")        { "PasswordComplexity = 1" }
    elseif ($_ -match "PasswordHistorySize")       { "PasswordHistorySize = 24" }
    elseif ($_ -match "LockoutBadCount")           { "LockoutBadCount = 5" }
    elseif ($_ -match "ResetLockoutCount")         { "ResetLockoutCount = 15" }
    elseif ($_ -match "LockoutDuration")           { "LockoutDuration = 30" }
    elseif ($_ -match "RequireLogonToChangePassword") { "RequireLogonToChangePassword = 1" }
    else { $_ }
} | Set-Content C:\secpol.cfg
secedit /configure /db C:\Windows\security\local.sdb /cfg C:\secpol.cfg /areas SECURITYPOLICY
net accounts
Expected result:Same end state as the manual Steps 2-5 above — net accounts at the end prints the new values.
If it fails:
  • If none of the -match conditions fire (values in the file look untouched), the exported .cfg may use different casing or spacing than the -match patterns expect on this Windows build — open C:\secpol.cfg in Notepad first to confirm the exact key names, and adjust the -match strings to match exactly if needed.
  • Set-Content failing with "Access is denied" has the same fix as the manual Step 3 note above — redirect the working copy to C:\Users\Public\.

Things to try / extra points#

Tip: Password Policy and Account Lockout Policy are among the most reliably scored, highest-yield items in CyberPatriot — they're simple checkboxes/numbers for the engine to verify and are almost always tested. Do this section early and don't skip it.

Tip: After using secedit, immediately re-run net accounts to confirm the values actually took — secedit import syntax errors fail silently in some Windows builds.

  • "Limit local account use of blank passwords to console logon only" should be Enabled — check under Security Options (Section 6).
  • If a user has no password and can't have one set for scenario reasons, that specific policy interaction is a classic trap — verify with net user <name> that Password Required is Yes.

CIS Benchmark cross-reference: The value ranges in the table above align closely with the CIS Microsoft Windows 10/11 Benchmark, Level 1 guidance for Account Policies — the published CIS baseline uses the same shape (password history in the 20s, minimum length around 14 characters, complexity enabled, lockout threshold in the low single digits). If you have access to the free CIS Benchmark PDF (published by the Center for Internet Security), it's a legitimate, citable source if a judge or mentor asks where a specific number came from, rather than "a checklist said so."

  • CIS Level 1 also calls out "Store passwords using reversible encryption" (must be Disabled — already reflected in the table above) as a setting worth double-checking specifically; it's easy to overlook because it defaults correctly on most images, but a vulnerable image may have flipped it.

  • If secpol.msc won't open or its Account Policies node looks empty/greyed-out (seen occasionally on Home editions or oddly-configured images), fall back to the net accounts command-line method above — it reads and can partially set the same underlying policy without the snap-in.

  • Double-check the policy actually applies locally and isn't being silently overridden by a domain GPO if this machine is domain-joined — gpresult /r (or the fuller /z dump discussed in Section 24) will show whether "Local Group Policy" or a domain policy actually won for each setting.

  • Each individual user account also has its own per-account password flags that override the domain-wide/local policy for that one account — worth a quick sanity check if one specific account seems immune to your policy changes:

powershell
Get-CimInstance Win32_UserAccount | Select Name, PasswordRequired, PasswordChangeable, PasswordExpires
Expected result:A table, one row per local account, showing whether each has per-account password flags overriding the policy.
If it fails:Slow to return on a domain-joined machine (it's also enumerating domain accounts) — that's normal, wait it out, or add -Filter "LocalAccount=True" to restrict to local accounts only and speed it up.

5. Local Security Policy — Audit Policy & User Rights Assignment#

Audit Policy (secpol.msc → Local Policies → Audit Policy)#

  • Set every audit category to Success and Failure unless the README says otherwise. This is explicitly called out in the source checklist as a category worth extra attention.
cmd
:: Enable auditing on every legacy category, success+failure
auditpol /set /category:"Account Logon" /success:enable /failure:enable
auditpol /set /category:"Account Management" /success:enable /failure:enable
auditpol /set /category:"Detailed Tracking" /success:enable /failure:enable
auditpol /set /category:"DS Access" /success:enable /failure:enable
auditpol /set /category:"Logon/Logoff" /success:enable /failure:enable
auditpol /set /category:"Object Access" /success:enable /failure:enable
auditpol /set /category:"Policy Change" /success:enable /failure:enable
auditpol /set /category:"Privilege Use" /success:enable /failure:enable
auditpol /set /category:"System" /success:enable /failure:enable

:: Or, blanket enable everything at once
auditpol /set /category:* /success:enable /failure:enable
Expected result:Each line prints The command was successfully executed.
If it fails:"The category name is unrecognized" for a specific category name — category names are version/locale-sensitive; run auditpol /list /category:* first to get the exact names this build recognizes, and use those verbatim instead of retyping from memory. "Access is denied" means the shell isn't elevated — re-open as Administrator.
powershell
# Review current audit policy state
auditpol /get /category:*
Expected result:A long table listing every subcategory with its current setting: No Auditing, Success, Failure, or Success and Failure.
If it fails:This is read-only and essentially can't fail short of "access denied" for a non-elevated shell — if the list looks unexpectedly short/incomplete, pipe it to a file (auditpol /get /category:* > C:\audit_state.txt) and open that in Notepad rather than scrolling a truncated console buffer.

User Rights Assignment#

Recommended baseline (adjust to README; the general rule is: sensitive rights go to Administrators only, and dangerous rights should be assigned to No One unless specifically required):

User Right Recommended Assignment
Access Credential Manager as a trusted caller Administrators
Access this computer from the network (No unauthorized accounts; keep Administrators/authenticated users only as required)
Act as part of the operating system No One
Add workstations to domain No One
Adjust memory quotas for a process No One (or SYSTEM/service accounts only)
Allow log on locally Administrators (+ authorized standard users per README)
Allow log on through Remote Desktop Services No One (unless RDP required)
Back up files and directories Administrators
Bypass traverse checking No One (leave default groups like LOCAL SERVICE/NETWORK SERVICE alone)
Change the system time No One (or Administrators only)
Change the time zone No One (or Administrators only)
Create a pagefile No One
Create a token object Administrators (rarely assigned at all)
Create global objects Administrators
Create permanent shared objects No One
Create symbolic links Administrators
Debug programs No One
Deny access to this computer from the network No One (empty unless blocking a specific bad account)
Deny log on as a batch job No One
Deny log on as a service No One
Deny log on locally No One
Deny log on through Remote Desktop Services No One
Enable computer and user accounts to be trusted for delegation Administrators
Force shutdown from a remote system No One
Generate security audits No One
Impersonate a client after authentication No One (leave built-in service accounts alone)
Increase a process working set No One
Increase scheduling priority Administrators
Load and unload device drivers Administrators
Lock pages in memory Administrators
Log on as a batch job No One
Log on as a service No One
Manage auditing and security log Administrators
Modify an object label Administrators
Modify firmware environment values Administrators
Perform volume maintenance tasks Administrators
Profile single process Administrators
Profile system performance Administrators
Remove computer from docking station Administrators
Replace a process level token Administrators
Restore files and directories Administrators
Shut down the system Administrators
Synchronize directory service data Administrators
Take ownership of files or other objects Administrators

Do not remove built-in NETWORK SERVICE / LOCAL SERVICE from rights they hold by default, even if the field appears to show "No One" as your target value — that guidance applies to user accounts, not the built-in service identities. Removing those breaks core OS functionality.

Command-Line Method#

cmd
:: Export the current user-rights assignment for review or forensic-question answers
secedit /export /cfg C:\rights.txt /areas USER_RIGHTS
Expected result:Prints The task has completed successfully. and creates C:\rights.txt — a plain-text INF-style file with a [Privilege Rights] section listing each Se*Right/Se*Privilege and the SIDs assigned to it (e.g. SeDebugPrivilege = *S-1-5-32-544 for Administrators).
If it fails:
  • "Access is denied" means the prompt isn't elevated — reopen cmd/PowerShell as Administrator.
  • If the file already exists and looks stale, delete it first or change the output path; secedit /export silently overwrites, so a stale file is usually a sign you ran it before a change took effect rather than a real error.
powershell
Select-String -Path C:\rights.txt -Pattern "SeDebugPrivilege","SeTakeOwnershipPrivilege","SeRemoteInteractiveLogonRight","SeNetworkLogonRight"
Expected result:
  • One matching line per right that's actually assigned to someone, in the form SeDebugPrivilege = *S-1-5-32-544 (SIDs, not names — S-1-5-32-544 is the well-known SID for Administrators).
  • A right with no one assigned won't appear at all.
If it fails:
  • No output at all means either the right has zero assignees (fine, that's "No One") or C:\rights.txt doesn't exist yet — run the secedit /export command above first.
  • To translate an unfamiliar SID to a username, use wmic useraccount where sid='S-1-5-...' get name or Get-CimInstance Win32_UserAccount -Filter "SID='S-1-5-...'".

Things to try / extra points#

Tip (high yield): Watch for SeRemoteInteractiveLogonRight (Allow log on through RDS) and SeDenyRemoteInteractiveLogonRight — these directly gate who can RDP in, and vulnerable images commonly add an unauthorized account here.

Tip: SeDebugPrivilege and SeTakeOwnershipPrivilege granted to a non-admin standard user is a classic privilege-escalation plant — check these first if a forensics question mentions "elevated privileges" or "unusual access."

CIS Benchmark cross-reference: CIS's Advanced Audit Policy Configuration guidance (a more granular replacement for the legacy 9-category Audit Policy used above) recommends specific Success/Failure settings per subcategory rather than one blanket "enable everything" — some subcategories are recommended Failure-only specifically to cut down on log noise. The blanket auditpol /set /category:* /success:enable /failure:enable command in this section is a reasonable, safe superset for a competition round, but if you have time, opening secpol.msc → Advanced Audit Policy Configuration and reviewing the roughly 50 individual subcategories against the CIS per-subcategory table is a legitimate "extra credit" pass.

  • CIS Level 1 User Rights Assignment guidance also explicitly calls out adding Guest to the "Deny access to this computer from the network," "Deny log on as a batch job," "Deny log on as a service," and "Deny log on locally" rights (not just leaving them at "No One") — an enabled Guest account with logon rights left unrestricted is a classic combination vulnerability. Cross-check this if your image has the Guest account enabled for any reason.

  • Audit MPSSVC Rule-Level Policy Change — a CIS Level 1 Advanced Audit Policy subcategory that's easy to overlook because it's not one of the "big" categories, but it specifically logs changes to Windows Firewall rules (MPSSVC is the firewall service). Since firewall tampering is one of the most common things a scenario plants, having this enabled means you get a log trail if a rule gets silently added/removed after your initial pass:

    cmd
    auditpol /set /subcategory:"MPSSVC Rule-Level Policy Change" /success:enable /failure:enable
    
    Expected result:The command was successfully executed.
    If it fails:"The subcategory name is unrecognized" — the exact wording is version-sensitive; run auditpol /list /subcategory:"Policy Change" to see the exact subcategory names this build recognizes and copy the spelling verbatim (quotes and all).
  • auditpol /get /category:* is hard to read as a wall of console text — add /r for CSV-formatted output, which pastes cleanly into a spreadsheet or notes doc if you want to review all ~50 subcategories at once:

cmd
auditpol /get /category:* /r
Expected result:Comma-separated output with a header row (Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting) followed by one row per subcategory — pastes cleanly into Excel/Sheets via copy-paste or auditpol /get /category:* /r > C:\audit.csv then opening the CSV.
If it fails:Output looks identical to the non-/r version in a narrow console window — that's just word-wrap, not a real failure; redirect to a file and open it in Notepad/Excel to see the true CSV structure. "Access is denied" means the shell isn't elevated.
  • Back up your audit policy configuration once you've got it the way you want, so a later mistake (or a teammate accidentally re-running an old command) doesn't quietly undo your work:
cmd
auditpol /backup /file:C:\auditpolicy_backup.csv
:: To restore later if needed:
auditpol /restore /file:C:\auditpolicy_backup.csv
Expected result:
  • /backup prints The command was successfully executed. and creates the CSV file (despite the name, it's actually a full binary-safe audit policy dump, not a simple readable CSV — don't try to hand-edit it).
  • /restore re-applies whatever state was captured, also printing success.
If it fails:
  • "Access is denied" needs an elevated prompt.
  • If /restore seems to do nothing, verify you're restoring the right file and that it was actually written by /backup on this same OS version — an audit policy backup isn't reliably portable between different Windows builds.
  • If you'd rather review Audit Policy visually instead of parsing command output, secpol.msc → Security Settings → Advanced Audit Policy Configuration → System Audit Policies shows every subcategory with checkboxes for Success/Failure — a good option when double-checking a specific category rather than dumping everything.

6. Local Security Policy — Security Options#

secpol.mscLocal PoliciesSecurity Options.

Setting Recommended Value
Accounts: Administrator account status Enabled only if you are using it (per README); otherwise leave as configured by README
Accounts: Guest account status Disabled
Accounts: Limit local account use of blank passwords to console logon only Enabled
Accounts: Rename administrator account Rename it (unless currently logged on as it / README says not to)
Accounts: Rename guest account Rename it
Audit: Audit the access of global system objects Enabled
Audit: Audit the use of Backup and Restore privilege Enabled
Audit: Force audit policy subcategory settings... Enabled
Audit: Shut down system immediately if unable to log security audits Disabled
Devices: Allow undock without having to log on Disabled
Devices: Allowed to format and eject removable media Administrators
Devices: Prevent users from installing printer drivers Enabled
Devices: Restrict CD-ROM access to locally logged-on user only Enabled
Devices: Restrict floppy access to locally logged-on user only Enabled
Domain member: Digitally encrypt or sign secure channel data (always) Enabled
Domain member: Disable machine account password changes Disabled (leave changes allowed)
Domain member: Maximum machine account password age 30 days (or 13-day style hardened value if scenario calls for it)
Domain member: Require strong (Windows 2000 or later) session key Enabled
Interactive logon: Display user information when session is locked Do not display user information
Interactive logon: Do not display last user name Enabled
Interactive logon: Do not require CTRL+ALT+DEL Disabled
Interactive logon: Message text/title for users attempting to log on Leave blank unless README specifies a banner
Interactive logon: Number of previous logons to cache 0 (or 1–2 if offline domain logon is required)
Interactive logon: Prompt user to change password before expiration 5–14 days
Interactive logon: Require smart card Disabled (unless scenario requires)
Interactive logon: Smart card removal behavior Lock Workstation / No Action per scenario
Microsoft network client: Digitally sign communications (always) Enabled (or Disabled if it breaks required functionality — verify)
Microsoft network client: Send unencrypted password to third-party SMB servers Disabled
Microsoft network server: Amount of idle time required before suspending session 15–45 minutes
Microsoft network server: Digitally sign communications (always) Enabled
Microsoft network server: Disconnect clients when logon hours expire Enabled
Network access: Allow anonymous SID/Name translation Disabled
Network access: Do not allow anonymous enumeration of SAM accounts Enabled
Network access: Do not allow anonymous enumeration of SAM accounts and shares Enabled
Network access: Do not allow storage of passwords/credentials for network auth Enabled
Network access: Let Everyone permissions apply to anonymous users Disabled
Network access: Named pipes that can be accessed anonymously Clear/empty
Network access: Remotely accessible registry paths (and paths and sub-paths) Remove all/unnecessary entries
Network access: Restrict anonymous access to Named Pipes and Shares Enabled
Network access: Shares that can be accessed anonymously Clear/empty
Network access: Sharing and security model for local accounts Classic
Network security: Allow Local System to use computer identity for NTLM Disabled (per scenario)
Network security: Do not store LAN Manager hash value on next password change Enabled
Network security: LAN Manager authentication level Send NTLMv2 response only, refuse LM & NTLM
Network security: LDAP client signing requirements Require signing
Shutdown: Allow system to be shut down without having to log on Disabled
System objects: Require case insensitivity for non-Windows subsystems Enabled
User Account Control: Admin Approval Mode for the Built-in Administrator account Enabled
User Account Control: Behavior of the elevation prompt for administrators Prompt for consent on the secure desktop
User Account Control: Behavior of the elevation prompt for standard users Prompt for credentials on the secure desktop
User Account Control: Detect application installations and prompt for elevation Enabled
User Account Control: Only elevate UIAccess applications installed in secure locations Enabled
User Account Control: Run all administrators in Admin Approval Mode Enabled
User Account Control: Switch to the secure desktop when prompting for elevation Enabled
User Account Control: Virtualize file and registry write failures to per-user locations Enabled

If a listed policy isn't present on your specific image (varies by SKU/edition), skip it — use judgment.

Things to try / extra points#

Tip (high yield): Network access: Do not allow anonymous enumeration of SAM accounts (and shares) and LAN Manager authentication level are frequently included in scored checklists because they map directly to well-known enumeration/relay attacks — prioritize these.

Tip: Many of these Security Options can also be read/set via the registry directly if secpol.msc is being uncooperative (e.g., missing snap-in on Home editions) — search HKLM:\SYSTEM\CurrentControlSet\Control\Lsa for LAN Manager/anonymous-access values, and HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System for UAC/logon values.

powershell
# Restrict anonymous access / null sessions
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictAnonymous" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictAnonymousSAM" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "EveryoneIncludesAnonymous" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" -Name "RestrictNullSessAccess" -Value 1 -Type DWord
Expected result:
  • No output on success (PowerShell's Set-ItemProperty is silent by default).
  • Verify with Get-ItemProperty <path> -Name <name> afterward to confirm the value stuck.
If it fails:"Cannot find path" means the key doesn't exist yet on this build — recheck the path for typos, or the parent key genuinely may not exist (rare for Lsa/LanmanServer\Parameters, both are core keys present since XP). "Requested registry access is not allowed" means the shell isn't elevated — reopen PowerShell as Administrator.

CIS Benchmark cross-reference: This entire Security Options table (accounts, audit, devices, interactive logon, network access/security, UAC) is essentially a client-focused subset of CIS Microsoft Windows 10/11 Benchmark, Level 1, "Security Options." If you want to verify a value against an authoritative published source rather than this document, that's the section to open.

  • CIS Level 1 also recommends "Network security: Minimum session security for NTLM SSP based (including secure RPC) clients" and the matching "...servers" setting both be set to Require NTLMv2 session security, Require 128-bit encryption — a natural companion to the LAN Manager authentication level setting already in the table above.

  • Level 2 (worth trying if you have time and it doesn't break required functionality): CIS Level 2 recommends "Network access: Restrict clients allowed to make remote calls to SAM" be limited to Administrators. This is stricter than Level 1 and can break legitimate remote-administration tooling if your scenario relies on any — test carefully before depending on it for points.

  • secedit /export /cfg C:\secopts.cfg /areas SECURITYPOLICY dumps every Security Options value as plain text in one shot — much faster to skim (or grep with Select-String) than clicking through ~50 individual dialog boxes in secpol.msc one at a time when you just want to verify current state.

  • gpresult /z dumps the full effective policy actually applied to this machine and user — every Computer and User Configuration setting currently in force, from whatever combination of local policy, any GPOs, and any registry-level tampering produced it. Run it as a final verification pass after you've made your changes:

    powershell
    gpresult /z > C:\gpresult_after.txt
    
    Expected result:Creates a large text file (often several thousand lines) with COMPUTER SETTINGS and USER SETTINGS sections, each listing the winning GPO/local policy source and every applied setting value.
    If it fails:
    • "Access is denied" needs elevation.
    • If the file seems suspiciously short or missing whole sections, the account you're running it as may lack rights to read some policy data — run from an elevated Administrator prompt, not just any admin-group console.
    • gpresult /z can take 10-30+ seconds on domain-joined machines; it isn't hung, just slow. This is useful two ways: (1) it confirms your own hardening actually took effect (rather than trusting that clicking "Apply" in secpol.msc worked), and (2) it can surface policy-based sabotage you haven't found yet — a setting showing up in the effective result that you never configured and that isn't in this checklist is worth investigating.
  • "Network security: LAN Manager authentication level" has a direct registry equivalent if you'd rather script it than click through the dropdown — the value 5 corresponds to "Send NTLMv2 response only, refuse LM & NTLM" (the recommended setting in the table above):

powershell
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "LmCompatibilityLevel" -Value 5 -Type DWord
Expected result:
  • No output on success.
  • Confirm with Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name LmCompatibilityLevel which should return 5.
If it fails:"Property LmCompatibilityLevel does not exist" from the confirmation Get-ItemProperty on a fresh image is normal — Set-ItemProperty creates the value if missing, so run the Set first. "Requested registry access is not allowed" means the console isn't elevated.
  • "Network access: Do not allow anonymous enumeration of SAM accounts (and shares)" corresponds to RestrictAnonymous at the registry level: 0 = allow (bad, vulnerable default on some old images), 1 = don't allow enumeration of SAM accounts, 2 = don't allow enumeration of SAM accounts and shares (strictest, matches "and shares" in the policy name). Cross-check the live value if the secpol.msc GUI setting doesn't seem to be sticking:
powershell
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictAnonymous" -ErrorAction SilentlyContinue
Expected result:
  • A property listing including RestrictAnonymous : 1 (or 2 for the strictest "and shares" setting).
  • Matches whatever you set via secpol.msc or the earlier Set-ItemProperty command.
If it fails:
  • No RestrictAnonymous line in the output means the value has never been explicitly set (defaults apply, which vary by OS version) — that's why -ErrorAction SilentlyContinue is there, so it doesn't throw red error text for a missing value.
  • Set it explicitly with Set-ItemProperty ... -Value 1 -Type DWord rather than assuming the default is safe.

7. Windows Firewall#

GUI Method#

  1. Open wf.msc (Windows Firewall with Advanced Security) directly, or via MMC → Add/Remove Snap-insWindows Firewall with Advanced Security.
  2. On the home page, click Windows Firewall Properties. This one dialog has three tabs — Domain Profile, Private Profile, Public Profile — and you need to repeat the same four checks on each of the three tabs (Windows applies a different firewall configuration depending on which network type you're connected to, so all three need to be correct, not just the one currently active):
    • Firewall state dropdown: On. (This is the master switch for that profile — everything else is irrelevant if this is off.)
    • Inbound connections: Block (the default). (This is what actually stops unsolicited incoming traffic.)
    • Outbound connections: Allow (the default, unless README says otherwise). (Blocking outbound by default tends to break required functionality unless the scenario specifically calls for it — don't flip this without a reason.)
    • Click the Settings button (if reviewing notification behavior) and the Logging section's Customize button: set Log dropped packets = Yes, Log successful connections = Yes, and raise the log size limit (e.g., 4096–16384 KB). (This is what gives you evidence later if a forensics question asks about blocked/allowed connections.)
  3. Click OK to close the Properties dialog once all three tabs are done.
  4. Back on the main window, click Inbound Rules in the left pane and scan the list for anything related to: Telnet, netcat/nc/Ncat, File and Printer Sharing (unless required), Remote Assistance, Remote Desktop (unless required), SNMP, SMTP, or any other rule that shouldn't be allowing traffic in. Disable (don't delete) anything unauthorized you find.
  5. Click Outbound Rules and repeat the same review if the scenario calls for outbound restriction — this is less commonly needed than inbound review, but worth a glance.

Command-Line Method#

cmd
netsh advfirewall set allprofiles state on
netsh advfirewall set allprofiles firewallpolicy blockinbound,allowoutbound
netsh advfirewall set allprofiles logging droppedconnections enable
netsh advfirewall set allprofiles logging allowedconnections enable
Expected result:Each line prints Ok.
If it fails:"The requested operation requires elevation" means the prompt isn't Administrator — reopen elevated. "The parameter is incorrect" usually means a typo in the keyword (blockinbound,allowoutbound must be comma-separated with no space); retype carefully rather than reusing a hand-edited copy.
powershell
Get-NetFirewallProfile | Select Name, Enabled, DefaultInboundAction, DefaultOutboundAction
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True -DefaultInboundAction Block -DefaultOutboundAction Allow

# Review all enabled inbound rules for anything suspicious
Get-NetFirewallRule -Direction Inbound -Enabled True | Select DisplayName, Action, Profile

# Disable a specific suspicious rule
Disable-NetFirewallRule -DisplayName "Some Suspicious Rule Name"
Expected result:
  • Get-NetFirewallProfile returns three rows (Domain/Public/Private) each showing Enabled : True, DefaultInboundAction : Block, DefaultOutboundAction : Allow.
  • Get-NetFirewallRule returns a long table of active inbound rules — dozens to over a hundred is normal on a stock Windows install.
  • Disable-NetFirewallRule produces no output on success.
If it fails:Get-NetFirewallProfile/Set-NetFirewallProfile don't exist — these cmdlets require the NetSecurity module, present by default on Windows 8/Server 2012 and later; on Windows 7 use the netsh advfirewall commands above instead. "Cannot find a firewall rule that matches..." from Disable-NetFirewallRule means the -DisplayName string doesn't match exactly (it's case-insensitive but must match fully) — copy the exact name from the Get-NetFirewallRule output rather than retyping it.

Things to try / extra points#

powershell
# Flush DNS cache (source checklists call this out explicitly)
ipconfig /flushdns
Expected result:Successfully flushed the DNS Resolver Cache.
If it fails:
  • "The requested operation requires elevation" on some builds — reopen elevated.
  • This command essentially never fails otherwise; if DNS problems persist afterward the issue is elsewhere (bad DNS server config, hosts file tampering — see below), not the cache itself.
powershell
# Find listening ports and tie them back to a process (kill malicious listeners)
Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, OwningProcess | Sort-Object LocalPort
Get-Process -Id <PID>
Expected result:
  • A table of listening ports with their owning PID.
  • Common/expected ports on a default Windows box: 135 (RPC), 445 (SMB), 3389 (RDP, only if enabled), 5985 (WinRM, only if enabled).
  • Get-Process -Id <PID> resolves that PID to a process name and path.
If it fails:Get-NetTCPConnection doesn't exist on Windows 7/Server 2008 R2 (it's PowerShell 4.0+/NetTCPIP module) — fall back to netstat -ano below. "Cannot find a process with the process Id " means the process exited between the two commands (a short-lived connection) — rerun both back-to-back.
cmd
netstat -ano
Expected result:
  • Columns Proto, Local Address, Foreign Address, State, PID.
  • Works on every Windows version back to XP — this is the reliable fallback when Get-NetTCPConnection isn't available.
If it fails:
  • Output scrolls past too fast to read — pipe to a file (netstat -ano > C:\netstat.txt) or | more.
  • A PID of 0 next to State LISTENING is normal for some system entries; match PIDs against Task Manager's Details tab (enable the PID column) to identify the owning process.

Tip: Cross-reference every listening PID against Task Manager's Details tab (or Get-Process). Standard Windows processes you'll see repeatedly: System, svchost.exe, lsass.exe, services.exe, wininit.exe, spoolsv.exe. Anything unfamiliar tied to a listening port deserves a closer look — check its Get-Process -Id <PID> | Select Path and verify the digital signature.

powershell
# Check code-signing on a suspicious binary (built into Windows, no download needed)
Get-AuthenticodeSignature "C:\path\to\suspect.exe"
Expected result:Status : Valid with a SignerCertificate showing a real publisher (e.g. Microsoft Corporation) for legitimate signed binaries.
If it fails:
  • Status : NotSigned means the file has no digital signature at all — very common for legitimate small utilities too, so this alone isn't proof of malice, but combined with an unfamiliar name/location it's a red flag.
  • Status : HashMismatch means the file was modified after signing — treat as highly suspicious. "Cannot find path" means a typo in the path; use Test-Path or tab-completion first.
  • Check the hosts file for unauthorized DNS redirection — a classic hidden-persistence trick:
powershell
Get-Content C:\Windows\System32\drivers\etc\hosts | Where-Object { $_ -notlike "#*" -and $_.Trim() -ne "" }
Expected result:On a clean system, this typically returns nothing (all default lines are commented out) or just 127.0.0.1 localhost / ::1 localhost if those are uncommented.
If it fails:
  • "Cannot find path" if the drivers\etc folder path is mistyped — it's fixed on every Windows install, so double check for a typo rather than assuming it moved.
  • If you see entries mapping real domains (e.g. windowsupdate.microsoft.com, antivirus vendor domains) to arbitrary IPs, that's a classic malware persistence/AV-blocking technique — remove those lines with Notepad (run as Administrator to save) and keep only the localhost defaults. If you find extra entries beyond the commented-out defaults, remove them (keep only the 127.0.0.1 localhost / ::1 localhost style defaults unless the README requires specific entries).
  • Check for hidden port-forwarding/proxy rules and rogue static routes:
cmd
netsh interface portproxy show all
route print
Expected result:
  • portproxy show all on a clean machine usually prints an empty table (no Listen on/Connect to rows).
  • route print shows the routing table with a Network Destination/Netmask/Gateway/Interface/Metric header — the default route 0.0.0.0 should point to your actual gateway.
If it fails:
  • portproxy show all returning entries you didn't create is the actual finding, not a failure — those are the rogue rules to remove.
  • An unfamiliar persistent static route (flagged differently from DHCP-assigned routes, shown near the bottom under "Persistent Routes") is likewise a finding to investigate, not a command error. Remove unexpected port-proxy entries (netsh interface portproxy delete v4tov4 listenport=<port> listenaddress=<addr>) and unexpected static routes (route delete <destination>).
  • Disable legacy/insecure name resolution protocols that firewall rules alone don't stop:
powershell
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name "EnableMulticast" -Value 0 -Type DWord
Expected result:
  • No output (the Out-Null suppresses the New-Item confirmation, Set-ItemProperty is silent by default).
  • Confirms via Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name EnableMulticast returning 0.
If it fails:
  • "Requested registry access is not allowed" needs an elevated console.
  • This disables LLMNR (Link-Local Multicast Name Resolution), a common lateral-movement/credential-relay vector — if name resolution for local hostnames breaks afterward on a scenario that actually needs LLMNR, this is the setting to revert.

Tip: Never leave the firewall "off" while you work through the rest of the checklist "for convenience," then forget to turn it back on. Enable it early — it doesn't block your own admin activity in almost all CyberPatriot scenarios.

CIS Benchmark cross-reference: The three-profile (Domain/Private/Public), state-on/inbound-block/outbound-allow, log-everything approach in this section matches CIS Microsoft Windows 10/11 Benchmark, Level 1, "Windows Defender Firewall with Advanced Security" guidance directly.

  • CIS Level 1 specifies a minimum firewall log file size per profile (commonly cited around 16,384 KB) — if your logging size limit is left at Windows' tiny default, bump it up; a log that rotates too fast loses evidence you might need for forensics questions.

  • If the firewall configuration looks like it's been tampered with in a way that's hard to untangle rule-by-rule, resetting to Windows defaults and re-applying only what you need is often faster than auditing dozens of custom rules one at a time:

cmd
netsh advfirewall reset
Expected result:Ok.
If it fails:
  • "The requested operation requires elevation" needs an elevated prompt.
  • After this, the firewall is back to out-of-box defaults (state on, inbound block, outbound allow, but logging disabled and any custom rules gone) — always immediately re-run your state on/firewallpolicy/logging commands from earlier in this section, since a reset without follow-up leaves logging off.

This restores default rules and profile settings — re-run your profile state/logging configuration afterward, since the reset also clears those.

  • Once you're happy with the firewall configuration, export it so you have a known-good backup you can restore from without redoing everything by hand:
cmd
netsh advfirewall export "C:\firewall_backup.wfw"
:: To restore later:
netsh advfirewall import "C:\firewall_backup.wfw"
Expected result:
  • export prints Ok. and creates a binary .wfw file (don't try to open/edit it as text).
  • import prints Ok. and silently replaces the entire current firewall configuration with the saved one.
If it fails:
  • "Access is denied" needs elevation for both.
  • If import doesn't seem to change anything, verify the .wfw path is correct — a typo'd path fails silently in some builds rather than throwing a clear error, so re-check with Test-Path "C:\firewall_backup.wfw" in PowerShell first.
  • Custom rules added outside the normal "allow an app through the firewall" flow often lack a DisplayGroup (the category an app-installed rule normally belongs to) — filtering for that is a quick way to surface manually-added rules that might be planted:
powershell
Get-NetFirewallRule | Where-Object { -not $_.DisplayGroup -and $_.Enabled -eq "True" } | Select DisplayName, Direction, Action
Expected result:A short list (often empty or just a few entries) of enabled rules with no DisplayGroup — these are rules created individually (by an app installer's custom action, by netsh/PowerShell directly, or manually in the GUI) rather than as part of a named Windows feature group.
If it fails:
  • A long list here isn't a command failure — it just means this image has a lot of manually-added rules, which is common on machines with lots of third-party software.
  • Cross-check each DisplayName against what software is actually installed; anything referencing an unfamiliar name, a raw port number, or a suspicious path is worth disabling.
  • Quick GUI-free status check without opening wf.msc at all — useful for a fast sanity check mid-round:
cmd
netsh advfirewall show allprofiles
Expected result:A block per profile (Domain/Private/Public) showing State (ON/OFF), inbound/outbound default policy, and logging settings.
If it fails:No real error mode; if any profile shows State OFF, that's a real finding — enable it with netsh advfirewall set <profile>profile state on or netsh advfirewall set allprofiles state on for all three at once.

8. Malware & Unwanted Software Removal#

Reality check: Competition scoring images are frequently offline once the round starts, or have restricted internet. Don't build your strategy around downloading Malwarebytes/CCleaner/Spybot/Sysinternals mid-round if you haven't verified internet access is actually available and allowed. If your team practices with internet access, treat the tools below as "if available," and always have an offline (built-in tools) fallback plan — see the extra-points callouts.

GUI Tools (if internet/tools are available and permitted) — Installation & Use#

These are large, slow scans — start each one and keep working on other checklist sections while it runs rather than sitting and watching the progress bar. Do them in whatever order lets you multitask best; a common pattern is to kick off Malwarebytes first (it's usually the slowest), work on accounts/firewall/services while it runs, then handle CCleaner and Spybot's faster passes.

Malwarebytes (free edition — anti-malware scanner)

  1. Download from the official site, malwarebytes.com → Free Download. Don't use a mirror or search-result link you're not sure about.
  2. Run the installer. When it offers a Premium trial, uncheck/decline it — the free scan-and-remove functionality is everything you need, and accepting the trial just adds nag prompts.
  3. Let it launch after install. If it offers to update its detection database and you have internet, accept — an out-of-date scanner catches less.
  4. Click Scan and choose the most thorough option offered — labeled Full Scan in older versions, or just the default Scan button (which runs a full Threat Scan) in newer ones. Avoid "Quick Scan" if a more thorough option exists.
  5. Wait for it to finish (can take 10-30+ minutes) — go work on other sections.
  6. When it's done, review the results list, make sure everything found is selected, and click Quarantine/Remove Selected.
  7. Restart if it prompts you to, once you're at a natural stopping point.

CCleaner (free edition — junk/registry cleaner)

  1. Download from the official site, ccleaner.com. During install, watch for and decline any bundled extra software/toolbar offers in the installer.
  2. Open CCleaner. Go to the Cleaner (or Custom Clean, depending on version) tab.
  3. If prompted "Intelligently scan for cookies to keep," choose No — keep the pass simple and fast.
  4. Click Analyze, review what it found, then click Run Cleaner to clear temp/junk files.
  5. Switch to the Registry tab → Scan for Issues.
  6. Click Fix Selected Issues — it will offer to back up the change to a .reg file first. Accept this (click Yes) so you have a rollback path if fixing an entry breaks something.
  7. Click through and fix all listed issues.

Spybot – Search & Destroy (free "Home Use" edition — anti-spyware scanner)

  1. Download from the official site, safer-networking.org, selecting the free Home Use edition.
  2. During installation, if you're offered an install-type choice, pick the more advanced/thorough option (older versions phrase this as "I want more control, more feedback, and more responsibility") rather than the minimal default — this enables the fuller scan capability.
  3. After install, if prompted, check "Open Start Center" and "Check for new malware signatures," then click Finish.
  4. Before scanning, go to the Update tab and update definitions if internet is available.
  5. From the Start Center, run a System Scan.
  6. Let it complete (can be slow), review flagged items, select them, and remove/fix.

After running any/all of the above:

  • Re-check the scoring report. These tools sometimes flag or remove things unrelated to actual scoring criteria, and can occasionally interfere with a required program — don't let an AV tool uninstall or quarantine anything the README says is required. If something required goes missing after a scan, that's the first place to look.
  • Uninstall the cleaning tools themselves at the end if the scenario doesn't call for them to remain installed — leaving Malwarebytes/CCleaner/Spybot installed generally isn't a problem, but check your competition's specific guidance on staged/installed third-party tools.

Sysinternals Suite (Process Explorer, Autoruns, TCPView, Sigcheck) — portable, no installer needed If internet access is available and permitted: download the ZIP directly from Microsoft's official Sysinternals page (learn.microsoft.com/sysinternals → Downloads → Sysinternals Suite), extract it anywhere (e.g., C:\Tools\Sysinternals), and run the executables directly — no installation step, they're portable EXEs:

  • Process Explorer (procexp64.exe) — a far more detailed Task Manager replacement; right-click any process → Check VirusTotal (needs internet) or view its full path, loaded DLLs, and digital signature at a glance.
  • Autoruns (autoruns64.exe) — shows every autostart location Windows has (Run keys, services, scheduled tasks, IFEO, WMI subscriptions, and more) in one tabbed view — the single best tool for the persistence-hunting work in Section 22, when available.
  • TCPView (tcpview.exe) — live GUI view of every network connection and the process behind it, a GUI alternative to netstat -ano.
  • As covered earlier in this section: don't build your primary strategy around these being available, since a scoring image is frequently offline — but if your competition's rules allow pre-staging tools before the round starts, having a copy ready to go is a legitimate time-saver.

Removing Unwanted / Unauthorized Programs#

  • Control Panel → ProgramsUninstall a Program. Review every entry.
    • Uninstall anything not required by the README (games, P2P/torrent clients, cracking/keygen tools, remote-access tools not authorized, hacking tools, old vulnerable software versions).
    • Do not uninstall required software, browsers, runtimes (.NET, Visual C++ redistributables — these are dependencies for other software), or anything explicitly listed as authorized.
    • If uninstall fails with "access denied" or "in use," find and end the locking process in Task Manager (Details tab), then retry.
  • Some software hides itself from the visible Uninstall list but leaves registry traces. Check both 64-bit and 32-bit uninstall keys:
powershell
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
    Select DisplayName, DisplayVersion, Publisher, UninstallString | Where-Object { $_.DisplayName }

Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue |
    Select DisplayName, DisplayVersion, Publisher, UninstallString | Where-Object { $_.DisplayName }
Expected result:A list of installed programs (name, version, publisher, and the exact command to uninstall them) — the 64-bit key first, then the 32-bit (WOW6432Node) key for anything installed as a 32-bit app on a 64-bit OS.
If it fails:No error mode; a program showing here but NOT in Control Panel's visible list is exactly the "hidden from Uninstall" case this bullet is checking for — use the UninstallString value directly (paste it into an elevated Command Prompt/Run box) to remove it since there's no visible GUI entry to click.
powershell
# Alternative enumeration (can be slow / triggers reconfig side effects on some systems — use read-only listing, avoid calling .Uninstall() unless you mean it)
Get-CimInstance -ClassName Win32_Product | Select Name, Version, Vendor
Expected result:A list of MSI-installed applications (name/version/vendor) — note this only sees MSI-based installs, not every installed program (EXE-based installers won't show here, which is why the registry query above is the more complete primary method).
If it fails:Can be genuinely slow (the caution note above explains why — it triggers Windows Installer self-repair checks as a side effect) — this is expected behavior, not a hang, but exactly why the doc recommends the registry method as primary and this only as a fallback when you specifically need .Uninstall() scripting.

Caution: Win32_Product enumeration is known to trigger Windows Installer consistency-checking as a side effect on some systems (can be slow and, rarely, reconfigure/repair installed MSI packages). Prefer the registry Uninstall key query above for a safer read-only listing; use Win32_Product mainly when you specifically need .Uninstall() scripting against an MSI-based app.

Windows Defender Exclusions Audit#

A very common technique across CyberPatriot rounds: an exclusion gets added to Windows Defender's real-time scanning — an entire drive letter, a broad user-profile folder, or a specific "hiding spot" like C:\Users\Public — so that anything sitting there is silently never scanned. This is easy to miss because Defender otherwise still shows as "on" and "protecting" in the Security app; the exclusion list is a separate, less visible setting.

  • Check every exclusion category — path, file extension, and process are all separate lists, so check all three:
powershell
Get-MpPreference | Select-Object -ExpandProperty ExclusionPath
Get-MpPreference | Select-Object -ExpandProperty ExclusionExtension
Get-MpPreference | Select-Object -ExpandProperty ExclusionProcess
Expected result:Each prints a list of excluded paths/extensions/processes, or nothing at all if no exclusions are configured (the clean, expected outcome on most images).
If it fails:
  • "Property ExclusionPath cannot be found" style error is unusual for this cmdlet — if seen, confirm Windows Defender itself is actually the active AV (Get-MpComputerStatus) rather than a third-party AV having taken over, since Get-MpPreference reflects Defender's own config specifically.
  • Any non-empty result matching the red-flag patterns listed in the bullets below is a real, high-priority finding.
  • Treat any of the following as a red flag worth removing:
    • An exclusion pointing at an entire drive letter (C:\, D:\)
    • An exclusion pointing at a whole user profile folder (C:\Users\<name>\) rather than one specific, justifiable application subfolder
    • An exclusion pointing at Downloads, Temp, AppData\Roaming, or another common malware-drop location
    • A file-extension exclusion that's unusually broad (.exe, .dll, .*) rather than something narrow and clearly justified
  • Remove any confirmed-bad exclusion:
powershell
Remove-MpPreference -ExclusionPath "C:\Users\Public"
Remove-MpPreference -ExclusionExtension ".exe"
Remove-MpPreference -ExclusionProcess "suspicious.exe"
Expected result:Silent on success; re-run the Get-MpPreference queries above to confirm the entry is gone.
If it fails:
  • "Access is denied" — needs an elevated PowerShell session.
  • Removing an exclusion the README/scenario actually relies on (rare, but check first if the excluded path/process name looks tied to required software) can cause that software to get flagged/quarantined afterward — if a required app breaks after removing an exclusion, that's the likely cause.
  • Re-run a scan after removing exclusions — anything that was hiding behind them will only get caught on the next scan, not retroactively:
powershell
Start-MpScan -ScanType QuickScan
# Or for a more thorough (slower) pass:
Start-MpScan -ScanType FullScan
Expected result:Runs synchronously with no console output until it finishes; check results afterward via Get-MpThreatDetection or the Windows Security app's Protection History.
If it fails:Appears to "hang" — a FullScan genuinely can take a long time (potentially 30+ minutes depending on disk size); that's expected, not stuck — start it and move on to other checklist sections while it runs, exactly as the earlier Malwarebytes-timing tip in this section suggests. "Operation failed with error 0x8007xxxx" or similar occasionally happens if real-time protection itself is disabled — confirm Get-MpComputerStatus shows RealTimeProtectionEnabled: True first.

Tip: Exclusions can also be enforced via Administrative Templates/Group Policy registry keys instead of the live Get-MpPreference settings — if Get-MpPreference shows nothing but you still suspect exclusions, also check HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Exclusions\Paths (and the ...\Extensions / ...\Processes siblings), since GPO-set exclusions can be layered on separately from what the Security app shows you.

Things to try / extra points#

Tip: Get-Process | Sort-Object CPU -Descending and Get-Process | Sort-Object WS -Descending (working set/memory) can surface a resource-hungry malicious process you'd otherwise miss by just eyeballing Task Manager.

powershell
Get-Process | Sort-Object CPU -Descending | Select-Object -First 15 Name, Id, CPU, Path
Expected result:Top 15 processes by cumulative CPU time, with their executable path.
If it fails:
  • Some processes show blank Path even as Administrator — that's normal for protected system/SYSTEM-owned processes you don't have rights to inspect that deeply; not every blank path is suspicious.
  • Focus on unfamiliar process names, or a familiar name (e.g. svchost.exe) running from a Path OUTSIDE its normal System32 location — that mismatch is a much stronger signal than raw CPU usage alone.

Tip: Sysinternals tools (Process Explorer, Autoruns, TCPView, Sigcheck) are excellent for malware hunting but are not pre-installed on stock Windows and typically cannot be downloaded mid-competition if the scoring image has no internet access. If your team is allowed to stage tools before the round (check your competition's rules), pre-stage a portable copy; otherwise rely on the built-in PowerShell/CMD equivalents throughout this document (Get-Process, Get-CimInstance Win32_StartupCommand, Get-AuthenticodeSignature, registry Run-key queries, etc.) which ship with every Windows install.

  • Sweep for prohibited files — media, hacking tools, cracks — in common user-writable locations:
powershell
Get-ChildItem -Path C:\Users -Recurse -Include *.mp3,*.mp4,*.avi,*.mkv,*.wav,*.mov -ErrorAction SilentlyContinue |
    Select FullName, Length | Format-Table -AutoSize

Get-ChildItem -Path C:\Users\Public, C:\ProgramData, C:\Windows\Temp -Recurse `
    -Include *.mp3,*.mp4,*.avi,*.exe,*.bat,*.vbs,*.ps1 -ErrorAction SilentlyContinue
Expected result:A file listing (with sizes for the first query) of matching media/script/executable files, or empty if genuinely clean.
If it fails:
  • No error mode; can be slow scanning a large C:\Users tree — that's expected.
  • A hit doesn't automatically mean "delete it" — a .mp3 in a legitimately-authorized user's music folder isn't the same finding as one stashed in C:\ProgramData or C:\Windows\Temp; judge by location and context, not just extension.
  • Common CyberPatriot "prohibited items" to search for by name/keyword: nmap, Wireshark, Metasploit, Cain and Abel, netcat/nc/ncat, John the Ripper, keyloggers, LOIC/HOIC, uTorrent/BitTorrent/qBittorrent, any game titles (Steam, Minecraft, etc. unless authorized), cracking/keygen tools, TeamViewer/AnyDesk/remote-access software not authorized by README.
powershell
Get-ChildItem -Path "C:\","C:\Program Files","C:\Program Files (x86)","C:\Users" -Recurse -ErrorAction SilentlyContinue |
    Where-Object { $_.Name -match "nmap|wireshark|metasploit|cain|netcat|ncat|keygen|crack|nc\.exe|torrent" } |
    Select FullName
Expected result:File paths matching any of the listed keyword patterns, or nothing if clean.
If it fails:
  • This is a genuinely slow, full-C:\-adjacent recursive search — expect it to take a while, especially the first "C:\" path which re-scans everything the more specific paths after it already would (a bit redundant as written, but harmless, just slower than strictly necessary).
  • A hit on a filename merely containing "crack" (e.g. a legitimate file named crackers_recipe.docx) is a false positive from the broad pattern match — read the actual full path/filename before treating every regex hit as confirmed contraband.
  • Check for hidden secondary data streams (a way to hide payloads inside an otherwise normal file) — an advanced technique worth a quick sweep in user-writable folders:
powershell
Get-ChildItem -Path C:\Users -Recurse -Stream * -ErrorAction SilentlyContinue | Where-Object { $_.Stream -ne ':$DATA' }
Expected result:Empty on a clean system — every normal file only has the default :$DATA stream, so this filters down to just files WITH an extra alternate stream attached.
If it fails:No error mode; a hit is a genuine finding worth investigating — view the stream's content with Get-Content -Path "file.txt:StreamName".
  • Run the built-in System File Checker / DISM if you suspect core OS files were tampered with (safe, offline-capable):
cmd
sfc /scannow
DISM /Online /Cleanup-Image /RestoreHealth
Expected result:sfc /scannow takes several minutes and ends with "Windows Resource Protection did not find any integrity violations" (clean) or a message that violations were found and repaired (or not fully repaired).
If it fails:
  • "Windows Resource Protection found corrupt files but was unable to fix some of them" means the local component store itself is damaged — run the DISM /RestoreHealth line to repair the store first, then re-run sfc /scannow.
  • If DISM also fails with no source found and this image is offline, that specific repair may not be fully achievable — see the tip immediately below.

Tip: DISM /RestoreHealth needs a source of clean files; if it fails offline due to no WSUS/internet source, that's expected on an air-gapped scoring VM — sfc /scannow alone still checks and repairs from the local component store when possible.

CIS Benchmark cross-reference: Beyond the AV/cleaner tools above, CIS Level 1 has a dedicated "Windows Defender Antivirus" / "Microsoft Defender Antivirus" Administrative Templates block worth checking: real-time protection must stay on, cloud-delivered protection and automatic sample submission should be enabled, and PUA (Potentially Unwanted Application) protection should be set to Block. Check under gpedit.msc → Computer Configuration → Administrative Templates → Windows Components → Microsoft Defender Antivirus (exact path name varies slightly by Windows version) rather than assuming defaults are fine on a vulnerable image.

powershell
# Quick check of current Defender configuration without changing anything
Get-MpPreference | Select DisableRealtimeMonitoring, MAPSReporting, SubmitSamplesConsent, PUAProtection
Get-MpComputerStatus | Select AntivirusEnabled, RealTimeProtectionEnabled, AntispywareEnabled
Expected result:DisableRealtimeMonitoring: False, AntivirusEnabled/RealTimeProtectionEnabled/AntispywareEnabled all True on a healthy system.
If it fails:
  • "not recognized" on very old Windows 7-era builds without Defender's PowerShell module — use the Security Center GUI instead.
  • Any True value for DisableRealtimeMonitoring, or False on the enabled/protection flags, is a serious, high-priority finding — fix with Set-MpPreference -DisableRealtimeMonitoring $false.
  • Two more CIS Level 1 Defender settings that live outside the basic on/off toggle and are easy to miss: Network Protection (blocks connections to known-malicious sites/IPs at the network level — separate from browser-based SmartScreen) and e-mail scanning (scans email attachments/content, off by default):

    powershell
    Set-MpPreference -EnableNetworkProtection Enabled
    Set-MpPreference -DisableEmailScanning $false
    
    Expected result:
    • Silent on success.
    • Verify with Get-MpPreference | Select EnableNetworkProtection, DisableEmailScanning.
    If it fails:
    • "The operation requires elevation" needs an Administrator PowerShell session.
    • Network Protection needs Defender's real-time protection already enabled to function — if it doesn't seem to be blocking anything, confirm real-time protection status first (checked in the query just above this bullet).
  • Check signature freshness — a Defender that's "on" but running on ancient virus definitions is barely better than no AV at all, and is an easy thing to overlook since the app doesn't loudly warn you:

powershell
Get-MpComputerStatus | Select AntivirusSignatureLastUpdated, AntivirusSignatureAge, AntispywareSignatureAge

If internet access is available, force an update: Update-MpSignature. Expected result: AntivirusSignatureAge in days — low single digits is healthy. If it fails: A large age (weeks/months) on an offline image is expected and often unfixable without internet — note it rather than looping on Update-MpSignature, which will just time out if there's genuinely no connectivity. Update-MpSignature failing with a network error confirms no internet rather than indicating a broken command.

  • Check Defender's own detection history — if it already caught and quarantined something, that's often the fastest way to find out what the "planted malware" for this round actually was, without doing a from-scratch file sweep:
powershell
Get-MpThreatDetection
Get-MpThreat
Expected result:Lists any threats Defender has already detected/quarantined, with names and paths — genuinely useful shortcut for forensics questions about "identify the malware."
If it fails:Empty output just means nothing's been caught yet (either genuinely clean, or real-time protection wasn't on when the threat arrived) — not a broken command; don't conclude "no malware present" purely from an empty result here without also doing an active scan.
  • If a forensics question gives you a known-bad file hash to search for, compare it directly instead of relying on Defender to have already caught it:
powershell
Get-ChildItem -Path C:\ -Recurse -ErrorAction SilentlyContinue |
    Get-FileHash -Algorithm SHA256 -ErrorAction SilentlyContinue |
    Where-Object { $_.Hash -eq "PUT_KNOWN_BAD_HASH_HERE" }
Expected result:The matching file's path if found, or nothing if it's not (or not present as SHA256 — try MD5/SHA1 if the given hash is a different algorithm and length).
If it fails:This is a genuinely slow, whole-C:\ hash-everything operation — the tip right below already flags this; narrow -Path if you have any lead on where to look, since hashing every file on the drive can take a long time.

This is a slow, whole-disk operation — narrow the -Path to a specific folder if you have any idea where to look first.


9. Services Hardening#

Open via services.msc (Start → type it) or MMC → Add/Remove Snap-inServices. Sort by name and compare against the table below. If a service isn't listed here, don't panic — research it (executable path, description, install date) rather than guessing.

README always wins. If a scenario requires Remote Desktop, print sharing, IIS, SQL Server, etc. for a stated business reason, leave the relevant service(s) running and don't blindly disable per this table.

Service Name Recommended State
ActiveX Installer Disabled
Adaptive Brightness Disabled
Application Experience Manual
Application Identity Manual
Application Information Manual
Application Layer Gateway Service Disabled
Background Intelligent Transfer Service Manual
Base Filtering Engine Automatic
BitLocker Drive Encryption Service Manual
Bitlocker Level Backup Engine Service Disabled
Bluetooth Support Service Disabled (unless Bluetooth is required)
Certificate Propagation Disabled
CNG Key Isolation Manual
COM+ Event System Manual
COM+ System Application Manual
Computer Browser Manual/Disabled
Credential Manager Manual
Cryptographic Services Automatic
DCOM Server Process Launcher Automatic
Desktop Window Manager Session Manager Automatic
DHCP Client Automatic
Diagnostic Policy Service Automatic
Diagnostic Service Host Manual
Diagnostic System Host Manual
Disk Defragmenter Disabled
Distributed Link Tracking Client Manual
Distributed Transaction Coordinator Manual
DNS Client Automatic
Encrypting File System Manual
Extensible Authentication Protocol Manual
Fax Disabled
Function Discovery Provider Host Manual
Function Discovery Resource Publication Manual
Group Policy Client Automatic
Health Key and Certificate Management Manual
HomeGroup Listener Disabled
HomeGroup Provider Disabled
Human Interface Device Access Disabled
IKE and AuthIP IPsec Keying Modules Manual
Interactive Services Detection Disabled
Internet Connection Sharing Disabled
IP Helper Manual
IPsec Policy Agent Manual
KtmRm for Distributed Transaction Coordinator Disabled
Link-Layer Topology Discovery Mapper Manual
Microsoft .NET Framework NGEN v2.0 Manual
Microsoft iSCSI Initiator Service Disabled
Microsoft Software Shadow Copy Provider Disabled
Multimedia Class Scheduler Disabled
Net.Tcp Port Sharing Service Disabled
Netlogon Disabled (unless domain-joined and required)
Network Access Protection Agent Manual
Network Connections Manual
Network List Service Manual
Network Location Awareness Manual
Network Store Interface Service Automatic
Parental Controls Disabled
Peer Name Resolution Protocol Disabled
Peer Networking Grouping Disabled
Peer Networking Identity Manager Disabled
Performance Logs & Alerts Manual
Plug and Play Automatic (caution: source list said Disabled — do NOT disable this; PnP is required for hardware to function. Treat this as an error in the historical checklist and leave PnP on its default Automatic setting.)
PNP-X IP Bus Enumerator Disabled
PNRP Machine Name Publication Service Disabled
Portable Device Enumerator Service Disabled
Power Automatic
Print Spooler Disabled (unless printing is required — then Automatic)
Problem Reports and Solutions Control Panel Support Manual
Program Compatibility Assistant Service Manual
Protected Storage Manual
Quality Windows Audio Video Experience Disabled
Remote Access Auto Connection Manager Disabled
Remote Access Connection Manager Disabled
Remote Desktop Configuration Disabled (unless RDP required)
Remote Desktop Services Disabled (unless RDP required)
Remote Procedure Call (RPC) Automatic (never disable — required for the OS to function)
Remote Procedure Call (RPC) Locator Manual
Remote Registry Disabled
RIP Listener Disabled
Routing and Remote Access Disabled
RPC Endpoint Mapper Automatic (never disable)
Secondary Logon Disabled
Secure Socket Tunneling Protocol Service Disabled
Security Accounts Manager Automatic (never disable)
Security Center Automatic
Server Disabled (unless file/print sharing is required)
Shell Hardware Detection Disabled
Smart Card Disabled (unless smart cards required)
Smart Card Removal Policy Disabled
SNMP Trap Disabled
Software Protection Automatic
SPP Notification Service Manual
SSDP Discovery Disabled
Superfetch / SysMain Manual
System Event Notification Service Automatic
Tablet PC Input Service Disabled
Task Scheduler Automatic (needed for many legitimate OS/maintenance tasks and for you to audit scheduled tasks — do not disable; audit its contents instead, see Section 21)
TCP/IP NetBIOS Helper Disabled
Telephony Disabled
Telnet Disabled
Themes Manual
Thread Ordering Server Manual
TP AutoConnect Service Disabled
TP VC Gateway Service Disabled
TPM Base Services Disabled (unless BitLocker/TPM features required)
UPnP Device Host Disabled
User Profile Service Automatic (never disable — required for login)
Virtual Disk Manual
VMware Tools / VMware Snapshot Provider Automatic/Manual (leave running in virtualized competition images — required for the environment itself)
Volume Shadow Copy Manual (leave Automatic/Manual, not fully disabled, if System Restore/backups are in use)
WebClient Disabled
Windows Audio Automatic
Windows Audio Endpoint Builder Automatic (source list said Disabled — needed alongside Windows Audio for sound; keep Automatic unless you intend to fully silence the box)
Windows Backup Manual
Windows Biometric Service Disabled (unless biometrics required)
Windows CardSpace Disabled
Windows Color System Disabled
Windows Connect Now Disabled
Windows Defender / Microsoft Defender Antivirus Automatic — never disable
Windows Driver Foundation Manual
Windows Error Reporting Service Manual
Windows Event Collector Disabled
Windows Event Log Automatic (never disable — you need this for forensics/scoring)
Windows Firewall Automatic — never disable
Windows Font Cache Manual (leave enabled; disabling can cause rendering slowdowns)
Windows Image Acquisition Disabled (unless scanners/cameras required)
Windows Installer Manual
Windows Management Instrumentation Automatic (never disable — required for most of the PowerShell/WMI commands in this document)
Windows Media Player Network Sharing Service Disabled
Windows Modules Installer Manual
Windows Remote Management (WinRM) Disabled (unless remote management required)
Windows Search Automatic (leave default; disabling only saves resources, not security)
Windows Time Manual/Automatic
Windows Update Automatic
WinHTTP Web Proxy Auto-Discovery Service Disabled
Wired AutoConfig Manual
WLAN AutoConfig Manual (Automatic if Wi-Fi is the primary connection)
WMI Performance Adapter Disabled
Workstation Automatic
WWAN AutoConfig Manual

Correction note: Two entries in the historical source table (Plug and Play = Disabled, Windows Audio Endpoint Builder = Disabled) would break basic OS functionality if actually applied and are flagged above as likely transcription errors from the original document — do not disable Plug and Play or fully break audio unless you have a specific reason to.

Explicitly call out (from source material) as commonly-needed-to-disable, non-default services if present: SMTP, Bonjour, Remote Access Auto Connection Manager, Remote Access Connection Manager, Remote Desktop Configuration, Remote Desktop Services, Remote Registry, RIP Listener, World Wide Web Publishing Service (indicates IIS is running), NetMeeting Remote Desktop Sharing, Simple File Sharing, SSDP Discovery, Windows Messenger Service.

Modern/Optional Services Not on the Classic List (CIS-confirmed gaps)#

The service table above traces back to an older Windows 7/8-era baseline and misses several services that ship on modern Windows 10/11 images and are explicitly called out in the current CIS Windows Benchmark:

  • OpenSSH Server (sshd)(L1) should be uninstalled/disabled unless explicitly required. This is an optional Windows feature (Settings → Apps → Optional Features) that, once enabled, opens a full SSH remote-access path into the box — a real and easily-missed backdoor since competitors instinctively check RDP but often forget Windows ships its own SSH server option.
    powershell
    Get-WindowsCapability -Online | Where-Object Name -like "OpenSSH.Server*"
    Get-Service sshd -ErrorAction SilentlyContinue
    # If present and not required:
    Stop-Service sshd; Set-Service sshd -StartupType Disabled
    Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
    
  • Windows Subsystem for Linux (LxssManager)(L1) should be disabled unless required. WSL gives a full Linux userland running alongside Windows, which is both a legitimate attack-surface expansion and a way to run Linux tools that Windows-only security tooling won't see.
    powershell
    Get-Service LxssManager -ErrorAction SilentlyContinue
    Set-Service LxssManager -StartupType Disabled -ErrorAction SilentlyContinue
    
    Expected result: Get-Service shows current status if WSL/LxssManager is installed, or nothing (suppressed error) if it isn't — most client images won't have it at all. Set-Service is silent on success. If it fails: No error mode given the suppression flag; absence is the common case and means this bullet is a no-op, not a failure.

Command-Line Method#

powershell
# See everything currently running — fastest way to spot something unexpected
Get-Service | Where-Object { $_.Status -eq "Running" } | Select-Object Name, DisplayName | Sort-Object Name

# Disable and stop a specific service
Set-Service -Name "RemoteRegistry" -StartupType Disabled -Status Stopped
Set-Service -Name "TlntSvr" -StartupType Disabled -Status Stopped
Expected result:
  • First command lists all running services alphabetically.
  • Set-Service calls are silent on success.
If it fails:"Cannot find any service with service name 'TlntSvr'" just means Telnet Server isn't installed on this image — nothing to do. "Access is denied" needs an elevated session.
cmd
sc query state= all
sc qc <servicename>
sc config <servicename> start= disabled
sc stop <servicename>
Expected result:sc query lists every service with its state; sc qc shows one service's configuration (binary path, start type, display name); sc config/sc stop are silent or print [SC] ChangeServiceConfig SUCCESS.
If it fails:sc config's syntax is famously picky about spacing — the space after start= (and every key=) is required, start=disabled (no space) fails with a syntax error while start= disabled (with space) works; this trips up almost everyone the first time they use sc.exe. "Access is denied" needs elevation. "OpenService FAILED 1060: The specified service does not exist" means a typo'd <servicename> — get exact names from sc query state= all first.

Spoofed / Impersonating Service Names#

A recurring planted-vulnerability pattern: a malicious service is given a name deliberately similar to a real Windows service — a fake variant of svchost, a near-duplicate of a legitimate service's display name with a typo, or a service with a vague, self-referential description (e.g. "Provides service functionality" that doesn't actually describe anything). At a glance in services.msc these blend right in with the ~150 legitimate entries.

  • Pull name, display name, executable path, and the account it runs as all together, so you can eyeball inconsistencies in one table instead of clicking into each service's Properties individually:
powershell
Get-CimInstance Win32_Service | Select-Object Name, DisplayName, PathName, StartName | Sort-Object Name
Expected result:A full table of every service (running or not) with its executable path and run-as account, alphabetized.
If it fails:No error mode; this is the baseline table the next few narrower queries filter down from.
  • Cross-reference the executable path against where it should be — genuine core Windows services run from C:\Windows\System32\ (or occasionally C:\Windows\SysWOW64\), not from a user profile, AppData, ProgramData, or a temp folder:
powershell
Get-CimInstance Win32_Service | Where-Object { $_.PathName -and $_.PathName -notmatch '^"?C:\\Windows\\(System32|SysWOW64)' -and $_.PathName -notmatch '^"?C:\\Program Files' } |
    Select-Object Name, DisplayName, PathName, StartName

This will also catch legitimately-installed third-party services (antivirus, VMware Tools, printer drivers) — the point isn't that every result is bad, it's that this list is now small enough to actually review by eye instead of scrolling past 150 entries. Expected result: A shorter list than the full table — mostly legitimate third-party software as the callout notes. If it fails: No error mode; a hit running from AppData, a temp folder, or C:\Users\Public (rather than a recognizable Program Files subfolder for known software) is the pattern actually worth chasing.

  • Check the digital signature on anything that looks even slightly off — a real Microsoft service binary will show a valid Microsoft signature:
powershell
Get-AuthenticodeSignature "C:\Windows\System32\suspicious_svc.exe" | Select Status, SignerCertificate
Expected result:Status: Valid with a SignerCertificate showing a Microsoft (or other recognized vendor) subject for legitimate software.
If it fails:Status: NotSigned or HashMismatch on something claiming to be a core Windows component is a serious, high-priority finding. "Cannot find path" just means you need the actual path from the earlier PathName query, not the literal placeholder shown here.
  • Services running under an unusual account are worth a second look — most legitimate services run as LocalSystem, NT AUTHORITY\LocalService, NT AUTHORITY\NetworkService, or a proper NT SERVICE\<name> virtual account, not as a specific named user (especially not an Administrator account):
powershell
Get-CimInstance Win32_Service | Where-Object { $_.StartName -and $_.StartName -notmatch 'LocalSystem|NT AUTHORITY|NT SERVICE' } |
    Select-Object Name, DisplayName, StartName
Expected result:Usually a short list, or empty — most services correctly use the built-in service accounts.
If it fails:No error mode; a service running as a named human/admin account (especially one with an obviously weak or default-sounding password) is a real, concerning finding — that account's credentials, if ever compromised, directly grant whatever that service can do.

Things to try / extra points#

Tip: For any service you don't recognize, right-click → Properties → check the Path to Executable. Type that path into Get-AuthenticodeSignature or just navigate to the folder in Explorer (don't double-click it) and check the file's Properties → Digital Signatures tab. An unsigned binary running as a "service" in a weird folder (C:\Users\...\AppData instead of C:\Windows\System32 or C:\Program Files\...) is a strong malware indicator.

powershell
Get-CimInstance Win32_Service | Select Name, DisplayName, State, StartMode, PathName | Sort-Object State -Descending
Expected result:Full service table sorted so Running services appear first (alphabetical descending on State puts "Running" ahead of "Stopped").
If it fails:No error mode; this is a general-purpose starting table for the two more targeted queries below.
  • Services with StartMode = Auto but currently State = Stopped are worth a glance — that mismatch can mean the service crashed, was manually stopped after being tampered with, or is misconfigured in a way that's itself the vulnerability being scored:
powershell
Get-CimInstance Win32_Service | Where-Object { $_.StartMode -eq "Auto" -and $_.State -eq "Stopped" } | Select Name, DisplayName, PathName
Expected result:A short list, ideally empty — every hit is a service that SHOULD be running but isn't.
If it fails:No error mode; investigate each hit with Get-EventLog/Get-WinEvent for why it stopped (crash vs. manual stop) before just restarting it blindly — if it crashed due to tampering, restarting without fixing the underlying cause just means it crashes again.
  • Hunt for unquoted service path vulnerabilities — a classic privilege-escalation flaw where a service path with spaces and no quotes lets an attacker plant an executable earlier in the path:
powershell
Get-CimInstance Win32_Service | Where-Object { $_.PathName -notlike '"*' -and $_.PathName -like '* *' } |
    Select-Object Name, PathName
Expected result:Ideally empty; any hit is a real vulnerability.
If it fails:No error mode; fix a hit by wrapping its PathName in quotes via the registry ImagePath value at HKLM:\SYSTEM\CurrentControlSet\Services\<ServiceName>, then restart the service to confirm it still starts correctly with the quoted path.

Tip: A blank/missing service Description field is unusual for genuine Microsoft services — the original checklist author's rule of thumb ("Microsoft is meticulous about descriptions; a missing one is suspicious") is a reasonable heuristic, not a guarantee. Verify with signature checks too.

CIS Benchmark note: Unlike the Account/Audit/Security Options sections above, the CIS Windows Benchmark does not publish a comprehensive "which services should be on/off" table like the one in this section — service hardening of this kind is more of a general security-hygiene practice (closer to Microsoft's own Security Compliance Toolkit baselines) than a specific CIS control. Don't expect to find a 1:1 citation for every row in the Services table above; treat that table as community-sourced practical guidance rather than a CIS-derived standard.


10. Startup Programs#

GUI Method#

  • Windows 7/8: msconfigStartup tab.
  • Windows 8.1/10/11: Task Manager → Startup tab (or Startup Apps in Settings on Win11).
  • Only expected/required items should remain enabled — e.g., legitimate virtualization tools if this is itself a VM guest, an authorized antivirus, or software explicitly required by the README. Disable everything else.
  • For anything suspicious, note its name and file path, research it, and remove/uninstall the underlying program if it's confirmed unwanted (see Section 8).

Command-Line Method#

powershell
Get-CimInstance Win32_StartupCommand | Select Name, Command, Location, User
Expected result:A table of startup entries with the command line, registry/folder source, and which user account it applies to.
If it fails:No error mode; this cmdlet aggregates Run keys AND Startup folders in one view, which is why it's the fastest first check before diving into the individual registry paths below.
cmd
wmic startup get Caption,Command,Location,User
Expected result:Similar table via the older wmic interface.
If it fails:wmic is removed by default starting Windows 11 24H2 — if "not recognized," rely on the PowerShell Get-CimInstance version above instead.

Things to try / extra points#

  • Startup entries also live in the registry Run keys — check all of these, not just msconfig/Task Manager's view (some malware writes directly to the registry and doesn't always surface cleanly in the GUI):
powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run*" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*" -ErrorAction SilentlyContinue
Expected result:Each prints the Run key's value-name/command pairs — a handful of legitimate vendor entries is normal (this is where things like driver tray utilities and update checkers commonly live).
If it fails:
  • No error mode given the suppression flag.
  • This only checks the currently logged-in user's HKCU — a different user's Run entries require loading their hive (reg load HKU\Temp C:\Users\<user>\NTUSER.DAT) or logging in as them directly to check via their own HKCU.
  • Also check the Startup folders directly (shortcuts placed here run at logon without needing a registry entry):
powershell
Get-ChildItem "C:\Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
Get-ChildItem "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"
Expected result:Lists .lnk/executable files in each user's personal Startup folder and the shared all-users one — often empty or with just one or two legitimate shortcuts.
If it fails:No error mode; an unfamiliar shortcut here is worth checking its actual Target (see the shortcut-target-inspection bullet further down this section) since the displayed name/icon can be misleading.

Tip: Anything referencing nc.exe, netcat, ncat, bfk, telnet, or an obfuscated/base64-looking command line in a Run key is an immediate red flag — remove the registry value (Remove-ItemProperty) and delete the referenced file.

  • Don't stop at Run — check the related RunOnce and RunOnceEx keys too. These are meant for one-time setup tasks that self-delete after running, but malware sometimes (ab)uses them the same way as Run for a slightly less obvious persistence spot:
powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue
Expected result:Usually empty — legitimate RunOnce entries are typically transient (installer post-reboot steps) and self-delete after firing, so persistent entries sitting here are more unusual than in the regular Run key.
If it fails:No error mode given the suppression flag; treat any hit here with a bit more suspicion than a Run key entry precisely because RunOnce isn't meant to accumulate persistent entries.
  • Typing shell:startup or shell:common startup directly into the File Explorer address bar jumps straight to the current user's or all-users' Startup folder — a faster GUI alternative to typing out the full AppData\Roaming\... path from Section 10's command-line method.

  • If a Startup folder shortcut (.lnk file) looks legitimate by name but you want to confirm what it actually launches, check its Properties → Shortcut tab → Target field, or read it via PowerShell — a shortcut's displayed icon/name can be completely disconnected from what it really points to:

powershell
$sh = New-Object -ComObject WScript.Shell
$sh.CreateShortcut("C:\Users\Public\Desktop\SomeShortcut.lnk").TargetPath
Expected result:Prints the shortcut's actual target executable path/command as a string.
If it fails:
  • "Cannot find path" — use the real .lnk path from your Startup-folder listing above, not the placeholder.
  • If TargetPath shows something wildly different from what the shortcut's name/icon suggests (e.g. named "Adobe Update" but targeting powershell.exe -enc <base64>), that's a serious, high-priority finding.
  • See Section 22 for deeper persistence hunting (Winlogon hijacks, IFEO debugger hijacks, AppInit_DLLs, WMI event subscriptions) that goes beyond what msconfig/Task Manager will ever show you.

11. Windows Updates#

  • Control Panel → System and SecurityWindows UpdateChange settings → set to Install updates automatically (or the strongest option your README/scenario allows).
  • Click Check for Updates and install everything available, if internet access is available and the scenario allows it.
  • Before restarting to apply updates, make sure you know the admin password and have taken a fresh restore point / noted your progress — some rounds are timed and a bad restart costs you time.
  • Service Packs are a Windows 7-and-earlier concept; Windows 10/11 roll everything into cumulative updates — don't waste time hunting for a "service pack" on modern images.
powershell
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 20
Expected result:The 20 most recently installed updates (KB numbers) with install dates.
If it fails:Blank InstalledOn for some entries is a known cosmetic quirk, not an error — cross-check with Get-CimInstance Win32_QuickFixEngineering for an alternate view if dates matter for a forensics answer.
cmd
wmic qfe list brief /format:table
Expected result:A table of installed updates via the older wmic interface.
If it fails:wmic is removed by default on Windows 11 24H2+ — use the PowerShell Get-HotFix version above instead if "not recognized."

Why this matters right now, not just in principle: Microsoft's August 2026 Patch Tuesday alone fixed roughly 400 vulnerabilities, including a Windows Ancillary Function Driver (WinSock) elevation-of-privilege flaw (CVE-2026-68820) that was actively exploited before a patch existed, and a critical Microsoft QUIC remote-code-execution bug (CVE-2026-62815, CVSS 9.8) reachable with no authentication. "Fully updated" isn't a checkbox for its own sake — a single missed monthly cumulative update can leave one of these open. Get-HotFix/wmic qfe above is how you actually verify updates installed, not just that the setting says "automatic."

Things to try / extra points#

Tip: If the scoring VM has no internet access, Windows Update literally cannot download anything — don't burn time repeatedly clicking "Check for updates." Confirm connectivity first (Test-NetConnection, or just try a browser) and move on to other sections if updates truly aren't reachable. Many CyberPatriot images intentionally have some updates missing that cannot be resolved without internet, and partial credit for "Automatic Updates enabled" as a setting is still worth doing regardless of whether updates can download.

powershell
Test-NetConnection -ComputerName 8.8.8.8 -InformationLevel Detailed
Expected result:PingSucceeded: True with round-trip time stats if internet is reachable.
If it fails:
  • PingSucceeded: False confirms no internet — stop trying to download updates/tools and move to other sections, exactly as the tip above recommends.
  • If ICMP is specifically blocked but other traffic isn't, this can give a false "no internet" reading — cross-check with Test-NetConnection -ComputerName 8.8.8.8 -Port 443 (TCP-based) if you suspect ping alone is misleading.
  • Verify Windows Update the service is running/Automatic (see Section 9) — a disabled Windows Update service is sometimes the actual vulnerability being scored, independent of whether updates can download.

  • Windows 10/11 also uses a separate Update Orchestrator Service (UsoSvc) alongside the classic Windows Update service — check both, since disabling just one can leave updates silently non-functional even though "Windows Update" itself shows as running:

powershell
Get-Service -Name wuauserv, UsoSvc | Select Name, DisplayName, Status, StartType
Expected result:Both services shown, ideally not Disabled for StartType (Windows Update itself is often Manual/on-demand even when healthy — that's normal, not a finding by itself).
If it fails:
  • "Cannot find any service with service name 'UsoSvc'" on very old builds (pre-Windows 10) — this service doesn't exist there, ignore it.
  • StartType: Disabled on either is a real finding — fix with Set-Service <name> -StartupType Manual (their normal default state).
  • If "Check for updates" in the Settings app seems stuck or unresponsive, UsoClient StartScan triggers the same scan from the command line and sometimes un-sticks a hung GUI check:
cmd
UsoClient StartScan
Expected result:No console output (it's a fire-and-forget trigger) — check Settings → Windows Update afterward to see if a scan is now progressing.
If it fails:
  • "not recognized" on very old builds where this tool doesn't exist — just use the Settings app's "Check for updates" button instead.
  • This command genuinely gives no feedback either way, so the only way to confirm it worked is watching the Settings app UI change state.
  • A pending update that needs a reboot to finish applying can itself look like "updates aren't working" — check for a pending-reboot flag before assuming something's broken:
powershell
Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"
Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
Expected result:True/False for each — True means a reboot is pending to finish applying an already-installed update.
If it fails:
  • No error mode; these are simple existence checks.
  • If either is True, reboot when you're at a natural stopping point (per the Snapshot Checkpoint note below) rather than assuming updates are stuck.
  • Review Windows Update's own event log for install failures or blocked updates instead of guessing why an update didn't apply:
powershell
Get-WinEvent -LogName "Microsoft-Windows-WindowsUpdateClient/Operational" -MaxEvents 30 -ErrorAction SilentlyContinue |
    Select TimeCreated, Id, Message
Expected result:Recent update-related events (scan started, download progress, install success/failure) with details.
If it fails:
  • "No events were found" (suppressed by the error action flag) just means nothing's happened recently in this log — not a broken command.
  • A recurring failure Event ID is worth searching by that specific number for the actual error meaning.

Snapshot Checkpoint: Installing updates can trigger a reboot, and a reboot is exactly when an earlier broken change (bad service, bad UAC/RDP setting) surfaces as a hard lockout you can't easily fix while offline. Snapshot before you kick off updates or restart, so a bad reboot doesn't strand you.


12. User Account Control (UAC)#

GUI Method#

  • Control Panel → System and SecurityAction CenterChange User Account Control settings.
  • Move the slider to the top ("Always notify") and click OK (not just close the window — closing without OK discards the change).

Registry / Command-Line Method#

powershell
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableLUA" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "ConsentPromptBehaviorAdmin" -Value 2 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "PromptOnSecureDesktop" -Value 1 -Type DWord
Expected result:Silent on success; a logoff/logon or reboot is needed for EnableLUA changes to fully take effect (the other two apply more immediately but a fresh session is the safest way to confirm all three).
If it fails:
  • "Access is denied" needs elevation.
  • If UAC behavior doesn't seem to change after logging back in, verify with the read-back query further down this section rather than assuming the setting didn't apply — sometimes it's just that you're testing from a session that started before the change.

Things to try / extra points#

Tip: EnableLUA = 0 (UAC fully off) is a very common planted vulnerability — always verify it's 1. A machine with UAC disabled will also silently let a lot of the "run as administrator" prompts you'd normally expect just not happen, which is itself a clue something's off if you notice it.

Tip: ConsentPromptBehaviorAdmin values: 0 = elevate without prompting (bad), 2 = prompt for consent on secure desktop (recommended default), 5 = prompt for consent for non-Windows binaries. Verify it isn't 0.

CIS Benchmark cross-reference: Every registry value set in this section maps 1:1 to a named CIS Microsoft Windows 10/11 Benchmark, Level 1 "User Account Control:" Security Option (Admin Approval Mode, elevation prompt behavior for admins/standard users, detect app installations, secure desktop prompting, virtualize file/registry writes) — see the full list already in Section 6's table.

  • A closely related CIS Level 1 control worth checking alongside UAC: Windows Installer → "Always install with elevated privileges" should be Disabled. If it's Enabled (for both the Computer Configuration and User Configuration versions of the setting), any user — including a standard, non-admin account — can install an MSI package with full SYSTEM privileges, which is a direct and well-known privilege-escalation path that UAC alone won't stop.
powershell
# Check both halves of the "Always install with elevated privileges" setting (both must exist and be 0/absent to be safe)
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer" -Name "AlwaysInstallElevated" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer" -Name "AlwaysInstallElevated" -ErrorAction SilentlyContinue
Expected result:No output (property absent, the safe default) or AlwaysInstallElevated: 0.
If it fails:A value of 1 on EITHER key (both must be 1 for the vulnerability to actually be exploitable, but either being 1 is worth fixing) is a serious, high-priority finding — fix with Set-ItemProperty ... -Value 0 -Type DWord on whichever key showed 1, creating the key with -Force if it doesn't exist yet but you're setting it explicitly.
  • There's a fifth, easy-to-miss UAC registry value: FilterAdministratorToken controls whether Admin Approval Mode applies to the built-in Administrator account specifically (separate from EnableLUA, which controls UAC for everyone else). If this is 0, the built-in Administrator account silently runs with full, un-prompted elevation even with UAC otherwise on:
powershell
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "FilterAdministratorToken" -Value 1 -Type DWord
Expected result:Silent on success; requires logoff/logon to take effect, same as the core UAC settings above.
If it fails:
  • No special error mode beyond permissions.
  • Once set, the built-in Administrator account will itself now see UAC consent prompts like any other admin — expected behavior, not a bug, if you notice the built-in Administrator suddenly getting prompted where it didn't before.
  • If the Control Panel slider feels unreliable or is missing on your build, secpol.msc → Local Policies → Security Options has the same UAC settings as named policies (see Section 6) — a more direct path if the Action Center GUI is being uncooperative.

  • Verify all the values actually took, in one readable pass, rather than trusting that each Set-ItemProperty command silently succeeding means the setting is correct:

powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" |
    Select EnableLUA, ConsentPromptBehaviorAdmin, PromptOnSecureDesktop, FilterAdministratorToken
Expected result:EnableLUA: 1, ConsentPromptBehaviorAdmin: 2, PromptOnSecureDesktop: 1, FilterAdministratorToken: 1 if every earlier setting in this section landed correctly.
If it fails:Any value showing blank/$null means that specific property was never set (still at OS default, which for EnableLUA/PromptOnSecureDesktop is usually already the secure value — but don't assume, always confirm with this read-back rather than trusting the Set-ItemProperty calls silently succeeding).

13. Network Shares#

GUI / Command-Line Method#

cmd
net share
Expected result:Lists every share, its path, and remarks — includes default admin shares (C$, ADMIN$, IPC$) alongside any custom ones.
If it fails:No real error mode; this command essentially always works.
  • For every share not required, delete it:
cmd
net share <sharename> /delete
Expected result:Prints "The command completed successfully."
If it fails:
  • "The network connection could not be found" if the share name has a typo — get exact names from bare net share first.
  • Deleting a share that turns out to be required breaks whatever depended on it — re-share it with net share <name>=<path> if you need to undo this.
  • Shares ending in $ are hidden administrative/default shares — IPC$, C$, ADMIN$ are default Windows shares and IPC$ regenerates on reboot regardless. Only remove non-default, unauthorized shares unless the README explicitly says to strip default admin shares too (this can break some legitimate remote administration).

PowerShell Method#

powershell
Get-SmbShare
Get-SmbShare | Where-Object { $_.Name -notlike "*$" }
Remove-SmbShare -Name "ShareName" -Force
Expected result:
  • Get-SmbShare lists all shares; the filtered version excludes default $-suffixed admin shares.
  • Remove-SmbShare -Force is silent on success.
If it fails:
  • "not recognized" on very old builds (pre-Windows 8/2012) — use net share/net share ... /delete instead.
  • A custom share deliberately named to end in $ (a hiding trick) will be filtered OUT by the second command — always review the FULL unfiltered Get-SmbShare list too, not just the filtered view, or you'll miss exactly the kind of share this section warns about.
  • Also check share-level permissions on anything that must remain shared — make sure Everyone: Full Control isn't set on a share that should be restricted:
powershell
Get-SmbShareAccess -Name "ShareName"
Expected result:Lists account/permission pairs for that share (e.g. Everyone: Full).
If it fails:
  • "Cannot find the share" — use an exact name from Get-SmbShare.
  • Everyone: Full on a share that should be restricted is the classic finding — fix with Grant-SmbShareAccess/Revoke-SmbShareAccess, or via the Sharing tab in Explorer's folder Properties.

Things to try / extra points#

Tip: shrpubw (Share a Folder Wizard) is a fast GUI alternative for creating a properly permissioned share if the README requires you to create one for a specific business reason — don't just use "Everyone/Full Control" defaults.

  • Harden SMB itself, not just individual shares:
powershell
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
Set-SmbServerConfiguration -RequireSecuritySignature $true -Force
Expected result:Feature state changes to Disabled (may need a reboot to fully complete despite -NoRestart); the signature requirement is silent on success.
If it fails:
  • "Feature name is unknown" — confirm the exact name with Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol first; naming can differ slightly across builds.
  • If an old device on the network genuinely needs SMBv1, this will break connectivity to it — rare in a competition scenario but worth a moment's thought before applying.

SMBv1 is obsolete and vulnerable (EternalBlue/WannaCry-class exploits) — disabling it is safe on essentially every modern image and is a strong, low-risk point-scoring action.

  • Another CIS Level 1 SMB control worth setting alongside SMB1 removal: LanmanWorkstation → "Enable insecure guest logons" should be Disabled. When enabled, this setting lets the SMB client silently fall back to unauthenticated guest access against a remote share instead of failing — a subtle vulnerability that has nothing to do with your own shares, but with how this machine connects to others.
powershell
Set-SmbClientConfiguration -EnableInsecureGuestLogons $false -Force
Expected result:
  • Silent on success.
  • Verify with Get-SmbClientConfiguration | Select EnableInsecureGuestLogons.
If it fails:If this machine legitimately needs to connect to an old NAS/share that only offers guest access, disabling this will break that connection — low risk in most competition scenarios, but worth a moment's thought if the README describes such a dependency.

Snapshot Checkpoint: The next section disables Remote Desktop and Remote Assistance. If you are currently connected to this machine over RDP rather than sitting at its console, disabling RDP here can disconnect you and lock you out of your own session. Confirm you have local/console access (or another authorized admin who does) before proceeding, and take a snapshot first regardless — this is one of the easiest ways to accidentally strand your own team mid-round.


14. Remote Desktop & Remote Access#

GUI Method#

  • Right-click This PC/My ComputerPropertiesRemote settings (or Advanced System SettingsRemote tab).
  • Uncheck Allow Remote Assistance connections to this computer.
  • Set Remote Desktop to Don't allow connections to this computerunless the README explicitly requires RDP access for a stated user/reason, in which case use the most restrictive allowed option (e.g., "Allow connections only from computers running Remote Desktop with Network Level Authentication").
  • Apply, OK.

Registry / Command-Line Method#

powershell
# Disable RDP entirely
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 1 -Type DWord

# If RDP must stay enabled, at least require Network Level Authentication
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 1 -Type DWord

# Disable Remote Assistance and RDP shadowing/monitoring
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Remote Assistance" -Name "fAllowToGetHelp" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -Name "Shadow" -Value 0 -Type DWord
Expected result:Each silent on success; the RDP-deny setting takes effect immediately (no reboot needed) — new RDP connection attempts are refused right away.
If it fails:If you're managing this machine over RDP right now, the first command disconnects you immediately — exactly what the Snapshot Checkpoint just above this section warns about; only run it from local/console access, or from a different remote channel you know will survive. "Cannot find path" on the NLA/Remote-Assistance/Shadow lines means the key doesn't exist yet on this build — add -Force to create it.

Things to try / extra points#

CIS Benchmark cross-reference: The full Remote Desktop Services Administrative Templates block in Section 24's appendix (Do not allow drive/COM port/LPT port/smart card redirection, Always prompt for a password, Require secure RPC communication, Require user authentication with NLA, Set client connection encryption level: High) is drawn directly from CIS Microsoft Windows 10/11 Benchmark, Level 1 RDS guidance — if RDP is required by your scenario, that block is the fastest way to harden it without disabling it outright.

Tip: If RDP is required by the README, verify who's allowed in via the Remote Desktop Users group (see Section 3) — an unauthorized member there is a classic vulnerability even when RDP itself is legitimately needed.

  • Check for third-party remote access tools too (TeamViewer, AnyDesk, VNC, LogMeIn, Chrome Remote Desktop) — these bypass Windows' own RDP controls entirely and are common "unauthorized remote access" plants. Uninstall unless authorized.
powershell
Get-Process | Where-Object { $_.ProcessName -match "teamviewer|anydesk|vnc|logmein" }
Get-Service | Where-Object { $_.DisplayName -match "TeamViewer|VNC|AnyDesk" }
What this filter is doing
Where-Object filters a list down to only the items matching a condition. $_.ProcessName means "this process's name." -match checks against a regex pattern, and the | (pipe) characters inside the quotes mean "or" — so this reads as "keep any process whose name contains teamviewer, OR anydesk, OR vnc, OR logmein," catching several remote-access tools with one line instead of four separate checks.
Expected result:Matching processes/services if any of these tools are installed and running, or nothing if clean.
If it fails:No error mode; a hit needs a judgment call against the README — if not explicitly authorized, uninstall via Control Panel/Settings → Apps (stopping the process/service alone doesn't remove it, and it can just restart) rather than just killing the process.

15. Data Execution Prevention & Exploit Mitigations#

GUI Method (DEP)#

  • Control Panel → view by Small IconsSystemAdvanced system settingsPerformance section → SettingsData Execution Prevention tab.
  • Select Turn on DEP for all programs and services except those I select, and leave the exceptions list empty unless a required program genuinely needs an exception (rare, and should be justified by the README).

Command-Line / System-Wide Mitigations#

powershell
# Turn on the major system-wide exploit mitigations in one shot (DEP, SEHOP, ASLR-related force relocation, etc.)
Set-ProcessMitigation -System -Enable DEP, EmulateAtlThunks, SEHOP, ForceRelocateImages
What this command does
This is one cmdlet turning on four separate exploit-mitigation features system-wide at once, comma-separated in a single -Enable list: DEP (blocks code from running in memory marked "data only"), SEHOP (protects a specific Windows exception-handling mechanism attackers abuse), and ForceRelocateImages (a stronger form of ASLR, randomizing where programs load in memory so exploits can't predict addresses).
Expected result:
  • Silent on success.
  • Verify with Get-ProcessMitigation -System.
If it fails:
  • "not recognized" on Windows 7/early 8 — this cmdlet needs Windows 8.1+; use the DEP GUI method above as the fallback on older builds.
  • Rarely breaks legitimate software on a modern OS, but if an older required application starts crashing after this, DEP/mitigation incompatibility is worth checking first via that app's own compatibility settings.
powershell
# Protect LSASS memory from credential-dumping tools (e.g., Mimikatz-style attacks)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -Value 1 -Type DWord
Expected result:Silent on success; requires a reboot to take effect.
If it fails:
  • No common error beyond permissions.
  • Can interfere with legitimate security/monitoring tools or some VPN clients that hook LSASS — test required functionality after rebooting.
powershell
# CIS Level 1 (MS Security Guide): disable WDigest, which caches a reversible plaintext-equivalent
# copy of the logon password in LSASS memory purely for backward compatibility with old auth schemes.
# This is one of the very first things a credential-dumping tool checks for.
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -Value 0 -Type DWord
Expected result:Silent on success; takes effect for new logons (existing sessions may still have cached credentials until they log off/on).
If it fails:
  • "Cannot find path" if the WDigest key doesn't exist yet — add -Force.
  • Extremely low functional risk; WDigest auth is legacy and rarely relied upon by anything modern.
powershell
# CIS Level 1 (MSS Legacy): force Safe DLL Search Mode, which searches the system directories
# before the current working directory when an app loads a DLL by name — blocks a classic DLL
# hijacking/planting technique where malware drops a same-named malicious DLL next to a legit exe.
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "SafeDllSearchMode" -Value 1 -Type DWord
Expected result:Silent on success; this is actually the Windows default already on modern builds, so this command is often a no-op confirming an already-correct state.
If it fails:No real error mode; if it reads back as 0 on this specific image, that's a real finding since it's an unusual thing to have deliberately disabled.
powershell
# CIS Level 1 (Administrative Templates > System > Early Launch Antimalware): make sure the
# Early-Launch Antimalware boot driver only allows Good/Unknown drivers (or Good/Unknown/Bad-but-critical)
# to load at boot — this stops a malicious or unsigned boot-start driver from loading before AV can scan it.
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\EarlyLaunch" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\EarlyLaunch" -Name "DriverLoadPolicy" -Value 3 -Type DWord
Expected result:
  • Silent on success; both commands run with no output.
  • Takes effect on next boot.
If it fails:
  • "Access is denied" if not run elevated.
  • Value 3 = Good/Unknown/Bad-but-critical (the balanced default); 1 = Good only (strictest, can block legitimate but unsigned boot drivers — risky right before a competition ends if it breaks boot-critical hardware drivers); if the box fails to boot after a reboot, boot into Safe Mode and set this key back to 7 (disabled) or delete it.

Things to try / extra points#

Tip: Set-ProcessMitigation -System changes are broad and generally low-risk on a client workstation, making this a good "extra credit" action once the core checklist is done — but always test that required line-of-business software still launches afterward, especially older/legacy applications the README might call out.

Tip: RunAsPPL (LSA Protection) requires a reboot to take effect, and on older builds/some drivers can cause compatibility issues — apply it, but budget time to verify the box still boots and logs in cleanly afterward before moving on.

Tip: WDigest, Safe DLL Search Mode, and Early Launch Antimalware policy are all CIS Level 1 controls that are easy to miss because they don't show up in a typical GUI walkthrough — they're registry-only settings. All three are low-risk to apply (no reboot required for the first two; Early Launch Antimalware policy takes effect on next boot).


16. BitLocker & Encryption#

BitLocker is less commonly a core scored item on client images than on the policy side (the Administrative Templates reference in Section 24 has a full BitLocker GPO block), but still worth checking:

  • Control Panel → BitLocker Drive Encryption — check current status of all drives.
  • If the README requires encryption on a specific drive, enable it: right-click the drive → Turn on BitLocker and follow the wizard (choose to save the recovery key somewhere accessible to you, e.g., a file on a USB stick provided by the competition, or print it — never leave it as the only unencrypted copy on the same drive if avoidable).
  • If BitLocker is already on and the README doesn't call for it, do not disable it — decrypting can take a long time and provides no points; leave it alone unless specifically instructed.
powershell
Get-BitLockerVolume
manage-bde -status
Expected result:A table (or text report from manage-bde) listing each volume with its VolumeStatus (FullyDecrypted/FullyEncrypted/EncryptionInProgress) and ProtectionStatus (On/Off).
If it fails:
  • Get-BitLockerVolume is "not recognized" on Windows editions without BitLocker (e.g., Home edition) — BitLocker is a Pro/Enterprise/Education feature; check the edition with Get-ComputerInfo | Select WindowsProductName before assuming it's missing/misconfigured.
  • manage-bde requires an elevated prompt.

Tip: BitLocker Drive Encryption service should be at least Manual (see Services table) if BitLocker is or might be used — don't disable it if the README wants encryption enabled.

Tip: EFS (Encrypting File System) is a separate, file/folder-level encryption feature independent of BitLocker — if the README asks about "encrypted files," check cipher /u /n to list EFS-encrypted files without changing anything.

cmd
cipher /u /n
What /u and /n mean
cipher is normally used to wipe free disk space, but with these two flags it does something different: /u updates the user's EFS (Encrypting File System) key info, and /n tells it NOT to actually re-encrypt anything while doing so — combined, this just lists which files are EFS-encrypted without changing a single one.
Expected result:Lists any EFS-encrypted files under the current user's profile (or wherever pointed), with no changes made (/u /n = update user's key info without actually re-encrypting).
If it fails:
  • Returns nothing/empty if no EFS-encrypted files exist — that's a normal clean result, not an error.
  • Must be run once per user profile you want to check (it only scans the currently-logged-on user's accessible files by default).

17. Internet Explorer / Edge / Browser Security#

Internet Explorer (legacy, still present on many images)#

  • Open IE → ToolsInternet Options.
  • General tab: set homepage to a neutral page (e.g., about:blank or a scenario-approved page — don't assume google.com is always correct if the README specifies something else).
  • General → Browsing History → Settings: choose Never on the "Check for newer versions of stored pages" option, and enable Delete browsing history on exit.
  • Security tab: raise the security level for each zone toward High.
  • Privacy tab: raise to Block All Cookies (or the strictest level that doesn't break required functionality).
  • Content tab: clear SSL state.
  • Content → AutoComplete Settings: uncheck all boxes, then clear AutoComplete history and check Manage Passwords is empty.
  • Apply, OK. Repeat similarly (best effort, exact steps vary) for any other installed browser (Chrome, Firefox, Edge).

Chrome / Firefox / Edge (Chromium) — Policy-Based Hardening#

  • Prefer setting browser security via Group Policy ADMX templates / registry policy keys so settings can't be casually changed back through the UI, rather than only clicking through in-browser settings.
powershell
# Example: disable Firefox's built-in password manager via policy
New-Item -Path "HKLM:\SOFTWARE\Policies\Mozilla\Firefox" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Mozilla\Firefox" -Name "OfferToSaveLogins" -Value 0 -Type DWord
Expected result:Silent on success; Firefox picks up the policy on next launch (no reboot needed), greying out the password-saving option in about:preferences.
If it fails:
  • No error if Firefox isn't installed — the key is just created and does nothing.
  • If Firefox is installed but the setting doesn't grey out, confirm the browser was fully closed (not just the window — check for a lingering firefox.exe process) and relaunched; policy keys are read at startup.

Things to try / extra points#

Tip: Saved credentials/autofill data in any browser is a common scored item — check Settings → Passwords (Chrome/Edge) and about:logins (Firefox) and clear anything that shouldn't be stored, especially on a shared/kiosk-style scenario machine.

  • Clear Windows' own saved credentials (Control Panel → User AccountsManage your credentials) — remove everything under both Windows Credentials and Web Credentials unless the README says a saved credential is required.
cmd
cmdkey /list
cmdkey /delete:<TargetName>
Expected result:/list prints each stored credential's Target, Type, and User/delete prints confirmation the target was removed.
If it fails:"CMDKEY: Not Found" from /delete if you mistype the <TargetName> — copy it exactly (including any LegacyGeneric:target= prefix) from the /list output rather than retyping it by hand.

Tip: Set each browser to auto-update if internet access allows — outdated browser versions are a common "missing updates" style vulnerability distinct from Windows Update itself.


18. Power Settings#

  • Control Panel → System and SecurityPower Options.
  • Require a password on wakeup — enable this.
  • Choose when to turn off the display / Change advanced power settings → set a reasonably short display/sleep timeout (e.g., 1–15 minutes, whatever the README/scenario expects) for both battery and plugged-in states.
  • Save changes.
powershell
powercfg /query
powercfg /change monitor-timeout-ac 10
powercfg /change standby-timeout-ac 15
Expected result:/query dumps the active power plan's full settings tree; the two /change commands are silent on success.
If it fails:/change only affects the AC (plugged-in) profile by design here — on a laptop image, also run the -dc equivalents (monitor-timeout-dc, standby-timeout-dc) or the README/rubric may still flag battery-mode timeouts as unset. "Access is denied" means the prompt isn't elevated.

Things to try / extra points#

Tip: "Require a password on wakeup" is a simple, high-confidence checkbox-style item — quick and reliable points, do it early.


19. Prohibited & Unauthorized Software / Files#

  • Cross-check every installed program (Section 8) against the README's authorized list, with special attention to:
    • Games (Steam, Minecraft, Solitaire/other bundled Windows games, emulators, ROMs)
    • Hacking/pentesting tools (nmap, Wireshark, Metasploit, Cain & Abel, netcat, John the Ripper, Hydra, keyloggers, LOIC/HOIC, Aircrack-ng)
    • P2P/torrent clients (uTorrent, BitTorrent, qBittorrent, Vuze, LimeWire, eMule)
    • Cracks/keygens/pirated software indicators
    • Unauthorized remote access tools (see Section 14)
    • Media files in user profiles that violate an "acceptable use" style scenario rule (mp3/mp4/avi/etc. outside of anything explicitly authorized)
powershell
# Remove built-in/provisioned game & Xbox apps (adjust the match pattern to your scenario's definition of "unauthorized")
Get-AppxPackage -AllUsers | Where-Object { $_.Name -match "Xbox|Games|Zune|Solitaire" } |
    Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -match "Xbox|Games|Zune|Solitaire" } |
    Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
Expected result:Silent on success (errors suppressed by design); re-running Get-AppxPackage -AllUsers | Where-Object Name -match "Xbox|Games|Zune|Solitaire" afterward should return nothing.
If it fails:
  • Some packages are protected system components that refuse removal even with -AllUsers — that's expected for a few Xbox-identity packages tied to the OS itself; don't chase those further, they aren't "installed games" in the scored sense.
  • If nothing is removed at all, confirm you're running as an actual admin PowerShell window (AppX cmdlets silently no-op for non-admins more often than they error).
powershell
# Broad file sweep for prohibited media across all user profiles
Get-ChildItem -Path C:\Users -Recurse -Include *.mp3,*.mp4,*.avi,*.mkv,*.wav,*.wmv,*.mov -ErrorAction SilentlyContinue |
    Select FullName, Length, LastWriteTime
Expected result:A list of every matching media file found under any user profile, with path/size/modified date.
If it fails:
  • Can take a long time on a large disk — that's normal, not a hang; let it finish.
  • -Include only works reliably here because -Recurse is present; if you add a -Path without a trailing wildcard behavior changes on older PowerShell versions — test on a small folder first if results look wrong.
  • Files in AppData or Windows-owned media (sample music/videos) will show up too; cross-reference against the README before deleting anything — don't nuke default Windows sample media as if it were user-added contraband.
  • Windows Copilot / Widgets / Cortana — three newer consumer-shell features that ship enabled by default on current Windows 11 images and are explicitly CIS Level 1 "should be Disabled" items. None of these are malware, but each is an unauthorized-software-adjacent attack surface (cloud AI assistant with system access, a widgets panel that pulls remote content, a voice assistant with microphone access) that a strict scenario is likely to flag:
powershell
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot" -Name "TurnOffWindowsCopilot" -Value 1 -Type DWord
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Dsh" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Dsh" -Name "AllowNewsAndInterests" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name "AllowCortana" -Value 0 -Type DWord
Expected result:Silent on success; Copilot/Widgets/Cortana disappear from the taskbar after a sign-out/sign-in or Explorer restart (Stop-Process -Name explorer -Force then let it relaunch, or just reboot).
If it fails:
  • "Cannot find path" on the last line if Windows Search key doesn't exist yet — add New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Force before it.
  • These features don't exist at all pre-Windows 11 (Copilot) or on older Windows 10 builds (Widgets) — "not recognized"/no visible change on those images is expected, not a failure, just skip this block.

Things to try / extra points#

Tip: Before deleting any flagged file, double check it isn't referenced by a forensics question ("what is the name of the largest media file on this system?") — screenshot/record first, delete second.

Tip: Renamed file extensions are a known trick (virus.exe renamed to virus.jpg.exe or virus.txt) — when in doubt, check actual file type/magic bytes rather than trusting the extension:

powershell
Get-Item "C:\path\to\suspicious.jpg" | Select Name, Extension, Length
# Or open in a hex-capable tool / check file signature bytes manually if truly suspicious
Expected result:File metadata only — this does NOT tell you the true file type, just the claimed extension; genuine verification requires opening the file or checking magic bytes.
If it fails:
  • No error mode.
  • To actually check magic bytes without a hex editor, Format-Hex "C:\path\to\suspicious.jpg" -Count 16 in PowerShell 5.1+ shows the first bytes — an EXE starts with 4D 5A ("MZ"), a real JPEG starts with FF D8 FF; a mismatch is the actual proof of a renamed/disguised file.
  • Disable Autorun/AutoPlay globally — a classic vector for "prohibited/malicious content auto-launching from removable media":
powershell
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "NoDriveTypeAutoRun" -Value 255 -Type DWord
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer" -Name "NoAutoplayfornonVolume" -Value 1 -Type DWord
Expected result:Silent on success; takes effect immediately for new media insertions, no reboot required.
If it fails:
  • No common error beyond permissions/missing path (fixed by -Force on New-Item, already included).
  • 255 (0xFF) disables Autorun on all drive types; if a required scenario workflow depends on Autorun for a specific approved drive type, that's a real conflict — check the README before applying blanket lockdown.

20. Windows Features (Add/Remove Components)#

GUI Method#

  • Control Panel → Programs and FeaturesTurn Windows features on or off (or optionalfeatures.exe directly).
  • Disable (unless required by README):
    • Games
    • Internet Information Services (IIS) and IIS Hostable Web Core
    • Media Features (if scenario disallows media playback)
    • Print and Document Services (unless printing required)
    • SNMP
    • Telnet Client / Telnet Server
    • TFTP Client
    • XPS Services / XPS Viewer
  • Be careful with Windows PowerShell — the historical source checklist lists it as something to disable, but doing so removes your own ability to run most commands in this document. Only disable PowerShell if the README explicitly requires it and you're finished using it, or use PowerShell 2.0-engine-removal-style hardening (removing the legacy v2 engine, Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2) instead of removing PowerShell entirely.

Command-Line Method#

powershell
Get-WindowsOptionalFeature -Online | Where-Object { $_.State -eq "Enabled" } | Select FeatureName

Disable-WindowsOptionalFeature -Online -FeatureName TelnetClient, TFTP, PeerToPeer -NoRestart
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2, MicrosoftWindowsPowerShellV2Root -NoRestart
Expected result:The Get- line lists every currently-enabled optional feature by name; each Disable- call reports RestartNeeded : True/False (with -NoRestart you defer the actual reboot).
If it fails:
  • "The feature name X is unknown" if a listed feature isn't present on this SKU/build — not every feature exists on every Windows edition; drop the missing name from the list and re-run with the rest.
  • Disabling SMB1Protocol can break connectivity to very old file shares/printers that still require SMBv1 — check the README/network requirements before disabling if the scenario mentions legacy shared devices.
  • Changes queue until the next reboot; nothing takes effect until you restart.

Things to try / extra points#

Tip: If World Wide Web Publishing Service shows up running (see Services), that means IIS is installed — treat it the same as any other unauthorized server role on a client workstation and disable the feature entirely unless the README specifically calls for a web server role.

Tip: Removable-media/USB storage can be blocked entirely at the driver level if the scenario calls for locking down physical data-exfiltration vectors:

powershell
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\USBSTOR" -Name "Start" -Value 4 -Type DWord

Value 4 disables the USB mass-storage driver from starting; 3 restores default (manual start, i.e. normal USB drive functionality). Don't apply this if the competition needs you to transfer files via USB.

Expected result:Silent on success; takes effect the next time a USB storage device is plugged in (already-connected devices keep working until unplugged/replugged, or reboot to apply immediately).
If it fails:
  • "Access is denied" without elevation.
  • If you accidentally lock yourself out of a USB drive you need (e.g., the scoring engine/README delivered via USB), set the value back to 3 and unplug/replug the drive — no reboot required to restore access.

21. Scheduled Tasks#

GUI Method#

  • Open taskschd.msc (Task Scheduler).
  • Browse the Task Scheduler Library, expanding all folders (don't just check the root).
  • Review every non-Microsoft task, and any Microsoft-path task that looks off (unexpected trigger, unexpected action/binary). Disable or delete unauthorized tasks.

Command-Line Method#

powershell
Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" } | Select TaskName, TaskPath, State

# Focus on non-Microsoft tasks specifically — these are far more likely to be planted
Get-ScheduledTask | Where-Object { $_.State -ne "Disabled" -and $_.TaskPath -notlike "\Microsoft*" } |
    Select-Object TaskName, TaskPath
Expected result:A table of every active (non-disabled) task with name, folder path, and state — the second command narrows to non-Microsoft tasks, which is the higher-signal list to review first.
If it fails:Get-ScheduledTask is "not recognized" on PowerShell 2.0/very old images — fall back entirely to the schtasks command below, which works on every Windows version back to XP.
cmd
schtasks /query /fo LIST /v
Expected result:A verbose list-format dump of every task including Task Name, Next/Last Run Time, and (critically) the Task To Run field showing the actual command/binary executed.
If it fails:No error mode; output is long — pipe to more (schtasks /query /fo LIST /v | more) or redirect to a file (schtasks /query /fo LIST /v > tasks.txt) if it scrolls past what you can review on screen.

Things to try / extra points#

Tip: Malicious scheduled tasks are one of the most common persistence mechanisms used in vulnerable CyberPatriot images — always check the task's Actions tab for what program/script it actually runs, not just its name (a task can be named "Adobe Update Check" and run something else entirely).

powershell
Get-ScheduledTask -TaskName "SuspiciousTaskName" | Select -ExpandProperty Actions
Expected result:The task's Execute (program/script path) and Arguments fields — this is the ground truth of what the task actually does, regardless of its display name.
If it fails:"No MSFT_ScheduledTask objects found" if the name is wrong or has trailing whitespace — copy the exact TaskName from the earlier Get-ScheduledTask output rather than retyping.
  • To disable a confirmed-bad task without breaking a required trigger pattern you might want to reference later, disable it rather than deleting outright (mirrors the "disable, don't delete" philosophy from account management):
powershell
Disable-ScheduledTask -TaskName "SuspiciousTaskName" -TaskPath "\"
Expected result:Returns the task object with State : Disabled.
If it fails:"No MSFT_ScheduledTask objects found" if -TaskPath doesn't match — -TaskPath must match the task's folder exactly (root is "\", but subfolder tasks need e.g. "\Microsoft\Windows\SomeFolder\" with both leading and trailing backslashes); get the exact value from the TaskPath column in the earlier query rather than guessing.

22. Registry Autoruns & Hidden Persistence#

Beyond msconfig/Task Manager Startup entries (Section 10), several registry locations are classic malware persistence points that the GUI startup tools do not show.

Image File Execution Options (IFEO) "Sticky Keys" Hijack#

A famous technique: redirect the debugger for an accessibility tool (sethc.exe, utilman.exe, osk.exe, magnify.exe, narrator.exe, displayswitch.exe) to cmd.exe, giving SYSTEM-level shell access from the logon screen.

powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*" -ErrorAction SilentlyContinue |
    Select-Object PSChildName, Debugger
Expected result:On a clean machine, this returns nothing (or only entries with no Debugger value populated) — IFEO subkeys legitimately exist for things like Visual Studio JIT debugging, but a Debugger value pointing at a shell is the red flag, not the mere existence of IFEO entries.
If it fails:
  • No error mode.
  • Don't panic at IFEO subkeys for unrelated apps (some legitimate software uses IFEO for compatibility shims) — only act on entries where PSChildName is an accessibility tool (sethc.exe, utilman.exe, etc.) with a Debugger value set at all.
  • If any Debugger value points to cmd.exe, powershell.exe, or anything other than the tool's own expected behavior, delete that Debugger value/key immediately. Expected result: Remove-ItemProperty -Path "HKLM:\SOFTWARE\...\Image File Execution Options\sethc.exe" -Name "Debugger" (or delete the whole subkey with Remove-Item) — silent on success. If it fails: "Access is denied" without elevation. After removal, test by pressing Shift 5 times at the logon screen (not while logged in) to confirm Sticky Keys launches normally instead of a command prompt.

Winlogon Shell/Userinit Hijack#

powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" | Select-Object Shell, Userinit
Expected result:Shell : explorer.exe and Userinit : C:\Windows\system32\userinit.exe,.
If it fails:
  • No error mode.
  • To fix a hijacked value: Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "Shell" -Value "explorer.exe" (and similarly for Userinit, remembering the trailing comma) — takes effect on next logon, so log off/on or reboot to confirm the fix actually stuck rather than trusting the registry read alone.
  • Expected defaults: Shell = explorer.exe, Userinit = C:\Windows\system32\userinit.exe, (note the trailing comma is normal). Anything else appended or substituted is a persistence/hijack indicator — restore the defaults.

AppInit_DLLs / AppCertDlls (DLL Injection)#

powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Session Manager\AppCertDlls" -ErrorAction SilentlyContinue
Expected result:Empty AppInit_DLLs string value (or the property/key absent entirely) on a clean machine; AppCertDlls key is normally absent altogether.
If it fails:No error mode; errors are suppressed by design so an absent key just returns nothing — that's the clean/expected case, not a failure.
  • These should normally be empty/absent. If populated with an unfamiliar DLL path, that DLL is being force-loaded into every process (or every process calling CreateProcess, for AppCertDlls) — investigate and clear it:
powershell
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 0 -Type DWord
Expected result:Silent on success; this disables the AppInit_DLLs loading mechanism entirely (belt-and-suspenders alongside clearing the DLL path itself) on both native and WOW64 (32-bit-on-64-bit) registry views.
If it fails:
  • "Cannot find path" on the WOW6432Node line on a genuine 32-bit OS — that registry view doesn't exist there; skip that line and run only the native path.
  • To fully remediate a populated AppInit_DLLs value, also clear the DLL path itself: Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -Value "".

Admin-Tool Sabotage via Policy Registry Keys#

A recurring, low-tech CyberPatriot technique: the scenario (or a "malicious insider") disables Task Manager, cmd.exe, or Control Panel for the current user via raw registry policy keys — without a corresponding Group Policy Object, so it won't show up when you check gpresult. This matters because a locked Task Manager or cmd.exe is usually hiding a bigger problem: if you can't open Task Manager, you can't see the malicious process; if cmd.exe is blocked, some of your own remediation commands may silently fail.

powershell
# 1. Check the three classic "lock the admin out of their own tools" keys
Get-ItemProperty "HKCU:\Software\Policies\Microsoft\Windows\System" -Name "DisableCMD" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name "DisableTaskMgr" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "NoControlPanel" -ErrorAction SilentlyContinue
Expected result:No output (property doesn't exist) on a clean profile; a returned object with the property set to 1/2 means that tool is sabotaged for this user.
If it fails:If Task Manager is already locked and you need to confirm sabotage visually too, try Ctrl+Shift+Esc — "Task Manager has been disabled by your administrator" confirms it independent of the registry read.
  • If any of these keys exist and are set to 1 (or 2 for DisableCMD, which also blocks .bat/.cmd scripts), that tool has been deliberately sabotaged for the current user. Remove or zero them out:
powershell
# 2. Remove/zero each one that was found set
Remove-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\System" -Name "DisableCMD" -ErrorAction SilentlyContinue
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name "DisableTaskMgr" -ErrorAction SilentlyContinue
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "NoControlPanel" -ErrorAction SilentlyContinue
Expected result:Silent on success (errors suppressed by design, so a key that was never present just no-ops); takes effect immediately for Control Panel/Task Manager, may need a log off/on for cmd.exe restrictions to fully clear.
If it fails:If cmd.exe itself is what's blocked (DisableCMD = 2) you may not be able to run this PowerShell block from a blocked cmd.exe window at all — run it from a PowerShell window instead (PowerShell isn't affected by DisableCMD), or via Task Manager's "Run new task" if Task Manager itself is still accessible.
  • These are per-user (HKCU) keys, so if there are multiple user profiles on the box, repeat the check for each one by loading their hive (reg load) or checking HKEY_USERS\<SID>\... instead of just your own logged-in profile's HKCU.

WMI Event Subscriptions (Fileless Persistence)#

powershell
Get-CimInstance -Namespace root\subscription -ClassName __EventConsumer
Get-CimInstance -Namespace root\subscription -ClassName __EventFilter
Get-CimInstance -Namespace root\subscription -ClassName __FilterToConsumerBinding
What WMI event subscriptions are
This checks for a fileless persistence trick: WMI (Windows Management Instrumentation) can be configured to automatically run a command whenever some condition is met (e.g., "every time a process named X starts") — with no file ever written to disk and no entry in the normal Startup/Task Scheduler lists. __EventFilter defines the trigger condition, __EventConsumer defines what runs, and __FilterToConsumerBinding links the two together — malware sets up all three, so all three need checking.
Expected result:
  • Empty output on a clean machine (these classes normally have zero instances).
  • Any returned object — especially a CommandLineEventConsumer with a suspicious CommandLineTemplate — is a real persistence finding.
If it fails:
  • "Invalid namespace" is very unusual (this namespace exists on all modern Windows) — more likely just genuinely empty results, which is the expected clean state.
  • To remove a confirmed-malicious binding, delete in this order — binding first, then filter and consumer — via Get-CimInstance ... | Remove-CimInstance, since removing the filter/consumer first can leave an orphaned binding reference.
  • These allow malware to execute on a trigger (e.g., "every time a process named X starts") without any file or Run-key ever appearing — this is an advanced technique but worth a quick look on a harder image or if a forensics question hints at "no obvious startup entry found."

Things to try / extra points#

Tip: This class of persistence (IFEO, Winlogon, AppInit_DLLs, WMI subscriptions) is rare in beginner-level CyberPatriot images but shows up more in advanced/high-scoring rounds. If your team has already done the "obvious" checklist items and the score seems capped, this section is where to look next.

Tip: Environment variables can also be abused for persistence/injection — a quick sanity check:

powershell
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Expected result:Standard system environment variables (Path, TEMP, windir, etc.) with expected values — Path should contain only legitimate system/application directories.
If it fails:
  • No error mode.
  • A Path entry pointing at an unusual writable user-owned folder (e.g., something under AppData or C:\Users\Public) is the actual red flag — that folder could contain a malicious binary shadowing a legitimate command name via search-order hijacking.
  • Reset system folder permissions if you suspect a rootkit modified ACLs on core Windows directories (use cautiously — this is a broad, slow operation):
cmd
icacls "C:\Windows\System32" /reset /T /C /Q
What each icacls flag means
/reset resets permissions back to their inherited defaults. /T applies it recursively through every subfolder. /C tells it to keep going even if it hits an error on an individual locked file, instead of stopping the whole operation. /Q suppresses the normal per-file success messages so you just get a final summary instead of a huge scroll of text.
Expected result:Scrolling output as it processes every file/folder under System32, ending with a summary; can take several minutes.
If it fails:
  • This is a heavy, disruptive operation — resetting inherited ACLs on the entire System32 tree can break third-party security software or drivers that legitimately customized permissions there; only run this if you have specific, strong evidence of ACL tampering (not as a routine step), and be prepared that it may require a reboot afterward if the system behaves oddly.
  • /C continues past individual access-denied errors on locked system files rather than aborting — some "failed" lines for in-use files during the run are normal and expected, not a sign the whole operation failed.

23. Event Log Review & Audit Logging#

GUI Method#

  • Open eventvwr.msc.
  • Review Windows Logs → Security for logon failures (Event ID 4625), new user creation (4720), account enabled/disabled (4722/4725), group membership changes (4728/4732/4756), and any other anomalies relevant to forensics questions.
  • Review Windows Logs → System and Application for service failures, driver issues, or crash patterns.
  • Increase log size / set retention so logs aren't silently overwritten before you can review them (Properties on each log → increase Maximum log size, set "Overwrite events as needed" or "Archive the log when full").

Command-Line Method#

powershell
Get-WinEvent -LogName Security -MaxEvents 100 | Select TimeCreated, Id, Message

# Failed logons specifically
Get-WinEvent -LogName Security -FilterXPath "*[System[EventID=4625]]" -MaxEvents 50

# New local user created
Get-WinEvent -LogName Security -FilterXPath "*[System[EventID=4720]]" -MaxEvents 50
Expected result:A table of matching events, newest first, with timestamp/ID/message text.
If it fails:
  • "No events were found that match the specified selection criteria" for the filtered queries just means zero matching events exist (e.g., no failed logons yet) — that's a valid clean result, not an error. "Attempted to perform an unauthorized operation" means the Security log requires an elevated PowerShell session to read even for viewing.
  • If the Security log's audit policy hasn't been configured (see next block), event ID 4720/4625 may simply never have been logged in the first place regardless of query correctness.

Enabling Full Auditing (also covered in Section 5, repeated here for context)#

cmd
auditpol /set /category:* /success:enable /failure:enable
Expected result:The command was successfully executed.
If it fails:
  • "Access is denied" without an elevated prompt.
  • Enabling every category at max verbosity generates a LOT of log volume — combined with the log-size increase noted below, otherwise logs will rotate/overwrite fast and you'll lose the very evidence you just started collecting.

PowerShell Script-Block Logging (advanced/extra credit)#

powershell
Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope LocalMachine -Force

New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Force | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 -Type DWord
Expected result:Silent on success; script-block logging starts capturing decoded PowerShell command content to the Microsoft-Windows-PowerShell/Operational event log (Event ID 4104) for any script run afterward.
If it fails:See the caution note directly below — Set-ExecutionPolicy Restricted breaks your own future .ps1 script execution for the rest of the round; if that happens and you need scripts working again, run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force to loosen it back up.

Caution: Setting the PowerShell execution policy to Restricted will block your own future .ps1 scripts from running (though inline commands typed directly into the console still work). If you plan to keep using PowerShell scripts during the round, use RemoteSigned instead, or apply Restricted only as your very last step before moving on.

Things to try / extra points#

Tip: Never clear the event logs to "clean things up" — that destroys forensic evidence you may still need for scoring questions, and log-tampering itself is sometimes a scored/penalized action.

Tip: wevtutil qe Security /c:1 /rd:true /f:text (or the Get-WinEvent equivalents above) let you pull specific recent entries fast without opening the heavier Event Viewer GUI — useful under time pressure.

CIS Benchmark cross-reference: CIS Level 1 recommends sizing the four core Event Logs well beyond Windows' small defaults — commonly cited figures are roughly 32,768 KB or larger for the Application, Setup, and System logs, and a much larger 196,608 KB or larger for the Security log specifically (it fills up fastest once full auditing is on). If you're not certain of the exact current CIS figure, erring generously large is safe and low-risk — the goal is simply "don't silently lose evidence to log rotation."


24. Group Policy / secpol.msc / Administrative Templates Reference#

Use gpedit.msc (Local Group Policy Editor — not available on Home editions) for Administrative Templates, and secpol.msc for the Account Policies / Local Policies items already covered in Sections 4–6. Add snap-ins via mmc.exeFile → Add/Remove Snap-in if the direct .msc shortcuts aren't available on your edition.

Do this section last. As the original source material warns: these Administrative Template changes can be extremely restrictive and, in aggregate, may limit your own ability to keep working on the box (disabled Control Panel pages, locked toolbars, blocked installers, etc.). Make sure every other section is done first.

Commonly-Tested / High-Yield Administrative Template Settings#

Based on general CyberPatriot community experience, these categories come up often enough to prioritize within the huge Administrative Templates tree. Many of them are also explicit CIS Microsoft Windows 10/11 Benchmark, Level 1 controls, noted below where that's the case — Level 1 means "broad-compatibility hardening," generally safe to apply on a competition image without breaking required functionality.

Category Setting Recommended Value
Windows Components → AutoPlay Policies Turn off Autoplay Enabled (All Drives) — CIS Level 1
Windows Components → AutoPlay Policies Turn off Autoplay for non-volume devices Enabled — CIS Level 1
Windows Components → Windows Update Configure Automatic Updates Enabled, "Auto download and schedule the install"
Windows Components → Windows Defender Turn off Windows Defender Disabled (i.e., do NOT turn it off)
Windows Components → Windows Defender Turn off real-time protection Disabled (i.e., keep real-time protection ON) — CIS Level 1
Windows Components → Remote Desktop Services Allow users to connect remotely using RDS Disabled (unless required)
Windows Components → Windows Installer Disable Windows Installer Disabled (leave installer enabled unless scenario says otherwise)
Windows Components → Windows Installer Always install with elevated privileges DisabledCIS Level 1, see Section 12
System → Removable Storage Access All removable storage classes: Deny all access Enabled (only if the scenario wants removable media blocked entirely)
System → Device Installation Restrictions Prevent installation of removable devices Enabled (same caveat as above)
System → Logon Do not process the legacy run list Enabled
System → Logon Do not display network selection UI Enabled — CIS Level 1 (stops selecting/changing Wi-Fi networks from the lock screen without logging in)
System → User Profiles Turn off the advertising ID Enabled — CIS Level 1
Network → Network Connections → Windows Firewall Protect all network connections Enabled
Network → Lanman Server Hash publication for BranchCache Disabled
Network → Lanman Workstation Enable insecure guest logons Disabled — CIS Level 1, see Section 13
Network → Network Provider Hardened UNC Paths (require mutual authentication and integrity for \\*\NETLOGON and \\*\SYSVOL) Enabled — CIS Level 1 (most relevant on domain-joined machines; low-risk to set regardless)
Network → Microsoft Peer-to-Peer Networking Turn off Microsoft Peer-to-Peer networking services Enabled
Windows Components → Internet Explorer Turn off InPrivate Browsing Enabled (if scenario disallows private browsing)
Windows Components → Event Log Service Max log size / Retain old events Sized generously; retain events on — see Section 23 for CIS-cited size figures
Windows Components → Windows Update Do not display "install updates and shut down" Enabled
Windows Components → Cloud Content Turn off Microsoft consumer experiences Enabled — CIS Level 1
Windows Components → Data Collection and Preview Builds Allow Telemetry Enabled, lowest available level (e.g. "Security" or "Basic" depending on edition) — CIS Level 1
Control Panel → Personalization Prevent enabling lock screen camera / Prevent enabling lock screen slide show Enabled — CIS Level 1

Treat this curated table as a starting point, not an exhaustive guarantee — CyberPatriot does not publish an official scoring rubric, so "commonly tested" here is drawn from general community experience with these categories historically appearing across many practice/competition images, not a promise about any specific round. The CIS Level 1 annotations are based on well-established, widely-cited CIS Windows Benchmark categories; exact setting names/paths can shift slightly between Windows 10 and 11 builds, so verify the live control in gpedit.msc matches the description if it looks off.

CIS Level 2 — Defense-in-Depth (Worth Trying If Time Permits)#

CIS Level 2 controls are stricter than Level 1 and are meant for higher-security environments — they carry more risk of breaking legitimate functionality (remote administration tooling, cross-device features, peripherals), so apply them only after the rest of this document is done and you've confirmed they don't conflict with anything the README requires.

Category Setting Recommended Value
System → Remote Procedure Call Restrict Unauthenticated RPC clients Enabled, Authenticated
System → Remote Procedure Call RPC Endpoint Mapper Client Authentication Enabled
System → OS Policies Allow Clipboard synchronization across devices Disabled
System → OS Policies Allow upload of User Activities Disabled
Windows Components → Camera Allow use of Camera Disabled
Local Security Policy → Security Options Network access: Restrict clients allowed to make remote calls to SAM Administrators (see Section 6)

These are genuinely optional "extra credit" — a CyberPatriot image can score well without any of them, and a few (Clipboard sync, RPC restrictions) have real potential to interfere with a scenario that expects those features to work. Test after applying, don't just set-and-forget.

Full Administrative Templates Reference (from historical checklist source)#

The table below is preserved from the original "Ultimate Windows Checklist" GPO reference for completeness. It is organized by the same category structure as gpedit.msc. Treat "Not configured" values as leave alone / lowest priority — they represent the source checklist's judgment that the setting didn't need to deviate from default. This is the exhaustive appendix; work through the rest of this document first, then use this if you have time remaining and want to squeeze out additional hardening.

Control Panel

Setting Value
Regional and Language Options → Restrict the UI languages Windows uses Enabled – English
Regional and Language Options → Force selected system UI language to override User UI language Disabled
User Accounts → Apply the default user logon picture to all users Enabled

Network — BITS

Setting Value
Do not allow the BITS client to use Windows Branch Cache Enabled
Do not allow the computer to act as a BITS peer-caching client Enabled
Do not allow the computer to act as a BITS peer-caching server Enabled
Allow BITS peer-caching Disabled
Time-out for inactive BITS jobs Enabled, 1 Day
Limit the maximum network bandwidth for BITS background transfers Enabled, 0
Limit the maximum network bandwidth Enabled, 1
Limit the BITS peer-cache size Enabled, 1
Limit the age of files in the BITS peer-cache Enabled, 1
Limit the maximum BITS job download time Enabled, 1
Limit the maximum number of files in a BITS job Enabled, 1
Limit the maximum number of BITS jobs for this computer Enabled, 1
Limit the maximum number of BITS jobs per user Enabled, 1
Limit the maximum number of ranges per file in a BITS job Enabled, 1

Network — Branch Cache

Setting Value
Turn on BranchCache Disabled
Set BranchCache Distributed Cache mode Disabled
Set BranchCache Hosted Cache mode Disabled
Configure BranchCache for network files Disabled
Set percentage of disk space used for client computer cache Enabled, 1

Network — DNS Client

Setting Value
Allow DNS suffix appending to unqualified multi-label name queries Disabled
Dynamic Update Enabled
Registration Refresh Interval Enabled, 1000
TTL set in the A and PTR record Enabled, 300
Update Security Level / Update Top Level Domain Zones Enabled
Primary DNS Suffix Devolution Enabled
Turn off Multicast Name Resolution (LLMNR) Enabled

Network — Lanman Server / Link-Layer Topology Discovery / Peer-to-Peer

Setting Value
Hash publication for BranchCache Disabled
Disable password strength validation for Peer Grouping Disabled
Turn off Microsoft Peer-to-Peer networking services Enabled
PNRP Clouds (Global/Link-Local/Site-Local) — Turn off Multicast Bootstrap Enabled
PNRP Clouds — Turn off PNRP cloud creation Enabled
PNRP Clouds — Set PNRP cloud to resolve only Enabled

Network — Network Connections (Windows Firewall legacy policy)

Setting Value (Domain & Standard Profiles)
Protect all network connections Enabled
Allow inbound file and printer sharing exception Disabled
Allow logging Enabled
Prohibit notifications Disabled
Allow inbound remote administration exception Disabled
Allow inbound UPnP framework exception Disabled
Windows Firewall: Allow authenticated IPsec bypass Disabled
Prohibit installation/configuration of Network Bridge Disabled
Prohibit use of Internet Connection Firewall on DNS domain network Disabled
Prohibit use of Internet Connection Sharing on DNS domain network Enabled
Require domain users to elevate when setting a network's location Enabled

Network — Offline Files

Setting Value
Sub-folders always available offline Disabled
Administratively assigned offline files Disabled
Limit disk space used by Offline Files Enabled, 1, 1
Allow or disallow use of the Offline Files feature Disabled
Encrypt the Offline Files cache Enabled
Event logging level Enabled, 3
Prevent use of Offline Files folder Enabled
Remove "Make Available Offline" Enabled
Prohibit "Make Available Offline" for these file/folders Enabled
Turn off reminder balloons Enabled
Enable transparent caching Disabled
At logoff, delete local copy of user's offline files Enabled
Turn on economical application of admin-assigned Offline Files Disabled
Reminder balloon frequency / initial lifetime / lifetime Disabled
Synchronize all offline files before logging off / on / before suspend Disabled

Network — SNMP / SSL / TCP-IP / Windows Connect Now

Setting Value
SNMP Communities Disabled
SNMP Permitted Managers Disabled
SNMP Traps for public community Disabled
SSL Cipher Suite Order Disabled
Prohibit access of the Windows Connect Now wizards Enabled

Network — Printers

Setting Value
Allow Print Spooler to accept client connections Disabled
Allow printers to be published Disabled
Allow pruning of published printers Disabled
Always render print jobs on the server Disabled
Automatically publish new printers in AD Disabled
Computer location Enabled
Custom support URL in Printers folder Disabled
Disallow installation of printers using kernel-mode drivers Enabled
Execute print drivers in isolated processes Disabled
Log directory pruning retry events Enabled
Only use Package Point and Print Enabled
Override print driver execution compatibility setting Enabled
Pre-populate printer search location text Disabled
Printer browsing Disabled
Prune printers not automatically republished Disabled
Web-based printing Disabled

System — Credentials Delegation

Setting Value
Allow delegating default/fresh/saved credentials (all variants) Disabled
Allow delegating credentials with NTLM-only server authentication (all variants) Disabled
Deny delegating default/fresh/saved credentials Enabled

System — Device Installation

Setting Value
Allow admins to override Device Installation Restriction policies Enabled
Allow installation of devices matching any of these device IDs Disabled
Allow installation of devices using drivers matching these classes Disabled
Prevent installation of devices not described by other policy settings Enabled
Prevent installation of removable devices Enabled
Allow remote access to the PnP interface Disabled
Configure device installation timeout Enabled, 300
Do not send a Windows error report on generic driver installation failure Enabled
Prevent creation of a system restore point during device activity Enabled
Prevent device metadata retrieval from the Internet Enabled
Prioritize all digitally signed drivers equally Enabled
Turn off "found new hardware" balloons during device installation Enabled
Prevent redirection of USB devices Enabled

System — Disk NV Cache / Disk Quotas

Setting Value
Turn off Boot and Resume Optimizations Enabled
Turn off Cache Power Mode Enabled
Turn off Non-volatile Cache Feature Enabled
Turn off solid state mode Enabled
Apply policy to removable media (Disk Quotas) Enabled
Enable disk quotas Enabled
Log event when quota limit / warning level exceeded Enabled

System — Distributed COM / Driver Installation / Enhanced Storage

Setting Value
Allow local activation security check exemptions Disabled
Define Activation Security Check exemptions Disabled
Allow non-admins to install drivers for these device setup classes Disabled
Allow Enhanced Storage certificate provisioning Enabled
Allow only USB root hub connected Enhanced Storage devices Disabled
Do not allow non-Enhanced Storage removable devices Enabled
Lock Enhanced Storage when the computer is locked Enabled

System — File System / Group Policy Processing

Setting Value
Do not allow compression on all NTFS volumes Enabled
Enable NTFS pagefile encryption Enabled
Disable delete notifications on all volumes Enabled
Selectively allow the evaluation of a symbolic link Disabled
Allow cross-forest user policy and roaming user profiles Disabled
Always use local ADM files for Group Policy Object Editor Disabled
Disallow interactive users from generating RSOP data Enabled
Group Policy refresh interval for computers/domain controllers Enabled, 180 min / 20 min offset
Remove users' ability to invoke machine policy refresh Enabled
Turn off background refresh of Group Policy Disabled
Turn off RSOP logging Disabled

System — Internet Communication Management

Setting Value
Turn off downloading of print drivers over HTTP Enabled
Turn off Event Viewer "Events.asp" links Enabled
Turn off handwriting personalization data sharing Enabled
Turn off handwriting recognition error reporting Enabled
Turn off Internet Connection Wizard if URL referring to Microsoft Enabled
Turn off Internet download for web publishing/online ordering wizards Enabled
Turn off Internet File Association service Enabled
Turn off printing over HTTP Enabled
Turn off Registration if URL referring to Microsoft Enabled
Turn off Search Companion content file updates Enabled
Turn off "Order Prints" picture task Enabled
Turn off "Publish to Web" task Enabled
Turn off Windows Messenger customer experience Enabled
Turn off Windows Error Reporting Enabled
Turn off Windows Update device driver searching Disabled

System — iSCSI / Kerberos / Locale Services

Setting Value
Do not allow additional session logins Enabled
Do not allow changes to initiator IQN name Enabled
Do not allow changes to initiator CHAP secret Enabled
Do not allow connections without IPsec Enabled
Do not allow sessions without mutual/one-way CHAP Enabled
Do not allow manual configuration of iSCSI targets/portals/iSNS Enabled
Require strict KDC validation Enabled
Require strict target SPN match on RPC Enabled
Use forest search order Enabled
Disallow changing of geographic location Enabled
Disallow selection of custom locales Enabled
Disallow user override of locale settings Enabled
Restrict system/user locales Enabled, en-US

System — Logon / Power Management

Setting Value
Always use classic logon Enabled
Do not process the legacy run list Enabled
Do not process the run-once list Enabled
Don't display the "Getting Started" welcome screen at logon Enabled
Hide entry points for Fast User Switching Enabled
Run these programs at user logon Disabled
Turn off Windows Startup Sound Enabled
Turn off the hard disk (on battery / plugged in) Enabled, 150
Require a password when a computer wakes (on battery / plugged in) Enabled
Specify the System Hibernate/Sleep/Unattended Sleep Timeout Enabled, 450–600
Reduce Display Brightness / Specify Display Dim Brightness Enabled, 180
Turn off Adaptive Display Timeout Enabled, 240
Turn off the display (on battery / plugged in) Enabled, 300
Allow restore of system to default state (Recovery) Enabled

System — Remote Assistance / RPC / Removable Storage / Scripts

Setting Value
Configure Offer Remote Assistance Disabled
Configure Solicited Remote Assistance Disabled
Turn on session logging (Remote Assistance) Enabled
Restrictions for Unauthenticated RPC clients Enabled, Authenticated without exceptions
RPC Endpoint Mapper Client Authentication Enabled
Removable storage classes — deny all access Not configured by default (Enable if scenario requires locking down removable media)
Allow logon scripts when NetBIOS/WINS disabled Disabled
Run startup scripts visible Enabled
Turn off System Restore Disabled (i.e., leave System Restore ON)

System — Troubleshooting, User Profiles, Windows File Protection

Setting Value
Notify blocked drivers Enabled
Detect application failures caused by deprecated COM/Windows components Enabled, All
MSDT: Turn on interactive communication with Support Disabled
MSDT: Restrict tool download Enabled
Add the administrators security group to roaming user profiles Enabled
Delete user profiles older than a specified number of days Enabled, 29
Delete cached copies of roaming profiles Enabled
Only allow local user profiles Enabled
Do not log users on with temporary profiles Enabled
Hide the file scan progress window (WFP) Disabled
Limit Windows File Protection cache size Enabled, 50

Windows Components — AutoPlay, Backup, Biometrics

Setting Value
Turn off Autoplay Enabled
Turn off Autoplay for non-volume devices Enabled
Prevent backing up to local disks/network location/optical media Enabled
Turn off the ability to back up data files / create a system image Enabled
Allow domain users to log on using biometrics Disabled
Allow the use of biometrics Disabled

Windows Components — BitLocker Drive Encryption

Setting Value
Fixed/Removable/OS Drives — most sub-settings Not configured by default; configure per README if BitLocker is in scope
Choose drive encryption method and cipher strength Not configured by default; set explicitly if BitLocker required
Store BitLocker recovery info in Active Directory Not configured (domain-only)

Windows Components — Credential UI, Desktop Gadgets, DWM

Setting Value
Enumerate administrator accounts on elevation Disabled
Require trusted path for credential entry Enabled
Turn off desktop gadgets Enabled
Turn off user-installed desktop gadgets Enabled
Do not allow color changes / desktop composition / Flip3D / window animations (DWM) Enabled (disable these effects)

Windows Components — Event Log Service

Log Setting Value
Application / Security / Setup / System Backup log automatically when full Enabled
Application / Security / Setup / System Max Log Size Enabled, 2046 (KB) or larger
Application / Security / Setup / System Retain old events Enabled

Windows Components — Game Explorer / HomeGroup

Setting Value
Turn off downloading of game information Enabled
Turn off game updates Enabled
Turn off tracking of last play time Enabled
Prevent the computer from joining a HomeGroup Enabled

Windows Components — Internet Explorer (selected high-value entries)

Setting Value
Turn off Accelerators Enabled
Turn off Compatibility View / Compatibility View button Enabled
Prevent deleting cookies/passwords/temp files/history (Delete Browsing History) Enabled (i.e., admin-locks the delete-history controls)
Security Zones: Use only machine settings Enabled
Security Zones: Do not allow users to add/change sites or policies Enabled
Turn on Warn about certificate address mismatch Enabled
Disable the Advanced/Connections/Content/General/Privacy/Programs/Security pages Enabled
Prevent ignoring certificate errors Enabled
Turn off InPrivate Browsing Enabled
Turn off Tracking Protection / InPrivate Filtering Enabled
Add-on Management: Deny all add-ons unless specifically allowed Enabled
Turn on ActiveX Filtering Enabled
Restrict File Download / Restrict ActiveX Install (Internet Explorer Processes) Enabled
Prevent Internet Explorer security settings check Disabled (allow the check)
Disable changing connection/proxy/Automatic Configuration settings Enabled
Disable Periodic Check for updates and Automatic Install prompts Enabled
Prevent bypassing SmartScreen Filter warnings Enabled
Prevent participation in the Customer Experience Improvement Program Enabled
Turn off the auto-complete feature for web addresses Enabled
Turn off the security settings check feature Disabled

Windows Components — Location and Sensors, NetMeeting, Parental Controls

Setting Value
Turn off location / location scripting / sensors Enabled
Disable remote Desktop Sharing (NetMeeting) Enabled
Make Parental Control panel visible Disabled

Windows Components — Remote Desktop Services (full block)

Setting Value
Allow users to connect remotely using RD Disabled (unless required)
Automatic reconnection Disabled
Restrict Remote Desktop Services users to a single session Enabled
Do not allow clipboard/COM port/drive/LPT port/smart card redirection Enabled
Do not allow supported Plug and Play device redirection Enabled
Set the RD licensing mode Enabled, Per User
Do not allow client printer redirection Enabled
Always show desktop on connection Enabled
Always prompt for a password upon connection Enabled
Require secure RPC communication Enabled
Require user authentication for remote connections using NLA Enabled
Set client connection encryption level Enabled, High
Set time limit for active but idle RDS sessions Enabled, 15 min
Set time limit for disconnected sessions Enabled, 10 min
Do not use temporary folders per session Enabled

Windows Components — RSS Feeds, Search, Security Center

Setting Value
Turn off addition/removal of feeds Enabled
Turn off background sync for feeds Enabled
Turn off download of enclosures Enabled
Allow indexing of encrypted files Disabled
Do not allow web search Enabled
Prevent adding UNC locations to index Enabled
Prevent indexing email attachments / offline files cache / Outlook / public folders Enabled
Turn on Security Center Enabled

Windows Components — Sound Recorder, Tablet PC, Task Scheduler

Setting Value
Do not allow Sound Recorder to run Enabled
Do not allow Sniping Tool / Windows Journal / InkBall to run Enabled
Turn off automatic learning (Handwriting Personalization) Enabled
Hide Advanced Properties checkbox / Property Pages (Task Scheduler) Enabled
Prohibit Browse / Drag-and-Drop / new task creation / task deletion Enabled

Windows Components — Windows Calendar, Color System, Customer Experience

Setting Value
Turn off Windows Calendar Enabled
Prohibit installing/uninstalling color profiles Enabled
Turn off Customer Experience Improvement Program data collection Disabled (i.e., turn CEIP off is achieved by Disabling the "allow" toggle — verify against your build's exact wording)

Windows Components — Windows Defender

Setting Value
Check for new signatures before scheduled scans Enabled
Turn off real-time monitoring Disabled (keep real-time monitoring ON)
Turn off Windows Defender Disabled (keep Defender ON)
Turn off routinely taking action Enabled (source value — verify against current Defender terminology on your build, as this UI has changed significantly across Windows versions)

Windows Components — Windows Error Reporting

Setting Value
Disable Windows Error Reporting Enabled
Display Error Notification Disabled
Do not send additional data Enabled
Report OS errors / unplanned shutdown events Disabled

Windows Components — Windows Explorer, Installer, Logon Options

Setting Value
Turn off Data Execution Prevention for Explorer Disabled (i.e., leave DEP protection for Explorer ON)
Turn off numerical sorting in Windows Explorer Enabled
Cache transforms in secure location on workstation Enabled
Enable user control over installs Enabled
Prohibit non-admins from applying vendor-signed updates Enabled
Prohibit patching / Prohibit removal of updates / Prohibit user installs Enabled
Turn off creation of System Restore checkpoints (Windows Installer) Enabled
Disable or enable software Secure Attention Sequence Enabled

Windows Components — Windows Media, Messenger, Mobility Center, Remote Management

Setting Value
Do not allow Windows Media Center to run Enabled
Prevent Windows Media DRM Internet Access Enabled
Prevent Desktop shortcut creation / media sharing / Quick Launch shortcut (WMP) Enabled
Do not allow Windows Messenger to be run Enabled
Turn off Windows Mobility Center Enabled
WinRM Client/Server — Allow Basic authentication Disabled
WinRM Client/Server — Allow unencrypted traffic Disabled
WinRM Client/Server — Disallow Kerberos authentication Disabled (leave Kerberos allowed)
Windows Remote Shell — Allow Remote Shell access Disabled

Windows Components — Windows SideShow, System Resource Manager, Windows Update

Setting Value
Require a PIN to access data on devices running Windows SideShow Enabled
Turn off Windows SideShow Enabled
Allow automatic updates immediate installation Disabled
Allow non-admins to receive update notifications Disabled
Configure Automatic Updates Enabled — auto download & schedule install
Do not adjust default option to "install updates and shut down" Enabled
No auto-restart with logged-on users for scheduled installations Enabled
Turn on recommended updates via Automatic Updates Enabled
Turn on Software Notifications Disabled

This appendix intentionally preserves the source document's structure and values for reference completeness. Some entries reflect Windows 7/Server 2008-era terminology (e.g., specific Windows Media Center or Tablet PC options) that may not exist on Windows 10/11 images — skip anything not present on your target OS rather than trying to force it.

Things to try / extra points#

Tip: gpresult /h C:\gpreport.html generates a full HTML report of currently applied Group Policy settings — a fast way to sanity-check what's actually in effect after you make changes, and a good source for answering forensics questions about current policy state.

cmd
gpresult /h C:\gpreport.html
gpupdate /force
Expected result:
  • gpresult writes an HTML file to C:\gpreport.html (open it in a browser to review); gpupdate /force prints Updating policy...
  • Computer Policy update has completed successfully.
  • User Policy update has completed successfully.
If it fails:
  • "Access is denied" writing to C:\ root without elevation — target a path you own, e.g. C:\Users\<you>\Desktop\gpreport.html.
  • gpupdate /force doing nothing/appearing to hang briefly is normal on a non-domain machine (local policy applies almost instantly) — a genuine hang for more than a minute or two suggests a broken GPO client-side extension, in which case reboot instead of waiting.

Tip: On Windows Home editions without gpedit.msc, many of the same registry-backed policies can still be set directly via Set-ItemProperty under HKLM:\SOFTWARE\Policies\... and HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\... — the GPO editor is just a GUI for registry values in most cases. Search for the specific policy name plus "registry key" if you need the exact path and are on a Home SKU.

Tip: If you want an authoritative source to cross-check this whole section against (rather than just this document), look up the free CIS Microsoft Windows 10/11 Benchmark, published by the Center for Internet Security. It's organized in the same Level 1/Level 2 structure referenced throughout this section, is free to download after a quick registration, and is a legitimate, citable standard if a mentor, judge, or teammate asks "where did this setting come from?"


25. Final Pass / Wrap-Up#

Snapshot Checkpoint — pre-submission: Once everything below checks out and the box is in a good, stable, scoring state, take one more snapshot before you walk away or the round ends. If the VM crashes, gets reset, or something breaks in the last few minutes, this is the checkpoint that saves your final score instead of an earlier, less-hardened one.

  • Re-read the README one more time — confirm every explicit requirement is satisfied and nothing required was disabled/removed/uninstalled.
  • Re-check the scoring report; note anything still flagged and work it methodically rather than randomly re-clicking settings.
  • Confirm you can still log in as an authorized administrator (don't lock yourself out with an over-aggressive UAC/RDP/account change).
  • Confirm the firewall is on, Defender/real-time protection is on, and Automatic Updates is configured.
  • Confirm no required service was accidentally disabled (re-run Get-Service | Where Status -eq Running and sanity-check against the README's required functionality).
  • Take a final restore point / snapshot once you're in a good, stable, scoring state.
  • If time remains, revisit Section 22 and Section 24's full appendix for additional hardening — these are the highest-effort, lowest-urgency items and good use of leftover time.

Final tip: Perfect is the enemy of done — a checklist you complete 90% of beats one you complete 40% of because you got stuck perfecting Administrative Templates minutiae early. Work broad-to-deep: accounts → policy → firewall → services → malware/files → everything else → the deep appendix.