# SwampCTF 2025
## Forensics
### Homework Help

In this chall, I got a **.vhd (Virtual Hard Disk)** file. So I open it with **FTK Imager**.

The request is related to some notes so I first check folder *School* for a little bit infomation

In the *Hacking* folder, it seem likes it is the note that we need to find. I focus on **Hacking Notes.docx** that have Size:14, it is a file that was deleted but not erasing completely.
I try to export this file, open it and get the flag

**FLAG: swampCTF{n0thing_i5_3v3r_d3l3t3d}**
### Preferential Treatment

Resouce: gpnightmare.pcap
It is a pcacp file. First, open it with Wireshark

We get some SMB packets, that maybe something hidden under this protocol. Following TCP stream to have more infomation

We got some xml data with cpassword was encrypted. Searching a little bit in Internet, i found that `cpassword` was encrypted using AES-256 with fixed key (published by Microsoft).
So I decrypted it with **gpp-decrypt** tool and got the flag

**FLAG: swampCTF{4v3r463_w1nd0w5_53cur17y}**
### Planetary Storage

Resource: PlanetaryStorage.zip
Unzip this file, I got some locked .ldb files and a LOG file

First, i check the LOG file.

Ok, it seem like this man open L0@2 and write some data, repeat with L0@7 and L0@10. And we got 000002.ldb, 000007.ldb, 000010.ldb. Information maybe was divided into each file.
About .ldb files, I searched and it related to LevelDB, something about OrbitDB, hmmm. First, I just used `strings` to read it

This had a record (L0@2), with field /_localHeads, and the payload is so sus, it's in base64. Let decrypt it

I got some base64 in base64, so continue decrypt one more time with new base64

I got some words, it is the information was written into L0@2. So I check L0@7 and L0@10 in the same way. Yeah, payload in L0@10 gave me the flag

**FLAG: swampCTF{1pf5-b453d-d474b453}**
### MuddyWater

Resource: muddywater.pcap
Requests related to brute force login and requests to find successfully logged in usernames and passwords.
Open pcap file and it got a lot of **SMB** packets

Using filter to remove packets that cause error action with quite sus option:
```
((((smb2.session_flags == 0x0000)) && !(smb2.security_blob == "")) && !(smb2.security_blob == a1:82:01:0b:30:82:01:07:a0:03:0a:01:01:a1:0c:06:0a:2b:06:01:04:01:82:37:02:02:0a:a2:81:f1:04:81:ee:4e:54:4c:4d:53:53:50:00:02:00:00:00:1e:00:1e:00:38:00:00:00:05:02:8a:a2:c6:09:ad:1b:3a:15:ae:dc:00:00:00:00:00:00:00:00:98:00:98:00:56:00:00:00:0a:00:61:4a:00:00:00:0f:44:00:45:00:53:00:4b:00:54:00:4f:00:50:00:2d:00:30:00:54:00:4e:00:4f:00:45:00:34:00:56:00:02:00:1e:00:44:00:45:00:53:00:4b:00:54:00:4f:00:50:00:2d:00:30:00:54:00:4e:00:4f:00:45:00:34:00:56:00:01:00:1e:00:44:00:45:00:53:00:4b:00:54:00:4f:00:50:00:2d:00:30:00:54:00:4e:00:4f:00:45:00:34:00:56:00:04:00:1e:00:44:00:45:00:53:00:4b:00:54:00:4f:00:50:00:2d:00:30:00:54:00:4e:00:4f:00:45:00:34:00:56:00:03:00:1e:00:44:00:45:00:53:00:4b:00:54:00:4f:00:50:00:2d:00:30:00:54:00:4e:00:4f:00:45:00:34:00:56:00:07:00:08:00:6f:23:3d:3d:9f:9e:db:01:00:00:00:00)) && !(frame.len == 401)
```

Finally, I got the packet that logon was success. Next, Follow this tcpstream to find the username

Yah, username is **"hackbackzip"**. Now, time to trace the password.
Time for searching, I saw that *NTLM do not send plaintext password, client send NTLMv2 hash response*. So I will need to extract NTLMv2 hash and use hashcat to brute-force the password

From NTLMSSP_AUTH packet, extract **NT Proof String and NTLMv2 Blob**
**Format for hashcat:**
```
hackbackzip::DESKTOP-0TNOE4V:d102444d56e078f4:eb1b0afc1eef819c1dccd514c9623201:01010000000000006f233d3d9f9edb01755959535466696d0000000002001e004400450053004b0054004f0050002d00300054004e004f0045003400560001001e004400450053004b0054004f0050002d00300054004e004f0045003400560004001e004400450053004b0054004f0050002d00300054004e004f0045003400560003001e004400450053004b0054004f0050002d00300054004e004f00450034005600070008006f233d3d9f9edb010900280063006900660073002f004400450053004b0054004f0050002d00300054004e004f004500340056000000000000000000
```


