← Back to Academy
Room 02

Windows in the Real World

Not a certification guide. This room is about how Windows actually works inside companies — the stuff you will be expected to know starting day one. We go slow, we use analogies, and we explain the why behind every command. By the end you should be able to sit down at any Windows machine in any company and know exactly what you're looking at.

Windows Room

The OS Itself

Before you touch a single command, you need to understand what you are actually looking at when you open a Windows machine. Most people use Windows every day but have no idea how it is structured underneath. That gap is exactly where attackers live.

Think of Windows like a building. The ground floor is the hardware — the CPU, RAM, disk. The next floor up is the kernel, which is the core of the OS. It talks directly to the hardware and controls everything. Above that is where you live — the applications, the desktop, the things you see and click. You never talk to the hardware directly. You go through the kernel, which decides what is and is not allowed.

Why does that matter? Because malware wants to get as deep into that building as possible. A virus running as a regular user is on the top floor — limited power. A virus running as SYSTEM is basically in the basement with access to everything. Understanding where processes run in this hierarchy is fundamental to understanding what is dangerous and what is not.

The folder structure — where things actually live

This is not just trivia. When you are investigating an incident or setting up a new machine, knowing the folder layout tells you immediately whether something is normal or suspicious.

  • C:\Windows\System32 — this is the heart of the OS. Core system binaries live here: cmd.exe, notepad.exe, lsass.exe. Legitimate processes live here. Malware also loves to drop files here and name them to look like legitimate files. If you see a process called svch0st.exe (zero instead of O) running from System32, that is not Windows, that is malware.
  • C:\Users\[username]\AppData — hidden by default. Applications store their data here. Also one of the most common places malware stages itself because regular users can write to it without needing admin rights. If you see a scheduled task or startup entry pointing to AppData, pay attention.
  • C:\Program Files — where 64-bit applications install. You need admin rights to write here, which is why it is safer than AppData.
  • C:\Program Files (x86) — same thing but for 32-bit applications running on a 64-bit system. Yes, they are separate. No, you do not need to memorize which is which — just know both exist.
  • C:\Windows\Temp and C:\Users\[user]\AppData\Local\Temp — temporary files. Cleared sometimes on reboot. A shocking amount of malware executes from here. Any legitimate installer that drops an executable in Temp and runs it should immediately raise your eyebrow.
  • C:\ProgramData — also hidden by default. Application data shared across all users on the machine. Another common malware location because it is writable by applications.
Analogy

The Windows folder structure is like a hotel. Program Files is the secure storage room — you need a key (admin rights) to put things there. AppData and Temp are like the hotel room itself — your stuff can go there freely, which is exactly why criminals use them.

The Registry — Windows' brain

The Registry is a giant database that stores almost every configuration setting for Windows and for installed applications. Think of it as the settings file for the entire operating system. Every time you install software, change a wallpaper, or connect to a WiFi network, something gets written to the registry.

The keys you need to know about from a security perspective:

# Programs that run automatically when Windows starts
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

# Services configuration
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services

# Installed software list
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

Attackers love the Run keys. If malware wants to survive a reboot, it adds an entry there. Any security investigation should check those keys early.

Real World

I have been called in to look at a machine where the user kept getting infected "out of nowhere" after every reinstall. Turned out the backup they were restoring from included a registry Run key pointing to a dropper in AppData. Every restore brought the malware back with it. Check the registry. Always.

Windows editions you will actually see

Not all Windows is the same. In corporate environments you will mostly see:

  • Windows 10/11 Pro — on workstations in smaller companies. Has BitLocker, Remote Desktop, but lacks some enterprise management features.
  • Windows 10/11 Enterprise — in larger organizations. Adds Credential Guard, AppLocker, DirectAccess, longer support cycles. This is what you want in a security-conscious environment.
  • Windows Server 2019/2022 — on servers. No desktop experience by default (just a command line) in many deployments. Runs Active Directory, DNS, DHCP, file shares.

CMD — The Command Prompt

CMD is old. It has been around since the DOS days in the 1980s. And yet it is on every single Windows machine ever made and it still works even when PowerShell is locked down. Every IT person needs to know it cold.

Open CMD by pressing Win+R, typing cmd, and hitting Enter. If you need admin rights, search for CMD in the Start Menu, right-click it, and choose "Run as Administrator." You will see a black window with a prompt like C:\Users\weston>. That path tells you where you currently are in the file system.

Analogy

CMD is like giving instructions to Windows by writing notes. You write the command, press Enter, Windows reads it and does the thing. No clicking, no menus — just direct instructions. It feels slower at first, but once you know the commands, you can do in three seconds what takes thirty clicks in the GUI.

Getting around the file system

# Where am I right now?
cd

# Go somewhere specific
cd C:\Users\weston\Documents

# Go up one level (like clicking the back button)
cd ..

# Go all the way to the root of the drive
cd \

# Switch to a different drive entirely
D:

# List everything in the current folder
dir

# List everything including hidden files
dir /a

# Search recursively for a specific file type
dir /s /b *.log

The /s flag means "search in subfolders too." The /b flag means "bare format" — just the file paths, no extra info. Combine them and you get a clean list of every .log file on that drive. You will use this constantly when investigating incidents or finding config files.

Creating and deleting things

# Create a new folder
mkdir C:\Temp\MyProject

# Delete a folder and everything inside it (no confirmation prompt)
rmdir /s /q C:\Temp\MyProject

