Windows Event Logs TryHackMe Walkthrough

9 min readSep 2, 2023

TL;DR Walkthrough of how we completed the TryHackMe Windows Event Logs room, part of the Cyber Defense pathway.

A full list of our TryHackMe walkthroughs and cheatsheets is here.


The Windows Event Logs room, part of the Cyber Defense pathway, focuses on Windows logs in general, Event Ids, and how to query the logs using Event Viewer, wevtutil, Get-WinEvent, and XPath queries.

We didn’t use Event Viewer at all while finding the answers. We only did the bare minimum in wevtutil and XPath queries to answer the questions specifically on those methods. Luckily The Dutch Hacker helpfully provided the syntax for those questions. I really appreciated the help.

We used Get-WinEvent for 90% or more of the questions. We had previously covered Get-EventLog here last year. Get-EventLog is deprecated, hence this room was great practice with Get-WinEvent. Luckily the syntax is quite similar, as seen here, and here.

We also got some good practice in with PowerDecode and de-obfuscating PowerShell code during the last part of the room.

Our methodology

We connected to the VM via xfreerdp.

xfreerdp /v: /u:administrator /p:blueT3aming! /dynamic-resolution

We then performed the entire room in PowerShell_ISE. I have always been a big fan of the ISE because

  • It suggests commands & options
  • It supports tab completion
  • It shows you where you may have made a syntax error
  • It works well for writing & immediately running small ForEach loops and other such simple things
  • It’s built in to Windows

We will blow through the first 6 tasks and simply show the question, the query we ran, and the answer. We will spend more time on Task 7 and go more in depth into our thought process there.

Task 2 Event Viewer

What is the Event ID for the earliest recorded event?

Get-WinEvent -LogName Microsoft-Windows-PowerShell/Operational -Last 1

Or specifically:

(Get-WinEvent -LogName Microsoft-Windows-PowerShell/Operational | Select-Object -Last 1).Id


Filter on Event ID 4104. What was the 2nd command executed in the PowerShell session?

Get-WinEvent -LogName Microsoft-Windows-PowerShell/Operational | Where-Object {$_.Id -eq “4104”} | Select-Object -Last 2 | Select-Object Message | Format-List


What is the Task Category for Event ID 4104?

(Get-WinEvent -LogName Microsoft-Windows-PowerShell/Operational | Where-Object {$_.Id -eq “4104”} | Select-Object -Last 1).TaskDisplayName

Execute a Remote Command

Analyze the Windows PowerShell log. What is the Task Category for Event ID 800?

(Get-WinEvent -LogName “Windows PowerShell” | Where-Object {$_.Id -eq “800”} | Select-Object -Last 1 | Select-Object *).TaskDisplayName

Pipeline Execution Details

Task 3 wevtutil.exe

How many log names are in the machine?

(wevtutil enum-logs).Count


What event files would be read when using the query-events command?

wevtutil query-events /?

“Read events from an event log, log file or using structured query.”

Scroll down after doing ‘wevtutil query-events /?’ to find the rest of the answers.

What option would you use to provide a path to a log file?


What is the VALUE for /q?

Xpath query

The questions below are based on this command:

wevtutil qe Application /c:3 /rd:true /f:text

What is the log name?


What is the /rd option for?

event read direction

What is the /c option for?

Maximum number of events to read

Task 4 Get-WinEvent

Execute the command from Example 1 (as is). What are the names of the logs related to OpenSSH?

Get-WinEvent -ListLog * | Select-Object LogName | Select-String “ssh”



Execute the command from Example 8. Instead of the string *Policy* search for *PowerShell*. What is the name of the 3rd log provider?

(Get-WinEvent -ListProvider *Powershell*).Name[2]


Execute the command from Example 9. Use Microsoft-Windows-PowerShell as the log provider. How many event ids are displayed for this event provider?

(Get-WinEvent -ListProvider Microsoft-Windows-PowerShell).Events.Id.Count

Gives 188, which is apparently wrong

THM’s hint said to use | Format-Table ID, Description , so:

((Get-WinEvent -ListProvider Microsoft-Windows-PowerShell).Events | Format-Table Id, Description).Count

Give 192, which is right. Odd.

How do you specify the number of events to display?


Get-WinEvent -LogName Application –MaxEvents 10


When using the FilterHashtable parameter and filtering by level, what is the value for Informational?

Check Microsoft’s documentation and we see:

Informational = 4

Task 5 XPath Queries

Using the knowledge gained on Get-WinEvent and XPath, what is the query to find WLMS events with a System Time of 2020–12–15T01:09:08.940277500Z?

Get-WinEvent -LogName Application -FilterXPath ‘*/System/Provider[@Name=”WLMS”] and */System/TimeCreated[@Name=”SystemTime”]=”2020–12–15T01:09:08.940277500Z”’

Using Get-WinEvent and XPath, what is the query to find a user named Sam with an Logon Event ID of 4720?

Get-WinEvent -LogName Security -FilterXPath ‘*/EventData/Data[@Name=”TargetUserName”]=”Sam” and */System/EventID=4720’

Based on the previous query, how many results are returned?


Based on the output from the question #2, what is Message?

Get-WinEvent -LogName Security -FilterXPath ‘*/EventData/Data[@Name=”TargetUserName”]=”Sam” and */System/EventID=4720’ | Select-Object Message | Format-List

Both events have the same message:

A user account was created.

Still working with Sam as the user, what time was Event ID 4724 recorded? (MM/DD/YYYY H:MM:SS [AM/PM])

Get-WinEvent -LogName Security | Where-Object {($_.Id -eq “4724”) -and ($_.Message -like “*Sam*”)}


