Trend Micro CTF Asia Pacific & Japan 2015 Online Qualifier Writeup

この大会は2015/9/26 13:00(JST)~2015/9/27 13:00(JST)に開催されました。
今回も個人で参戦。結果は2問しか解けず、300点でした。
順位は記録し忘れました。
こんなにできないとは全然ダメですね。もっと勉強しないと...です。
自分で解けた2問だけをWriteupとして書いておきます。

Analysis-others (100)

pdfファイルが与えられている。
PDFStreamDumperで見てみると、<xmpGImg:image>で囲まれた部分が怪しいと感じた。これを何とか読める形にしたい。いろいろ調べると添付ファイルありのメールをテキストで見ると、こういう感じになっている。
...ということで添付ファイルありのメールに添付ファイル部分を置き換えてみる。それから添付ファイルを見てみると、jpeg画像でフラグが書かれている。

TMCTF{There is always light behind the clouds.}

f:id:satou-y:20151010200758j:plain

Programming (200)

ひたすら四則演算の計算を解いていく問題。
pythonで自動で計算するようプログラムを書いてみたが、特にローマ数字が出てきたり、アルファベットの数字(hundredとか)で問題が出てきたときはプログラムに悩んだ。
それでもいろいろ試して、こんなコードで何とかフラグをゲットできた。コードはあまり綺麗ではないが...。

import socket

def r2a(roman):
    num = 0
    r_n = {
        'M': 1000,
        'D': 500,
        'C': 100,
        'L': 50,
        'X': 10,
        'V': 5,
        'I': 1
    }
    pre = 0
    for i in range(len(roman) - 1, -1, -1):
        c = roman[i]
        if not c in r_n:
            return roman
        n = r_n[c]
        if n >= pre:
            num += n
            pre = n
        else:
            num -= n
    return num

def e2a(eng):
    d_units = {'zero':0,'one':1,'two':2,'three':3,'four':4,'five':5,'six':6,'seven':7,'eight':8,'nine':9}
    d_teens = {'ten':10,'eleven':11,'twelve':12,'thirteen':13,'fourteen':14,'fifteen':15,
               'sixteen':16,'seventeen':17,'eighteen':18,'nineteen':19}
    tys = {'twenty':20,'thirty':30,'forty':40,'fifty':50,'sixty':60,'seventy':70,'eighty':80,'ninety':90}
    hdrd = {'hundred':100}
    thsd = {'billion':1000000000,'million':1000000,'thousand':1000}

    word = eng.split()
    num = len(word)
    calc = 0
    t_calc = 0
    h_calc = 0
    for j in range(0, num):
        if d_units.has_key(word[j]):
            if j < num - 1:
                if hdrd.has_key(word[j+1]):
                    h_calc = d_units.get(word[j], 0)
                else:
                    t_calc += d_units.get(word[j], 0)
            else:
                t_calc += d_units.get(word[j], 0)
        if d_teens.has_key(word[j]):
            t_calc += d_teens.get(word[j], 0)
        if tys.has_key(word[j]):
            t_calc += tys.get(word[j], 0)
        if hdrd.has_key(word[j]):
            t_calc += h_calc * hdrd.get(word[j], 0)
        if thsd.has_key(word[j]):
            calc += t_calc * thsd.get(word[j], 0)
            t_calc = 0
            h_calc = 0
    calc += t_calc

    return calc

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('ctfquest.trendmicro.co.jp', 51740))
for i in range(1, 10000):
	exp = s.recv(2048)
	print exp
	if exp.find('Congratulations!') > -1:
		break
	exp = exp.replace('=', '')
	exp = exp.replace(',', '')
	array = exp.split()
	fml = ""
	tmp = ""
	for num in range(0, len(array)):
		if array[num].islower():
			if tmp == "":
				tmp = array[num]
			else:
				tmp += " " + array[num]
		else:
			if tmp == "":
				if array[num] != "=":
					fml += str(r2a(array[num]))
			else:
				fml += str(e2a(tmp))
				if array[num] != "=":
					fml += str(r2a(array[num]))
				tmp = ""
	
	ans = str(eval(fml))
	print ans
	s.sendall(ans)
TMCTF{U D1D 17!}

後で少し調べたらromanというモジュールがあるらしく、ローマ数字とアラビア数字との変換が簡単にできるみたい。