# Free Flag on Network
Export Objects -> HTTP -> Save all (save vào 1 folder)
Mở 1 file thì ta thấy có dạng

Quăng lên Chat thì ta thấy nó gợi ý là tách
```
import os
import base64
import re
def extract_and_decode_files():
flags = []
for i in range(100):
filename = f"flag{i}.txt"
if not os.path.exists(filename):
print(f"File {filename} không tồn tại")
continue
with open(filename, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# Tìm tất cả các đoạn base64 trong file
base64_pattern = r'([A-Za-z0-9+/]{20,}={0,2})'
base64_matches = re.findall(base64_pattern, content)
for b64_data in base64_matches:
try:
# Thử decode base64
decoded = base64.b64decode(b64_data)
# Thử decode thành string UTF-8
try:
text = decoded.decode('utf-8')
if any(keyword in text.lower() for keyword in ['flag', 'ctf', 'wannafreshman', 'freeflag']):
flags.append(f"flag{i}: {text}")
print(f"Found in flag{i}: {text}")
except:
pass
# Kiểm tra xem có phải là text có thể đọc được không
try:
text = decoded.decode('latin-1')
if re.search(r'flag\{[^}]+\}', text) or any(keyword in text.lower() for keyword in ['flag', 'ctf']):
flags.append(f"flag{i}: {text}")
print(f"Found in flag{i}: {text}")
except:
pass
except Exception as e:
continue
# Nếu không tìm thấy gì trong base64, thử tìm trực tiếp trong file
if re.search(r'flag\{[^}]+\}', content, re.IGNORECASE):
match = re.search(r'flag\{[^}]+\}', content, re.IGNORECASE)
flags.append(f"flag{i}: {match.group()}")
print(f"Found directly in flag{i}: {match.group()}")
return flags
def extract_specific_base64():
"""Trích xuất và decode đoạn base64 dài nhất từ mỗi file"""
flags = []
for i in range(100):
filename = f"flag{i}.txt"
if not os.path.exists(filename):
continue
with open(filename, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# Tìm đoạn base64 dài nhất (có thể là nội dung file)
base64_pattern = r'([A-Za-z0-9+/]{50,}={0,2})'
base64_matches = re.findall(base64_pattern, content)
if base64_matches:
longest_b64 = max(base64_matches, key=len)
try:
decoded = base64.b64decode(longest_b64)
# Thử nhiều encoding khác nhau
for encoding in ['utf-8', 'latin-1', 'ascii']:
try:
text = decoded.decode(encoding)
if any(keyword in text.lower() for keyword in ['flag', 'ctf']):
flags.append(f"flag{i}: {text}")
print(f"Found in flag{i} with {encoding}: {text[:100]}...")
break
except:
continue
# Nếu không decode được thành text, có thể là binary data
# Lưu ra file để phân tích
with open(f"decoded_{i}.bin", 'wb') as f:
f.write(decoded)
except Exception as e:
print(f"Error decoding flag{i}: {e}")
return flags
if __name__ == "__main__":
print("Đang tìm flag trong các file...")
# Phương pháp 1: Tìm kiếm tổng quát
flags1 = extract_and_decode_files()
# Phương pháp 2: Trích xuất base64 cụ thể
flags2 = extract_specific_base64()
# Kết hợp kết quả
all_flags = list(set(flags1 + flags2))
print("\n" + "="*50)
print("KẾT QUẢ TÌM ĐƯỢC:")
print("="*50)
for flag in all_flags:
print(flag)
if not all_flags:
print("Không tìm thấy flag nào. Kiểm tra các file decoded_*.bin để phân tích thêm.")
```
Mở thử 1 file decoded_0.bin bằng HxD thì thấy file bị đảo -> file gốc là PNG vì ở cuối ta thấy GNP, cũng như các chunk của PNG như pHYs, gAMA,... Thêm hint là reverse + có nhiều file nhỏ lẻ nên em nghĩ là sẽ ghép lại các file -> decode ra file png.

