# Write Up KCSC Recruitment 2025 [MISC]

---
# 1. The Ultimate Steganography

Lúc đầu đọc qua mình tưởng author quên cho file hay link gì đó, thế nhưng mãi không thấy ai hỏi cũng như đính chính lại nên mình nghĩ có thể bị ẩn đâu đó trong nguồn trang, F12 thử và mình phát hiện điều thú vị:

```bash=
‌‌‌‌‍‬‬‌‌‌‌‌‍‍‌‌‌‌‌‍‍‌‌‌‌‌‍‌‌‌‌‌‌‍‌‌‌‌‌‌‬‬May‌‌‌‌‌‬ ‌‌‌‌‌‬this ‌‌‌‌‍‬‍‌inspires ‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‍‬‌‌‌‌‍‬‍‍‌‌‌‌‌‬‬‌‌‌‌‍‬‍‌‌‌‌‍‬‌‌‌‌‍‬you‌‌‌‌‍‬‍‌‌‌‌‍‬‌‌‌‌‌‍‬‍‍ to‌‌‌‌‌‬‬‌‌‌‌‍‬‌ become‌‌‌‌‍‬‌‌‌‌‍‬‍ a‌‌‌‌‌‬‌‌‌‌‍‬‍‬ ‌‌‌‌‍‬‬‍steg‌‌‌‌‍‬‌/‌‌‌‌‍‬‍‍‌‌‌‌‌‬‌‌‌‌‍‬‍‌guess ‌‌‌‌‌‬god‌‌‌‌‌‌‍‌‌‌‌‍‍‌‌‌‌‍‌‬‌ ‌‌‌‌‍‍‌‌‌‌‍‌‍‌‌‌‌‍‬‬‌‌‌‌‍‬‍‌‌‌‌‍‌‬‬‌‌‌‌‍‬‍‍‌‌‌‌‍‍‌‌‌‌‍‍‬(‌‌‌‌‍‬‌‌‌‌‌‍‍‍‍ツ‌‌‌‌‍‬‌‌‌‌‌‍‌‌‌‌‌‍‍‬‌‌‌‌‍‌‬‌‌‌‌‍‌‌)‌‌‌‌‍‌‍‌‌‌‌‌‍‬‍‌‌‌‌‌‍‍‍‌‌‌‌‌‍‬‬‌‌‌‌‌‬‍‌‌‌‌‌‌‌‌‌‌‌‍‬‍‌‌‌‌‍‌‌‌‌‌‌‍‍‌‌‌‌‌‍‌‌‌‌‌‌‍‌‌‌‌‌‍‬‬‌‌‌‌‍‌‍‍‌‌‌‌‍‌‍‌‌‌‌‌‍‌‌‌‌‌‌‌‬‌‌‌‌‍‍‬‌‌‌‌‍‬‬‍‌‌‌‌‍‬‍‍‌‌‌‌‍‍‌‌‌‌‌‌‌‌‌‍‍‍‌‌‌‌‍‌‌‌‌‌‍‌‌‌‌‌‌‌‍‌‌‌‌‍‌‌‌‌‌‍‬‬‌‌‌‌‌‍‬‌‍‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‬‬‌‌‌‌‍‬‍
```
Tra thử vài trang thì mình biết được đây là dạng `zero width`, cop đoạn mô tả đó và cho vào tool này:
> https://330k.github.io/misc_tools/unicode_steganography.html

Có được https://drive.google.com/file/d/1_H_MkgJe_vlUlOvNCDdTz-0mLtpOkEDL/view?usp=sharing, truy cập và mình có 2 file:

File python có nội dung:
```python=
with open(r"Flag.txt", "rb") as f:
d = f.read()
z = [i for i in d]
k = "O young one, art thou perchance playing at Forensics amiss, or art thou merely a dabbler in the realm of Miscellanies?".encode()
for i in range(len(d)):
z[i] = d[i] ^ k[i % len(k)]
z = z[::-1]
with open(r"Flag.enc", "wb") as f:
[f.write(int.to_bytes(i)) for i in z]
SUPER_PASSWORD = "kDHK4W2oxBhNuBgilWdgjwSLYQhb4wpG+F2l58NoAeU="
```
Đoạn code trên thực hiện việc mã hóa nội dung của file Flag.txt bằng một khóa cụ thể và lưu kết quả vào file Flag.enc. Cụ thể, đầu tiên nó đọc nội dung file Flag.txt dưới dạng byte, sau đó sử dụng một chuỗi khóa (mã hóa dưới dạng byte) để mã hóa nội dung bằng cách thực hiện phép toán XOR giữa từng byte của dữ liệu và khóa. Sau khi mã hóa xong, kết quả được đảo ngược (reverse) và ghi vào file mới Flag.enc. Cuối cùng, một chuỗi mật khẩu SUPER_PASSWORD cũng được định nghĩa nhưng không được sử dụng trong phần mã này. Vậy ta cũng chỉ cần đảo ngược quá trình trên để khôi phục file:
```python=
with open(r"result.png", "rb") as f:
z = f.read()
z = z[::-1]
k = "O young one, art thou perchance playing at Forensics amiss, or art thou merely a dabbler in the realm of Miscellanies?".encode()
d = [z[i] ^ k[i % len(k)] for i in range(len(z))]
with open(r"Flag.png", "wb") as f:
f.write(bytes(d))
```
Mình có được ảnh jpg:

