Introduction

In the DMZ between the two sides, Pepper Minstix and Wunorse Openslae are standing next to The Great Elf Conflict:

image-20241124151859949

Pepper warns me about intelligence about oncoming attacks from Team Wombley:

Pepper Minstix

Pepper Minstix

This is weird, I got some intel about an imminent attack.

Pepper Minstix here! I’ve got urgent news from neutral ground.

The North Pole is facing a serious cyber threat, and it’s putting all the factions on edge. The culprits? Some troublemakers from Team Wombley.

They’ve launched a barrage of phishing attacks, ransomware, and even some sneaky espionage, causing quite the stir.

It’s time to jump into action and get cracking on this investigation—there’s plenty of cyber-sleuthing to do.

You’ll be digging into KQL logs, tracking down phishing schemes, and tracing compromised accounts like a seasoned pro.

Malware infections have already breached Alabaster Snowball’s systems, so we need swift action.

Your top mission: neutralize these threats, with a focus on the ransomware wreaking havoc from Team Wombley.

It’s a hefty challenge, but I know you’re up to it. We need your expertise to restore order and keep the peace.

You’ve got the tools, the skills, and the know-how—let’s show Team Wombley we mean business.

Ready to dive in? Let’s defend the North Pole and bring back the holiday harmony!

Wunrose doesn’t deny it:

Wunorse Openslae

Wunorse Openslae

Hey, Wunorse here. We at Team Wombley pulled off some nasty stuff.

Phishing attacks, ransomware, and cyber espionage, oh yeah!

We pulled loads of all-nighters to make it all happen. Energy drinks rock!

Our teams did what Alabaster said we never could and breached Santa’s network. We’re so rad.

It would take a master defender to fix all the damage we caused. But defense is so lame! Offense is where it’s at.

You should just leave them to panic and join our side. We’re the coolest, don’t you want to be like us?

KC7 Overview

The link in the badge or the globe on the map lead to The Great Elf Conflict page on KC7. KC7 is a free-to-play gamified upskilling platform that offers all kinds of modules that allow for investigating malicious events in the web browser.

image-20241124164133508 expand

The Play Now button at the top right opens a list of 27 standard KC7 modules available to the community at the time of this writing.

I’ll create an account and login to the Holiday Hack challenge module for this year.

The setup is to have a question down the left side, and the panel to run KQL queries on the right:

image-20241124164520412

Clickong on “Section 1: KQL 101” at the top, I’ll see the list of sections in this module:

image-20241124164549585

There are four sections, each with between seven and eleven questions.

To get credit for each section in my snowball badge, I’ll need to give it the last answer to each section. Finishing two sections grants a silver solve, and all four gives gold.

KQL 101

Question 1

Alt text

Welcome to your mission to solve the The Great Elf Conflict! To do so, you’ll need to harness the power of KQL (Kusto Query Language) to navigate through the data and uncover crucial evidence.

Your next step is to meet with Eve Snowshoes, Cyber Engineer, at the at the North Pole Cyber Defense Unit. Eve is known for unmatched expertise in KQL and has been eagerly awaiting your arrival.

Eve greets you with a nod and gestures toward the terminal. “KQL is like a key, unlocking the hidden secrets buried within the data.”

Type let’s do this to begin your KQL training.

I’ll enter “let’s do this” to solve and move on to the next question.

Answer: let’s do this

Question 2

The first command Eve Snowshoes teaches you is one of the most useful in querying data with KQL. It helps you peek inside each table, which is critical for understanding the structure and the kind of information you’re dealing with. By knowing what’s in each table, you’ll be able to create more precise queries and uncover exactly what you need.

Employees
| take 10 

Eve has shared the first table with you. Now, run a take 10 on all the other tables to see what they contain.

You can find the tables you have access to at the top of the ADX query window.

Once you’ve examined all the tables, type when in doubt take 10 to proceed.

I can start with a “take 10” on Employees to check out the data:

image-20241124190203418Click for full size image

This gives a good feel for what is in the table.

I can look at what other tables exist with .show tables:

image-20241124190238638

I can spend some time looking at them, but I’ll show that as I get to each in the analysis.

Answer: when in doubt take 10

Question 3

Now, let’s gather more intelligence on the employees. To do this, we can use the count operator to quickly calculate the number of rows in a table. This is helpful for understanding the scale of the data you’re working with.