# Copy a file
copy report.txt C:\Backup\

# Move a file (same as copy + delete original)
move report.txt C:\Archive\

# Delete a file, force it even if read-only, no confirmation
del /f /q badfile.txt

# Rename a file
rename oldname.txt newname.txt
Watch Out

rmdir /s /q deletes everything with zero confirmation. There is no recycle bin, no undo. Triple-check your path before running it. I have seen people accidentally run this on C:\ instead of a subfolder. That machine needed a rebuild.

Network commands — the ones you actually use

# The most important network command you will ever run.
# Shows your IP, subnet mask, default gateway, DNS servers, MAC address.
# When something is wrong with networking, run this first.
ipconfig /all

# DNS cache is like a local contacts list of website names to IPs.
# When a site is unreachable or resolving to the wrong place, flush it.
ipconfig /flushdns

# If you are on DHCP and your IP is wrong, release the current one
# and ask the DHCP server for a fresh one.
ipconfig /release
ipconfig /renew

# Can I reach this device?
ping 192.168.1.1
ping google.com

# Ping forever until you press Ctrl+C (useful when testing if something comes back online)
ping 192.168.1.1 -t

# Trace the route a packet takes to reach a destination.
# Each line is a router ("hop") the packet passed through.
# Where it stops is where the problem is.
tracert google.com

# DNS lookup — ask a DNS server what IP belongs to a domain name
nslookup google.com

# Ask a specific DNS server instead of your default one
nslookup google.com 8.8.8.8

# Show all active network connections with their process IDs
# ESTABLISHED = active connection, LISTENING = waiting for connections
netstat -ano

# Same but also show which .exe owns each connection (requires admin)
netstat -b

Learn to read netstat -ano output. The last column is the Process ID (PID). If you see a suspicious connection, grab the PID and run tasklist | findstr [PID] to find out which program made it.

Users and system info

# Who am I logged in as?
whoami

# What groups do I belong to? (important for understanding what I can access)
whoami /groups

# What special privileges do I have right now?
whoami /priv

# Full system information — OS version, hostname, RAM, hotfixes installed
systeminfo

# List all local user accounts
net user

# Details on a specific user — last login, password expiry, group memberships
net user weston

# List who has local admin rights on this machine
net localgroup administrators

# All running processes
tasklist

# Force-kill a process by its PID
taskkill /PID 4532 /F

# Force-kill by name
taskkill /IM notepad.exe /F
Real World

In almost every investigation I run, the first three commands I use are whoami /groups, netstat -ano, and tasklist. They tell me who I am, what is connected to the outside world, and what is running. In under 60 seconds I have a clear picture of the machine's current state.

PowerShell

PowerShell is what CMD would be if it was built today. It is a full scripting language built on top of the .NET framework, which means it can do things CMD can only dream about. It is also the primary tool attackers use after they get into a Windows machine — so understanding it from both directions is essential.

Open PowerShell the same way as CMD — Win+R, type powershell. For admin: search in Start Menu, right-click, Run as Administrator. The prompt looks like PS C:\Users\weston>.

Analogy

If CMD is a basic calculator, PowerShell is a full spreadsheet application. The calculator can add numbers. The spreadsheet can add numbers, sort them, filter them, graph them, and email the results automatically. PowerShell works with objects — not just text output — which means you can take the output of one command and filter, sort, or pipe it into another with surgical precision.

Basic navigation and the pipeline

# Same navigation as CMD but with PowerShell commands
Get-Location                    # Where am I? (same as pwd or cd with no args)
Set-Location C:\Users\weston    # Go here (same as cd)
Get-ChildItem                   # List files (same as dir or ls)
Get-ChildItem -Hidden           # Show hidden files too

# The pipeline: take output and do more things with it
# Find all .log files modified in the last day
Get-ChildItem -Recurse -Filter *.log | Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-1)}

# List files sorted by size, largest first
Get-ChildItem | Sort-Object Length -Descending | Select-Object Name, Length

The | pipe symbol is the key to PowerShell's power. It passes the output of the left command into the right command as input. Where-Object is a filter — you give it a condition and it only passes through objects that match. Select-Object picks which properties you want to see.

Processes and services

# All running processes with path to the executable
Get-Process | Select-Object Name, Id, Path | Sort-Object Name

# Find a specific process
Get-Process -Name "chrome"

# Which process is using a specific port? (combine two commands)
$pid = (Get-NetTCPConnection -LocalPort 443 -ErrorAction SilentlyContinue).OwningProcess
Get-Process -Id $pid

# Kill a process
Stop-Process -Name "notepad" -Force

# All services and their status
Get-Service | Sort-Object Status

# Only the running ones
Get-Service | Where-Object {$_.Status -eq "Running"}

# Start, stop, restart a service
Start-Service -Name "wuauserv"
Stop-Service -Name "wuauserv"
Restart-Service -Name "Spooler"

Networking in PowerShell

# All network adapters with their IPs, DNS, gateways
Get-NetIPConfiguration

# Just the IP addresses
Get-NetIPAddress | Where-Object {$_.AddressFamily -eq "IPv4"}

# Set a static IP address
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.1.50 -PrefixLength 24 -DefaultGateway 192.168.1.1

# Set DNS servers
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses "192.168.1.10","8.8.8.8"

# All established TCP connections
Get-NetTCPConnection | Where-Object {$_.State -eq "Established"} | Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort,OwningProcess

