Another writeup for the HuntressCTF: “Nightmare on Hunt Street”. This is a five-part challenge that dives into Windows Forensics. I managed to questions 1,2,3 and 5 during the event, with the 4th question being solved by my teammate K-Scorpio (shoutout!) on Discord.

Challenge Description

We’re presented with a single ZIP file and the following questions where each question has a flag associated with it.

  1. What is the IP address of the host that the attacker used?
  2. How many times was the compromised account brute-forced?
  3. What is the name of the offensive security tool that was used to gain initial access?
  4. How many unique enumeration commands were run with net.exe?
  5. What password was successfully given to the user created?

Solve #1

What is the IP address of the host that the attacker used?

I started out by unzipping the provided file, which produced three Windows event log files:

┌──(kali㉿kali)-[~/huntress]
└─$ unzip logs-parts1-5.zip
Archive:  logs-parts1-5.zip
  inflating: Application.evtx        
  inflating: __MACOSX/._Application.evtx  
  inflating: Security.evtx           
  inflating: __MACOSX/._Security.evtx  
  inflating: System.evtx             
  inflating: __MACOSX/._System.evtx 

To solve this challenge, I wanted to use the chainsaw tool that was shown to me throughout the HackTheBox CDSA learning path. Solving the first question turned out to be quite simple once I got the proper grep string:

