Windows Fundamentals · beginner · ~9 min

Event Viewer and Windows logging

**What you will learn** - Open and navigate the Windows **Event Log** (Security, System, Application) using **Event Viewer** and **Get-WinEvent**. - Recognise the high-value **event IDs** defenders watch — 4624, 4625, 4672, 4688, 7045, 1102 — and say what each one means. - Read the **logon type** field to tell a keyboard logon from a network or RDP logon. - Build a simple detection idea (for example, a burst of failed logons) and describe how to reconstruct an incident timeline from events. - Explain, in defensive terms, why log integrity matters and why clearing logs is itself a monitored, high-signal event.

Overview

Security objective: the asset you are protecting is the audit trail — the record of who authenticated, what ran, and what services were installed on a Windows host. The threat is an attacker who logs on with stolen credentials, runs tools, installs persistence, and then tries to hide. What you will learn to detect is that activity as it appears in the event logs, and what you will learn to preserve is the integrity of the log itself.

Windows continuously records activity in the Event Log. It is split into separate logs, the most important of which are:

  • Security — authentication and audit events. This is the defender's primary source.
  • System — service, driver, and OS-level events.
  • Application — events raised by installed programs.

You read these logs two ways:

  • Event Viewer (eventvwr.msc) — the built-in graphical browser.
  • Get-WinEvent — a PowerShell command for querying logs precisely and at scale.

This lesson builds directly on Windows users, groups, and SIDs (the prereq). Every logon event ties back to an account and its SID; every privileged logon (4672) means a security principal that belongs to a powerful group like Administrators was used. If you cannot read a SID or reason about group membership, the logs will not make sense. Think of this as the Windows counterpart to reading /var/log/auth.log on Linux — same idea, different field names.

Why it matters

In authorized professional work, event logs are where defence actually happens.

  • SOC analysts and incident responders live in these logs. When an alert fires, they pivot across event IDs to answer who logged on, from where, with what privileges, and what did they run. A believable incident timeline is built almost entirely from Security and System events.
  • Detection engineers write rules against these IDs — for example, "alert when one source produces many 4625 events in a short window" (a password brute-force or spraying signature). Knowing the fields is a prerequisite to writing good detections that catch attacks without drowning the team in false positives.
  • Penetration testers and red teamers need to understand logging from the other side: their authorized actions are recorded. A newly installed service raises 7045; a logon raises 4624. Clearing the Security log raises 1102, which is a loud, high-priority alert and is normally out of scope for a test. Good testers report what they touched so the blue team can validate their detections — that collaboration is the whole point of an engagement.

Whether you end up on blue team or red team, fluency in Windows logging is one of the most transferable skills in the field.

Core concepts

1. The Event Log and its channels

Definition. The Event Log is a structured, append-oriented store of events. Each event has a source, an Event ID, a level (Information/Warning/Error/Audit Success/Audit Failure), a timestamp, and named data fields.

How it works. Different components write to different channels (logs):

Channel What it records Defender use
Security Logons, privilege use, audit policy, log clears Primary source for intrusion detection
System Services, drivers, OS components Persistence and stability signals
Application Events from installed programs App errors, some security tools

When / when not. Use Security for authentication questions; use System for "was a service installed?"; use Application for program-specific detail. Not every interesting action is logged by default — for example, process creation (4688) and command lines must be enabled via audit policy first.

Pitfall. Assuming an event's absence proves nothing happened. If auditing for that category was never enabled, the event simply was never written.

2. The event IDs defenders watch

Event ID Log Meaning Why it matters
4624 Security Successful logon Establishes who was on the host and how
4625 Security Failed logon Bursts suggest brute-force / password spraying
4672 Security Special privileges assigned at logon Effectively an administrator logon
4688 Security A new process was created Shows what ran (command line if enabled)
7045 System A service was installed Classic persistence / lateral-movement signal
1102 Security The Security log was cleared High-signal anti-forensics indicator

Pitfall. Treating a single 4625 as an attack. People mistype passwords constantly. It is the pattern — many failures across many accounts from one source in a short window — that signals spraying.

3. Logon types

Definition. A field inside 4624/4625 that says how the session was created.

Type Name Typical cause
2 Interactive Someone at the physical keyboard / local console
3 Network SMB file share, remote authentication
10 RemoteInteractive Remote Desktop (RDP)

How it works. A type 10 logon at 03:00 to a server that normally only sees type 2 is worth a second look. Analysts triage almost every logon question by first checking the type.