Employees
| count

How many elves did you find?

Running that command shows 90 rows in the Employees table:

image-20241124165740742

Answer: 90

Question 4

You can use the where operator with the Employees table to locate a specific elf. Here’s a template you can follow:

Employees
| where <field><operator><value>

Field: The column you want to filter by (e.g., role).

Operator: The condition you’re applying (e.g., == for an exact match).

Value: The specific value you’re looking for in the field (e.g., Chief Elf Officer).

Can you find out the name of the Chief Toy Maker?

I’ll start with a look at the columns in the Employees table with a “take 10”:

image-20241124165908691Click for full size image

The “role” column seems useful here. I’ll update the query to filter on the target role:

image-20241124170013497

Answer: Shinny Upatree

Question 5

Here are some additional operators the North Pole Cyber Defense Unit commonly uses.

== : Checks if two values are exactly the same. Case-sensitive.

contains : Checks if a string appears anywhere, even as part of a word. Not case-sensitive.

has : Checks if a string is a whole word. Not case-sensitive.

has_any : Checks if any of the specified words are present. Not case-sensitive.

in : Checks if a value matches any item in a list. Case-sensitive.

This challenge is just another opportunity to play. I’ll note that == and in are case-sensitive, where as contains, has, and has_any are not.

Answer: operator

Question 6

We can learn more about an elf by cross-referencing information from other tables. Let’s take a look at Angel Candysalt’s correspondence. First, retrieve her email address from the Employees table, and then use it in a query in the Email table.

Email
| where recipient == "<insert Angel Candysalt’s email address here>"
| count

How many emails did Angel Candysalt receive?

I’ll start with a “take 10” on the Email table to get a feel for it:

image-20241124170253651Click for full size image

recipient seems like the column to filter on.

I don’t know Angel’s email. There’s a few ways to find it. One would be to go back to the Employees table, and filter on name contains "angel":

image-20241124170441864Click for full size image

This gives angel_candysalt@santaworkshopgeeseislands.org. Or I could do something similar in the recipient field in the Email table directly:

image-20241124170546561Click for full size image

There’s a lot of rows, but I don’t have to look too far to find the full email.

Now I can get a more exact count filtering on the full email:

image-20241124170713482

This is the correct answer, though since email addresses are not typically case-sensitive. The safer way to do this would be to wrap recipient in a tolower call:

image-20241124170916223

It doesn’t change the answer here, but is worth considering.

Answer: 31

Question 7

You can use the distinct operator to filter for unique values in a specific column.

Here’s a start:

Email
| where sender has "<insert domain name here>"
| distinct <field you need>
| count

How many distinct recipients were seen in the email logs from twinkle_frostington@santaworkshopgeeseislands.org?

I”ll use the same kind of filter as the previous question, but this time add another filter to get distinct records:

image-20241124171208781

The query returns a list of recipients. I’ll use count to get the number:

image-20241124171233989

Answer: 32

Question 8

It’s time to put everything we’ve learned into action!

OutboundNetworkEvents
| where src_ip == "<insert IP here>"
| <operator> <field>
| <operator>

How many distinct websites did Twinkle Frostington visit?

A “take 10” look at the OutboundNetworkEvents table shows that it has a source_ip column, but nothing for user:

image-20241124171425021Click for full size image

The Employees table allows me to map user name to IP:

image-20241124171503493Click for full size image

Searching for Twinkle, I’ll find their IP as 10.10.0.36:

image-20241124171611349Click for full size image

Now I’ll search OutboundNetworkEvents for 10.10.0.36:

image-20241124171726504Click for full size image

I don’t need a distinct or count, as I can tell on a quick look there are four rows each with unique URLs.

Answer: 4

Question 9

How many distinct domains in the PassiveDns records contain the word green?

PassiveDns
| where <field> contains “<value>”
| <operator> <field>
| <operator>

You may have notice we’re using contains instead of has here. That’s because has will look for an exact match (the word on its own), while contains will look for the specified sequence of letters, regardless of what comes before or after it. You can try both on your query to see the difference!

To see what PassiveDns has, I’ll start with “take 10”:

image-20241124171930746

It’s simply timestamp, ip, and domain. Given that I want records where the domain contains “green”, I’ll add that:

image-20241124172103242