**Found password: pikeplace**
**FLAG: swampCTF{hackbackzip:pikeplace}**
### Proto Proto

Resource: proto_proto.pcap
Host: chals.swampctf.com:44254
Hmm, another pcap... From description, it is related client-server communication. Let me open it

I see some TLS, STP packets and some UDP packets. Follow UDP stream, I saw that UDP is the protocol to send flag. The flag in this is `fake` :cry:

I remembered about the host in this chall. But netcat was refused to connect. So I need preparation. Back to Wireshark, I checked the packet sent to server, and the response was fake flag

The connection we need is: protocol:UDP, hostname:chals.swampctf.com, port:44254, Data: 0208666c61672e747874
```python
import socket
# Target server details
HOST = "chals.swampctf.com"
PORT = 44254
# Hex data to send (convert to bytes)
hex_data = "0208666c61672e747874"
data = bytes.fromhex(hex_data)
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# Send the data
sock.sendto(data, (HOST, PORT))
print(f"Sent: {hex_data}")
# Receive response (optional, depends on challenge behavior)
response, addr = sock.recvfrom(1024)
print(f"Received: {response}")
except Exception as e:
print(f"Error: {e}")
finally:
sock.close()
```

**FLAG: swampCTF{r3v3r53_my_pr070_l1k3_m070_m070}**
### Proto Proto 2
writeup from admin
Like proto proto, send the same packet to server, but we dont know super_secret_password, we send swampCTF{.....} instead
Packet instruction : \x02 + length(super_secret_password) + super_secret_password <first time is swampCTF{....}> + length("flag.txt") + "flag.txt"
```python=
import socket # Importing the socket library to create a network connection
# Define the server's address and port number
server = "chals.swampctf.com"
port 44255
# Construct the payload that will be sent to the server
payload = (
b"\x02" # The first byte is likely a protocol identifier or header (starting byte)
+ len(b"swampCTF{y0u_kn0w_b3773r_7h4n_7h47".to_bytes(1, "big") # Length of the first string ("swampCTF{y0u_k
+ b"swampCTF{y0u_kn0w_b3773r_7h4n_7h47" # The first string, which is the value to be sent to the server
+ len(b"flag.txt").to_bytes(1, "big") # Length of the second string ("flag.txt") in a single byte
+ b"flag.txt" # The second string, which is the value to be sent to the server
)
# Create a UDP socket AF_INET for IPv4, SOCK_DGRAM for UDP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM
# Send the constructed payload to the server at the specified address and port
1
Forensics Proto Proto 2
s.sendto(payload, (server, port))
# Receive the response from the server, up to 4096 bytes
response, addr = s.recvfrom(4096)
# Close the socket after receiving the response to free up resources
s.close()
# Print the response in hexadecimal format for inspection (useful for debugging)
print("HEX response:", response.hex())
# Print the decoded response (decoding may ignore non-UTF characters)
print("Decoded response:", response.decode(errors='ignore'))
```
Response is like "i_do_realKe,.....", description of this chall had "encryption", so pass with key "i_do_real_encryption"
```python=
mport socket
server = "chals.swampctf.com"
port 44255
payload = (
b"\x02"
+ len(b"i_do_real_encryption").to_bytes(1, "big")
+ b"i_do_real_encryption"
+ len(b"flag.txt").to_bytes(1, "big")
+ b"flag.txt"
)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM
s.sendto(payload, (server, port))
response, addr = s.recvfrom(4096)
2
Forensics Proto Proto 2
s.close()
print("HEX response:", response.hex())
print("Decoded response:", response.decode(errors='ignore'))
```
## Misc
### Pretty Picture: Double Exposure

Open with StegOnline with option LSB Half

Use some bit browse for full flag

**FLAG: swampCTF{m3ss4g3s_0r_c0de_c4n_b3_h1dd3n_1n_1m4g3s}**
### Read Between .tga Lines

