# [InterKosenCTF 2019] Hugtto! ###### tags: `InterKosenCTF 2019`, `forensics` ## 概要 `emiru.png`に対してflagを隠す処理をして結果とスクリプトをtar.gzにまとめている。処理の内容は単純で、0〜2の乱数によってr, g, bの下位1ビットにビットを格納している。 乱数のシードを知る必要があるが、tar.gzが生成された時刻に近いのでそれを利用する。 ## 解法 tarでタイムスタンプを見てみる。 ``` $ tar -t -v --full-time -f hugtto.tar.gz -rw-rw-r-- ptr/ptr 1346615 2019-08-01 14:07:10 ./steg_emiru.png -rw-rw-r-- ptr/ptr 1009 2019-08-01 14:06:22 steg.py ``` タイムゾーンや画像処理の方向が縦であることなどに注意してデコーダを書く。 ```python from PIL import Image import random import datetime img = Image.open("steg_emiru.png") width, height = img.size bin_prefix = [] for c in "KosenCTF{": for i in range(8): bin_prefix.append((ord(c) >> i) & 1) approx = int(datetime.datetime.strptime( '2019-08-01 14:00:00', '%Y-%m-%d %H:%M:%S' ).timestamp()) for seed in range(approx, approx + 0x1000): random.seed(seed) bin_flag = [] for i in range(len(bin_prefix)): x, y = i // width, i % width rnd = random.randint(0, 2) r, g, b = img.getpixel((x, y)) if rnd == 0: bin_flag.append(r & 1) if rnd == 1: bin_flag.append(g & 1) if rnd == 2: bin_flag.append(b & 1) if bin_flag[i] != bin_prefix[i]: break else: print("[+] Found seed: {}".format(seed)) break else: print("[-] Invalid approx") exit(1) random.seed(seed) flag = "" char = [] for i in range(8 * 128): x, y = i // width, i % width rnd = random.randint(0, 2) r, g, b = img.getpixel((x, y)) if rnd == 0: char.append(r & 1) if rnd == 1: char.append(g & 1) if rnd == 2: char.append(b & 1) if len(char) == 8: x = 0 for j in range(8): x |= char[j] << j flag += chr(x) char = [] print(flag) ``` はい。 ``` KosenCTF{Her_name_is_EMIRU_AISAKI_who_is_appeared_in_Hugtto!PreCure} ```