InterKosenCTF Writeup
InterKosenCTFにチームterpomoとして参加しました.一人チームです. 結果は36位でした. ぼちぼちですね
Kurukuru Shuffle
フラグをクルクル~っと混ぜたものと,まぜまぜするためのコードが渡されます.
from secret import flag from random import randrange def is_prime(N): if N % 2 == 0: return False i = 3 while i * i < N: if N % i == 0: return False i += 2 return True L = len(flag) assert is_prime(L) encrypted = list(flag) k = randrange(1, L) while True: a = randrange(0, L) b = randrange(0, L) if a != b: break i = k for _ in range(L): s = (i + a) % L t = (i + b) % L encrypted[s], encrypted[t] = encrypted[t], encrypted[s] i = (i + k) % L encrypted = "".join(encrypted) print(encrypted)
暗号化のための鍵として3つのランダムな値が使われていますが,大きな数字ではないので愚直に全探索して,フラグっぽい文字列を探してあげます.
KosenCTF{us4m1m1_m4sk_s3np41_1s_r34lly_cut3_38769915}
Hugtto!
フラグを埋め込んだ画像ファイル(steg_emiru.png)と埋め込みに使ったコードが渡されます.
from PIL import Image from secret import flag from datetime import datetime import tarfile import sys import random random.seed(int(datetime.now().timestamp())) bin_flag = [] for c in flag: for i in range(8): bin_flag.append((ord(c) >> i) & 1) img = Image.open("./emiru.png") new_img = Image.new("RGB", img.size) w, h = img.size i = 0 for x in range(w): for y in range(h): r, g, b = img.getpixel((x, y)) rnd = random.randint(0, 2) if rnd == 0: r = (r & 0xFE) | bin_flag[i % len(bin_flag)] new_img.putpixel((x, y), (r, g, b)) elif rnd == 1: g = (g & 0xFE) | bin_flag[i % len(bin_flag)] new_img.putpixel((x, y), (r, g, b)) elif rnd == 2: b = (b & 0xFE) | bin_flag[i % len(bin_flag)] new_img.putpixel((x, y), (r, g, b)) i += 1 new_img.save("./steg_emiru.png") with tarfile.open("stegano.tar.gz", "w:gz") as tar: tar.add("./steg_emiru.png") tar.add(sys.argv[0])
どうやらフラグを1bitずつ画像のr,g,bの最終1bitのどれかに入れているらしいです. フラグの形式が分かっているのでフラグ長を調べて~と思いましたが,この問題のジャンルはforensicsなのです!(なのです!) フラグの1bitがrgbのどれに入るかは乱数によって決定されており,乱数のseedにはdatetime.now()が使われています. ということで,exiftoolでsteg_emiru.pngの最終編集時間を調べます.
File Modification Date/Time : 2019:08:06 11:44:18+09:00
この時刻をseedに使えば解けると思いましたが解けなかったので結局この付近の時刻を全探索して解きました. 探すべき時間がこれではないのか,そもそも想定解ではないのかはルールーに聞いてほしいのです
import sys from PIL import Image import datetime import random bin_flag =0 bin_r ="" bin_g ="" bin_b ="" img = Image.open("./steg_emiru.png") new_img = Image.new("RGB", img.size) w, h = img.size i=0 bin_flag=0 rev_flag=0 b_flag=0 st=[] for d in range (1,7): for ho in range (24): for m in range (60): for s in range (60): print(d,ho,m,s) bin_r="" i=0 bin_flag=0 rev_flag=0 b_flag=0 dt_jst = datetime.datetime(2019,8, d,ho, m, s, 0,tzinfo=datetime.timezone(datetime.timedelta(hours=9))) random.seed(int(dt_jst.timestamp())) for x in range(w): for y in range(h): rnd = random.randint(0, 2) r, g, b = img.getpixel((x, y)) rb=(r & 1) gb=(g & 1) bb=(b & 1) if (rnd==0): bin_flag=bin_flag<<1 | rb if (rnd==1): bin_flag=bin_flag<<1 | gb if (rnd==2): bin_flag=bin_flag<<1 | bb if (i%8==7 and i!=0): for z in range (8): rev_flag=((rev_flag<<1) |((bin_flag>>z) & 1)) bin_r+=(chr(rev_flag)) bin_flag=0 rev_flag=0 if (i==7 and bin_r[0]!="K"): b_flag=1 break if (i == 15 and bin_r[1]!="o"): b_flag=1 break if (i == 23 and bin_r[2]!="s"): b_flag=1 break elif i==23: print ("Perfect!!!!!!!!!!!!!!!!!!") i += 1 if (i==800): b_flag=1 break if (b_flag==1): b_flag=0 break if (bin_r[0]=="K" and bin_r[1]=="o" and bin_r[2]=="s" and bin_r[3]=="e"): st.append(bin_r) a1,a2,a3,a4=d,ho,m,s print(st) print(d,ho,m,s)
KosenCTF{Her_name_is_EMIRU_AISAKI_who_is_appeared_in_Hugtto!PreCure}
ちなみに私のアイコンもえみるちゃんです.愛らしいですね. 私はキュアマジカル/十六夜リコが好きです(イケメンなので)
basic crackme
ELFが渡されます. 引数に入っている文字列がフラグと前方一致しているとYES!と返してくれます(途中で途切れているフラグでも可). ちゃんとassemblyを読めと声が聞こえた気がしたのでIDAを使って読んでみます. まとめると,引数の文字のn文字目を左4bitシフトしたものと右4bitシフトしたものをorして(n-1)を足してあげます. これがマジックナンバーと一致すればOKということみたいです. 挙動をpythonで再現し,全探索してあげたものがこちらになります.
import sys li =[0xb4,0xf7,0x39,0x59,0xea,0x39,0x4B,0x6B,0xbf,0x80,0x3d,0xd1,0x42,0x10,0xe4,0x42,0x105,0x58,0x15,0x108,0xab,0x18,0xe8,0xcd,0x1b,0xeb,0x51,0x1e,0x111,0x44,0x51,0x86,0x53,0x48,0x59,0x36,0x10A,0x9b,0xfd] flag=[0xb4,0xf7,0x39,0x59,0xea,0x39,0x4B,0x6B,0xbf,0x80,0x3d,0xd1,0x42,0x10,0xe4,0x42,0x105,0x58,0x15,0x108,0xab,0x18,0xe8,0xcd,0x1b,0xeb,0x51,0x1e,0x111,0x44,0x51,0x86,0x53,0x48,0x59,0x36,0x10A,0x9b,0xfd] for i in range(len(li)): for j in range(3,125): k=(j<<4)&0xFF l=(j>>4) m=k|l m+=i if (m==(li[i])): flag[i]=(chr(j)) break print(flag)
KosenCTF{w3lc0m3_t0_y0-k0-s0_r3v3rs1ng}
lost world
Can you restore my root user? I don't remember the password. Try running dmesg | grep KosenCTF after logging in.
パスワードを忘れたらしいので再設定します. うっかり者の先人たちの知恵を借りながらやりました.
起動したらSHIFTキー連打でRecovery modeに入ります. eキーを押してシングルユーザーモードにしてなんやかんやでパスワードを再設定できればOKです. rootでログインできたら問題文にあるとおりdmesg | grep KosenCTFを実行するとフラグが現われます. 何を参考にして解いたのか記憶がないのでざっくりになってしまいました. 反省します.
KosenCTF{u_c4n_r3s3t_r00t_p4ssw0rd_1n_VM}
感想
初心者向けと聞かされてほいほいと参加してしまいましたが,普通に難しい問題が多くて苦戦しました. 勉強になる問題がたくさんあったので復習させていただきたいと思います. 最後に,運営の皆様お疲れさまでした.