Pico CTF 2025
Hey, fellow hackers! 🏴☠️
I’m dropping a writeup for the Pico CTF 2025 challenges!️. I teamed up with my squad, P4rad0x. Let’s jump straight into the action! 💻🔥
Web
Cookie Monster Secret Recipe

A challenge named after everyone’s favorite blue, cookie-loving monster. The challenge name hints at cookies, implying that authentication or sensitive information might be stored within browser cookies.

Upon visiting the website, I inspected the cookies using the browser's developer tools (Application > Cookies).
The cookie value was base64-encoded, which is a common method of simple obfuscation.
Decoding the base64 string revealed the flag.

picoCTF{c00k1e_m0nster_l0ves_c00kies_057BCB51}
Heap-Dump

A web-based challenge involving an API where memory dumps might be accessible.

Navigated through the web interface and identified api-docs revealing various API endpoints.

One particular endpoint, /heapdump, caught my attention as it could contain sensitive memory data. Using curl, I accessed the /heapdump and filtered through the output with grep to extract the flag.
picoCTF{Pat!3nt_15_Th3_K3y_388d10f7}
n0s4n1ty 1

This challenge involved a file upload functionality that could be exploited for Remote Code Execution (RCE).

The website allowed users to upload files without restriction. I attempted uploading a basic PHP command injection script to execute arbitrary commands.
After successfully uploading the file, I accessed it via the browser and executed system commands. Using cat flag, I retrieved the flag from the server.

picoCTF{wh47_c4n_u_d0_wPHP_a4ca6ea0}
SSTI1

A web form suggested the possibility of Server-Side Template Injection (SSTI), a common vulnerability in improperly sanitized template engines.
Entered {{ 7*7 }} in the input field to confirm SSTI vulnerability. The output 49 verified that user input was being evaluated as code.


Once the vulnerability is confirmed, I can escalate it to execute system commands or read sensitive files. Extracted the flag using:

Reversing
Flag Hunters

This challenge presented a Python script that dynamically sings a song, inserting the flag into the lyrics. The flag is stored in a file called flag.txt and is referenced within the script.
Understanding the code:
The script reads the flag from
flag.txtand integrates it into the song lyrics.It defines a song structure using labeled sections (
[VERSE1],[REFRAIN], etc.).The function
reader(song, startLab``el)processes the song lyrics and follows control flow logic based onRETURNstatements and user input.The
Crowd:prompt expects input, but simply providingRETURN 0;RETURN 0skips unnecessary interaction and proceeds to reveal the flag.The ';' is provided here because of
for line in song_lines[lip].split(';'):splits the songs label with it and it will be converted into integer hereelif re.match(r"RETURN [0-9]+", line):and it goes to the line "0" which is start of the program where it has the flag.
Connected to the remote instance via Netcat:
Observed the song lyrics being printed dynamically. Responded with RETURN 0;RETURN 0 when prompted, allowing the script to cycle through and eventually print the flag
picoCTF{70637h3r_f0r3v3r_a3d964ee}
Forensics
RED

In this challenge, I was provided with a PNG file red.png and the word "RED" is all over the challenge.
The first step was to analyze the image using forensic tools. PNG files often hide information through steganography.
The zsteg tool, commonly used for extracting hidden messages from PNG images, was employed for analysis.
Running zsteg red.png revealed a Base64-encoded string. Decoding the Base64 string revealed the flag.
picoCTF{r3d_1s_th3_ult1m4t3_cur3_f0r_54dn355_}
Ph4nt0m 1ntrud3r

The challenge provided a PCAP (Packet Capture) file myNetworkTraffic.pcap. Given the nature of network forensic challenges, I anticipated the flag might be hidden within packet data.
First, I opened the PCAP file using Wireshark. Observed a significant amount of TCP segment data, possibly encrypted or encoded.