Pitfall. Confusing type 3 (network) with type 10 (RDP). Both are "remote," but type 3 is usually service-to-service, while type 10 is an interactive desktop session — very different risk.

4. Log integrity

Definition. The trustworthiness of the record. Clearing the Security log writes event 1102 before the log is emptied, so the clear itself cannot be hidden locally.

Why it matters defensively. Forwarding logs to a central collector (WEF/SIEM) means that even if a host's local log is cleared, the evidence already left the box. The gap on the host plus a 1102 is itself strong evidence of tampering.

THREAT MODEL: Windows host authentication & audit trail

  Assets                          Trust boundary            Entry points
  ------------------------------  ------------------------  ----------------------
  [ User accounts / SIDs ]        ||  Network perimeter  || <- RDP  (logon type 10)
  [ Local admin privileges ]      ||                     || <- SMB  (logon type 3)
  [ Services (persistence) ]      ||   Host OS boundary  || <- Console (logon type 2)
  [ The Event Log itself ] <====  ||  (audit subsystem)  ||
                                  ------------------------
         |                                 |
         v                                 v
   Local Security log  --forward-->  Central SIEM / WEF collector
   (can be cleared: 1102)            (off-host copy: tamper-evident)

  Detections: 4625 bursts (spray), 4672 (admin logon), 7045 (new service),
              1102 (log cleared), off-hours logon type 10.

Knowledge check

  1. What asset is protected? — The audit trail: the record of authentications, process starts, and service installs on the host.
  2. Where is the trust boundary? — At the network perimeter (who may reach RDP/SMB) and at the host OS/audit subsystem (who may read or clear the log).
  3. What insecure assumption lets an attacker hide? — Believing the local log is the only copy. Forwarding logs off-host defeats that.
  4. Which events detect a brute-force followed by admin access? — A burst of 4625, then a 4624, then 4672 for the same account.
  5. Why practise this only in an authorized lab? — Generating logons, failed logons, and service installs on a system you do not own is unauthorized access; do it only on hosts you own or are contracted to test.

Syntax notes

The core defensive command is Get-WinEvent in PowerShell. It reads a channel and lets you filter server-side, which is far faster than exporting everything.

# Read the 20 most recent failed-logon events from the Security log.
# -FilterHashtable filters at the source (fast, precise).
Get-WinEvent -FilterHashtable @{
    LogName = 'Security';   # which channel
    Id      = 4625          # failed logon
} -MaxEvents 20 |
    Select-Object TimeCreated, Id, @{
        Name = 'Account'
        Expression = { $_.Properties[5].Value }   # target account name
    }

Annotated pieces:

  • -FilterHashtable @{ LogName=...; Id=... } — the efficient way to filter; add StartTime/EndTime keys to bound a window.
  • $_.Properties[N].Value — event fields are positional; index 5 is the target user name for 4625 on modern Windows. Always confirm the index for your event and OS build before trusting it.
  • To open the GUI instead: run eventvwr.msc, then browse Windows Logs -> Security.

Run these only on a host you own or are authorized to test (see the lab checklist in Practice tasks).

Lesson

Windows records activity in the Event Log. You can browse it with Event Viewer (eventvwr) or query it with PowerShell (Get-WinEvent).

The main logs

  • Security — authentication and audit events (the defender's primary log).
  • System — service and driver events.
  • Application — app-level events.

Event IDs worth knowing

  • 4624 — successful logon.
  • 4625 — failed logon. Bursts of 4625 suggest brute force or password spraying.
  • 4672 — special privileges assigned (an admin logon).
  • 4688 — process creation; shows what ran.
  • 7045 — a service was installed. This is a classic attacker-persistence signal.

Logon types

The logon type recorded in a 4624 event tells you how the user connected:

  • Type 3 — network (SMB).
  • Type 10 — RemoteInteractive (RDP).
  • Type 2 — interactive (local).

Defenders triage events by these types.

Both sides of the work

  • Blue team / SOC: build detections and incident timelines from these IDs.
  • Red team / pentesters: know that your actions generate events — a new service produces 7045, a logon produces 4624. Also know that clearing logs is itself logged as a high-signal event (1102) and is usually out of scope.

Code examples

The shape below is INSECURE detection -> SECURE detection -> VERIFY. The "insecure" part is a weak detection rule, not an exploit — a common beginner mistake that misses real attacks and floods analysts with noise.

1) WARNING: intentionally vulnerable — use only in a local, isolated, authorized lab. Do not deploy.

A naive rule that alerts on any single failed logon. It is defensive code, but it is a bad detection: too noisy to be useful, and it misses the pattern that actually matters.