There’s 10 records, or I can add a count to see that more clearly:

image-20241124172124274

The hint points out that contains is better than has here, as has looks for green as a word, and contains just looks for those five bytes regardless of what’s around it. has finds nothing here:

image-20241124172211120

Answer: 10

Question 10

Sometimes, you’ll need to investigate multiple elves at once. Typing each one manually or searching for them one by one isn’t practical. That’s where let statements come in handy. A let statement allows you to save values into a variable, which you can then easily access in your query.

Let’s look at an example. To find the URLs they accessed, we’ll first need their IP addresses. But there are so many Twinkles! So we’ll save the IP addresses in a let statement, like this:

let twinkle_ips =
Employees
| where name has "<the name we’re looking for>"
| distinct ip_addr;

This saves the result of the query into a variable. Now, you can use that result easily in another query:

OutboundNetworkEvents  
| where src_ip in (twinkle_ips)  
| distinct <field>

How many distinct URLs did elves with the first name Twinkle visit?

Question 10 starts to show the real power of KQL. I need to first look at elves with the first name Twinkle. Given that there is no first name column, I’ll want to look for name that starts with “Twinkle “:

image-20241124172519572

The space after the name is important here, as otherwise it gets “Twinkles Snowfall”, but I don’t think that should be included. I could have used has, but that would also return an elf with the last name Twinkle (none in this set, but still a flaw in the query).

I can save these IPs in a variable. If I just do that, it returns an error:

image-20241124172916625

I have to have something that outputs. I’ll add the next query:

image-20241124172954558Click for full size image

This shows all the events visited by Twinkle elves. To get a count on distinct URLs, I’ll add that:

image-20241124173047200

There’s 8.

Answer: 8

Operation Surrender: Alabaster’s Espionage

Question 1

Eve Snowshoes approaches with a focused expression. “Welcome to Operation Surrender: Alabaster’s Espionage. In this phase, Team Alabaster has executed a covert operation, and your mission is to unravel their tactics. You’ll need to piece together the clues and analyze the data to understand how they gained an advantage.”

Type surrender to get started!

Answer: surrender

Question 2

Alt text

Team Alabaster, with their limited resources, was growing desperate for an edge over Team Wombley. Knowing that a direct attack would be costly and difficult, they turned to espionage. Their plan? A carefully crafted phishing email that appeared harmless but was designed to deceive Team Wombley into downloading a malicious file. The email contained a deceptive message with the keyword “surrender” urging Wombley’s members to click on a link.

Now, it’s up to you to trace the origins of this operation.

Who was the sender of the phishing email that set this plan into motion?

Try checking out the email table using the knowledge you gained in the previous section!

A quick survey of the Email table shows the only column that might have content information in it is the subject column:

image-20241124175803697Click for full size image

A filter on subject has "surrender" shows a bunch of emails with similar subject lines, “Offlicial Surrender Notice From Camp Alabaster”:

image-20241124175907778Click for full size image

I’ll look at the distinct senders:

image-20241124175955532

Answer: surrender@northpolemail.com

Question 3

Team Alabaster’s phishing attack wasn’t just aimed at a single target—it was a coordinated assault on all of Team Wombley. Every member received the cleverly disguised email, enticing them to click the malicious link that would compromise their systems.

Hint: the distinct operator would help here Your mission is to determine the full scale of this operation.

How many elves from Team Wombley received the phishing email?

I’ll start from the previous, but replace distinct sender with distincy recipient:

image-20241124180121560 expand

With count it shows 22:

image-20241124180202267

Answer: 22

Question 4

The phishing email from Team Alabaster included a link to a file that appeared legitimate to Team Wombley. This document, disguised as an important communication, was part of a carefully orchestrated plan to deceive Wombley’s members into taking the bait.

To understand the full extent of this operation, we need to identify the file where the link led to in the email.

What was the filename of the document that Team Alabaster distributed in their phishing email?

I’ll replace the distinct recipient with distinct link:

image-20241124180343921

There’s a few different URLs, but they all host Team_Wombley_Surrender.doc.

Answer: Team_Wombley_Surrender.doc

Question 5

As the phishing emails landed in the inboxes of Team Wombley, one elf was the first to click the URL, unknowingly triggering the start of Team Alabaster’s plan. By connecting the employees to their network activity, we can trace who fell for the deception first. To find the answer, you’ll need to join two tables: Employees and OutboundNetworkEvents. The goal is to match employees with the outbound network events they initiated by using their IP addresses.