Execution policy — why your scripts might not run

By default, Windows will not run PowerShell scripts you downloaded from the internet. This is called the execution policy. When you try to run a script and get a red error saying it cannot be loaded, this is why.

# Check current policy
Get-ExecutionPolicy

# The possible values:
# Restricted   = no scripts at all (default on some systems)
# RemoteSigned = local scripts ok, downloaded scripts need a signature
# Unrestricted = run anything
# Bypass       = ignore the policy entirely (used by attackers and installers)

# Allow scripts for this session only (does not permanently change anything)
Set-ExecutionPolicy Bypass -Scope Process

# Change permanently for current user
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Watch Out

If you ever see a script or installer telling you to run Set-ExecutionPolicy Unrestricted permanently, that is a red flag. Legitimate software does not need you to remove all PowerShell protection system-wide. Malware installers do.

Active Directory from PowerShell

# Load the AD module first (needs RSAT or to run on a DC)
Import-Module ActiveDirectory

# Find a user and show all their properties
Get-ADUser -Identity weston -Properties *

# Search for users by name pattern
Get-ADUser -Filter {Name -like "west*"} | Select-Object Name, SamAccountName, Enabled, LastLogonDate

# Find users who have not logged in for 90 days (stale accounts = security risk)
$cutoff = (Get-Date).AddDays(-90)
Get-ADUser -Filter {LastLogonDate -lt $cutoff -and Enabled -eq $true} | Select-Object Name, LastLogonDate

# Unlock a locked account (happens when someone gets their password wrong too many times)
Unlock-ADAccount -Identity weston

# Force a password reset at next login
Set-ADUser -Identity weston -ChangePasswordAtLogon $true

# List all members of a group
Get-ADGroupMember -Identity "Domain Admins" | Select-Object Name, SamAccountName

# Add a user to a group
Add-ADGroupMember -Identity "IT Support" -Members weston

Batch Files

A batch file is just a text file with a list of CMD commands that run one after another. You have probably seen them — files ending in .bat or .cmd. IT departments use them for everything: automated backups, user setup scripts, scheduled maintenance. Knowing how to write and read them is a basic IT skill.

Analogy

Imagine you make the same coffee every morning: fill water, add beans, press brew, wait, pour. A batch file is like writing those steps on a card and handing it to someone else. You wrote the instructions once — they just follow them every time without thinking.

The basics

@echo off
# @echo off stops the commands themselves from printing to the screen.
# Without it, every line of your script prints before it runs. Messy.
# Always put this as your first line.

setlocal
# Keeps any variables you set inside this script.
# Without it, your variables leak into the CMD session after the script finishes.

# Variables are set with = and used with %name%
set BACKUPDIR=C:\Backups
set LOGFILE=C:\Logs\backup.log

echo Starting backup...
echo Backup dir is: %BACKUPDIR%

# If/else
if exist "%BACKUPDIR%" (
    echo Backup directory already exists.
) else (
    echo Creating backup directory...
    mkdir "%BACKUPDIR%"
)

echo Done. >> %LOGFILE%
# >> appends to a file. > would overwrite it.

pause
# Keeps the window open so you can read the output.
# Remove this if running from Task Scheduler.

A real example — nightly cleanup script

@echo off
setlocal

set LOGPATH=C:\AppLogs
set DAYSOLD=30
set LOGFILE=C:\Scripts\cleanup.log

echo [%DATE% %TIME%] Starting cleanup of logs older than %DAYSOLD% days >> %LOGFILE%

# forfiles loops through files matching criteria
# /p = path, /s = include subfolders, /m = file pattern
# /d = date filter (negative = older than N days)
# /c = command to run on each match (@path = full path to the file)
forfiles /p "%LOGPATH%" /s /m *.log /d -%DAYSOLD% /c "cmd /c del @path"

echo [%DATE% %TIME%] Cleanup complete >> %LOGFILE%
echo Cleanup finished.

Running batch files

# From CMD, just type the path
C:\Scripts\myscript.bat

# Double-click in Windows Explorer (runs as current user)

# Run as administrator: right-click the file > Run as administrator

# From Task Scheduler, to run silently and capture output:
cmd /c "C:\Scripts\myscript.bat" >> "C:\Logs\output.log" 2>&1
# 2>&1 means "send error output to the same place as regular output"

Network Configuration

Every IT job involves configuring network settings at some point. Whether it is setting up a new machine, troubleshooting why someone cannot connect, or joining a machine to the domain — you need to know how to control IP addresses and DNS.

Static IP vs DHCP — understanding the difference first

When a device connects to a network, it needs an IP address. There are two ways it gets one:

  • DHCP (automatic) — the network has a DHCP server that hands out IP addresses automatically. Your laptop at home uses this. Most workstations in a company use this. Easy, no manual work.
  • Static (manual) — you configure the IP address yourself and it never changes. Servers, printers, cameras, domain controllers — anything that other devices need to reliably find uses a static IP. You cannot have your domain controller changing its IP every day.
Analogy

DHCP is like a hotel handing you whatever room is available when you check in. Static IP is like owning an apartment — your address is always the same and people can always find you there. Your workstation can be a hotel guest. Your DNS server needs a permanent address.

Changing IP via CMD

# Set a static IP address
# Replace "Ethernet" with your adapter name (check with: netsh interface show interface)
netsh interface ip set address "Ethernet" static 192.168.1.50 255.255.255.0 192.168.1.1

