Space Heroes CTF Writeup

2022/04/01 ~ 2022/04/03まで開催されたSpace Heroes CTFのwriteup。
チーム DCDC で出場した。

  • 個人得点:754pt
  • チーム得点:2454pt
  • チーム順位:62位 / 778チーム

forensics問しか解いてないけど、OpenCVでガチャガチャやったので備忘として残しておく。

Forensics

Star Pcap (100pt)

pcapファイルが渡される。
中身はICMPのみが取得されているただのパケットキャプチャファイルだが、ICMP codeがASCIIと同期している。
ICMP Codeを読めばフラグ。

shctf{L0g1c-i$-th3-begiNNing-0f-wi$doM}

Netflix and CTF (100pt)

pcapファイルが渡される。
中身はHTTP通信を中心として取得されているただのパケットキャプチャファイル。
定期的にPOSTしており、/keypress/Lit_〇ではキーを押下したタイミングでPOSTが投げられているっぽい。
パケットキャプチャ

Lit_〇の部分を抜粋して結合するとフラグ。

shctf{T1m3-is-th3-ultimat3-curr3Ncy}

The Legend of the Chozo (100pt)

corruptedData.chrという謎のファイルが渡される。
バイナリを読むと普通にPNGファイルのファイルヘッダをいい感じに修正すればOK。

修正前:

100000000: 5047 890a 4e0d 0a1a 0d48 4400 5200 0049  PG..N....HD.R..I
200000010: 0000 00f0 0000 0139 0806 0000 00ae c5ad  .......9........
3                    ----snip to EOF---

修正後:

100000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
200000010: 0000 00f0 0000 0139 0806 0000 00ae c5ad  .......9........
3                    ----snip to EOF---

修正するとファイルを開けるようになる。
画像の中にフラグ。

修正後ファイル

shctf{CH0Z0_rU1N5}

Interstellar Mystery (254pt)

  • master0-3.qcow2
  • master0-4.qcow2

という2つのファイルが渡される。
qcow2はqemuで使われているディスクイメージを単一のファイルにまとめたもの。
virtualboxを使っている人はvmdkとかを想像するとわかりやすいかも。

これをLinuxにマウントしていく。

 1sudo mkdir /mnt/master0-3
 2sudo mkdir /mnt/master0-4
 3
 4sudo modprobe nbd max_part=8
 5sudo qemu-nbd --connect=/dev/nbd0 ./master0-3.qcow2
 6sudo qemu-nbd --connect=/dev/nbd1 ./master0-4.qcow2
 7
 8sudo mount /dev/nbd0 /mnt/master0-3
 9# mount: /mnt/master0-3: wrong fs type, bad option, bad superblock on /dev/nbd0, missing codepage or helper program, or other error.
10sudo mount /dev/nbd1 /mnt/master0-4

参考: https://gist.github.com/shamil/62935d9b456a6f9877b5

master0-3.qcow2がマウントできなかったが、master0-4.qcow2のほうはマウントできた。
中にはeというバイナリファイルだけがあった。
stringsで文字列抽出し、フラグフォーマットであるshctfをgrepで抜き出すとフラグ。
これ想定解なのか?

shctf{btrfs_is_awsome}

Buzz’s Secret Watch (Part 1) (100pt)

なんか8つの点がチカチカする動画が渡される。 下にGifにした奴を貼っておく。
Gifにしたやつ

8bit = 1byteなのでまあこの辺の点数帯ならASCII文字を表したいんだろうなあと容易に想像ができる。
人力で読める長さだけど、めんどくさすぎるのでOpenCVでパーサを書いた。

 1import cv2
 2import numpy as np
 3
 4
 5coordinates = [(360,699), (394,697), (430,700), (469,698), (501,700), (537,694), (575,696), (604,697)]
 6
 7
 8def onMouse(event, x, y, flags, params):
 9    if event == cv2.EVENT_LBUTTONDOWN:
10        print(f"({x},{y})")
11        print(f"COLOR: B,G,R({img[y,x,:]})")
12
13#MOV_PATH = "./buzzsaw.avi"
14MOV_PATH = "./buzz-bin.avi"
15cap = cv2.VideoCapture(MOV_PATH)
16
17
18while True:
19    ret, img = cap.read()
20    #cv2.imshow("cap", img)
21
22    hsv = img
23    lower_green= np.array([0, 150, 0], dtype = "uint8") 
24    upper_green= np.array([30, 255, 30], dtype = "uint8")
25
26    chk_green= cv2.inRange(hsv, lower_green, upper_green)
27    contours, hierarchy = cv2.findContours(chk_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
28    #cv2.imshow("green_point",chk_green)
29    img_contour = cv2.drawContours(hsv, contours, -1, (255, 0, 0), 3)
30
31    #cv2.imshow("green_path", img_contour)
32
33    lamps = []
34    arr = [0]*8
35    for contour in contours:
36        for i,coordinate in enumerate(coordinates):
37            retval = cv2.pointPolygonTest(contour, coordinate, False) 
38            if retval == 1 or retval == 0:
39                arr[i]=1
40            #cv2.waitKey(0)
41    if sum(arr) != 0:
42        print("".join(map(str, arr)))
43
44
45    #cv2.setMouseCallback("cap", onMouse)
46
47    # EMERG BRERK
48    if cv2.waitKey(1) & 0xFF == ord("q"):
49        break
50
51cap.release()
52cv2.destroyAllWindows()

OpenCV使ってなさ過ぎて普通に時間がかかった。
やっていることとしては単純で、動画を1フレーム毎に以下のようなチェックをしている。

  • 緑の物体が出てきたら輪郭検出を実施
  • 輪郭内に指定した座標群(coordinates)が入っているかどうかをチェック。

前に個人が作ったようなCaptchaもどきを邪悪な方法で攻略しようとしたとき以来、OpenCVを触っていなかったためいい再学習の機会になった。
実際に動かしてみると、やはり明滅で出力されているのがASCII文字列だった。

shctf{Sh3r1ff-tH1s-is-n0-t1m3-t0-pAn1c}

Buzz’s Secret Watch (Part 2) (100pt)

Part 1に続きほぼ同じフォーマットの動画が渡される。
変更点は点滅がクソクソ早くなったことと動画の時間がかなり長くなっていること。
人力の解読はほぼ不可能なレベルになっていた。
解法だが、Part 1で書いたパーサで一撃で解けた。めんどくさがらずにちゃんと書いてよかったね。
出力はELF形式のバイナリだったが、バイナリをstringsで文字列抽出するとフラグが出てくる。

shctf{Th1s-Isnt-Fly1ng-THis-Is-FAlliNg-W1th-Styl3}

お気持ち

OpenCV完全に忘れててつらい。
新年度だし今年は色々とがんばっていき!