Here’s an example query to help you:

Employees
| join kind=inner (
    OutboundNetworkEvents
) on $left.ip_addr == $right.src_ip // condition to match rows
| where url contains "< maybe a filename :) >"
| project name, ip_addr, url, timestamp // project returns only the information you select
| sort by timestamp asc //sorts time ascending

This query will give you a list of employees who clicked on the phishing URL. The first person to click will be at the top of the list!

Who was the first person from Team Wombley to click the URL in the phishing email?

This is fun because I can use a join on two tables. I’ll need the name from the Employees table and the timestamp from the OutboundNetworkEvents table:

image-20241124180816456Click for full size image

By sorting on timestamp asc, the first click is at the top, at 2024-11-27 14:11:45.

Answer: Joyelle Tinseltoe

Interestingly, there are no logs in PassiveDns for the domain alabastersurrender.org, suggesting some kind of gap in data.

Question 6

Once the phishing email was clicked and the malicious document was downloaded, another file was created upon execution of the .doc. This file allowed Team Alabaster to gain further insight into Team Wombley’s operations. To uncover this, you’ll need to investigate the processes that were executed on Joyelle Tinseltoe’s machine.

Your mission is to determine the name of the file that was created after the .doc was executed.

Focus on Joyelle Tinseltoe’s hostname and explore the ProcessEvents table. This table tracks which processes were started and by which machines. By filtering for Joyelle’s hostname and looking at the timestamps around the time the file was executed, you should find what you’re looking for. Here’s an example to help guide you:

ProcessEvents
| where timestamp between(datetime("2024-11-25T09:00:37Z") .. datetime("2024-11-26T17:20:37Z")) //you’ll need to modify this
| where hostname == "<Joyelle's hostname>"

This query will show processes that ran on Joyelle Tinseltoe’s machine within the given timeframe.

What was the filename that was created after the .doc was downloaded and executed?

I haven’t really looked at the ProcessEvents table yet, so I’ll “take 10”:

image-20241124181111012

As far as looking at a specific computer at a specific time, I’ll use the timestamp as well as either the hostname or the username.

The Employees table shows Joyelle Tinseltoe’s username is jotinseltoe and hostname is Elf-Lap-W-Tinseltoe:

image-20241124181310238

The previous question showed that Joyelle’s host clicked at 2024-11-27 14:11:45, so I’ll get the events on that computer for the minute following:

image-20241124181520994

There are two events. The first is Explorer launching the Word documement. One second later, keylogger.exe runs from the AppData\Roaming directory.

Answer: keylogger.exe

Question 7

Alt text

Well done on piecing together the clues and unraveling the operation!

Team Alabaster’s phishing email, sent from surrender@northpolemail.com, targeted 22 elves from Team Wombley. The email contained a malicious document named Team_Wombley_Surrender.doc, which led to the first click by Joyelle Tinseltoe.

After the document was downloaded and executed, a malicious file was created, impacting the entire Team Wombley as it ran on all their machines, giving Team Alabaster access to their keystrokes!

To obtain your flag use the KQL below with your last answer!

let flag = "Change This!";
let base64_encoded = base64_encode_tostring(flag);
print base64_encoded

Enter your flag to continue

The previous answer was “keylogger.exe”, which results in:

image-20241124182025464

Answer: a2V5bG9nZ2VyLmV4ZQ==

Beyond Root

Team_Wombley_Surrender.doc

Continuing a bit with this thread, I’ll look at FileWriteEvents for the document and the keylogger. The document is written 26 times:

image-20241124193300608

I’ll note that the process_name is always a browser, such as Chrome, Edge, or Firefox. Interestingly, the sha256 of the written file is unique for each writing, suggesting some kind of customization of the malware at the server.

keylogger.exe

keylogger.exe was written 24 times:

image-20241124193523215

Of those 24, there are three different SHA256 hashes:

image-20241124193557807

582fb1a22cfa18dd496422a72eda806509d94ca1a6befef707973ea2a2be453c is a EICAR test file according to VirusTotal:

image-20241124193708008