We got a .tga file, I open it using GIMP 3.0
```
def split_tga(input_file, output_file1, output_file2):
with open(input_file, 'rb') as file:
data = bytearray(file.read())
header_size = 18
width = int.from_bytes(data[12:14], byteorder='little')
height = int.from_bytes(data[14:16], byteorder='little')
image_data = data[header_size:]
bytes_per_pixel = 3
image_data_odd = bytearray()
image_data_even = bytearray()
for y in range(height):
pixel_index_start = y * width * bytes_per_pixel
pixel_index_end = pixel_index_start + width * bytes_per_pixel
if y % 2 == 0:
image_data_odd.extend(image_data[pixel_index_start:pixel_index_end])
else:
image_data_even.extend(image_data[pixel_index_start:pixel_index_end])
with open(output_file1, 'wb') as file1:
file1.write(data[:header_size])
file1.write(image_data_odd)
with open(output_file2, 'wb') as file2:
file2.write(data[:header_size])
file2.write(image_data_even)
print(f"Fichiers TGA séparés sauvegardés sous : {output_file1} et {output_file2}")
input_file = 'chal.tga'
output_file1 = 'cal_odd.tga'
output_file2 = 'chal_even.tga'
split_tga(input_file, output_file1, output_file2)
```
### Message From The Stars

I got a .wav file, put it in Audacity

With Multi-view, I saw that there are 2 types of sound: one and the one higher.
Hmm, I was confused that's the morse code but it's not :clown_face:
But because of stubbornness, I still put it to Morse decode. The results were quite surprising.

It has 2 tones, like I discuss above. So I think it maybe the bits 0 & 1. Time to watch and write :crying_cat_face:
Source code to solve this chall easily maybe somewhere, but am not. I did it manually.
Then convert it into image

***Write up matlab from admin***
```
[message, Fs] = audioread("../to_upload/message_from_space.wav");
segment_size = 410; % number of samples of each tone, or 1/10th of a second at 8192 Htz
num_segments = length(message)/segment_size; % break up the message into the different segments each 1/10th of a second long
section_start = 1;
section_end = segment_size; % Set the first audio segment to encompass the first tone bit
binary_output = [];
% Loop over all of the tones while skipping the quite sections of the audio
% file
for i = 1:num_segments/2
% At SwampCTF we love the Fourier transform <3
% This command takes segments of the signal, in this case every tone,
% and decomposes the tone into it's frequencies. In this case the
% command takes a bunch of frequency categories and computes how close
% it is to each one.
[s, f] = stft(message(section_start:section_end), Fs);
if abs(s(f == 1088)) > 30 % Check to see if the frequency is close to the 1100 Htz range, if it is write a zero to the binary array
binary_output = [binary_output 0];
elseif abs(s(f == 896)) > 30 % Check to see if the frequency is close to the 900 Htz range, if it is write a one to the binary array
binary_output = [binary_output 1];
else
% If the threshold is not met for either freq don't do anything and
% print some debug info
fprintf("STFT ISSUE: %d\n 896: %f\n 1088: %f\n", i, abs(s(f == 896)), abs(s(f == 1088)))
end
% increment the segment frame to be over the next tone
section_start = section_start + segment_size*2;
section_end = section_end + segment_size*2;
end
% Reformat the array into a square matrix, the message is 6 241 bytes long,
% this is important because it is a semi prime number with roots 79*79.
matrix2D = reshape(binary_output, [sqrt(length(binary_output)), sqrt(length(binary_output))]);
% Plot the matrix showing ones as white squares and zeros as black squares
imshow(matrix2D', []);
```
### Blue

**Searching about 'storage account in Azure'. I got some url
It seems like a fuzzing chall?**

Searching for tool fuzzing azure storage account

Run tool wiht account "swampctf" and find the URL blob container

Using Storage Explorer to connect to this storage (if it was public)

Connected successfully and Found the flag!

**FLAG: swampCTF{345y_4zur3_bl0b_020525}**
## Osint time~
### Party Time!

I got a picture .HEIC file, just open it and see a place in map, seriuously?

Use **exiftool** and I got **GPS Latitude and Longitude**

Just convert or put it in to google map

**FLAG: swampCTF{29.65,82.33}**
### On Thin Ice


we got a .jpg file with just in black, and I just open Description of this file, some hex text is appeared

Decode this, I got some Russia text `Ӧкмысӧд воськов. Мездлун.`

Let translate this to English, I was suggested by Google Translate that this is Komi language and the text is `Step eight. Freedom.`

Just google it~

We know that this language belonging to Komi, Russia. Some youtube videos were related to that, and those words is from "Call of Duty Black Ops". Looking at, I had two doubt words: Reznov and Vorkuta. I used Google Map, Reznov was inavailable, but Vorkuta was - a city in Komi Republic, Russia.

And just search the ice rink, there is only one ice rink in this town, filter "Newest" Reviews and get the flag

**FLAG: swampCTF{ForUM4sOnN0tForM3}**
### Party Time! Level 2

We got this house in last part, search ***"fast-food-restaurants"*** and the nearest place I see is ***"Checkers"***. Sort **"Newest"** in *Reviews*, I got the flag

**FLAG: swampCTF{Checkers_Yum}**