# Set DNS servers
netsh interface ip set dns "Ethernet" static 192.168.1.10
netsh interface ip add dns "Ethernet" 8.8.8.8 index=2

# Switch back to DHCP
netsh interface ip set address "Ethernet" dhcp
netsh interface ip set dns "Ethernet" dhcp

# Check the result
ipconfig /all

Joining a machine to the domain

In a corporate environment, every workstation is "joined" to the domain. This means the domain controller manages it — it can push Group Policy settings, manage user logins, and control what the machine does. A machine not joined to the domain is like a rogue employee who ignores all company rules.

Before You Join

The machine must be able to reach a domain controller before joining will work. That means its DNS must be pointed at the DC's IP address, not at 8.8.8.8 or your router. This is the cause of 90% of domain join failures. Set DNS to the DC's IP first, then join.

# Via PowerShell — cleaner and scriptable
Add-Computer -DomainName "company.local" -Credential (Get-Credential) -Restart
# -Credential will prompt you for a domain admin username and password
# -Restart reboots the machine automatically after joining

# Via GUI: Right-click This PC > Properties > Advanced system settings
# > Computer Name tab > Change > select Domain, type the domain name

# Leave the domain (remove from domain, join a workgroup)
Remove-Computer -WorkgroupName "WORKGROUP" -Credential (Get-Credential) -Restart -Force

Local Admin

Every Windows machine has a built-in Administrator account. It has full control over that specific machine. Understanding local admin — what it is, when to use it, and why it is dangerous — is one of the most practically important things in this room.

There are two types of admin accounts you will deal with:

  • Local Administrator — exists on the machine itself. Has full control over that machine only. Even if the network goes down or the domain controller is unreachable, the local admin account still works.
  • Domain Administrator — an account in Active Directory that has admin rights across the entire domain. Much more powerful, much more dangerous if compromised.
Analogy

Local admin is like a master key to a single apartment. Domain admin is like a master key to every apartment in every building the company owns. You hand out the single-apartment key carefully. The master key should almost never leave the safe.

Managing the built-in Administrator account

# Check if the built-in Administrator is enabled
net user Administrator

# Enable it (disabled by default on modern Windows)
net user Administrator /active:yes

# Give it a strong password
net user Administrator "Str0ng!Pass#2024"

# Disable it when done — you do not want an enabled local admin
# sitting around with no one monitoring it
net user Administrator /active:no

Adding a user to the local Administrators group

# CMD method
net localgroup administrators weston /add

# PowerShell method
Add-LocalGroupMember -Group "Administrators" -Member "weston"

# Check who currently has local admin rights
net localgroup administrators
Get-LocalGroupMember -Group "Administrators"
Security Reality

In smaller companies, almost everyone has local admin on their own machine "because it is easier." This is one of the most dangerous configurations I see. When a user is a local admin and they open a malicious email attachment, the malware runs with admin rights automatically — no UAC prompt, no warning. This is the express lane from phishing email to full domain compromise.

Domains, Forests, and Organizational Units

When you walk into a company with more than about 20 employees, their Windows environment almost certainly runs Active Directory. Understanding its structure from the ground up is not optional — it is the foundation everything else builds on.

What is a domain?

A domain is a group of computers, users, and resources that are all managed together under one central authority. When you log in at work with your company email and password, you are authenticating against a domain. The domain has a name — something like company.local or company.com.

The key thing the domain gives you is centralized control. Instead of configuring 500 computers individually, you configure the domain once and it pushes settings to everything. Password policy? Set it once, applies to everyone. Need to block USB drives on all machines? One Group Policy Object, done in minutes.

Analogy

A domain is like a franchise system. McDonald's corporate headquarters (the domain controller) sets the rules — menu, uniforms, procedures. Every individual restaurant (workstation) follows those rules automatically. You do not call each restaurant individually. You update the policy at headquarters and it propagates.

What is a forest?

A forest is the top-level container. It can hold one or more domains. Most companies have a single-domain forest — one domain, one set of rules, simple. Large enterprises with subsidiaries or international operations might have multiple domains within one forest, or even multiple forests with trust relationships between them.

You will not deal with multi-forest environments often at the start of your career, but you need to know they exist. When a company gets acquired, suddenly you have two forests that need to trust each other so employees can access each other's resources.

Organizational Units — how things are organized inside a domain

OUs are like folders inside the domain. You use them to organize users, computers, and groups — and critically, to control which Group Policies apply to which machines and users.

company.local                         # The domain itself
├── Workstations                      # OU for all desktop machines
│   ├── Finance                       # Sub-OU for Finance department machines
│   ├── HR                            # Sub-OU for HR machines
│   └── IT                            # Sub-OU for IT machines
├── Servers                           # OU for servers
│   ├── DomainControllers             # DCs go in their own OU
│   ├── FileServers
│   └── WebServers
├── Users                             # OU for user accounts
│   ├── Executives
│   ├── Staff
│   └── ServiceAccounts               # Accounts used by applications, not humans
└── Groups                            # Security and distribution groups

Why does this structure matter? Because if you put the Finance computers in the Finance OU, you can apply a Group Policy to just that OU — maybe blocking USB drives or forcing a specific screensaver. IT computers in the IT OU can have more relaxed policies. This is how you enforce different security standards for different parts of the company without managing each machine individually.

Real World