1dc1dbfc1d636fed5cebe43787a7abf2df4fbb51e1beaec34ba72dd5152edc81 and dd053f38f5e60cd8750df450a13833c96d1285e78480323a54abab4a536f6317 are as well.

Operation Snowfall: Team Wombley’s Ransomware Raid

Question 1

Alt text

“Fantastic work on completing Section 2!” Eve Snowshoes, Senior Security Analyst, says with a proud smile.

“You’ve demonstrated sharp investigative skills, uncovering every detail of Team Wombley’s attack on Alabaster. Your ability to navigate the complexities of cyber warfare has been impressive.

But now, we embark on Operation Snowfall: Team Wombley’s Ransomware Raid. This time, the difficulty will increase as we dive into more sophisticated attacks. Stay sharp, and let’s see if you can rise to the occasion once again!”

Type snowfall to begin

Answer: snowfall

Question 2

Alt text

Team Wombley’s assault began with a password spray attack, targeting several accounts within Team Alabaster. This attack relied on repeated login attempts using common passwords, hoping to find weak entry points. The key to uncovering this tactic is identifying the source of the attack.

Authentication events can be found in the AuthenticationEvents table. Look for a pattern of failed login attempts.

Here’s a query to guide you:

AuthenticationEvents
| where result == "Failed Login"
| summarize FailedAttempts = count() by username, src_ip, result
| where FailedAttempts >= 5
| sort by FailedAttempts desc

What was the IP address associated with the password spray?

The query they give in the question is a good one. It’s taking AuthenticationEvents where the result is login failure, and grouping by username and src_ip. Then it sorts from most to fewest:

image-20241124183034902

By far the most common IP is 59.l171.58.12, which is definitely failing a lot. If I just group by src_ip, it’s even more stark:

image-20241124183121624

Answer: 59.171.58.12

Question 3

Alt text

After launching the password spray attack, Team Wombley potentially had success and logged into several accounts, gaining access to sensitive systems.

Eve Snowshoes weighs in: “This is where things start to get dangerous. The number of compromised accounts will show us just how far they’ve infiltrated.”

How many unique accounts were impacted where there was a successful login from 59.171.58.12?

Having identified the password spray, the next obvious question is where was the same malicious IP successful? A quick “take 10” on the AuthenticationEvents table shows the successful result is “Successful Login”:

image-20241124183335286

I’ll filter events that are from that IP and successful, and find 31 events!

image-20241124183444543

It isn’t quite that bad, as there could be repeated usernames in there. I’ll get a list of distinct username, and then count:

image-20241124183618687

Answer: 23

Question 4

Alt text

In order to login to the compromised accounts, Team Wombley leveraged a service that was accessible externally to gain control over Alabaster’s devices.

Eve Snowshoes remarks, “Identifying the service that was open externally is critical. It shows us how the attackers were able to bypass defenses and access the network. This is a common weak point in many systems.”

What service was used to access these accounts/devices?

Taking a closer look at the malicious AuthenticationEvents, there’s a description field:

image-20241124183926906

All of the events are over remote desktop, or RDP!

Answer: RDP

Question 5

Once Team Wombley gained access to Alabaster’s system, they targeted sensitive files for exfiltration. Eve Snowshoes emphasizes, “When critical files are exfiltrated, it can lead to devastating consequences. Knowing exactly what was taken will allow us to assess the damage and prepare a response.”

The ProcessEvents table will help you track activities that occurred on Alabaster’s laptop. By narrowing down the events by timestamp and hostname, you’ll be able to pinpoint the file that was exfiltrated.

What file was exfiltrated from Alabaster’s laptop?

I’ll start by getting information about Alabaster:

image-20241124184137334

Next, I’ll look at when the malicious IP logged into Alabaster’s computer:

image-20241124184227496

There’s only one event, at 2024-12-11 01:39:50 over RDP.

There are no ProcessEvents immediately following the login, so I’ll look at all events after that timestamp. 16.5 hours later (at [1]), they run whoami, net user, and net view, which are pretty classes enumeration commands:

image-20241124184918189

At [2], they run a long PowerShell command, and then move Secret_Files.zip first into a temp directory, and then into an SMB share on wocube’s host.

At [3], they delete two PDF docs and the zip archive. At [4] they clear the event logs and then at [5] start running what sounds like ransomware.

Answer: Secret_Files.zip

Question 6