# WEAK DETECTION - do not rely on this.
# Fires on EVERY 4625, including honest typos. Analysts will mute it,
# and a slow, spread-out password spray still slips through.
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4625 } -MaxEvents 50 |
    ForEach-Object { Write-Warning "Failed logon at $($_.TimeCreated)" }

2) SECURE fix — detect the pattern, not the single event

Count failed logons per source account within a time window and only alert past a threshold. This catches brute-force and spraying while tolerating normal typos.

# BETTER DETECTION: threshold + time window + grouping.
$WindowMinutes = 15
$Threshold     = 10          # tune to your baseline
$since = (Get-Date).AddMinutes(-$WindowMinutes)

$events = Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4625
    StartTime = $since
} -ErrorAction SilentlyContinue

$events |
    Group-Object { $_.Properties[5].Value } |          # group by target account
    Where-Object { $_.Count -ge $Threshold } |
    ForEach-Object {
        [pscustomobject]@{
            Account   = $_.Name
            Failures  = $_.Count
            Window    = "$WindowMinutes min"
            FirstSeen = ($_.Group.TimeCreated | Sort-Object | Select-Object -First 1)
            Alert     = 'Possible brute-force / password spray'
        }
    }

3) VERIFY the detection rejects noise and accepts real attacks (lab only)

On a local, isolated lab VM you own, generate controlled failures against a throwaway account, then confirm the rule stays quiet below threshold and fires above it.

# LAB ONLY. Run on a VM you own. Uses a disposable local test account.
# This triggers real 4625 events with WRONG passwords on purpose.
$acct = 'labtestuser'
$wrong = ConvertTo-SecureString 'definitely-wrong-pw' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($acct, $wrong)

# Produce a handful of failures (below threshold) -> rule should stay SILENT.
1..5 | ForEach-Object {
    Start-Process cmd.exe -Credential $cred -ErrorAction SilentlyContinue
}
# Then produce enough to cross the threshold -> rule should ALERT.
1..12 | ForEach-Object {
    Start-Process cmd.exe -Credential $cred -ErrorAction SilentlyContinue
}
# Re-run the SECURE detection above and confirm exactly one alert for $acct.

Expected behaviour. With 5 failures the SECURE rule prints nothing (below threshold). With 12 failures it prints one row naming labtestuser, the failure count, and the window. The WEAK rule, by contrast, would have shouted 17 times. This proves the fix accepts a real attack pattern and rejects ordinary noise.

Line by line

Walkthrough of the SECURE detection.

  1. $WindowMinutes = 15 / $Threshold = 10 — the two tuning knobs. Together they define "too many failures, too fast." You set these from your own baseline of normal failed logons.
  2. $since = (Get-Date).AddMinutes(-$WindowMinutes) — computes the start of the look-back window (15 minutes ago).
  3. Get-WinEvent -FilterHashtable @{ ... StartTime=$since } — pulls only 4625 events from the Security log inside the window. Filtering at the source keeps it fast even on busy hosts. -ErrorAction SilentlyContinue avoids a hard error when the window contains zero matching events.
  4. Group-Object { $_.Properties[5].Value } — buckets the events by target account name (field index 5 for 4625). After this, each group is one account with a .Count of failures.
  5. Where-Object { $_.Count -ge $Threshold } — keeps only accounts at or above the threshold. This single line is what turns "noisy per-event" into "meaningful per-pattern."
  6. The [pscustomobject] block — formats each surviving group into a tidy alert row with the account, failure count, window, first-seen time, and a verdict string.

Trace with the lab data.

Stage 5-failure run 12-failure run
Events pulled by Get-WinEvent 5 12
After Group-Object (labtestuser) Count = 5 Count = 12
After Where-Object (>= 10) dropped kept
Output (nothing) 1 alert row

The value that decides everything is .Count versus $Threshold: 5 is below 10 so the group is discarded; 12 is above so it becomes an alert.

Common mistakes

Mistake 1 — Alerting on single events.

  • Wrong: fire on every 4625.
  • Why wrong: honest typos create constant 4625s; analysts mute the noisy rule and then miss the real attack.
  • Corrected: threshold + time window + grouping, as in the SECURE example.
  • Recognise/prevent: if a rule fires dozens of times an hour in normal operation, it is mistuned.

