H4ckIT CTF 2016 Online Writeup

この大会は2016/9/24 3:00(JST)~2016/10/3 2:00(JST)に開催されました。
今回もチームで参戦。結果は3205点で1058チーム中48位でした。
自分で解けた問題をWriteupとして書いておきます。

Portugal - Interceptor (Crypt0 95)

3組のN,Cが与えられ、eは3。Hastad's broadcast attackで攻撃する。

#!/usr/bin/env python3
N1 = 770208589881542620069464504676753940863383387375206105769618980879024439269509554947844785478530186900134626128158103023729084548188699148790609927825292033592633940440572111772824335381678715673885064259498347
C1 = 258166178649724503599487742934802526287669691117141193813325965154020153722514921601647187648221919500612597559946901707669147251080002815987547531468665467566717005154808254718275802205355468913739057891997227
N2 = 106029085775257663206752546375038215862082305275547745288123714455124823687650121623933685907396184977471397594827179834728616028018749658416501123200018793097004318016219287128691152925005220998650615458757301
C2 = 82342298625679176036356883676775402119977430710726682485896193234656155980362739001985197966750770180888029807855818454089816725548543443170829318551678199285146042967925331334056196451472012024481821115035402
N3 = 982308372262755389818559610780064346354778261071556063666893379698883592369924570665565343844555904810263378627630061263713965527697379617881447335759744375543004650980257156437858044538492769168139674955430611
C3 = 22930648200320670438709812150490964905599922007583385162042233495430878700029124482085825428033535726942144974904739350649202042807155611342972937745074828452371571955451553963306102347454278380033279926425450

import functools
import itertools

def chinese_remainder(n, a):
    sum = 0
    prod = functools.reduce(lambda a, b: a*b, n)
    for n_i, a_i in zip(n, a):
        p = prod // n_i
        sum += a_i * mul_inv(p, n_i) * p
    return sum % prod
 
def mul_inv(a, b):
    b0 = b
    x0, x1 = 0, 1
    if b == 1: return 1
    while a > 1:
        q = a // b
        a, b = b, a%b
        x0, x1 = x1 - q * x0, x0
    if x1 < 0: x1 += b0
    return x1

def inv_pow(c, e):
    low = -1
    high = c+1
    while low + 1 < high:
        m = (low + high) // 2
        p = pow(m, e)
        if p < c:
            low = m
        else:
            high = m
    m = high
    assert pow(m, e) == c
    return m
 
N = [N1, N2, N3]
C = [C1, C2, C3]
e = len(N)
a = chinese_remainder(N, C)
for n, c in zip(N, C):
    assert a % n == c
m = inv_pow(a, e)
print(bytes.fromhex(hex(m)[2:]).decode())

実行すると、以下の通り復号される。
key=bff149a0b87f5b0e00d9dd364e9ddaa0

h4ck1t{bff149a0b87f5b0e00d9dd364e9ddaa0}

Senegal - Evil_Corps (Crypt0 115)

恐らく換字暗号。似ているアルファベットに変換してみる。

暗号 平文
+ T
θ O
Δ D
ӕ A
\ Y
ω W
Σ E
F
¦ I
ɲ N
λ L
Ͻ C
M
P
Ϧ H
9 G
ʁ R
τ J
β B
§ S
V
µ U
ϟ K
Q
X
ɀ Z

以下の文章になる。

TODAY WE FINALLY COMPLETED THE GREAT PLANTATION PROJECT
AND BELOW IS ENTITIES WE HAVE IN OUR POCKET FOR NOW
         :
WELL TAKE YOUR JUICY FLAG CRYPTOMANIAC
FLAGIS MASSONSAREEVERYWHERELOOKBEHINDYOU
WELL TAKE YOUR JUICY FLAG CRYPTOMANIAC
         :
OH YES MR HOLMES WE WERE ENGAGED AFTER THE FIRST WALK THAT WE TOOK HOSMERMR ANGELWAS A CASHIER IN AN OFFICE IN LEADENHALL STREETAND

WHAT OFFICE

33行目にフラグが書かれている。

h4ck1t{MASSONSAREEVERYWHERELOOKBEHINDYOU}

Brazil - p13c3 0f c4k3 (Foren$ics 100)