Tuy nhiên thì dung lượng của nó khá lớn, nên mình đoán là file đã bị nhúng dữ liệu khác:


Ở trong nó chứa 1 file zip có 2 ảnh, nhưng nó bị đặt pass, mình dùng john crack thì có được pass là `alice`, có được 2 ảnh png, nhìn qua thì giống nhau nhưng thực tế lại khác:

Sau khi thử đủ mọi cách mình có biết (xor với pass,...), không đem lại gì thì mình đã hỏi anh author về bài, anh cho mình biết là dữ liệu ẩn sẽ nằm trong 1 ảnh. Vấn đề là nó ở ảnh nào và bị ẩn như thế nào, sau khi mò 1 lúc thì mình biết được đó là ở các pixel ảnh, 2 ảnh có số lượng y hệt nhau, thế nhưng ở 1 số pixel nhất định thì sẽ có 1 giá trị khác:
```bash=
Ví dụ:
Điểm 0:
File 1: (0,0): (22, 54, 105, 255)
File 2: (0,0): (255, 54, 105, 255)
=> ở đây thì giá trị đặc biệt đó là 255 (nó là giá trị thay cho 22)
Các giá trị này khi decode decimal ta sẽ thấy được nó là 1 ảnh jpg.
```
Trong quá trình làm thì không biết do ảnh có vấn đề hay sao nhưng mình bị thiếu 1 vài bytes, nhưng author quên mất đề nên chấp nhận hướng đi của mình là đúng, script phân tích pixel và so sánh:
```python=
from PIL import Image
def analyze_pixel_values(img_path, output_file):
img = Image.open(img_path)
arr = img.load()
with open(output_file, 'w', encoding='utf-8') as f:
for y in range(img.height):
for x in range(img.width):
r, g, b, a = arr[x, y]
f.write(f"({x},{y}): ({r}, {g}, {b}, {a})\n")
if __name__ == "__main__":
analyze_pixel_values("hollow1.png", "pixel_values1.txt")
```
```python=
def read_pixel_file(filename):
with open(filename, 'r') as file:
pixels = file.readlines()
return pixels
def compare_pixel_files(file1, file2, output_file):
pixels1 = read_pixel_file(file1)
pixels2 = read_pixel_file(file2)
if len(pixels1) != len(pixels2):
with open(output_file, 'w', encoding='utf-8') as out_file:
out_file.write("Hai file không cùng số dòng.\n")
return
differences = []
for i in range(len(pixels1)):
if pixels1[i] != pixels2[i]:
differences.append((i, pixels1[i], pixels2[i]))
with open(output_file, 'w', encoding='utf-8') as out_file:
if differences:
out_file.write("")
for diff in differences:
out_file.write(f"Điểm {diff[0]}:\n")
out_file.write(f"File 1: {diff[1]}")
out_file.write(f"File 2: {diff[2]}")
else:
out_file.write("Không có sự khác biệt giữa hai file.\n")
file1 = 'pixel_values1.txt'
file2 = 'pixel_values2.txt'
output_file = 'differences_output.txt'
compare_pixel_files(file1, file2, output_file)
```
```python=
import re
with open('differences_output.txt', 'r', encoding='utf-8') as file:
content = file.read()
pattern = re.compile(
r"Điểm (\d+):\nFile 1: .*? \((\d+), (\d+), (\d+), (\d+)\)\nFile 2: .*? \((\d+), (\d+), (\d+), (\d+)\)"
)
matches = pattern.findall(content)
multi_change_points = []
changed_values = []
for match in matches:
point_id = int(match[0])
file1_values = tuple(map(int, match[1:5]))
file2_values = tuple(map(int, match[5:]))
changes = [f2 for f1, f2 in zip(file1_values, file2_values) if f1 != f2]
if len(changes) > 1:
multi_change_points.append((point_id, changes))
changed_values.extend(changes)
with open('multi_change_points.txt', 'w', encoding='utf-8') as output_file:
for point_id, changes in multi_change_points:
output_file.write(f"Điểm {point_id}: {changes}\n")
print(f"Tổng số điểm có nhiều giá trị thay đổi: {len(multi_change_points)}")
print(f"Tổng số giá trị thay đổi: {len(changed_values)}")
with open('changed_values1.txt', 'w', encoding='utf-8') as output_file:
for value in changed_values:
output_file.write(f"{value} ")
```
Sau khi phân tích xong kết quả mình nhận được là các giá trị decimal, decode nó ta sẽ nhận được ảnh jpg tương tự ảnh author cho lúc đầu:


Bây giờ là lúc ta sử dụng super pass mà author cho lúc đầu
> SUPER_PASSWORD = "kDHK4W2oxBhNuBgilWdgjwSLYQhb4wpG+F2l58NoAeU="
>
Nhìn ảnh thì sẽ biết ngay dùng tool nào:

> FLag: KCSC{M3m0ri4l_t0_th3_Stego_King,_In_th3_CTF5_f4r_4b0v3,_thr0ugh_it5_54crific3_KCSC_l45t_3t3rn4l}
---