Mistake 2 — Assuming 4688 always has command lines.

  • Wrong: expecting to see full command lines in process-creation events out of the box.
  • Why wrong: process-creation auditing and command-line capture are off by default and must be enabled via audit policy / Group Policy.
  • Corrected: enable the relevant audit subcategory in a lab, then confirm 4688 events appear with the command line field populated.
  • Recognise/prevent: if 4688 is missing entirely, auditing is not enabled — absence is not innocence.

Mistake 3 — Reading only the local log during an incident.

  • Wrong: trusting a single host's local Security log as the whole truth.
  • Why wrong: an attacker with admin rights can clear it (leaving a 1102, but destroying detail).
  • Corrected: forward events to a central SIEM/WEF collector so an off-host copy survives.
  • Recognise/prevent: a 1102 plus a suspicious time gap in local events is a tampering red flag — cross-check the central copy.

Mistake 4 — Confusing logon types.

  • Wrong: treating a type 3 (network) logon as an interactive intrusion.
  • Why wrong: type 3 is routine service/SMB traffic; type 10 (RDP) is the interactive remote session you usually care about.
  • Corrected: always read the logon type field before judging risk.
  • Recognise/prevent: off-hours type 10 to a normally-console-only host is the pattern to escalate.

Debugging tips

"Get-WinEvent : No events were found" — Your filter matched nothing. Widen the window (StartTime), remove the Id key temporarily to confirm the channel has data, and check you are querying the right LogName.

"Access is denied" reading the Security log — The Security channel requires elevation. Open PowerShell as Administrator (on a host you are authorized to use).

Wrong field appears for $_.Properties[N] — Field indexes differ between event IDs and OS builds. Debug by piping one event to Format-List * or inspecting $_.Properties and $_.Message to find the correct index before hard-coding it.

4688 events missing — Process-creation auditing is not enabled. Confirm audit policy in your lab, regenerate an event, and re-query.

Detection never fires in the lab — Confirm your test actions actually produced 4625s (query them directly), check the clock/timezone on StartTime, and verify $Threshold is reachable given how many failures you generated.

Questions to ask when it fails: Is auditing enabled for this category? Am I elevated? Is my time window correct and in the right timezone? Am I reading the right channel and field index? Is there an off-host copy to compare against?

Memory safety

Security & safety — detection, logging, and privacy

What to log when you build detections or record an investigation:

  • Timestamp (with timezone / UTC) of the event and of the detection.
  • Source — host name, source IP/workstation, and the initiating account SID.
  • Resource / action — the event ID, target account, service name (for 7045), or process (for 4688).
  • Result — success vs failure (Audit Success / Audit Failure).
  • Security decision — what your rule concluded (for example, "threshold exceeded: possible spray").
  • Correlation id — a case or engagement id so related events can be joined across hosts.

What to NEVER log:

  • Passwords or password-attempt contents, tokens, session cookies, Kerberos tickets, or private keys.
  • Full secrets from command lines (4688 can capture them) — redact before storing.
  • Unneeded PII. Keep only what the investigation needs, and apply retention limits.

Events that signal abuse: 4625 bursts (brute-force/spray), a 4625 burst followed by 4624 + 4672 for the same account (successful compromise to admin), 7045 for an unexpected service (persistence), 1102 (log cleared), and off-hours type 10 logons.

How false positives arise: vulnerability scanners and monitoring agents generate authentication noise; a user returning from holiday mistypes an expired password repeatedly; service accounts fail after a password rotation. Tune thresholds against a real baseline and maintain an allow-list of known-benign sources so genuine attacks stand out.

Integrity reminders: decoding or reading a log entry is not the same as proving it is authentic — trust off-host forwarded copies over a single local log. Passing an automated log-hygiene scan does not prove a host is secure, and no logging setup is ever "completely secure"; it reduces blind spots, it does not eliminate them.

Real-world uses

Authorized real-world use case. A SOC receives an alert that a finance server saw many failed logons overnight. An analyst queries the Security log, finds a burst of 4625 across several accounts from one workstation (password spraying), then a single 4624 and 4672 for one account (the spray succeeded and gained admin), followed by 7045 in the System log (a service installed for persistence). From these events alone they reconstruct the timeline, scope the compromise, and hand a clear remediation list to IT. The off-host SIEM copy lets them trust the record even though the local log was later found cleared (1102).

Best-practice habits.

Practice Beginner Advanced
Validation Confirm auditing is enabled before trusting event absence Baseline normal 4625/4624 volumes per host to tune thresholds
Least privilege Only elevate when the Security log requires it Restrict who can read/clear logs; monitor those grants
Secure defaults Enable process-creation (4688) auditing in the lab Deploy audit policy via Group Policy fleet-wide
Logging Record timestamp, source, account, result Forward all Security/System events to a tamper-evident SIEM
Error handling Handle empty result sets gracefully Alert when log forwarding stops (a blind-spot signal)

