RITSEC CTF 2019 Writeup

この大会は2019/11/16 2:00(JST)~2019/11/18 14:00(JST)に開催されました。
今回もチームで参戦。結果は1890点で900チーム中105位でした。
自分で解けた問題をWriteupとして書いておきます。

Free points! (Misc)

問題にフラグが書いてあった。

RITSEC{fr33_p0int5}

What's Discord? (Misc)

Discordに入ると、#announcementsチャネルのメッセージにフラグがあった。

RITSEC{its_like_irc-but_with_2_much_javascript}

Resume Bank! (Misc)

必須の項目を入力して、適当にPDFをアップロードして送信すると、フラグが表示された。

RITSEC{g3t_th3_r3sum3s}

Onion Layer Encoding (Misc)

何重にもbase64, base32, base16でエンコードしている。エンコードの種類を判定してデコードする。

import base64
import string

def get_info(s):
    alp = False
    for c in s:
        if c.islower():
            return 0
        if c not in string.hexdigits:
            alp = True
    if alp:
        return 1
    else:
        return 2

with open('onionlayerencoding.txt', 'r') as f:
    data = f.read()

while True:
    if data.startswith('RITSEC{'):
        break
    if get_info(data) == 0:
        data = base64.b64decode(data)
    elif get_info(data) == 1:
        data = base64.b32decode(data)
    else:
        data = base64.b16decode(data)

print data
RITSEC{0n1On_L4y3R}

WTF is this number? (Misc)

問題の暗号はこうなっている。

1111111111111111111111111111111111111111111111111111111111111111111111111111111111:1001001:10010:1010011:234:151:234:1100010:1221:115:47:311:74:6D:57:1100101:5A:310:2E:100:27:4B:45:300:340:2G:11100:72:1M:3P:41

:区切りでフラグの1文字ずつをエンコードしている。フラグの先頭がRITSECになると推測していろいろ試していたら、最初のみ文字列の長さで、あとは何番目か(1から開始)でbaseを変更してエンコードしているとわかった。

素数の種類の積がbase
例)2番目:2進数
  6番目:2×3で、種類は2,3なので6進数
  12番目:2^2×3で、種類は2,3なので6進数
  24番目:2^3×3で、種類は2,3なので6進数

以上を元にデコードする。

from sympy import factorint

enc = '1111111111111111111111111111111111111111111111111111111111111111111111111111111111:1001001:10010:1010011:234:151:234:1100010:1221:115:47:311:74:6D:57:1100101:5A:310:2E:100:27:4B:45:300:340:2G:11100:72:1M:3P:41'
codes = enc.split(':')

powers = {}
for i in range(1, len(codes) + 1):
    f = factorint(i)
    primes = 1
    for k, v in f.iteritems():
        primes *= k
    powers[i] = primes

flag = ''
for i in range(len(codes)):
    if i == 0:
        code = len(codes[i])
    else:
        base = i + 1
        if base in powers:
            base = powers[base]
        code = int(codes[i], base)
    flag += chr(code)

print flag
RITSEC{b4s3s_aRe_r4d1cal_Dud3s}

misdirection (Web)

ブラウザで接続すると、リダイレクトしているのがわかる。リダイレクトするURLを追ってみる。

