# LACTF 2025 ## misc/extended >What if I took my characters and... extended them? Đây là một challenge misc thiên về reverse. Challenge cho ta 1 file python và 1 file txt, ta cùng mở nó lên để xem: + File Python: ```python = flag = "lactf{REDACTED}" extended_flag = "" for c in flag: o = bin(ord(c))[2:].zfill(8) # Replace the first 0 with a 1 for i in range(8): if o[i] == "0": o = o[:i] + "1" + o[i + 1 :] break extended_flag += chr(int(o, 2)) print(extended_flag) with open("chall.txt", "wb") as f: f.write(extended_flag.encode("iso8859-1")) ``` + File txt: ``́áăôæûÆơîîé́ùßÅîïơçèßÔèéóß̀ïïëóßÄéææạ̊åîôßÏîßÍáăßÁîäß×éîäï÷óư`` Cụ thể như sau, đoạn code python trên đã thực hiện các bước như sau. Đầu tiên nó chuyển đổi từng kí tự của flag về thành dạng nhị phân có 8 bit sau đó thực hiện đổi bit 0 đầu tiên của từng kí tự thành bit 1 rồi ghi lại vào file chall.txt. Bây giờ công việc của ta đơn giản là viết code thay đổi giá trị nhị phân của từng kí tự, đưa bit 1 đầu tiên về 0 là có thể lấy lại được flag. ```python = with open("chall.txt", "rb") as f: extended_flag = f.read().decode("iso8859-1") flag = "" for c in extended_flag: o = bin(ord(c))[2:].zfill(8) for i in range(8): if o[i] == "1": o = o[:i] + "0" + o[i + 1:] break flag += chr(int(o, 2)) print(flag) ``` **Flag: lactf{Funnily_Enough_This_Looks_Different_On_Mac_And_Windows}** ## misc/mikumikubeam >Miku miku beaaammmmmmmmmmmmmmmmm >Author: r2uwu2 Ở challenge này, ta biết được người ta đã thực hiện giấu thông tin bằng **imagemagick** và ta được cho 2 ảnh, 1 ảnh là ảnh ban đầu và 1 ảnh là ảnh đã được ẩn thông tin và 1 file create.sh là file thực hiện giấu thông tin. File create.sh như sau: ```#!/bin/sh rm -rf build mkdir build flag="Pidgeon" # below msg size and offset taken from docs # miku actually randomized msg and offset owo msgsize="50x40" offset="+15+2" # create the message gif magick -gravity center -size $msgsize label:"$flag" build/message.gif magick identify build/message.gif # create steg image using imagemagick steg operator magick composite build/message.gif mikumikubeam.png -stegano $offset build/mikumikusteg.png cp build/mikumikusteg.png . ``` Cụ thể thì nó thực hiện tạo 1 file gif với kích thước ngẫu nhiên rồi giấu vào ảnh mikumikubeam.png bằng imagemagick rồi copy sang mikumikusteg.png. Với bài này, em có một cách làm brute-force với các bước như sau: + Đầu tiên em sẽ quan sát sự khác biệt giữa hai ảnh được cho + Dùng lệnh sau: **convert mikumikubeam.png mikumikusteg.png -metric PAE -compare difference.png** ![difference](https://hackmd.io/_uploads/rJfyPJz91x.png) + Bắt đầu với việc tìm offset, em quan sát được dựa trên bức ảnh difference.png. Có thể thấy sự khác biệt được thể hiện rõ qua các pixel đỏ và offset khi sử dụng trong imagemagick thì chỉ quan tâm tới x-offset còn y-offset bằng bao nhiêu cũng được, vì vậy ta biết được offset sẽ là pixel đỏ đầu tiên trong bức ảnh khác biệt này. + Tiếp đó, ta sẽ thực hiện tính redrange(diff) bằng cách xác định vị trí pixel đỏ đầu tiên và pixel đỏ cuối cùng. + Ta có code thực thi như sau: ```python= import numpy as np import imageio.v3 as imageio def find_offset(difference_file): diff = np.asarray(imageio.imread(difference_file)) for i, px in enumerate(diff[0, :1000]): if px[0] / max(1,px[1]) > 3: return i def find_redrange(difference_file): diff = np.asarray(imageio.imread(difference_file)) # Kích thước ảnh m, n, _ = diff.shape start = float("inf") end = -1 # Duyệt từng pixel để tìm pixel đỏ for i in range(m): for j in range(n): px = diff[i, j] idx2 = i * n + j if px[0] / max(px[1], 1) > 3: idx = i * n + j start = min(start, idx) end = max(end, idx) return end - start difference_file = "difference.png" print("Offset:", find_offset(difference_file)) redrange_value = find_redrange(difference_file) print("Redrange(diff):", redrange_value) ``` Ta có công thức như sau: **redrange(diff) / (width * height) ~ 16** Và em tính được **redrange(diff) = 278453** **=> width * height = 278453 / 16 ~ 17404** **=> sqrt(17404) ~ 131** Từ đó em có thể brute-force giá trị kích thước của nội dung được dấu vào trong bức ảnh, em sẽ brute-force với giá trị width từ **130 -> 260**, height sẽ bằng **17404 // width** mỗi lần em sẽ tăng giảm 2 đơn vị vì nếu chênh lệch 1 đơn vị thì ảnh vẫn có thể nhận diện được. Ta có code thực hiện trích xuất ảnh như sau: ```python= import subprocess def extract(width, height, filename='mikumikusteg.png', offsetx=243, offsety=0): output_filename = f'extracted/recovered{width}x{height}.png' cmd = f'convert -size {width}x{height}+{offsetx}+{offsety} stegano:{filename} {output_filename}' subprocess.run(cmd, shell=True, check=True) return f"Extracted {width}x{height} at offset ({offsetx}, {offsety}) -> {output_filename}" width = list(range(130, 260, 2)) height = list(range(1, 131, 2)) for w in width: h = 17404 // w result = extract(w, h) print(result) ``` Sẽ có tổng cộng 65 bức ảnh. ![image](https://hackmd.io/_uploads/rJQ82xUcyl.png) Và em tìm được flag ở kích thước 192x90 như sau: ![recovered192x90](https://hackmd.io/_uploads/BkbrngUqyl.png) **Flag: lactf{m1ku_m1ku_n1_s7eguwu}**