After exfiltrating critical files from Alabaster’s system, Team Wombley deployed a malicious payload to encrypt the device, leaving Alabaster locked out and in disarray.

Eve Snowshoes comments, “The final blow in this attack was the ransomware they unleashed. Finding the name of the malicious file will help us figure out how they crippled the system.”

What is the name of the malicious file that was run on Alabaster’s laptop?

As noted above, this is EncryptEverything.exe:

image-20241124185211002

Looking back at the interesting Powershell command, it’s running a base64-encoded command:

image-20241124185423132

Interestingly, this is a call to run EncryptEverything.exe as well:

$ echo "RW5jcnlwdEV2ZXJ5dGhpbmcuZXhlIC1mIC1hRg==" | base64 -d
EncryptEverything.exe -f -aF

Perhaps the actor started to run it but then killed it, deciding to exfil files first, and then came back 18 hours later to run it again.

Answer: EncryptEverything.exe

Question 7

Outstanding work! You’ve successfully pieced together the full scope of Team Wombley’s attack. Your investigative skills are truly impressive, and you’ve uncovered every critical detail.

Just to recap: Team Wombley launched a cyber assault on Alabaster, beginning with a password spray attack that allowed them to gain access to several accounts. Using an external service over RDP, they infiltrated Alabaster’s system, exfiltrating sensitive files including the blueprints for snowball cannons and drones. To further their attack, Wombley executed a malicious file, which encrypted Alabaster’s entire system leaving them locked out and in chaos.

To obtain your flag use the KQL below with your last answer!

let flag = "Change This!";
let base64_encoded = base64_encode_tostring(flag);
print base64_encoded

Enter your flag to continue

I’ll generate the flag using the previous answer:

image-20241124185634676

Answer: RW5jcnlwdEV2ZXJ5dGhpbmcuZXhl

Beyond Root

I was curious to see where the EncryptEverything.exe binary may have been written on other computers. Looking at the FileCreationEvents, it was written to Alabaster’s computer at 2024-12-15 14:52:13:

image-20241124192123287

It doesn’t look like it was written to any other host with that name. I’ll check the hash, and there’s a match on 36 computers:

image-20241124192434429

On every computer but Alabaster’s, it’s named notepad++.exe:

image-20241124192657879

I’ll search that hash in VirusTotal, but it doesn’t find anything, suggesting it’s probably not a legit notepad++.exe instance, but it’s hard to say for sure. I would definitely want to look more closely, though most of the timestamps are before the password spray attack, so it could be legit.

Echos in the Frost: Tracking the Unknown Threat

Question 1

As you close out the investigation into Team Wombley’s attack, Eve Snowshoes meets you with a serious expression. “You’ve done an incredible job so far, but now we face our most elusive adversary yet. This isn’t just another team—it’s an unknown, highly skilled threat actor who has been operating in the shadows, leaving behind only whispers of their presence. We’ve seen traces of their activity, but they’ve covered their tracks well.”

She pauses, the weight of the challenge ahead clear. “This is where things get even more difficult. We’re entering uncharted territory—prepare yourself for the toughest investigation yet. Follow the clues, stay sharp, and let’s uncover the truth behind these Echoes in the Frost.”

Type stay frosty to begin

Answer: stay frosty

Question 2

Noel Boetie, the IT administrator, reported receiving strange emails about a breach from colleagues. These emails might hold the first clue in uncovering the unknown threat actor’s methods. Your task is to identify when the first of these suspicious emails was received.

Eve Snowshoes remarks, “The timing of these phishing emails is critical. If we can identify the first one, we’ll have a better chance of tracing the threat actor’s initial moves.”

What was the timestamp of first phishing email about the breached credentials received by Noel Boetie?

I’ll need Noel’s email:

image-20241124194330763

I can try searching for all their email, but there’s 42:

image-20241124194417037

Since the prompt says they are about a breach, so I’ll start there:

image-20241124194536314

Answer: 2024-12-12T14:48:55Z

Interestingly, all three emails come from @santaworkshopgeeseislands.org email addresses!

Question 3

Noel Boetie followed the instructions in the phishing email, downloading and running the file, but reported that nothing seemed to happen afterward. However, this might have been the key moment when the unknown threat actor infiltrated the system.

When did Noel Boetie click the link to the first file?