(Get-WinEvent -LogName Security | Where-Object {($_.Id -eq “4724”) -and ($_.Message -like “*Sam*”)}).TimeCreated

12/17/2020 1:57:14 PM

What is the Provider Name?

$Event = Get-WinEvent -LogName Security | Where-Object {($_.Id -eq "4724") -and ($_.Message -like "*Sam*")} | Select-Object -Last 1 | Select-Object *



Task 7 Putting Theory into Practice

What event ID is to detect a PowerShell downgrade attack?


This one was really simple, I just Googled and found this description of Event Id 400 in no time.

What is the Date and Time this attack took place? (MM/DD/YYYY H:MM:SS [AM/PM])

$Attack = Get-WinEvent -Path ".\merged.evtx" | Where-Object {($_.Id -eq "400")} | Select-Object -Last 1 | Select-Object *


12/18/2020 7:50:33 AM

This one was a bit tricky because THM didn’t word the question very well. They meant “what is the DTG the most recent example of this attack took place?”

I ran the query with -First initially and THM told me I was wrong. It turns out there were over 30 instances of Event Id 400 in the log.

Bear in mind that Events are ‘top to bottom’ with the most recent being at the top, aka -First. -Last will return the Event at the bottom of the log, which is the oldest event in the log.

I kept singing the lyrics “going back in time” during this part to remind me. If it’s stupid but it works then it isn’t stupid, right?

A Log clear event was recorded. What is the ‘Event Record ID’?


There’s two ways to go about this one. I initially did it the duct tape way:

$Stuff = Get-WinEvent -Path “.\merged.evtx” | Select-Object -Last 1| Select-Object *

I first tried to find the PowerShell command Clear-EventLog, but came up empty.

However the best way to query this one is simply:

$Stuff = Get-WinEvent -Path “.\merged.evtx” | Were-Object {$_.Id -eq “104”}

What is the name of the computer?



What is the name of the first variable within the PowerShell command?

$CLI_Stuff = Get-WinEvent -Path ".\merged.evtx" | Where-Object {$_.ProviderName -like "*PowerShell*"} | Select-Object *

$CLI_Stuff | Select-Object -Last 1


The question didn’t specify that THM wanted the oldest event, luckily the hint did.

This query also solved the next two questions.

What is the Date and Time this attack took place? (MM/DD/YYYY H:MM:SS [AM/PM])

8/25/2020 10:09:28 PM

What is the Execution Process ID?


What is the Group Security ID of the group she enumerated?

$Enum = Get-WinEvent -Path ".\merged.evtx" | Where-Object {$_.Id -eq "4799"} | Select-Object *

ForEach($Enumeration in $Enum)
$Enumeration.Properties[2].Value.Value | Out-File SIDs.txt -Append

Get-Content .\SIDs.txt | Sort-Object -Unique





THM wanted the first one, but notice a pattern here. These are all well-known SIDs used for domain-relative RIDs.

The related domain groups in order:

  • Domain Admins
  • Domain Users
  • Domain Guests
  • Domain Backup Operators

The problem is that there was a lot of Event Id 4799 instances in the log and once again THM didn’t specify which one they wanted.

Hence we used a duct tape solution again and paired a query with a ForEach loop, then teased out the unique group SIDs that had been enumerated.

How did we pull just the SID of the group that was enumerated out of the log entries though?

Simple, we used a little trick:

#We're looking for the group's SID that was enumerated.

$x = 0
$z = 20
$x = $x + 1
while ($x -lt $z)

The loops spits out each data point in the Message and what number it corresponds to. Then one simply has to specify


if they want the group’s SID. If one wants a different data point, for example the SID of who did the enumerating, then just specify the corresponding number.

What is the event ID?


We already knew the answer to the last question as we used it in the query earlier.

Side note on obfuscated PowerShell code

THM didn’t ask anything besides the first variable, but I was curious about the obfuscated code we saw earlier.

I Google around and found a nifty project that someone had been kind enough to share here. One simply has to spin up a VM and download the code to it. Be advised that Defender will delete it, probably because of the handling of obfuscated code.

The result is still a bit hard to read, but we can tell it’s doing a few things:

  • Attempts to download a file from multiple sources
  • Checks to see file downloaded
  • Copies it to calc.exe’s path
  • Runs it

Needless to its suspicious and highly unlikely to be anything other than malicious. The organization would want to initiate their incident response plan. DESKTOP-RIPCLIP and the user with the SID S-1–5–21–2895499743–3664716236–3399808827–1001 are compromised.

Assuming this is a Domain User we would query:

Get-ADUser -Filter {SID -eq “ S-1–5–21–2895499743–3664716236–3399808827–1001”}


This THM room provided some good practice querying logs and had a nifty example of an obfuscated PowerShell command. The fictional organization in Task 7 had the right idea; enable PowerShell logging. Some try to block it entirely due to FUD, however attackers will just use VBA, VBScript, old school *.cmd, *.bat, or hell they’ll just use PowerShell without PowerShell.exe.

Use the principal of least privilege, audit, and don’t get tunnel vision on the tool. Attackers can use lots of different tools, but they won’t get far if they don’t have the privilege required. That is likely why the attacker was enumerating groups, they were looking for other users to attempt The Credential Theft Shuffle.


Get-EventLog is deprecated:

The Dutch Hacker’s Windows Event Logs writeup:

Another writeup, not very helpful, didn’t show their work:

PowerShell Downgrade Attack Event Id:

Event ID 1102 — audit log was cleared:

Deobfuscate PowerShell:

Event Id 4799; a local group was enumerated:

Well known SIDs:




I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.