I once audited an environment where every single computer and user was in the default "Computers" and "Users" containers at the domain root — nothing in OUs at all. You cannot apply targeted Group Policy to the default containers. It meant every policy applied to everything with no exceptions. IT admins had the same restrictions as the intern. Architects had the same access as receptionists. Structure your OUs from day one.

Domain Controllers

The Domain Controller is the most important server in a Windows environment. It is the brain of Active Directory. If it goes down, people cannot log in, Group Policy stops applying, and the whole environment slowly falls apart. You need to understand what it does and how to check on it.

What a DC actually does

  • Authentication — when you type your password at the login screen, your machine sends a request to the DC asking "is this correct?" The DC checks its database and says yes or no. This uses a protocol called Kerberos — more on that in the Networking room.
  • Authorization — the DC stores your group memberships, which determine what you can access. "Can this user open this file share?" — the DC knows.
  • DNS — in almost every corporate environment, the DC also runs the internal DNS server. This is why "DNS is always the problem" — because DNS and authentication are on the same server, and when one has issues, the other often does too.
  • SYSVOL — a shared folder on every DC that stores Group Policy files and login scripts. It replicates between all DCs. If SYSVOL replication breaks, machines start getting stale policies.
  • Replication — in any environment with more than one DC, they constantly sync changes with each other. New user created on DC1? DC2 gets a copy within minutes. This is why you always deploy at least two DCs — if one fails, authentication keeps working.

Checking DC health — the commands you need

# Which DC am I currently authenticating against?
nltest /dsgetdc:company.local

# Overall health check — runs a battery of tests on the DC
# Run this when something feels wrong. Look for FAILED in the output.
dcdiag /test:all

# Check replication status between DCs
# If you see failures here, your DCs are out of sync. Fix this urgently.
repadmin /replsummary

# More detailed replication info
repadmin /showrepl

# Force replication right now instead of waiting for the schedule
repadmin /syncall /AdeP

# Which server holds which FSMO roles?
# FSMO roles are special functions only one DC performs.
# PDC Emulator handles time sync and legacy authentication.
# If the PDC Emulator is down, password changes may not replicate correctly.
netdom query fsmo
Real World

The most common DC issue I see is broken SYSVOL replication. Symptoms are weird: some machines get Group Policy updates, others do not. Some users can log in from certain machines, others get errors. Run dcdiag /test:sysvolcheck and dcdiag /test:netlogons first. Nine times out of ten, that surfaces the problem.

Group Policy

Group Policy is how you enforce configuration across an entire domain from one place. It is one of the most powerful tools in Windows administration — and one of the most dangerous if you do not understand it, because one bad policy can break thousands of machines simultaneously.

Analogy

Group Policy is like a rulebook that every machine and user in the domain automatically follows. You write the rule once ("all machines must have the firewall enabled") and every machine in scope obeys it — even if a user tries to turn the firewall off, the policy turns it back on at next refresh. Group Policy wins. Always.

How GPO application order works

This is critical because policies can conflict, and understanding which one wins tells you why a machine might be behaving unexpectedly. Policies apply in this order:

  1. 1.Local Policy — settings configured on the machine itself. Weakest.
  2. 2.Site Policy — applied based on physical network location. Rarely used.
  3. 3.Domain Policy — applies to everything in the domain.
  4. 4.OU Policy — applies to machines/users in that specific OU. Strongest — closest OU wins if there is a conflict.

Last writer wins. So if Domain Policy says "minimum password length 8 characters" but the Finance OU Policy says "minimum 14 characters" — Finance users get 14 characters because the OU policy applied last.

Working with GPOs

# Open Group Policy Management Console (GUI)
gpmc.msc

# ---- PowerShell ----
Import-Module GroupPolicy

# Create a new GPO
New-GPO -Name "Workstation Security Baseline" -Comment "CIS baseline settings"

# Link it to an OU so it actually applies to something
New-GPLink -Name "Workstation Security Baseline" -Target "OU=Workstations,DC=company,DC=local"

# See what GPOs apply to the current machine and user
gpresult /r

# Full detailed HTML report — save this and open in a browser
gpresult /h C:\GPReport.html

# Force an immediate GPO refresh on your own machine
gpupdate /force

# Force a refresh on a remote machine
Invoke-GPUpdate -Computer "DESKTOP-WESTON01" -Force

The settings you actually configure in real environments

# Location: Computer Config > Policies > Windows Settings > Security Settings

# Password policy (Account Policies > Password Policy)
Minimum password length:           14 characters
Maximum password age:              90 days
Password complexity:               Enabled
Password history:                  24 passwords remembered

# Account lockout (Account Policies > Account Lockout Policy)
Account lockout threshold:         5 invalid attempts
Account lockout duration:          30 minutes
Reset lockout counter after:       30 minutes

# Location: Computer Config > Admin Templates > Windows Components > Windows PowerShell
Turn on Script Block Logging:      Enabled    # Logs every PowerShell command run
Turn on Module Logging:            Enabled    # Logs PowerShell module usage

# Location: Computer Config > Admin Templates > System > Audit Process Creation
Include command line in process creation events: Enabled  # CRITICAL for incident response

# Location: Computer Config > Admin Templates > System > Removable Storage Access
All Removable Storage classes: Deny all access: Enabled  # Blocks USB drives
Real World

The two GPO settings I enable first in any environment I inherit are PowerShell Script Block Logging and command line auditing in process creation. Combined with Sysmon, they turn a blind Windows environment into one where I can actually investigate what happened. Without them, you are flying blind in an incident.