The first email had a link to an echo.exe hosted on holidaybargainhunt.io:

image-20241124194626347

Interestingly, there were DNS resolutions to this domain starting five days before this phish, and none logged after:

image-20241124194803780

However, there’s an OutboundNetworkEvent less than half an hour after the email was sent:

image-20241124194850588

(And it seems like Noel may have clicked the other links as well).

Answer: 2024-12-12T15:13:55Z

Question 4

The phishing email directed Noel Boetie to download a file from an external domain.

Eve Snowshoes, “The domain and IP they used to host the malicious file is a key piece of evidence. It might lead us to other parts of their operation, so let’s find it.”

What was the IP for the domain where the file was hosted?

While the timestamps are all early in the PassiveDns data above, they do consistently show the same IP, 182.56.23.122.

Answer: 182.56.23.122

Question 5

Let’s back up for a moment. Now that we’re thinking this through, how did the unknown threat actor gain the credentials to execute this attack? We know that three users have been sending phishing emails, and we’ve identified the domain they used.

It’s time to dig deeper into the AuthenticationEvents and see if anything else unusual happened that might explain how these accounts were compromised.

Eve Snowshoes suggests, “We need to explore the AuthenticationEvents for these users. Attackers often use compromised accounts to blend in and send phishing emails internally. This might reveal how they gained access to the credentials.”

Let’s take a closer look at the authentication events. I wonder if any connection events from 182.56.23.122. If so what hostname was accessed?

There’s a single AuthenticationEvent from that IP:

image-20241124195315593

The computer logged into is WebApp-ElvesWorkshop.

Answer: WebApp-ElvesWorkshop

Question 6

It appears someone accessed the WebApp-ElvesWorkshop from the IP address 182.56.23.122. This could be a key moment in the attack. We need to investigate what was run on the app server and, more importantly, if the threat actor dumped any credentials from it.

Eve Snowshoes, “Accessing the web app from an external IP is a major red flag. If they managed to dump credentials from the app server, that could explain how they gained access to other parts of the system.”

What was the script that was run to obtain credentials?

The ProcessEvents for this host show almost two weeks after login some suspect commands:

image-20241124195632888

There’s some enumeration of the tasklist and the network. Then they add a user and add it to the administrators group.

But the interesting one is the powershell command:

image-20241124195736121

It’s downloading and running Invoke-Mimikatz from GitHub. This is dumping logon credentials from memory of the Windows system.

Answer: Invoke-Mimikatz.ps1

Question 7

Okay back to Noel, after downloading the file, Noel Boetie followed the instructions in the email and ran it, but mentioned that nothing appeared to happen.

Since the email came from an internal source, Noel assumed it was safe - yet this may have been the moment the unknown threat actor silently gained access. We need to identify exactly when Noel executed the file to trace the beginning of the attack.

Eve Snowshoes, “It’s easy to see why Noel thought the email was harmless - it came from an internal account. But attackers often use compromised internal sources to make their phishing attempts more believable.”

What is the timestamp where Noel executed the file?

The file was named echo.exe, so I’ll start with that:

image-20241124200458896

Answer: 2024-12-12T15:14:38Z

Question 8

After Noel ran the file, strange activity began on the system, including the download of a file called holidaycandy.hta. Keep in mind that attackers often use multiple domains to host different pieces of malware.

Eve explains, “Attackers frequently spread their operations across several domains to evade detection.”

What domain was the holidaycandy.hta file downloaded from?

I’ll want to look at all sorts of activity just after the echo.exe running timestamp starting with Noel’s computer. For the rest of that day, there’s a bunch of troubling activity:

image-20241124200845803

I’ll want to look into mulledwine.exe, clearly.exe, and holidaycandy.hta.

The FileCreationEvents table has timestamps for each of these on Boetie’s computer:

image-20241124201026214

The question wants to know where they (specifically holidaycandy.hta) came from. It looks like it was downloaded twice (less than a minute apart) from compromisedchristmastoys.com:

image-20241124201305733

Answer: compromisedchristmastoys.com

Question 9

An interesting series of events has occurred: the attacker downloaded a copy of frosty.txt, decoded it into a zip file, and used tar to extract the contents of frosty.zip into the Tasks directory.

This suggests the possibility that additional payloads or tools were delivered to Noel’s laptop. We need to investigate if any additional files appeared after this sequence.

