# 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**

+ 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.

Và em tìm được flag ở kích thước 192x90 như sau:

**Flag: lactf{m1ku_m1ku_n1_s7eguwu}**