Audit Policy

Audit Policy controls what Windows writes to the Security event log. By default, Windows logs embarrassingly little. Configuring audit policy correctly is the difference between being able to investigate an incident and having absolutely nothing to work with.

Analogy

Audit policy is like a security camera system. You can have 50 cameras in a building, but if only two of them have tapes in (are actually recording), most of the building has no coverage. By default, Windows has a lot of "cameras" but almost none of them are recording. Audit policy is how you put tapes in all of them.

Viewing and setting audit policy

# See what is currently configured
auditpol /get /category:*

# The output shows Success/Failure auditing for each category.
# "No Auditing" means nothing is being logged for that category.
# That is the default for many categories on a fresh Windows install.

# Enable specific categories manually (easier to do via GPO for a domain)
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Process Creation" /success:enable
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable

What to enable and why

# ---- ACCOUNT LOGON ----
Credential Validation:      Success, Failure
# Logs every password attempt. Failure shows brute force attacks.
# Success shows successful authentications.

Kerberos Authentication:    Success, Failure
# Kerberos is how domain logins work. Failures here often mean
# misconfigured services or active ticket attacks (Pass-the-Ticket).

# ---- ACCOUNT MANAGEMENT ----
User Account Management:    Success, Failure
# Who created, deleted, or modified user accounts?
# An attacker creating a new admin account shows up here.

Security Group Management:  Success
# Who was added to Domain Admins? Shows up here as Event ID 4728.

# ---- DETAILED TRACKING ----
Process Creation:           Success
# Event ID 4688. Logs every process that starts.
# This + command line logging = you can see exactly what ran on the machine.

# ---- LOGON/LOGOFF ----
Logon:                      Success, Failure
# Event ID 4624 (success) and 4625 (failure).
# 4625 with many failures in a short time = brute force in progress.

Special Logon:              Success
# Event ID 4672. Logs when someone logs in with admin privileges.
# Watch this one carefully.

# ---- POLICY CHANGE ----
Audit Policy Change:        Success, Failure
# If someone disables audit policy to cover their tracks, this logs it.
# Yes, it catches itself being disabled — at least the last entry.
Real World

I was called in after a domain compromise. The attacker had been in the environment for three weeks. With proper audit policy, I could have seen the exact moment they created their backdoor admin account, ran mimikatz, and moved laterally. Instead? The logs showed almost nothing. Default audit policy. Three weeks of activity, zero traces. Enable this stuff before you need it — not after.

Scheduled Tasks

Scheduled Tasks are Windows' built-in automation system. They run programs on a schedule, on a trigger, or in response to an event. IT uses them for maintenance and automation. Attackers use them for persistence — making sure their malware survives a reboot.

Analogy

A scheduled task is like setting an alarm on your phone. You set it once and it fires automatically without you doing anything. Except instead of waking you up, it runs a program. And if an attacker sets one, it runs their program every time the machine starts — even after a "cleanup."

Creating a scheduled task — three ways

# Method 1: Task Scheduler GUI
taskschd.msc
# Create Task > set name > Triggers tab (when to run) > Actions tab (what to run)
# Important: General tab > "Run whether user is logged on or not"
# + "Run with highest privileges" for tasks that need admin rights

# Method 2: CMD (quick and scriptable)
schtasks /create /tn "Database Backup" /tr "C:\Scripts\backup.bat" /sc DAILY /st 02:00 /ru SYSTEM
# /tn = task name
# /tr = task to run (the program/script)
# /sc = schedule (DAILY, WEEKLY, MONTHLY, ONSTART, ONLOGON)
# /st = start time
# /ru = run under which user account (SYSTEM runs even with no one logged in)

# Method 3: PowerShell (most flexible)
$action  = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NonInteractive -File C:\Scripts\cleanup.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "3:00AM"
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 1) -RunOnlyIfNetworkAvailable
Register-ScheduledTask -TaskName "Nightly Cleanup" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest -User "SYSTEM"

Managing and investigating tasks

# List ALL scheduled tasks with full details (verbose = /v)
schtasks /query /fo LIST /v

# Just the task names and next run time
schtasks /query /fo TABLE

# Run a task right now (without waiting for its schedule)
schtasks /run /tn "Database Backup"

# Delete a task
schtasks /delete /tn "Database Backup" /f

# PowerShell: list all tasks and what they actually run
Get-ScheduledTask | Select-Object TaskName, TaskPath, State | Sort-Object TaskPath
What Attackers Do

When investigating a compromised machine, check scheduled tasks early. Attacker-created tasks have telltale signs: they run PowerShell or cmd.exe with encoded commands, they run from AppData or Temp, they have names designed to look legitimate ("Windows Performance Monitor Helper", "Adobe Update Scheduler"). Any task pointing to a path outside of System32, Program Files, or a known application folder deserves a close look.

DNS and DHCP

In almost every corporate Windows environment, DNS and DHCP run on Windows Server — usually on the same server as the Domain Controller. These two services are the plumbing of the network. When they work, nobody notices. When they break, everything breaks and everyone notices.

DNS — the phonebook of the network

DNS translates names to IP addresses. When you type \\fileserver into File Explorer, DNS looks up what IP address "fileserver" maps to and sends you there. Without working DNS, you can still reach things by IP address — but nothing by name, which means domain authentication fails, file shares become unreachable, and email stops working.

Analogy