Eve Snowshoes, “When an attacker drops files like this, it’s often the prelude to more malicious actions. Let’s see if we can find out what else landed on Noel’s laptop.”

Did any additional files end up on Noel’s laptop after the attacker extracted frosty.zip?

what was the first file that was created after extraction?

For some reason, there are no FileCreationEvents for anything containing “frosty”:

image-20241124201816829

On 24 Dec, there’s a series of three ProcessCreation events on Noel’s computer that show the download of frosty.txt and what comes next. First, it uses PowerShell’s Invoke-WebRequest to download frosty.txt from holidaybargainhunt.io port 8080, saving it in C:\Windows\Tasks, and decoding it with certutil to frosty.zip:

image-20241124202103780

The next command one minute later uses tar to extract files into the same folder:

image-20241124202225282

Back on FileCreationEvents, the next file created after that time is about 35 minutes later, in the Tasks directory, sqlwriter.exe:

image-20241124202438436

Answer: sqlwriter.exe

Question 10

In the previous question, we discovered that two files, sqlwriter.exe and frost.dll, were downloaded onto Noel’s laptop. Immediately after, a registry key was added that ensures sqlwriter.exe will run every time Noel’s computer boots.

This persistence mechanism indicates the attacker’s intent to maintain long-term control over the system.

Eve Snowshoes, “Adding a registry key for persistence is a classic move by attackers to ensure their malicious software runs automatically. It’s crucial to understand how this persistence is set up to prevent further damage.”

What is the name of the property assigned to the new registry key?

There’s one last ProcessEvents after the tar call:

image-20241124202623106

It’s setting the run key (Att&ck T1547-001) to persist sqlwriter.exe to run on boot.

Answer: frosty

Question 11

Congratulations! You’ve successfully identified the threat actor’s tactics. The attacker gained access to WebApp-ElvesWorkshop from the IP address 182.56.23.122, dumped credentials, and used those to send phishing emails internally to Noel.

The malware family they used is called Wineloader, which employs a technique known as DLL sideloading. This technique works by placing a malicious DLL in the same directory as a legitimate executable (in this case, sqlwriter.exe).

When Windows tries to load a referenced DLL without a full path, it checks the executable’s current directory first, causing the malicious DLL to load automatically. Additionally, the attacker created a scheduled task to ensure sqlwriter.exe runs on system boot, allowing the malicious DLL to maintain persistence on the system.

To obtain your FINAL flag use the KQL below with your last answer!

let finalflag = "Change This!";
let base64_encoded = base64_encode_tostring(finalflag);
print base64_encoded

I’ll use the command given to calculate the base64 of “frosty”:

image-20241124202833212

Answer: ZnJvc3R5

Outro

KC7

KC7 is pleased with my work:

image-20241124203538356

I get a cool badge as well:

HHC2024

Elves

Pepper is more and more excited with each section solved:

Pepper Minstix

Pepper Minstix

Outstanding work! You’ve expertly sifted through the chaos of the KQL logs and uncovered crucial evidence. We’re one step closer to saving the North Pole!

Bravo! You’ve traced those phishing emails back to their devious source. Your sharp detective skills are keeping our elves safe from harm!

Fantastic! You’ve tracked down the compromised accounts and put a stop to the malicious activity. Our systems are stronger thanks to you!

Incredible! You’ve neutralized the ransomware and restored order across the North Pole. Peace has returned, and it’s all thanks to your relentless determination!

Ho-ho-holy snowflakes! You’ve done it! With the precision of a candy cane craftsman and the bravery of a reindeer on a foggy night, you’ve conquered all four tasks! You’re a true holiday hero!

Wunorse is bummed the attackers were foiled:

Wunorse Openslae

Wunorse Openslae

Dude, c’mon. I thought we were bros! Why are you messin’ with our achievements like that?

Those phishing emails were totally devious, you gotta admit. Now let’s head over to Wombley HQ and I’ll show you how we craft them.

Hey, we needed those accounts! Alright, broseph, you got one more chance or I’m telling Wombley how lame you are.

Why you gotta be like that? Not cool. We worked so hard on that ransomware, and you dismantled the whole thing. So many wasted energy drinks…

Whatevs, it’s all good. This was just a practice run anyways. The real attack is going down later. And it’s gonna be sick!