┌──(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx | grep 'IpAddress' | sort -u

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
    IpAddress: '-'
    IpAddress: 10.1.1.42

Seeing as we get one IP address back, 10.1.1.42, the answer is flag{10.1.1.42}!

Solve #2

How many times was the compromised account brute-forced?

In order to find how many times the compromised account was brute-forced, we need to know which account was compromised. That’s probably the most redundant sentence you’ve read today. I begin by searching the events for the successful logon and printing the unique associated target usernames. The event ID found for a successful logon event was found through a google search: 4624.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event | select(.System.EventID==4624) | .EventData.TargetUserName' | sort -u

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
"Jsmith"
"SYSTEM"

So from the output we know that the Jsmith account was the only user account to have a successful logon. But the question is how many times was a logon attempted? For that we need to find the event ID associated with a logon attempt, which ends out being 4625.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event | select((.System.EventID==4625) and (.EventData.TargetUserName=="Jsmith")) | "found!"' | wc -l

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
32

There’s a lot going on in this command so I’ll break it down:

  • chainsaw dump Security.evtx -j
    • Output all events in the EVTX file as JSON   | jq '.[].Event | select((.System.EventID==4625) and (.EventData.TargetUserName=="Jsmith")) | "found!"'
  • Run the JSON parser command in stages:
    • .[].Event => Filter the JSON objects to only include the Event key and value
    • select((.System.EventID==4625) and (.EventData.TargetUserName=="Jsmith")) => With this filtered JSON we want to filter out any event objects that don’t have failed logon attempts for Jsmith.`
    • | "found!" => Instead of outputting any event data for the remaining (matched) events, just output a string, making it easy to count how many events there are with the wc command.`
    • | wc -l => Count how many lines were outputted. We know from the jq command that for each matched event we will get a single line of found! being produced.

We see the answer of 32, meaning there were 32 failed logon attempts for Jsmith in these log files: flag{32}.

Solve – #3

What is the name of the offensive security tool that was used to gain initial access?

This one was a bit tricky, and at the time of writing is the one with the least amount of solves out of the 5. This is because the answer isn’t actually found in the file itself. The clues are in the file, but it takes some prior experience and pattern recognition to solve.

This was the last one I solved for the whole challenge, so I slightly edited a command that will be shown below in the solution for #5.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event | "\(.System.EventID) \(.EventData.CommandLine)"' | grep 4624 -A2

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
"4624 null"
"4627 null"
"4776 null"
--
"4624 null"
"4627 null"
"4688 C:\\Windows\\wgWMRHln.exe"
--
"4624 null"
"4627 null"
"4776 null"
--
"4624 null"
"4627 null"
"4776 null"
--
"4624 null"
"4627 null"
"4688 cmd.exe"
--
"4624 null"
"4627 null"
"4672 null"
--
"4624 null"
"4627 null"
"4688 C:\\Windows\\MrEQbpfX.exe"
--
"4624 null"
"4627 null"
"4776 null"
--
"4624 null"
"4627 null"
"4776 null"
--
"4624 null"
"4627 null"
"4688 powershell.exe"

What I did here was look for the CommandLine fields that occurred in events immediately following a successful logon (4624). It took some adjusting to see some useful information, but after including 2 events after successful logon we some some strange executables being run.

This is where the previous experience comes into play. A very common way to get a shell on a windows system you have local administrative access to is by using PsExec.

PsExec uses the Microsoft Windows Service Control Manager (SCM) to start an instance of the service on the remote system, which allows the tool to run the specified command or application with the account’s privileges of the service account on the remote system.

Source

PsExec uploads an executable with a random name (to avoid collisions) to the C:\Windows\ directory and starts a Windows service that executes it. Using the SCM to execute it means the executable runs as SYSTEM, which also explained why there was a logon for SYSTEM in question #2.

For further evidence we can look for the children processes created by services.exe and look for these randomly named executables.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event | "Parent Proccess: \(.EventData.ParentProcessName) Child Process: \(.EventData.CommandLine)"' | grep -i 'services.exe'

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
"Parent Proccess: C:\\Windows\\System32\\services.exe Child Process: C:\\Windows\\wgWMRHln.exe"
"Parent Proccess: C:\\Windows\\System32\\services.exe Child Process: C:\\Windows\\servicing\\TrustedInstaller.exe"
"Parent Proccess: C:\\Windows\\System32\\services.exe Child Process: C:\\Windows\\MrEQbpfX.exe"

The challenge accepts flag{psexec}, which took way longer for me to solve than I’d like to admit, since I didn’t notice the challenge asking for the answer in all lowercase…

Solve – #4

How many unique enumeration commands were run with net.exe?

This question was the one I personally didn’t solve, but I got the answer after the fact. Following the trend of questions #1 and #2, I formed a jq + grep command that looks for CommandLine fields including the net command.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event.EventData.CommandLine' | grep -v null | grep 'net'    

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
"net  user"
"C:\\Windows\\system32\\net1  user"
"net  localgroup"
"C:\\Windows\\system32\\net1  localgroup"
"net  share"
"C:\\Windows\\system32\\net1  share"
"netstat  -ano"
"net  user susan_admin \"SusanIsStrong123\" /ADD"
"C:\\Windows\\system32\\net1  user susan_admin \"SusanIsStrong123\" /ADD"
"\"C:\\Windows\\system32\\net.exe\" user susan_admin SusanIsStrong123 /ADD"
"C:\\Windows\\system32\\net1 user susan_admin SusanIsStrong123 /ADD"
"\"C:\\Windows\\system32\\net.exe\" user"
"C:\\Windows\\system32\\net1 user"
"\"C:\\Windows\\system32\\net.exe\" user susan_admin Susan123! /ADD"
"C:\\Windows\\system32\\net1 user susan_admin Susan123! /ADD"
"\"C:\\Windows\\system32\\net.exe\" localgroup administrators susan_admin /ADD"
"C:\\Windows\\system32\\net1 localgroup administrators susan_admin /ADD"
"\"C:\\Windows\\system32\\net.exe\" users"
"C:\\Windows\\system32\\net1 users"

The question specifically asks for “unique enumeration commands were run with net.exe”, so we can remove all the commands that aren’t for enumeration, such as the /ADD commands. Since they’re looking for “unique” commands, we know that net, net.exe and net1 are all using the same net.exe executable, so we will only count the unique invocations: user, users and share.

Therefore the answer is flag{3}.

Solve – #5

What password was successfully given to the user created?

Question five was actually the easiest of the bunch, and once I realized they didn’t need to be solved in order, I immediately went to solve this one. After a quick google search for the event ID associated with a user being successfully added. I cleaned up the jq command to be shown cleaner in this post, but I solved the challenge in the same way during the event.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ chainsaw dump Security.evtx -j | jq '.[].Event | "\(.System.EventID) \(.EventData.CommandLine)"' | grep -i -B1 -A2 '/ADD'  

 ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗███████╗ █████╗ ██╗    ██╗
██╔════╝██║  ██║██╔══██╗██║████╗  ██║██╔════╝██╔══██╗██║    ██║
██║     ███████║███████║██║██╔██╗ ██║███████╗███████║██║ █╗ ██║
██║     ██╔══██║██╔══██║██║██║╚██╗██║╚════██║██╔══██║██║███╗██║
╚██████╗██║  ██║██║  ██║██║██║ ╚████║███████║██║  ██║╚███╔███╔╝
 ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚══╝╚══╝
    By WithSecure Countercept (@FranticTyping, @AlexKornitzer)

[+] Dumping the contents of forensic artefacts from: Security.evtx (extensions: *)
[+] Loaded 1 forensic artefacts (1.1 MB)
[+] Done
"4689 null"
"4688 net  user susan_admin \"SusanIsStrong123\" /ADD"
"4688 C:\\Windows\\system32\\net1  user susan_admin \"SusanIsStrong123\" /ADD"
"4689 null"
"4689 null"
"4688 powershell.exe"
"4688 \"C:\\Windows\\system32\\net.exe\" user susan_admin SusanIsStrong123 /ADD"
"4688 C:\\Windows\\system32\\net1 user susan_admin SusanIsStrong123 /ADD"
"4689 null"
"4689 null"
--
"4689 null"
"4688 \"C:\\Windows\\system32\\net.exe\" user susan_admin Susan123! /ADD"
"4688 C:\\Windows\\system32\\net1 user susan_admin Susan123! /ADD"
"4728 null"
"4720 null"
--
"4689 null"
"4688 \"C:\\Windows\\system32\\net.exe\" localgroup administrators susan_admin /ADD"
"4688 C:\\Windows\\system32\\net1 localgroup administrators susan_admin /ADD"
"4732 null"
"4689 null"

What I did here was put every event’s EventID and CommandLine on a single line then grep for the invocation of net.exe with the /ADD flag. The output lets us see groups of events that immediately followed the attempt to add a user. After a quick google search, we find the event ID associated with correctly adding a user is 4720. This tells us that the middle grouping shown above was the successful command, as opposed to the first group. When I first tried this, I only looked for the event ID immediately following the attempt to add a user, which led me to find out event ID 4728 was for a user being successfully added to a group, so I adjusted the grep command to look for two events following the matched event and saw the expected 4720.

flag{Susan123!}