Docsディレクトリ配下にThumbs.dbがある。Thumbs Viewer (https://thumbsviewer.github.io/) でこのファイルを覗いてみる。
f:id:satou-y:20161006224249p:plain
この中にフラグが含まれているファイル名のものがある。

h4ck1t{75943a3ca2223076e997fe30e17597d4}

Argentina - r34n1m4710n (N3twork 100)

パケットNo.870周辺でFTPを行っているので、そのTCP Streamを見る。

220 (vsFTPd 3.0.3)
USER agent
331 Please specify the password.
PASS h4ck1t{i_G07_ur_f1l3s}
230 Login successful.
SYST
215 UNIX Type: L8
PWD
257 "/home/agent" is the current directory
TYPE I
200 Switching to Binary mode.
SIZE /home/agent
550 Could not get file size.
CWD /home/agent/
250 Directory successfully changed.
PASV
227 Entering Passive Mode (192,168,1,39,142,19).
LIST -l
150 Here comes the directory listing.
226 Directory send OK.
QUIT
221 Goodbye.

FTPのパスワードがフラグになっている。

h4ck1t{i_G07_ur_f1l3s}

Greenland - 7r0ubl3 (N3twork 200)

パケットNo.2023でFTPでsecret.zipをダウンロードしている。secret.zipをエクスポートし解凍してみると、secret.txtが入っていて、以下のように書いてある。
68 34 63 6b 31 74 7b 73 30 5f 33 34 73 59 5f 46 6c 34 67 5f 68 75 68 7d
ASCIIコードとして読み込み、文字にするコードを作成する。

with open('secret.txt', 'r') as f:
    codes = f.read()

codes = codes.split(' ')

flag = ''
for code in codes:
    flag += chr(int(code, 16))

print flag

実行するとフラグになる。

h4ck1t{s0_34sY_Fl4g_huh}

Paraguay - Hex0gator (PPC 250)

添付ファイルはzipファイル。解凍するとまたzipファイル。何回も圧縮されているらしい。そこで解凍・展開するコードを書く。

import shutil
import subprocess
import os

def unzip(filename):
    cmd = 'unzip %s' % filename
    subprocess.check_output( cmd.split(" ") )

def unrar(filename):
    cmd = 'unrar x %s' % filename
    subprocess.check_output( cmd.split(" ") )

def gunzip(filename):
    dstfilename = filename + '.gz'
    shutil.move(filename, dstfilename)
    cmd = 'gunzip %s' % dstfilename
    subprocess.check_output( cmd.split(" ") )
    cmd = 'tar xvf %s' % filename
    subprocess.check_output( cmd.split(" ") )

for i in range(100, 0, -1):
    srcfile = str(i)
    cmd = 'file %s' % srcfile
    ret = subprocess.check_output( cmd.split(" ") )
    print ret
    if 'Zip archive data' in ret:
        unzip(srcfile)
    elif 'RAR archive data' in ret:
        unrar(srcfile)
    elif 'gzip compressed data' in ret:
        gunzip(srcfile)
    dstfile = 'work_folder/%s' % str(i - 1)
    if i != 1:
        shutil.move(dstfile, '.')
    if i != 100:
        os.remove(srcfile)

実行すると、work_folderにflagファイルが入っている。
FLAG: 0W_MY_G0D_Y0U_M4D3_1T

h4ck1t{0W_MY_G0D_Y0U_M4D3_1T}

Honduras - Decode (Quiz 10)

2進数をASCIIコードして読み込むだけ。

codes = '01000010 01101001 01101110 01100001 01110010 01111001'

codes = codes.split(' ')

flag = 'h4ck1t{'
for code in codes:
    flag += chr(int(code, 2))
flag += '}'

print flag
h4ck1t{Binary}

Nicaragua - Decoding (Quiz 10)

Base64デコードする。
$ echo QkBTM19TMF9CQFMzXw== | base64 -d
B@S3_S0_B@S3_

h4ck1t{B@S3_S0_B@S3_}

Peru - Decode-2 (Quiz 10)

10進数をASCIIコードして読み込むだけ。

codes = '68 101 99 105 109 97 108'

codes = codes.split(' ')

flag = 'h4ck1t{'
for code in codes:
    flag += chr(int(code))
flag += '}'

print flag
h4ck1t{Decimal}

Bolivia - Name (Quiz 10)

最初のブラウザの開発者のファーストネームを答える問題。
Googleで「web browser inventor」を調べる。https://en.wikipedia.org/wiki/Web_browserに発明者「Tim Berners-Lee」が載っている。

h4ck1t{Tim}

Finland - American hacker (Quiz 10)

Pacific Bell, Nokia, IBM, Motorola networksをハッキングした有名なアメリカ人を答える問題。
Googleで「Pacific Bell, Nokia, IBM, Motorola networks American hacker」を調べる。http://www.complex.com/pop-culture/2015/02/the-most-dangerous-hackers-and-groups/kevin-mitnickに問題のハッカー「Kevin Mitnick」について書いてあった。

h4ck1t{Mitnick}

Czech Republic - Subnet (Quiz 10)

/9 ネットワークのサブネットマスクを答える問題。

h4ck1t{255.128.0.0}

Italy - First HackIT Ukraine (Quiz 10)

初めてHackIT Ukraineが行われた年を答える問題。
Googleで「HackIT Ukraine」を調べると、2015年までしか出てこない。

h4ck1t{2015}

Greece - Hosts (Quiz 10)

192.168.0.0/27のホストの数の最大値を答える問題。
2 ^ (32 - 27) - 2 = 30

h4ck1t{30}

Cote d'Ivoire - Internet (Quiz 10)

INTERnetの前は何だったかを答える問題。
Googleで「before INTERnet」を調べる。https://en.wikipedia.org/wiki/History_of_the_Internetに「ARPANET」と載っている。

h4ck1t{arpanet}

Madagascar - Decode-3 (Quiz 10)

暗号「Fhcre_frperg_grkg_ol_Pnrfne_Pvcure」の暗号の種類を答える問題。
http://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherでROT13の復号をすると、Super_secret_text_by_Caesar_Cipherとなる。

h4ck1t{Caesar}

Kyrgyzstan - Emails (Quiz 10)

メール転送に使われるプロトコルを答える問題。

h4ck1t{smtp}

Uzbekistan - Virus (Quiz 10)

自己増殖するウィルスを答える問題。

h4ck1t{worm}

Kazakhstan - Virus-2 (Quiz 10)

自分自身のコードを変えることができるウィルスを答える問題。
Googleで「virus changes own code」を調べると、「Polymorphic」という単語が出ている。

h4ck1t{polymorphic}

Bangladesh - Programming Language (Quiz 10)

次のプログラミング言語を答える問題。

--[+++++++<---->>-->+>+>+<<<<]
<.>++++[-<++++<++>>>->--<<]>>-.>--..>+.<<<.<<-.>>+>->>.+++[.<]<<++.

Brainfuck言語。念のため、Brainfuckオンラインツール https://sange.fi/esoteric/brainfuck/impl/interp/i.html で実行すると、「Hello World!」と表示された。間違いなくBrainfuck言語。

h4ck1t{brainfuck}

Costa Rica - OSI (Quiz 10)

OSIモデルの層の数を答える問題。

h4ck1t{7}

Guatemala - WPS (Quiz 10)

WPSをクラックするためにブルートフォースしなければならない組合せ数を答える問題。
Googleで「WPS ブルートフォース」を調べる。http://hoihoi-tec.seesaa.net/article/244500207.html に11000通りと書いてある。

h4ck1t{11000}

Venezuela - INTRUSHIELD (Quiz 10)

INTRUSHIELD IPS Rev. 1200/2600/4000のデフォルトパスワードを答える問題。
Googleで「default password INTRUSHIELD 1200/2600/4000」を調査する。https://community.spiceworks.com/how_to/1769-default-password-list?page=2にデフォルトパスワードが書いてある。

NAI	Intrushield IPS	1200/2600/4000	SSH + Web console	admin	admin123	Admin	By Nicolas Gregoire 
h4ck1t{admin123}

Colombia - Code name (Quiz 10)

CVE-2014-0160のコードネームを答える問題。
Googleで「CVE-2014-0160」を調べる。OpenSSL Heartbleed 脆弱性の話が出てくる。

h4ck1t{heartbleed}

Ecuador - Se@rch (Quiz 10)

インターネットの最初の検索エンジンを答える問題。
Googleで「first search engine in internet」を調べる。https://www.wordstream.com/articles/internet-search-engines-historyに「Archie」と載っている。

h4ck1t{archie}

Nigeria - B1ts (Quiz 10)

IPv6で使うビット数を答える問題。

h4ck1t{128}

Philippines - Virus-3 (Quiz 10)

最初のコンピュータウィルスの名前を答える問題。
Googleで「first computer virus」を調べる。https://en.wikipedia.org/wiki/Computer_virusに載っている。

h4ck1t{creeper}

Spain - Pe0pl3 (Quiz 10)

コンピュータでなく、人にハッキングするための攻撃タイプを答える問題。

h4ck1t{social engineering}

China - RTFspy($tego 150)

rtfファイルをテキストエディタで見て、4行目のデータをバイナリに起こす。

with open('test.rtf', 'r') as f:
    data = f.read()

data = data.split('\n')
b_data = data[3].strip()

codes = []
for i in range(0, len(b_data), 4):
    codes.append(int(b_data[i+2:i+4], 16))

bin = ''
for code in codes:
    bin += chr(code)

with open('rtf.bin', 'wb') as f:
    f.write(bin)

このバイナリを見ると、pngとzipが入っているように見える。0001~C90AをpngにC90B~をzipに保存する。保存したzipを解凍すると、flag.txtが入っていて、フラグが書いてあった。pngは関係なかったようだ。

h4ck1t{rtf_d0cs_4r3_awesome}

Algeria - Crypt0P1xels ($tego 250)

与えられたコードをもとに、画像のピクセルから情報を取り出す。

from PIL import Image

img = Image.open('encrypted.png').convert('RGB')

l, x, y = img.getpixel((0, 0))

FLAG = ''
for i in range(l):
    code, x, y = img.getpixel((x, y))
    FLAG += chr(code)

print FLAG

実行すると、1NF0RM$T10N_1$_N0T_$3CUR3_4NYM0R3 となる。

h4ck1t{1NF0RM$T10N_1$_N0T_$3CUR3_4NYM0R3}