Used tshark to extract TCP segment data. The data is indeed encoded using base64 and I decoded it.
There is so much unwanted data with frame length of "48" so i removed it and the remaining is the flag in wrong order.
nt_th4t } e1ff063 _34sy_t {1t_w4s picoCTF bh_4r_2
I assembled it as flag.
picoCTF{1t_w4snt_th4t_34sy_tbh_4r_2e1ff063}
Bitlocker-1

The challenge provided a Windows BitLocker-encrypted image file (MBR Boot Sector File) bitlocker.dd. The goal was to unlock and extract the flag.
First step for Identifying the file type I used the file command to confirm that the provided .dd file was an MBR boot sector with BitLocker encryption.
Secondly for the extracting password hashes I used bitlocker2john to extract BitLocker password hashes from the image file.
For cracking the hash, I used hashcat , which is a popular tool to for cracking hashes. It successfully cracked the hash and retrieved the password -> jacqueline

After that, I created a mount point and used dislocker tool to unlock BitLocker.
Then I mounted the decrypted BitLocker volume and accessed the file system to read the flag.txt file.
picoCTF{us3_b3tt3r_p4ssw0rd5_pl5!_3242adb1}
Cryptography
HashCrack

In this challenge, I had to connect to a remote server using netcat. Upon connection, the server presented a series of hashed passwords that I needed to crack in order to progress. The hashes were of different types, including MD5, SHA-1, and SHA-256.
Upon connecting to the server:
I received the following prompts:
MD5 Hash
Hash:
482c811da5d5b4bc6d497ffa98491e38Cracked password:
password123Response: "Correct! You've cracked the MD5 hash with no secret found!"
SHA-1 Hash
Hash:
b7a875fc1ea228b9061041b7cec4bd3c52ab3ce3Cracked password:
letmeinResponse: "Correct! You've cracked the SHA-1 hash with no secret found!"
SHA-256 Hash
Hash:
916e8c4f79b25028c9e467f1eb8eee6d6bbdff965f9928310ad30a8d88697745Cracked password:
qwerty098Response: "Correct! You've cracked the SHA-256 hash with a secret found."
The final response revealed the flag:
picoCTF{UseStr0nG_h@shEs_&PaSswDs!_29028be8}
Even RSA Can Be Broken???

In this challenge, I was given an RSA encryption script encrypt.py and had to decrypt an encrypted flag. The server provided the RSA parameters: N (modulus), e (public exponent), and the ciphertext.
Upon connecting to the server:
Understanding the Encryption Code
The encryption process in encrypt.py follows the standard RSA encryption technique:
So, i used an online tool dcode.fr which has RSA decryption function.

The decrypted message revealed the flag. picoCTF{tw0_1$_pr!m33991588e}
Binary Exploitation
PIE TIME

In this challenge, I was provided with a remote connection to a binary running on a server:
Additionally, we receive two downloadable files:
Analyzing the Source Code
The provided vuln.c code snippet is as follows:
Understanding the code:
The program prints the address of the
main()function.It prompts the user for an address to jump to.
It then treats the given input as a function pointer and executes it.
If an incorrect address is given, a segfault handler prevents crashes.
The
win()function, which prints the flag, is not explicitly called anywhere in the program.
The goal? Find and provide the correct address for win() so the program jumps to it!
Bypassing Position-Independent Executable (PIE)
Since PIE is enabled, the memory addresses change on each execution. However, the offset between functions remains the same. To determine this offset, we analyze the binary using Radare2:
Observations:
The offset between
win()andmain()is 150 bytes.When we connect to the remote server, it prints the dynamically assigned main() address.
Thus, we can calculate win() address:
win_address = main_address - 150
Connecting to the challenge server:
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_3d38fb4b}
General Skills
Rust Fixme 1

This is a challenges which presents a piece of Rust code with several syntax and logical errors. The goal is to identify and fix these issues to successfully decrypt an encrypted message.
Given Rust code with errors:
Fixed Rust code:
Key Fixes and Explanation:
Fixed missing semicolon (
;) → Rust requires semicolons to terminate statements.Replaced
ret;withreturn;→ Rust does not have aretkeyword.Corrected
println!syntax → Used{}instead of:?for formatted output.Passed
encrypted_bufferas a reference → Ensures proper memory handling.
picoCTF{4r3_y0u_4_ru$t4c30n_n0w?}
Rust Fixme 2

In this it requires modifying a function so that it correctly updates a mutable string passed as an argument.
Given Rust code with errors:
Fixed Rust code:
Key Fixes and Explanation:
Used
&mut String→ Allows modification ofborrowed_stringinside the function.Declared
party_foulas mutable →let mut party_foul = String::from("...").Passed
party_foulas&mut→ Enables mutation withindecrypt().
picoCTF{4r3_y0u_h4v1n5_fun_y31?}
Rust Fixme 3

This challenge focuses on eliminating unnecessary unsafe operations and ensuring safe memory handling in Rust.
Given Rust code with errors:
Fixed Rust code:
Key Fixes and Explanation:
Removed unnecessary raw pointer operations → Rust is memory-safe by default; avoid
unsafeunless absolutely needed.Used a simple reference (
&decrypted_buffer) instead of unsafe slices.Preserved Rust’s memory safety principles → The corrected code works efficiently without unsafe blocks.
picoCTF{n0w_y0uv3_f1x3d_1h3m_411}
Last updated
