# Free Flag on Network Export Objects -> HTTP -> Save all (save vào 1 folder) Mở 1 file thì ta thấy có dạng ![image](https://hackmd.io/_uploads/rJ6f72J6ll.png) 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. ![image](https://hackmd.io/_uploads/Sk69M2kpel.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: ![image](https://hackmd.io/_uploads/S1xgN3y6gl.png) # 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) ![image](https://hackmd.io/_uploads/HyAOE3yael.png) 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` ![image](https://hackmd.io/_uploads/Sy6fH3yaex.png) ` unzip hidden.zip` ![image](https://hackmd.io/_uploads/BJH4rnypgg.png) 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 ![image](https://hackmd.io/_uploads/Bk5pw2k6xg.png)