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.
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.
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.
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.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 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.
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.
Not all Windows is the same. In corporate environments you will mostly see:
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.
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.
# 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.
# 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
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.
# 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.
# 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
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 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>.
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.
# 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.
# 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"
# 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
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
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.
# 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
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.
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.
@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.
@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.
# 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"
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.
When a device connects to a network, it needs an IP address. There are two ways it gets one:
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.
# 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
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.
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
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 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.
# 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
# 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"
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.
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.
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.
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.
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.
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.
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.
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.
# 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
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 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.
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.
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:
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.
# 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
# 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
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 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.
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.
# 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
# ---- 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.
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 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.
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."
# 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"
# 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
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.
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 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.
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 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
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 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.
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.
# 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
# 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
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.
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.
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.
# 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
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.
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.
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.
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.
# 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
# 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