DNS is a contacts list. You know your colleague's name (fileserver.company.local) but you need their phone number (192.168.1.20) to actually call them. DNS is the contacts app that does that translation. If your contacts list is wrong or unreachable, you cannot call anyone — even if the phone itself works perfectly.

# ---- On the DNS server (Windows Server) ----

# View all DNS zones
Get-DnsServerZone

# View all A records (hostname to IP mappings) in a zone
Get-DnsServerResourceRecord -ZoneName "company.local" -RRType A

# Add a new A record (so machines can find a server by name)
Add-DnsServerResourceRecordA -ZoneName "company.local" -Name "newserver" -IPv4Address "192.168.1.100"

# Add a CNAME (alias) — so "fileserver" points to the real hostname
Add-DnsServerResourceRecordCName -ZoneName "company.local" -Name "files" -HostNameAlias "fileserver01.company.local"

# Delete a record
Remove-DnsServerResourceRecord -ZoneName "company.local" -Name "oldserver" -RRType A -Force

# ---- On any machine ----

# Which DNS server am I using?
ipconfig /all | findstr "DNS Servers"

# Look up a hostname
nslookup fileserver.company.local

# Flush local DNS cache (fixes "I changed the DNS record but can't reach the new IP")
ipconfig /flushdns

DHCP — automatic IP address distribution

DHCP hands out IP addresses automatically. Without it, every device would need a manually configured IP. In a company with 500 machines, manually assigning IPs is a nightmare. DHCP automates all of that.

# ---- On the DHCP server ----

# List all scopes (IP ranges being handed out)
Get-DhcpServerv4Scope

# See who currently has an IP from a scope (active leases)
Get-DhcpServerv4Lease -ScopeId 192.168.1.0

# Create a reservation (this printer always gets 192.168.1.50)
Add-DhcpServerv4Reservation -ScopeId 192.168.1.0 -IPAddress 192.168.1.50 -ClientId "AA-BB-CC-DD-EE-FF" -Description "HP LaserJet Finance Floor"
# The ClientId is the MAC address of the device

# Exclude a range from being handed out (reserved for manual assignment)
Add-DhcpServerv4ExclusionRange -ScopeId 192.168.1.0 -StartRange 192.168.1.1 -EndRange 192.168.1.20
# Typically: .1-.20 excluded (for routers, servers, printers with static IPs)
# .21-254 = DHCP range for workstations
Real World

The classic troubleshooting order for "I can't connect to anything": 1) Run ipconfig /all — do you have a valid IP, or a 169.254.x.x address? (169.254 = no DHCP response, machine gave itself an address). 2) Can you ping your default gateway? 3) Can you resolve DNS? nslookup google.com. 4) Can you reach the target by IP instead of name? If yes to 4 and no to 3, DNS is your problem. This process resolves 80% of network complaints.

Sysmon

Sysmon is a free tool from Microsoft Sysinternals. It runs silently in the background as a Windows service and writes extremely detailed logs about what is happening on the machine — far more than Windows logs by default. If you are serious about detection, Sysmon is the first thing you install on every endpoint.

Analogy

Default Windows logging is like a hotel with security cameras only in the lobby. You can see who came through the front door, but you have no idea what they did after that. Sysmon is like adding cameras to every hallway, every room entrance, every elevator — with facial recognition. Suddenly you know exactly where everyone went and what they touched.

What Sysmon logs that Windows doesn't

  • Event ID 1 — Process Creation with the full command line, the hash of the executable, and the parent process. This alone is transformative. You can see exactly what ran, from where, and what launched it.
  • Event ID 3 — Network Connection — which process connected to which IP and port. You can see malware calling home.
  • Event ID 7 — Image Loaded — which DLLs were loaded into which process. Useful for detecting DLL injection.
  • Event ID 8 — CreateRemoteThread — a classic process injection technique. This event fires when one process injects code into another.
  • Event ID 10 — ProcessAccess — when one process accesses another's memory. The most important one: LSASS access. LSASS stores credentials in memory. Mimikatz and other credential dumping tools access LSASS. This event catches them.
  • Event ID 11 — FileCreate — file created or overwritten, with timestamp and process that did it.
  • Event ID 22 — DNS Query — what hostname did this process look up? Malware calling back to a C2 server shows up here before the network connection is even made.

Installation

# Download Sysmon from Microsoft Sysinternals:
# https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon

# ALWAYS install with a config file. Without a config,
# Sysmon logs almost nothing useful by default.

# Download the SwiftOnSecurity config (best community baseline)
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml" -OutFile sysmonconfig.xml

# Install with config
.\sysmon64.exe -accepteula -i sysmonconfig.xml

# Update config without reinstalling
.\sysmon64.exe -c sysmonconfig.xml

# Verify it is running
Get-Service Sysmon64

# Uninstall (do not do this on production machines)
.\sysmon64.exe -u

Reading Sysmon logs

# Sysmon logs to: Applications and Services Logs > Microsoft > Windows > Sysmon > Operational
# You can also open Event Viewer, navigate there manually.

# Query Sysmon events in PowerShell
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 100

# Filter for just process creation (Event ID 1)
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object {$_.Id -eq 1} | Select-Object TimeCreated, Message

# Find any process that accessed LSASS memory (credential dumping indicator)
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object {$_.Id -eq 10 -and $_.Message -like "*lsass*"} | Select-Object TimeCreated, Message

# Find network connections to non-standard ports (potential C2 traffic)
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object {$_.Id -eq 3} | Select-Object TimeCreated, Message
Real World