For testers: document the events your authorized actions generate (7045, 4624) and share them so the blue team can validate detections — that hand-off is a deliverable, not an afterthought.

Practice tasks

All tasks are lab-only. Use a Windows VM you own or a purpose-built training range. Never run these against a system you are not authorized to test.

Authorization checklist (complete before starting):

  • I own this VM or have explicit written authorization to test it.
  • It is isolated (host-only / internal network), not production, not internet-exposed.
  • I have a snapshot to revert to.
  • I know the cleanup/reset steps for each task.

Beginner 1 — Tour the channels.

  • Objective: open Event Viewer (eventvwr.msc) and locate the Security, System, and Application logs.
  • Requirements: find one 4624 event; record its logon type, account, and time.
  • Constraints: read-only; do not clear anything.
  • Hints: Windows Logs -> Security; use the Filter Current Log pane.
  • Concepts: channels, event IDs, logon types.

Beginner 2 — Query with PowerShell.

  • Objective: use Get-WinEvent to pull the 10 most recent 4624 events.
  • Requirements: output TimeCreated, Id, and the account name field.
  • Input/Output: input = Security channel; output = a 10-row table.
  • Hints: -FilterHashtable @{ LogName='Security'; Id=4624 } -MaxEvents 10.
  • Concepts: server-side filtering, event fields.

Intermediate 1 — Build the threshold detection.

  • Objective: generate failed logons against a disposable lab account and confirm the SECURE rule fires only above threshold.
  • Requirements: produce a below-threshold run (silent) and an above-threshold run (one alert).
  • Constraints: disposable local account only; no real credentials.
  • Hints: reuse the VERIFY block; tune $Threshold to your baseline.
  • Concepts: grouping, time windows, false-positive control.
  • Defensive conclusion: document the tuned threshold, then re-run to verify it still fires on attack volume and stays quiet on noise.

Intermediate 2 — Enable and read 4688.

  • Objective: enable process-creation auditing in the lab, run a benign command, and find its 4688 event.
  • Requirements: show the process name and (if enabled) command line field.
  • Constraints: lab audit policy only.
  • Hints: absence of 4688 means auditing is off — enable it first.
  • Concepts: audit policy, process telemetry, "absence is not innocence."
  • Defensive conclusion: note what command-line capture reveals, and record the risk of secrets leaking into 4688 (redact before storing).

Challenge — Reconstruct an incident timeline.

  • Objective: on your lab VM, produce a controlled sequence — several 4625, then a 4624 + 4672 for one account, then install a dummy service (7045) — and rebuild the timeline purely from the logs.
  • Requirements: a chronological table of event ID, time, account, logon type, and your interpretation; identify which event marks the shift from attempt to compromise.
  • Constraints: lab only; do NOT clear logs (1102 is out of scope even in the lab unless you are practising detection of it).
  • Hints: correlate across Security (logon/priv) and System (service) channels; join on account and time.
  • Concepts: correlation, logon types, persistence signals.
  • Defensive conclusion: write the one-paragraph remediation (reset the account, remove the dummy service, tighten the audit/threshold) and verify by re-running your detection to confirm it would have caught the sequence.

Cleanup / reset for every task: delete any disposable test account and dummy service you created, clear your working variables, and revert the VM to its pre-lab snapshot so no test artefacts persist.

Summary

  • Windows records activity in the Event Log; the key channels are Security (auth/audit), System (services/drivers), and Application.
  • Read logs with Event Viewer (eventvwr.msc) or Get-WinEvent (filter server-side with -FilterHashtable).
  • Watch these IDs: 4624/4625 logon success/failure, 4672 admin logon, 4688 process creation, 7045 service installed, 1102 log cleared.
  • The logon type (2 interactive, 3 network, 10 RDP) tells you how a session was created — read it before judging risk.
  • Common mistakes: alerting on single events (tune with thresholds + windows), assuming 4688/command lines exist by default (enable auditing), trusting only the local log (forward off-host), and confusing logon types.
  • Defensive takeaways: detect patterns not single events; log timestamp/source/account/result/decision/correlation-id but never passwords, tokens, or unneeded PII; forward logs to a tamper-evident collector; and remember that reading a log is not proving its authenticity, and no setup is ever "completely secure."
  • Practise only on systems you own or are authorized to test, and revert to a snapshot afterwards.

Practice with these exercises