好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

SECCON 令和 CTF write-up

SECCON 令和 CTF に参加してみました。

f:id:kusuwada:20190501021048p:plain

なんと実質1問しか解けなかったのでwrite-up書くか悩んだのですが記念に載せておきます。

f:id:kusuwada:20190501021044p:plain

2時間しかないのでジョーク系の問題かと思っていたのですが、普通のCTFでした。結局Miscしか解かなかった…。

Crypto問題はなし、Webはexeファイル問題のみだったので諦め、ForensicはQRコード復元問題かと思った(が実際ちょっと違ったみたい)ので時間内は無理と判断し諦め、Pwn/Binaryは解けてる人が少なそうなので諦め、、、としていたら結局Miscしか残らなかったという。

参加人数は「フラグの例は?」を解いた人数が850人くらいでした。予想より多かったのか、アクセスが集中したようで、最初1時間くらいは繋がりにくかったみたい。その影響でか終了時間が1H延びてました。

[Misc] 零は?

nc zerois-o-reiwa.seccon.jp 23615

指定のホストに接続してみると

$ nc zerois-o-reiwa.seccon.jp 23615
[1/100]
0=78-?
?=78
[2/100]
0=84+96-?
?=180
[3/100]
0=?+59-83-65
?=
Timeout, bye.

どうやら100問でるみたい。
結構タイムアウト早いし、どんどん式が長くなっていきそうなので手動は無理っぽい。

汚いコードですが、ちょっとやってみて

  • 全部で100問っぽい
  • +, -, *演算子のみ出てきそう
  • 0割りのパターンが出てくる(この場合は解答を0にした)

考慮して組みました。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from pwn import *

host = 'zerois-o-reiwa.seccon.jp'
port = 23615

def calc(q):
    return eval(q)

# main
r = remote(host, port)
for i in range(101):
    print('------' + str(i) + '--------')
    question = r.recvline_contains(['0=', 'SECCON{']).decode()
    if 'SECCON{' in question:
        print(question)
        break
    print('question: ' + question)
    question = question[2:]

    # +,- 演算子と 数値・?・* 演算子のパートに分ける
    parts = []
    d = ''
    for c in question:
        if c == '+' or c == '-':
            if d != '':
                parts.append(d)
                d = ''
            parts.append(c)
        else:
            d += c
    parts.append(d)
    
    for i in range(len(parts)):
        # ? が含まれない部分の計算
        if '?' in parts[i]:
            if i==0:
                answer = -calc(''.join(parts[1:]))
            elif i>0 and parts[i-1]=='-':
                answer = calc(''.join(parts[:i-1] + parts[i+1:]))
            else:
                answer = -calc(''.join(parts[:i-1] + parts[i+1:]))
        # * 演算子が含まれる場合は、? 以外の演算をし、最後に割る
        if '*' in parts[i] and '?' in parts[i]:
            muls = parts[i].split('*')
            for m in muls:
                if m == '0':
                    answer = 0
                elif m != '?':
                    answer = answer // int(m)
    answer = str(answer)
    print('answer: ' + answer)
    r.sendline(answer.encode())

実行結果

------0--------
question: 0=?-59
answer: 59
------1--------
question: 0=85+79-?
answer: 164
------2--------
question: 0=61+?*62-3161
answer: 50

(略)

------97--------
question: 0=60-70*24+30*51-83+52+64*35-8+34-40*34-59*76+42+62*5-84-14*40+48+96-28*65-67*98+2+27-8*89+36-44*70+38-41*25*32-86+87*61-51+98+11-16*68-91*43+53+47*8-49+32-32*60-11+73*94+17-83*99*81-74+96*62+24-2*24-92+21-2*37+52+81-72*62+87-19*31-51+55*82-43+73*19+80*45-10*64+47-74-50+99*50*21+17-89*4+?
answer: 595488
------98--------
question: 0=68+97-84*41*57+90-7-32+25*90+87*24-9+96*40-29-28*78+97-62+3*84-47+89*86-52*66+49+41-75*93*23+92-94+93*60-98-82*43+82+65-39*48-38*8+26-18*74+17*19+53-69*73+82-31+24*57-71+82-42*39+59-34*5*58+71-58-30*86+62*42+54-9-54*71+32+89-36*5+47*0-93-76+53*54-98*63+74*50+7-51+81*19-31-?*0+78-48+82+364076
answer: 0
------99--------
question: 0=59*96+63-43-77+44*85*63+16-99-41+3*20-34+81*85-47*49+12*14-64+5-91*70+22+36*64-5+78-7*36*20+34-91*84+60-17*16-61+61*18-22+67-88+82*4+48*83-31*46+28-31+85*9-76+82*74-68*32-69+22+64*76-21*40+66-31*49+36-39-79*67+10-51+71*90+28-9*43-20*32+25+83*71-91+41*51-82+81-64*27*18-74+13-10*98+16-75+0*?-215736
answer: 0
------100--------
The flag is SECCON{REIWA_is_not_ZERO_IS}.

最後の方の問題は結構な長さの数式でした。