I cannot count how many investigations have been saved by Sysmon Event ID 1. Someone runs mimikatz from a suspicious path at 2am? Sysmon logged it with the full command line, the SHA256 hash of the binary, the parent process (so you can see how it was launched), and the user account. Without Sysmon, Windows' own event log would show nothing. With it, you have a complete forensic timeline in minutes.

Building Your Test Lab

You cannot learn this stuff by just reading about it. You need to break things. A home lab gives you a real Windows environment to practice on without any consequences. This section walks you through building one from scratch using free tools and free software.

Hypervisors — the software that runs VMs

A hypervisor lets you run multiple virtual machines on your physical computer. Each VM behaves like a completely separate computer — its own OS, its own IP, its own files — but they all share your physical hardware underneath.

  • VMware Workstation Pro — became free for personal use in 2024. The best option if you want something close to enterprise-grade. Download from broadcom.com (search "VMware Workstation Pro"). Mac users need VMware Fusion instead.
  • VirtualBox — completely free, open source, works on Windows, Mac, and Linux. Slightly less polished but totally functional for learning. Download at virtualbox.org. Also download and install the Extension Pack from the same page.

Getting Windows legally for free

# Microsoft provides 180-day evaluation ISOs — full versions, no tricks.
# When they expire, rebuild the VM. The content is the same.

Windows 11 Enterprise (180 days):
https://www.microsoft.com/en-us/evalcenter/evaluate-windows-11-enterprise

Windows Server 2022 (180 days):
https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2022

Windows 10 Enterprise (90 days):
https://www.microsoft.com/en-us/evalcenter/evaluate-windows-10-enterprise

Step-by-step: Your first Windows VM

STEP 01Create the VM in VMware

Open VMware Workstation, click Create a New Virtual Machine. Choose Custom (advanced). Select your downloaded Windows 11 ISO. VMware auto-detects it. Give the VM a name like "Win11-Lab". Set RAM to 4096 MB minimum (8192 is better), 2 CPU cores, disk at 60 GB dynamic allocation. VMware auto-adds a virtual TPM chip for Windows 11 — needed for the install to work.

STEP 02Configure networking before you boot

Before starting the VM, go to VM > Settings > Network Adapter. Your options:

NAT — VM shares your internet through your host machine. Simple, works for most learning. The VM cannot be reached directly from other devices.

Bridged — VM gets its own IP on your physical network, like a real separate machine. Use this when you need multiple VMs to talk to each other, or when you need to reach the VM from your host.

Host-Only — private network between your VMs and host only, no internet. Use for isolated lab segments where you do not want internet access.

For a domain lab: add two adapters — one NAT (for internet access to download tools), one Host-Only (so VMs can communicate with each other). VM Settings > Add > Network Adapter.

STEP 03Install Windows

Boot the VM. It boots from the ISO automatically. Language, click Install, no product key needed (click "I don't have a product key"), choose Windows 11 Enterprise Evaluation, Custom Install, click Next on the unallocated disk. Wait 15-20 minutes.

First boot setup: when it asks to sign in with a Microsoft account, click "Sign-in options" then "Domain join instead" (or "Offline account"). Keep it as a local account — cleaner for lab use.

STEP 04Install VMware Tools and take a snapshot

After Windows boots: VM menu > Install VMware Tools. A virtual CD appears inside Windows — open it and run the installer. This gives you proper screen resolution, clipboard sharing between host and VM, and drag-and-drop file transfer. Restart the VM.

Now, before you do anything else: VM menu > Snapshot > Take Snapshot. Name it "Clean Install." This is your restore point. If you break something, you can revert here in 30 seconds. Take snapshots constantly — before joining the domain, before installing Sysmon, before doing anything you might want to undo.

Building a domain lab — the minimal setup

# VM 1: Domain Controller
OS:      Windows Server 2022 Evaluation
RAM:     2 GB (no desktop GUI needed, just CLI)
Disk:    40 GB
Network: Host-Only adapter, static IP 192.168.100.10
Roles:   Active Directory, DNS, DHCP

# VM 2: Windows 11 Workstation
OS:      Windows 11 Enterprise Evaluation
RAM:     4 GB
Disk:    60 GB
Network: Host-Only adapter (gets IP from DC via DHCP)
Purpose: Domain-joined workstation to practice on

# Optional VM 3: Security tooling
OS:      Kali Linux or Ubuntu
Network: Host-Only adapter (192.168.100.30)
Purpose: Run Wireshark, nmap, and security tools against your lab

Promoting Windows Server to a Domain Controller

# On the Windows Server VM, open PowerShell as Administrator

# Step 1: Set static IP and point DNS at itself
New-NetIPAddress -InterfaceAlias "Ethernet0" -IPAddress 192.168.100.10 -PrefixLength 24 -DefaultGateway 192.168.100.1
Set-DnsClientServerAddress -InterfaceAlias "Ethernet0" -ServerAddresses 127.0.0.1

# Step 2: Install the Active Directory Domain Services role
Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools

# Step 3: Promote this server to a domain controller (creates a new forest)
Install-ADDSForest -DomainName "lab.local" -DomainNetbiosName "LAB" -InstallDns -Force
# It will ask for a SafeModeAdministratorPassword — this is used if AD breaks
# and you need to recover. Set something strong and remember it.
# Server restarts automatically. After restart, it is a DC.
# Log in as LAB\Administrator