Code đảo ngược mỗi file thành decoded_*_reversed.bin
```
import os
def batch_reverse_files(start_index=1, end_index=99):
"""
Tìm và đảo ngược thứ tự các byte của các file theo mẫu 'decoded_N.bin'.
Tạo ra file mới với tên 'decoded_N_reversed.bin'.
"""
# Lấy thư mục hiện tại nơi script đang chạy
current_dir = os.getcwd()
print(f"Bắt đầu đảo ngược file trong thư mục: {current_dir}\n")
files_processed = 0
# Lặp qua các chỉ số từ start_index đến end_index
for i in range(start_index, end_index + 1):
input_filename = f'decoded_{i}.bin'
output_filename = f'decoded_{i}_reversed.bin'
input_path = os.path.join(current_dir, input_filename)
output_path = os.path.join(current_dir, output_filename)
# Kiểm tra xem file có tồn tại không
if not os.path.exists(input_path):
# print(f"Bỏ qua: Không tìm thấy file '{input_filename}'")
continue
print(f"Xử lý file {i}/{end_index}: '{input_filename}' -> '{output_filename}'")
try:
# 1. Đọc toàn bộ nội dung file
with open(input_path, 'rb') as f:
file_data = f.read()
if not file_data:
print(f" [CẢNH BÁO] File '{input_filename}' trống, bỏ qua.")
continue
# 2. Đảo ngược thứ tự các byte
reversed_data = file_data[::-1]
# 3. Ghi dữ liệu đã đảo ngược ra file mới
with open(output_path, 'wb') as f_out:
f_out.write(reversed_data)
files_processed += 1
except Exception as e:
print(f" [LỖI] Xảy ra lỗi với file '{input_filename}': {e}")
# --- Tổng kết ---
print("\n" + "="*50)
print(f"QUÁ TRÌNH HOÀN TẤT: Đã đảo ngược {files_processed} file.")
print(f"Các file mới nằm trong thư mục '{current_dir}'.")
print("="*50)
# --- Chạy hàm ---
# Lưu ý: Đảm bảo các file 'decoded_N.bin' nằm cùng thư mục với script này
batch_reverse_files(start_index=1, end_index=99)
```
Sau khi đảo lại thì ta kết hợp các file và đổi tên thành .png:
```
import os
def concatenate_reversed_files(start_index=0, end_index=99, extension='bin'):
"""
Nối tất cả các file đã đảo ngược theo thứ tự số (từ 0 đến 99)
thành một file duy nhất.
"""
# Tên file kết quả
output_filename = f'combined_final_image.png' # Đặt tên .png ngay để dễ kiểm tra
current_dir = os.getcwd()
print(f"Bắt đầu nối các file {start_index} đến {end_index}...")
total_bytes = 0
files_found = 0
try:
# Mở file đầu ra ở chế độ ghi nhị phân (wb)
with open(os.path.join(current_dir, output_filename), 'wb') as outfile:
# Lặp qua các chỉ số từ start_index (0) đến end_index (99)
for i in range(start_index, end_index + 1):
# Tên file cần tìm
# Sử dụng cả hai khả năng: .bin hoặc .png (nếu bạn đã đổi tên)
input_filename_bin = f'decoded_{i}_reversed.bin'
input_filename_png = f'decoded_{i}_reversed.png'
# Ưu tiên tìm file .bin trước, nếu không có thì tìm .png
if os.path.exists(os.path.join(current_dir, input_filename_bin)):
input_path = os.path.join(current_dir, input_filename_bin)
name_to_print = input_filename_bin
elif os.path.exists(os.path.join(current_dir, input_filename_png)):
input_path = os.path.join(current_dir, input_filename_png)
name_to_print = input_filename_png
else:
# Bỏ qua nếu không tìm thấy file
continue
# 1. Đọc nội dung file
with open(input_path, 'rb') as infile:
file_data = infile.read()
# 2. Ghi nội dung vào file kết quả
outfile.write(file_data)
files_found += 1
total_bytes += len(file_data)
print(f"-> Đã nối file {i}: {name_to_print} ({len(file_data)} bytes)")
except Exception as e:
print(f"\n[LỖI] Xảy ra lỗi trong quá trình nối file: {e}")
return
# --- Tổng kết ---
print("\n" + "="*50)
print(f"QUÁ TRÌNH HOÀN TẤT: Đã nối {files_found} file.")
print(f"Tổng kích thước: {total_bytes / 1024:.2f} KB")
print(f"File kết quả: {output_filename}")
print("="*50)
# --- Chạy hàm ---
# Chạy script để nối các file đã đảo ngược từ 0 đến 99
concatenate_reversed_files()
```
Flag:

# What is it?
Mở file .wav nghe lên tiếng beep nên em đoán là mã morse, search tool [Morse Decoder](https://morsecode.world/international/decoder/audio-decoder-adaptive.html)

Tới khúc này lúc đó em tưởng pw là GOODLUCK nhưng thử miết không ra :v hóa ra là `passwordisgoodluck`
File .wav, có password nên em liên tưởng tới `steghide extract -sf chall.wav`

` unzip hidden.zip`

Em gửi lên chatgpt nhờ ẻm sửa hộ header và EOCD
```
dd if=next2.zip of=swapped.zip conv=swab
```
Unzip file swapped.zip và mở file lên đọc, ta có phần còn lại của flag