$ curl -s -I -L http://ctfchallenges.ritsec.club:5000/ | grep ^Location
Location: http://ctfchallenges.ritsec.club:5000/R
Location: http://ctfchallenges.ritsec.club:5000/S
Location: http://ctfchallenges.ritsec.club:5000/{
Location: http://ctfchallenges.ritsec.club:5000/4
Location: http://ctfchallenges.ritsec.club:5000/!
Location: http://ctfchallenges.ritsec.club:5000/w
Location: http://ctfchallenges.ritsec.club:5000/a
Location: http://ctfchallenges.ritsec.club:5000/y
Location: http://ctfchallenges.ritsec.club:5000/5
Location: http://ctfchallenges.ritsec.club:5000/_
Location: http://ctfchallenges.ritsec.club:5000/K
Location: http://ctfchallenges.ritsec.club:5000/e
Location: http://ctfchallenges.ritsec.club:5000/3
Location: http://ctfchallenges.ritsec.club:5000/p
Location: http://ctfchallenges.ritsec.club:5000/-
Location: http://ctfchallenges.ritsec.club:5000/m
Location: http://ctfchallenges.ritsec.club:5000/0
Location: http://ctfchallenges.ritsec.club:5000/v
Location: http://ctfchallenges.ritsec.club:5000/1
Location: http://ctfchallenges.ritsec.club:5000/n
Location: http://ctfchallenges.ritsec.club:5000/g
Location: http://ctfchallenges.ritsec.club:5000/}
Location: http://ctfchallenges.ritsec.club:5000/R
Location: http://ctfchallenges.ritsec.club:5000/S
Location: http://ctfchallenges.ritsec.club:5000/{
Location: http://ctfchallenges.ritsec.club:5000/4
Location: http://ctfchallenges.ritsec.club:5000/!
Location: http://ctfchallenges.ritsec.club:5000/w
Location: http://ctfchallenges.ritsec.club:5000/a
Location: http://ctfchallenges.ritsec.club:5000/y
Location: http://ctfchallenges.ritsec.club:5000/5
Location: http://ctfchallenges.ritsec.club:5000/_
Location: http://ctfchallenges.ritsec.club:5000/K
Location: http://ctfchallenges.ritsec.club:5000/e
Location: http://ctfchallenges.ritsec.club:5000/3
Location: http://ctfchallenges.ritsec.club:5000/p
Location: http://ctfchallenges.ritsec.club:5000/-
Location: http://ctfchallenges.ritsec.club:5000/m
Location: http://ctfchallenges.ritsec.club:5000/0
Location: http://ctfchallenges.ritsec.club:5000/v
Location: http://ctfchallenges.ritsec.club:5000/1
Location: http://ctfchallenges.ritsec.club:5000/n
Location: http://ctfchallenges.ritsec.club:5000/g
Location: http://ctfchallenges.ritsec.club:5000/}
Location: http://ctfchallenges.ritsec.club:5000/R
Location: http://ctfchallenges.ritsec.club:5000/S
Location: http://ctfchallenges.ritsec.club:5000/{
Location: http://ctfchallenges.ritsec.club:5000/4
Location: http://ctfchallenges.ritsec.club:5000/!
Location: http://ctfchallenges.ritsec.club:5000/w
Location: http://ctfchallenges.ritsec.club:5000/a

URLの末尾をつなげるとフラグになる。

RS{4!way5_Ke3p-m0v1ng}

Take it to the Cleaners (Forensics)

pngファイルが添付されている。EXIFを見てみる。

$ exiftool ritsec_logo2.png 
ExifTool Version Number         : 10.10
File Name                       : ritsec_logo2.png
Directory                       : .
File Size                       : 4.3 kB
File Modification Date/Time     : 2019:11:16 06:02:36+09:00
File Access Date/Time           : 2019:11:16 06:06:38+09:00
File Inode Change Date/Time     : 2019:11:16 06:02:36+09:00
File Permissions                : rwxrwxrwx
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 328
Image Height                    : 154
Bit Depth                       : 8
Color Type                      : Palette
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Palette                         : (Binary data 129 bytes, use -b option to extract)
Exif Byte Order                 : Big-endian (Motorola, MM)
Image Description               : Hi there! Looks like youre trying to solve the forensic_fails challenge! Good luck!
Resolution Unit                 : inches
Artist                          : Impos73r
Y Cb Cr Positioning             : Centered
Copyright                       : RITSEC 2018
Exif Version                    : 0231
Components Configuration        : Y, Cb, Cr, -
User Comment                    : RVZHRlJQe1NCRVJBRlZQRl9TTlZZRl9KQkFHX1VSWUNfTEJIX1VSRVJ9
Flashpix Version                : 0100
GPS Latitude Ref                : North
GPS Longitude Ref               : West
Image Size                      : 328x154
Megapixels                      : 0.051

User Commentにbase64文字列があるので、デコードしてみる。

$ echo RVZHRlJQe1NCRVJBRlZQRl9TTlZZRl9KQkFHX1VSWUNfTEJIX1VSRVJ9 | base64 -d
EVGFRP{SBERAFVPF_SNVYF_JBAG_URYC_LBH_URER}

さらにROT13デコードする。

$ echo RVZHRlJQe1NCRVJBRlZQRl9TTlZZRl9KQkFHX1VSWUNfTEJIX1VSRVJ9 | base64 -d | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
RITSEC{FORENSICS_FAILS_WONT_HELP_YOU_HERE}
RITSEC{FORENSICS_FAILS_WONT_HELP_YOU_HERE}

the_doge (Stego)

jpgファイルが添付されている。steghideでパスフレーズtreatを指定してみる。

$ steghide extract -sf the_doge.jpg 
Enter passphrase: 
wrote extracted data to "doge_ctf.txt".
$ cat doge_ctf.txt 
RITSEC{hAppY_l1L_doG3}
RITSEC{hAppY_l1L_doG3}

Shiny (Crypto)

黄金虫暗号。https://www.dcode.fr/gold-bug-poeで復号する。

POEWASTHEGOAT
RITSEC{poewasthegoat}