読者です 読者をやめる 読者になる 読者になる

Hackcon Mini Writeup

CTF writeup

この大会は2017/2/11 23:30(JST)~2017/2/12 3:29(JST)に開催されました。
今回もチームで参戦。結果は400点で110チーム中19位でした。
自分で解けた問題はWelcome問題だけです。一応Writeupとして書いておきます。

Welcome (Misc 5)

Telegramにjoinしようとしたら、フラグが表示された。

d4rk{Welcome_to_HCN_mini}c0de

Codegate 2017 prequals Writeup

CTF writeup

この大会は2017/2/10 9:00(JST)~2017/2/11 9:00(JST)に開催されました。
今回もチームで参戦。結果は100点で300チーム中119位でした。
自分で解けた問題はWelcome問題だけです。一応Writeupとして書いておきます。

Mic Check (50)

問題にフラグ「FLAG{Welcome_to_codegate2017}」が書いてある。
ブラケットの中がsubmitするフラグ。

Welcome_to_codegate2017

AlexCTF Writeup

CTF writeup

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

CR1: Ultracoded (Cryotography 50)

ONE, ZEROのスペース区切りの文字列。0,1に置き換え、2進数のASCIIコードとして文字に変換する。さらにBase64文字列になるので、デコードする。

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

data = data.replace('\n', '').split(' ')

b_data = ''
for i in range(len(data)):
    if data[i] == 'ZERO':
        b_data += '0'
    else:
        b_data += '1'

b64_data = ''
for i in range(0, len(b_data), 8):
    code = int(b_data[i:i+8], 2)
    b64_data += chr(code)

print b64_data.decode('base64')

すると、モールス信号が出てきた。

.- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -

Onlineツールで復号する。

ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT

"O"を"_"に変換する。

ALEXCTFTH15_1S_5UP3R_5ECR3T_TXT

{ }を付ける。

ALEXCTF{TH15_1S_5UP3R_5ECR3T_TXT}

CR3: What is this encryption (Cryotography 150)

eが非常に大きいRSA暗号の復号問題。Wiener's Attackの一部を流用し、復号する。

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(c, d, n)
    return hex(pt)[2:-1].decode('hex')

p = 0xa6055ec186de51800ddd6fcbf0192384ff42d707a55f57af4fcfb0d1dc7bd97055e8275cd4b78ec63c5d592f567c66393a061324aa2e6a8d8fc2a910cbee1ed9
q = 0xfa0f9463ea0a93b929c099320d31c277e0b0dbc65b189ed76124f5a1218f5d91fd0102a4c8de11f28be5e4d0ae91ab319f4537e97ed74bc663e972a4a9119307
e = 0x6d1fdab4ce3217b3fc32c9ed480a31d067fd57d93a9ab52b472dc393ab7852fbcb11abbebfd6aaae8032db1316dc22d3f7c3d631e24df13ef23d3b381a1c3e04abcc745d402ee3a031ac2718fae63b240837b4f657f29ca4702da9af22a3a019d68904a969ddb01bcf941df70af042f4fae5cbeb9c2151b324f387e525094c41
c = 0x7fe1a4f743675d1987d25d38111fae0f78bbea6852cba5beda47db76d119a3efe24cb04b9449f53becd43b0b46e269826a983f832abb53b7a7e24a43ad15378344ed5c20f51e268186d24c76050c1e73647523bd5f91d9b6ad3e86bbf9126588b1dee21e6997372e36c3e74284734748891829665086e0dc523ed23c386bb520

plaintext = decrypt(p, q, e, c)
print plaintext
ALEXCTF{RS4_I5_E55ENT1AL_T0_D0_BY_H4ND}

CR4: Poor RSA (Cryotography 200)

公開鍵と暗号化データをBASE64エンコードしたファイルが与えられている。
flag.b64をBASE64デコードしたファイルをflag.encとする。
公開鍵の内容を見てみる。

$ openssl rsa -pubin -text < key.pub
Public-Key: (399 bit)
Modulus:
    52:a9:9e:24:9e:e7:cf:3c:0c:bf:96:3a:00:96:61:
    77:2b:c9:cd:f6:e1:e3:fb:fc:6e:44:a0:7a:5e:0f:
    89:44:57:a9:f8:1c:3a:e1:32:ac:56:83:d3:5b:28:
    ba:5c:32:42:43
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
ME0wDQYJKoZIhvcNAQEBBQADPAAwOQIyUqmeJJ7nzzwMv5Y6AJZhdyvJzfbh4/v8
bkSgel4PiURXqfgcOuEyrFaD01soulwyQkMCAwEAAQ==
-----END PUBLIC KEY-----

次のnの値をfactordbで素因数分解する。

n = 0x52a99e249ee7cf3c0cbf963a009661772bc9cdf6e1e3fbfc6e44a07a5e0f894457a9f81c3ae132ac5683d35b28ba5c324243
(= 833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019)

この結果は以下のp, qの値となる。

p = 863653476616376575308866344984576466644942572246900013156919
q = 965445304326998194798282228842484732438457170595999523426901

この結果から秘密鍵を作成する。

$ rsatool.py -f PEM -o key.pri -p 863653476616376575308866344984576466644942572246900013156919 -q 965445304326998194798282228842484732438457170595999523426901
Using (p, q) to initialise RSA instance

n =
52a99e249ee7cf3c0cbf963a009661772bc9cdf6e1e3fbfc6e44a07a5e0f894457a9f81c3ae132ac
5683d35b28ba5c324243

e = 65537 (0x10001)

d =
33ad09ca06f50f9e90b1acae71f390d6b92f1d6d3b6614ff871181c4df08da4c5f5012457a643094
05eaecd6341e43027931

p =
899683060c76b9c0de581a69e0ea9d91bed1071beb1d924a37

q =
99cde74aedee87adffdd684cbc478e759870b4f20692f65255

Saving PEM as key.pri

秘密鍵を使って、暗号データを復号する。

$ openssl rsautl -decrypt -inkey key.pri < flag.enc
ALEXCTF{SMALL_PRIMES_ARE_BAD}
ALEXCTF{SMALL_PRIMES_ARE_BAD}

SC1: Math bot (Scripting 100)

計算問題を解いていくだけ。

#!/usr/bin/env python
import socket
import re

pattern = 'Question  (.+) :\n(.+)'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('195.154.53.62', 1337))

for i in range(1000):
    data = s.recv(1024)
    print data
    m = re.search(pattern, data)
    formula = m.group(2)
    formula = formula.replace('=', '')
    ans = str(eval(formula)) + '\n'
    print ans
    s.sendall(ans)

data = s.recv(1024)
print data

500回正解すると、フラグが表示された。

ALEXCTF{1_4M_l33t_b0t}

SC2: Cutie cat (Scripting 150)

画像のステガノグラフィの問題。いろいろ試したみたが、なかなかうまくいかなかった。PythonのSteganographyライブラリを使ったら、簡単にフラグを抽出できた。

from steganography.steganography import Steganography

secret_text = Steganography.decode('cat_with_secrets.png')
print secret_text
ALEXCTF{CATS_HIDE_SECRETS_DONT_THEY}

TR1: Hello there (Trivia 10)

freenodeで#alexctfに入る。

    :
19:14 *topic : Alexandria University student held capture the flag event ctf.oddcoder.com ALEXCTF{W3_w15h_y0u_g00d_luck}
ALEXCTF{W3_w15h_y0u_g00d_luck}

TR3: CA (Trivia 20)

AlexctfのHTTPS証明書の発行CAを答える問題。
証明書の発行者を見る。
f:id:satou-y:20170214194426p:plain

letsencrypt

BITSCTF 2017 Writeup

CTF writeup

この大会は2017/2/4 20:30(JST)~2017/2/5 18:00(JST)に開催されました。
今回もチームで参戦。結果は570点で275チーム中8位でした。
自分で解けた問題をWriteupとして書いておきます。

BotBot (web 10)

http://botbot.bitsctf.bits-quark.org/robots.txtにアクセスしたら、次のような表示。

Useragent *
Disallow: /fl4g

http://botbot.bitsctf.bits-quark.org/fl4g/にアクセスしたら、フラグが表示された。

BITCTF{take_a_look_at_googles_robots_txt}

Banana Princess (crypto 20)

添付のPDFはそのまま開けない。バイナリを確認すると、先頭が%CQSになっており、他のアルファベットもROT13になっている。変換して、PDFファイルを復号する。

with open('MinionQuest.pdf', 'rb') as f:
    data = f.read()

output = ''
for i in range(len(data)):
    code1 = ord(data[i])
    if code1 >= 65 and code1 <= 90:
        code2 = code1 + 13
        if code2 > 90:
            code2 = code2 - 26
    elif code1 >= 97 and code1 <= 122:
        code2 = code1 + 13
        if code2 > 122:
            code2 = code2 - 26
    else:
        code2 = code1
    output += chr(code2)

with open('flag.pdf', 'wb') as f:
    f.write(output)

ファイルを開くと黒い塗りつぶし箇所がある。
f:id:satou-y:20170209203814p:plain
画像コピーで切り出すと、フラグが見える。
f:id:satou-y:20170209203847p:plain

BITSCTF{save_the_kid}

fanfie (crypto 20)

先頭がBITSCTF{に復号できると考え、そのBASE32コードを見てみる。

>>> import base64
>>> base64.b32encode('BITSCTF{')
'IJEVIU2DKRDHW==='

以下のように対応していそう。

M->I
Z->J
Y->E
V->V
I->U
W->2
L->D
G->K
B->R
7->H
C->W

5置きに一定のシフトをすると元のBASE32文字列になりそう。

import base64

b32_letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
enc = 'MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI'

def b32_shift(c):
    index = b32_letters.index(c)
    index = (index * 5 - 20) % 32
    return b32_letters[index]

b32_enc = ''
for i in range(len(enc)):
    b32_enc += b32_shift(enc[i])
b32_enc += '======'

flag = base64.b32decode(b32_enc)
print flag
BITSCTF{S2VyY2tob2Zm}

Enigma (crypto 30)

暗号文は"&"が間に入っているのが目立つ。"&"と" "(スペース)のASCIIコードのXORをXOR鍵として、全体にXORをかけてみる。

e = [
    'Dtorouenc&Vguugaoct+Mihpio&dcuenksr|r&dco&06&Atgb&Hitbch&shb&73&Atgb&Qcurch(&Hcnkch&Uoc&cu&ui`itr',
    '60<56*&Bgu&Qcrrct&our&ncsrc&mjgt(&Tcach&gk&Gdchb',
    'Gbpghec&Ontc&Cohncor&7&Atgb&Hitbch&shb&4&Atgb&Iurch',
    'Bct&Eibc&`?t&bch&Rga&our&DORER@}@iemc+Qsj`&@q&466{',
    'Dctoenrc&bct&dtorouench&Kgtohc?dctqgensha&oh&Ontct&Tcaoih(&Acnch&Uoc&shbcteipct',
    'Qot&pct`cnjch&Ritvcbiu(&Hst&4&?dtoa(&Uchbch&Uoc&boc&Joc`ctshach&ui`itr'
]

key = ord('&') ^ ord(' ')

for i in range(len(e)):
    d = ''
    for j in range(len(e[i])):
        d += chr(ord(e[i][j]) ^ key)
    print d

実行結果は以下の通りで、フラグが含まれている。

Britische Passagier-Konvoi beschmutzt bei 60 Grad Norden und 15 Grad Westen. Nehmen Sie es sofort
06:30, Das Wetter ist heute klar. Regen am Abend
Advance Ihre Einheit 1 Grad Norden und 2 Grad Osten
Der Code f9r den Tag ist BITCTF{Focke-Wulf Fw 200}
Berichte der britischen Marine9berwachung in Ihrer Region. Gehen Sie undercover
Wir verfehlen Torpedos. Nur 2 9brig. Senden Sie die Lieferungen sofort
BITCTF{Focke-Wulf Fw 200}

Beginner's luck (crypto 40)

24バイトずつXORで暗号化している。PNGヘッダから予想しても先頭16バイトのみ、あとは後ろ8バイトをファイル終端で確認し、鍵を求める。

with open('BITSCTFfullhd.png', 'rb') as f:
    data = f.read()

PNG_HEAD = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52]
PNG_END  = [0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]

data_head = data[:16]
data_end = data[-8:]

key_head = ''
for i in range(len(data_head)):
    key_head += chr(PNG_HEAD[i] ^ ord(data_head[i]))

end_head = ''
for i in range(len(data_head)):
    end_head += chr(ord(key_head[i]) ^ ord(data[-24+i]))

#print end_head

key_end = ''
for i in range(24 - len(data_head)):
    key_end += chr(ord(end_head[-1]) ^ ord(data_end[i]))

key = key_head + key_end

flag = ''
for i in range(len(data)):
    flag += chr(ord(data[i]) ^ ord(key[i%24]))

with open('fullhd.png', 'wb') as f:
    f.write(flag)

復号すると画像ファイルにフラグが書かれている。
f:id:satou-y:20170209204715p:plain

BITSCTF{p_en_gee}

Black Hole (for 10)

stringsコマンドで文字列を見てみると、Base64文字列らしきものがあった。それをデコードすると、フラグだった。

$ strings black_hole.jpg
          :
UQklUQ1RGe1M1IDAwMTQrODF9
     :
$ echo QklUQ1RGe1M1IDAwMTQrODF9 | base64 -d
BITCTF{S5 0014+81}
BITCTF{S5 0014+81}

Woodstock-1 (for 10)

TCP Streamで見ると、フラグが含まれていることがわかる。

BITSCTF{such_s3cure_much_w0w}

Insomni'hack teaser 2017 Writeup

CTF writeup

この大会は2017/1/21 18:00(JST)~2017/1/23 6:00(JST)に開催されました。
今回もチームで参戦。結果は450点で339チーム中51位でした。
自分で解けた問題をWriteupとして書いておきます。

cryptoquizz (Misc/Crypto 50pt)

暗号学者の誕生した年を答えていくクイズ。
いろんな問題パターンを辞書にして答えていくスクリプトにした。
辞書にないものは答えられず、完全に対応したスクリプトではない。

#!/usr/bin/env python
import socket
import re

birth = {
    'Serge Vaudenay': 1968,
    'Gilles Brassard': 1955,
    'Scott Vanstone': 1947,
    'Claude Shannon': 1916,
    'Shafi Goldwasser': 1958,
    'Paul Kocher': 1973,
    'Bart Preneel': 1963,
    'Taher Elgamal': 1955,
    'Nigel P. Smart': 1967,
    'David Chaum': 1955,
    'Alan Turing': 1912,
    'Kaisa Nyberg': 1948,
    'Silvio Micali': 1954,
    'Moni Naor': 1961,
    'Joan Daemen': 1965,
    'Daniel Bleichenbacher': 1964,
    'Paulo Barreto': 1965,
    'Neal Koblitz': 1948,
    'Michael O. Rabin': 1931,
    'Xuejia Lai': 1954,
    'Vincent Rijmen': 1970,
    'Paul van Oorschot': 1950,
    'Adi Shamir': 1952,
    'Arjen K. Lenstra': 1956,
    'Dan Boneh': 1969,
    'Amit Sahai': 1974,
    'Eli Biham': 1960,
    'Whitfield Diffie': 1944,
    'Ueli Maurer': 1960,
    'Mihir Bellare': 1962,
    'Horst Feistel': 1915,
    'Ralph Merkle': 1952,
    'Don Coppersmith': 1950,
    'Jacques Patarin': 1965,
    'Alex Biryukov': 1969,
    'Jim Massey': 1934,
    'David Naccache': 1967,
    'Jean-Jacques Quisquater': 1945,
    'Amos Fiat': 1956,
    'Yvo Desmedt': 1956,
    'Donald Davies': 1924,
    'Niels Ferguson': 1965,
    'Ron Rivest': 1947,
    'Rafail Ostrovsky': 1963,
    'Jacques Stern': 1949,
    'Wang Xiaoyun': 1966,
    'Phil Rogaway': 1962,
    'Ivan Damgard': 1956,
    'Shai Halevi': 1966,
    'Daniel J. Bernstein': 1971,
    'Mitsuru Matsui': 1961,
    'Ross Anderson': 1956,
    'Martin Hellman': 1945,
    'Yehuda Lindell': 1971,
    'Lars Knudsen': 1962,
    'Claus-Peter Schnorr': 1943,
    'Ronald Cramer': 1968,
    'Victor S. Miller': 1947,
    'Douglas Stinson': 1956,
    'Antoine Joux': 1967
}

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('quizz.teaser.insomnihack.ch', 1031))
data = s.recv(1024)
print data

pattern = 'What is the birth year of (.+) \?'
for i in range(10):
    data = s.recv(1024)
    print data
    m = re.search(pattern, data)
    if m is None:
        data = s.recv(1024)
        print data
        m = re.search(pattern, data)
    name = m.group(1)
    ans = str(birth[name])
    print ans
    s.sendall(ans + '\n')

8回答えると、フラグが表示された。

INS{GENUINE_CRYPTOGRAPHER_BUT_NOT_YET_A_PROVEN_SKILLED_ONE}

33C3 CTF Writeup

CTF writeup

この大会は2016/12/28 5:00(JST)~2016/12/30 5:00(JST)に開催されました。
今回もチームで参戦。結果は1275点で278チーム中39位でした。
自分で解けた問題をWriteupとして書いておきます。

exfil (forensics 100)

Pythonコードとpcapファイルが与えられている。
Pythonコードを見ると、データをBASE32エンコードして、パディング文字を消した後、ドメイン名の前に一定の長さごとに.(ドット)を入れているようだ。データを復元してみる。
同じデータは省略し、ヘッダ情報もあるので、それは含めないようにする。

from scapy.all import *
import base64

def decode_b32(s):
    s = s.upper()
    for i in range(10):
        try:
            return base64.b32decode(s)
        except:
            s += b'='
    raise ValueError('Invalid base32')

packets = rdpcap('dump.pcap')

data = ''
tmp_data1 = ''
tmp_data2 = ''
for p in packets:
    if p[IP].dst == '192.168.0.121':
        if p.haslayer(DNSRR):
            enc = p[DNSRR].rdata.rsplit('.', 3)
            dec = decode_b32(enc[0].replace('.', ''))[6:]
            if len(dec) != 0 and tmp_data1 != dec:
                tmp_data1 = dec
                data += tmp_data1
        if p.haslayer(DNSQR):
            enc = p[DNSQR].qname.rsplit('.', 3)
            dec = decode_b32(enc[0].replace('.', ''))[6:]
            if len(dec) != 0 and tmp_data2 != dec:
                tmp_data2 = dec
                data += tmp_data2

print data

実行結果は以下の通りで、PGPのkeyと暗号化データ(secret.docx.gpg)を入手できる。

id
uid=1001(fpetry) gid=1001(fpetry) groups=1001(fpetry)
ls -alih
total 36K
2624184 drwxr-xr-x 2 fpetry fpetry 4.0K Dec 17 13:30 .
2621441 drwxr-xr-x 5 root   root   4.0K Dec 17 13:06 ..
2631209 -rw------- 1 fpetry fpetry   42 Dec 17 13:07 .bash_history
2627663 -rw-r--r-- 1 fpetry fpetry  220 Dec 17 13:06 .bash_logout
2631208 -rw-r--r-- 1 fpetry fpetry 3.7K Dec 17 13:06 .bashrc
2631221 -rw------- 1 fpetry fpetry   33 Dec 17 13:24 .lesshst
2627664 -rw-r--r-- 1 fpetry fpetry  675 Dec 17 13:06 .profile
2631216 -rw-r--r-- 1 fpetry fpetry 4.0K Dec 17 13:17 secret.docx
2631218 -rw------- 1 fpetry fpetry  908 Dec 17 13:21 .viminfo
cat > key << EOF
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFhNxEIBCACokqjLjvpwnm/lCdKTnT/vFqnohml2xZo/WiMAr4h3CdTal4yf
CBbYeZYXI4S9RNVl3+5j2h2yCssQ5S4ydWV2oy550qqh7K41u78L4FcT4lwgdbhD
gHyRdiHpqZ15JIdHQBm1Tc4ZQNKiRmzgDZqroa/YfkGi7l35BDGId9VjwttZg6y4
4I4j0NwnSdkhx3je+YUhDRSXXw55jhLsCqEVUaBpl4T3y93QkbxSEupPOQZ2TBNJ
Hv454UDToUU9SwgkhARivA7dMV43RR21hyUdFAuRcVXzEZCS1nsF7nE9sgVGZ6fs
BXeU/oPF6o86TqgPkBKrwYk2XTA3pf1DgVyvABEBAAG0I29wZXJhdG9yIGZyb20g
aGVsbCA8dGVhbUBraXRjdGYuZGU+iQFOBBMBCAA4FiEE0Rl3XS1+y7q+DPr51DzA
YtDYFh8FAlhNxEICGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ1DzAYtDY
Fh/FoQgAj5df/QfWefsQrMkGEH38prNfPXRN8+G2gJbjYj2fliKvwqiOAiX7AtoQ
txlwU45eVCRwSq41uLBOhNiNDKlo62Rlz5d7ZCRd0hoewPpH+gMVrsUBym3WNy6k
kvHBelOWOTqDSEW/BWyhk+UTDnMb1M0LP/NpcDHbYvR/KQhaP2N1SRz9Ye05Xs/B
DRT+lzFnXstgXsPrOOXV1J4924IfbwGRamx0N4aDzEUqkN80PfwTjaCWdrz0Cgym
BYVZOpHKuoDS/IK6/jxo4Q5N+BlAkN+9a7VeofbSor4X5Whrcr1hkIfGZ2xFAGsq
wTxTZsO5Kxg6O3Q2X4J4Wv5sntaJGbkBDQRYTcRCAQgA1NCwlE21HcHZDBMrP5ww
0F3POpoNv9umqrEfZhijhZ6DemJI8x9bImQyQGpJmyzUrUNSD4Il6dLZ6izT8Qme
QAZ4jVs76qjm2NnK4a8Y8FbvbVhy3FF38rom4jUkq2kEGRD9MCBZU4v8EFFxdUHB
TO/+asPieFvOje8quYOGQvm8Pv2yESpW2qRqZSqtpW3ovtWCrwuhtqNE2MkaKfzR
sWJ59ZFGcj+8FnEEZpZ6ssCHC1cKy01w6yTUwiCz0uYhrBp694YI0Aj1L9haeB92
RtA3YsoQ/5WOtA2cDB4+E402okCQAQbx6nQphYLkqQRsk+G9JWdqjfUVRw9sQnbo
lQARAQABiQE2BBgBCAAgFiEE0Rl3XS1+y7q+DPr51DzAYtDYFh8FAlhNxEICGwwA
CgkQ1DzAYtDYFh/5wwf/Rkx/aRIO8gdGh9grecQ3RT0zUh4nuJD+IOryBp+Unf9h
8vuSDI1m1cFq3bBAiaZE3xq91dMG9jG3upMI4ZSzxtStD7k38BnFFausoAtO/2PN
CqghyAdZUixFDFdJh0/F1tVwAi435dNRdGYQfgOgwx9z11nexDS8V+VKYj3cQFrg
M5SIARGzI/G7vI53KLL6DeACUVG/ihjGfxZKaqgUKwlK8LUjzYQDH7foUyT3JcRY
VSBmYq2jEFoMoV8BJHYFDd1/0T/Q7p5sTNfnPmkuHShoL9xoWs3F1uZ7qAu62S/z
lv+fGfdzCZnubp254S3mLsyokuyZ7xjy/i0m2a5fVQ==
=XS5g
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PRIVATE KEY BLOCK-----

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
=+woj
-----END PGP PRIVATE KEY BLOCK-----
EOF
gpg --import key
gpg: directory `/home/fpetry/.gnupg' created
gpg: new configuration file `/home/fpetry/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/fpetry/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/home/fpetry/.gnupg/secring.gpg' created
gpg: keyring `/home/fpetry/.gnupg/pubring.gpg' created
gpg: /home/fpetry/.gnupg/trustdb.gpg: trustdb created
gpg: key D0D8161F: public key "operator from hell <team@kitctf.de>" imported
gpg: key D0D8161F: secret key imported
gpg: key D0D8161F: "operator from hell <team@kitctf.de>" not changed
gpg: Total number processed: 2
gpg:               imported: 1  (RSA: 1)
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
ls
key
secret.docx
gpg --encrypt --recipient team@kitctf.de --trust-model always secret.docx
ls -alih
total 56K
2624184 drwxr-xr-x 3 fpetry fpetry 4.0K Dec 17 13:31 .
2621441 drwxr-xr-x 5 root   root   4.0K Dec 17 13:06 ..
2631209 -rw------- 1 fpetry fpetry   42 Dec 17 13:07 .bash_history
2627663 -rw-r--r-- 1 fpetry fpetry  220 Dec 17 13:06 .bash_logout
2631208 -rw-r--r-- 1 fpetry fpetry 3.7K Dec 17 13:06 .bashrc
2631219 drwx------ 2 fpetry fpetry 4.0K Dec 17 13:31 .gnupg
2631217 -rw-rw-r-- 1 fpetry fpetry 5.2K Dec 17 13:31 key
2631221 -rw------- 1 fpetry fpetry   33 Dec 17 13:24 .lesshst
2627664 -rw-r--r-- 1 fpetry fpetry  675 Dec 17 13:06 .profile
2631216 -rw-r--r-- 1 fpetry fpetry 4.0K Dec 17 13:17 secret.docx
2631222 -rw-rw-r-- 1 fpetry fpetry 4.4K Dec 17 13:31 secret.docx.gpg
2631218 -rw------- 1 fpetry fpetry  908 Dec 17 13:21 .viminfo
echo -n START_OF_FILE ; cat secret.docx.gpg; echo END_OF_FILE
START_OF_FILE・L+ソ0「j ヤSクi_&€|e:翡リ・ZAリフ墸ア渥w蕣Nルマ・・榛・g・ム・,評x+3G・ヘfホ_・・・・f]・O派クリェゥ浣 Nヒ@ネN6>\85・€・zソ\€)ln:#[リノ+ヲ膾ユz・T.<Qトノ溝ハ靉骨越3#v" у}ユBI・崛瞹A晨E叡蒟ム}レ;ツJア: ハL橄!゙貧8P・阜2{ヲ芙4q圭ホヒペAナLェ5q僂・・リ・便QR・} ^zメ彧タa・・モ霻マ{レn>」e鼓・N・・>yH#ク禔&柄・・Eイb$ニrホ・]a・ラシF=・ワハHネ・ⅲ・領オ・糢G+Ox{:+ホォ脣・'ロ|6ツ・<ーヨ;ミ<ッ ±俔クWチmヒ菅B精ロユLメ€・fケ靈スl4・・フ贐%セH=_l・eゥf臨$,qウ,末6ォ袁alネ.l・エR!Zンハ杜
・`q4埖ォ寐5~l剰、ン性ゥ乗テ・・;I・ー
wキ㌣ム。・4~*9蝓ェ・・d・覿T	鞏・・{'・旡ッ凌ミ?ッヤヨ・ニィp}罍驕;l・印イ・2FB・(.dノ裂堙ヨl^o/ィヲaZ釚e営綿・ラv+合・%}・「Y2・~1ェ;ad?Mヲ€~*ォ&クDpコヒN
€」zメ壇3・姫 ・5Qァ場・ハヌロヨ祀Wリ徼畷8ト#垓・ラ簔・ンハ1好タ@TムN+チ・・Jヌzィ|Rナ*声゙uz=Nツ杆ユアヤ・ィ鐐.・lB	サ0魂q
・鑰モ鞭・DE」テカシMイィьソンイレ焔pMD5゚E・・
&・紺恟ユワゥモ√+・jサVcf6・ラ:=i△)ーD
Xキリ9kd*U惹・・禛谺p刺/%m\摧	レ/・r
ヨ€Pム hョ・Mリ5,:ス・
・アK・裃ヨオ后ヨクロ箇ーロДトXト・
3ン5ル)5ニZ5・ル+ォ/Y貉・・{゚Bユ弘hユ「漓x1鈹@・・櫪リYA<-Gツt⑬ミ-廩チD・rヨ@KVヤ?Sオ ヌ・Q}A` ヅi8・フッF」€・゙「膕V・ヲ"QЫFXl・イP糾5珖ヒ\㌻籵・x\鐘`・・ァン.{ZゥャMrゥ6・琴キャ・紙XタU.ミ飯nxラ㎡)||wォeメホZ・]蛎7椪ォ・チ」UaGリ踐Q・_〃罇?[チロスE|・[・T解チ竰ェ-Bヲnク>l・5ム'"`・・韓オT ~ム萬゙m舜!痲D・鎧琇ツツ0ネ.
ェィ・VHロxン・@ナサゥト偽。イ・UW%・耀カ6ホ6;ィ洗>uIz「キpxruL;rfラ^K(tAAd澑吹假佗涓ユソカウ・リ駻・#テp・ソ呱$#チ4E亙ォ.Yイー・スOケワ・昉・u践N醇エフ事オ栲DWニ紂qR當9ン・ホノ・&・gェ・αl趁$f<ャョゥヨ飯3
カv€ナ'癖唆カ某|溥・垣r・マ~・ヒx燈・晏$o械;抓ソ>ヘヒ沽Rョ~tソヒニQS・
キ\潼ヘ1壘{漸8_獷・嫖「ノg巛勍l・ム2ネHy・zリ?「ッャrh@[ス!・r・闃y・ネコテ<クタW驀jo=ワlフ/ZキW」SF|z^ワ窰3ケtエチ&狼%o 0,稍キ晝メ・繆к8Q€0,・)悽NR}yW氣タ溿マ・コヨ蓐%Iル+沼ヌ;MO)芸X8タRキd(ミ・セs謠J坙・モ4・ィ#(ク険ヨワ7$簓?迺サ[・+ネ[
ミ:|追歎慂 w}ウワ}SD・
ZCc_裸j・
R(カ筬ウ歳双ナ゙ワ`j・・提ヌ
/8・・ョオモC蹇m€:ツ褄rホ・レアリュ`・Zeユ|ー7フカ0メ﨎・gM・uフD5トオエ・綣シ_/エ鑵・撻mcXDムエ^1Tロ殕ク}ゥ*M「ュタオ猖ス・・/屏ムM&0'ヌ.ツホヒャF|DR6樞N・=I#{、ャpk膾3};ニ>楪・]ユコ睥X必鹿CA嵐Caツラh\K{hW・クロソ劦}oごA・
・r・ネ \ハホf」ヌチ/@D繝モ゚XチI・TロIr・qPルV;+ォI瀬7・%莅-浚・嫦・3嗄^ョ$コ・ヒ・ソッzゥ f浯・	・j@;]€筌劜縺」pェIョ:イョp絣キGi?・ュpミ\8]ヘ¬イ6躾紛4瓊蒡テ「ラリpヘ・ 黴指C$4ハ/y
ヒヨオ勺トsスJ9エ欧>,ヌLJbea廟ヘ4ルX<・#ハiォヒ'$L゙IT・ m・ケ・ルp8マカモキ芭ロ貝ホ・2g・,Mヤz・オ/|ユL?シSy・;=胤
gle-ス・Jハ<VHhスャソ又マム・・ケユミa~カ・・@pWuォ欧碼EH`スRfQqメm・z五ト・' ナホ「B?|・メIホQタ]愷→7ヨQリv?゚・zユO\Gホ・ヂ)・籘ロ佯胖ホユ・ヘモ薹・~oソ・-ヲル胛、=>U暿Hソ %F1?|#タPt訌・Klァホネヤ^eェ皇《q`・αワ檠xィ/,S枋オ*RyN$・
i扶Jjァdノヤ	-イY夘Q|ス$・ュチ&8t)ヨiヨyT酩婀ツW・Xト
サA・モ@=テW゙eM、嫻ェ・・;,・・・レ&・o垓dト,nッ$<・ル!・uk奪4s-3u<f・k}Tンワ	・|イェ・V冩ツヤ+ゥ・・z・w柵ョ・'0ル洲ル・ェキッ[ムS
ツt~hェ0閔VルB・ロ1aon・ムXラ|
 ンホn蛬-c儺|z^2gヨ゙渫jユ・・Yン<?K
Lナ汽・・Dm*cu<ー労ヤ@8ヌ・N蕗|リム クV!」ェ%ロ・ヒテ疎cZゲ。・ゥ盃ニ「ノウ・q元*イEv%q4弴セI「・ァソEk・+マ牝za(㊨・ノヘ硅H^ォaゥmレ飯乳琳oカ・鉐 A 」mT・
|t
f・タ・・ュCゥg鸞p>?・ハ7諸纏テ
磊P>.?マ・ハ(・uオェW(4ハュホ<<ナ抑・k籖JVZ)ュス茉bw
J}。`Xヲ・エ畢~ヘ-uァKワ嘔?・・セz,等ウR・6p」テH・'Tュ1・忞|攀・zア$煖・+G暈ル\冓ヒG章5・阿ノ
Y
c・ャ~Lヨ;[V}o芍9[8-・ハ・s夏/・赧・
;|此E福ナケ﨎6#M筋・﨨%ゥ]エc,ヲJm則・秩%。 レr{ーМ・
膵m・屏'q⑰サ・X・・ヨ	\志[。。 9、ワテホ莉・イk・・オJャb屬mt ホ\テ・鯣c-7・[}・*#・始#ォd尺:Lホ「・ー褝5曲゚ロネゾオマヤwf<!ニタt喪ヒg
G寇
;・・・モ・y'ヘ賰奚EサZエS鈍}艇臟・ラs、ヲYげイ#5・゚ヤu・ーゥワ#aハリ/USa-WミゥシwaGヤ
・0JeeXp陂・6ォXム\UqK	寵5鴇9ィ,壗ー隍	フ4Lオ)忿侖€3蝨	ネヌ傚ラ・貴7V・双・・・[`czJ	_・フ橸偃ウ%ネ辣 eンeヒ[%ッ竺由・fヤ・ト.・ォ|ワクh欝・a\ゥナク鷽ゥaヨ€]OLm、Eハソ嬌瑢ヌヘユP)!・=g87キL縮n゚1$R@5ⅥRJ瓶 ;x
Dエ/ チ・泗悌囑aメサ婉ソG$m鬯.2韓・恃-%・ヒDラ4Lチ・/カ茴wVid・34hw・・n:ウ・C)Xmyシャネ学€着・。・ルeK%*+FT&Kチッマ・}sァョス[?nサ5・・Wロ衍ヨ2ェm8V z]_Z9饑爭F轆鈴切膃ェ掀sリシミ攪23レJ5L・゙8b丶mト葦q・鋩}ソヤ浴ユ・n~7 ・	藁ゥェソⅥ・F3An蛻Pモ・榊トョ}オ8Zメsン淇.k」ョ冝vCI(漸・S€cOF[M黯モb'Sカ・'∂・ェニフ€ゥム1・゚・・シw芒9・|&Fセr+ニp梼・・
ュ&ミ&嚮$ャ魵FZウ・ ・・。ト+ヒT@)タWDSIノ昱・墜ホx'ノⅠ・b・#\ォモC#シ・窃ヨQ・Pユヘ6niSヨニ
|WDノZ教.Lニ肭SモヨエO@c
・qテY>O・甎ワフテ・]g・レフtL	*ヲJ啣RY_堆蜻・・ワレ・Bァサ8・#?メ)[・・・・勝Pヘqy・.1b レッR焉"ノvイ・タニンA#7Bァ・ウ團苔・ノ舘サ曵#ムェ]・P貿=。i~~N€ソ象卯・=壯qルP・ン
レsヲ-.=A6糴ク`秕.寸B捕ヤmメ・gセオ・」%ィ「オ9NニNm・?ッBタ肋lヒノgl{・゙拍カ&mムQホッA存Q・・・wヒhィttマ・?戉黥{ニヒ
レ娼匯[ユ^ラ・m!フ_lMA^D睇S譛?7\b臟	Vjウ::@。1d・シヨ"<0㌶%Ybo審ヌニ&ンイリbェ(.瑯O1<苹r奕ル8瞋ォEf踪スイ0ハ洫=END_OF_FILE
[?1;2c[?1;2c[?1;2c[?
/bin/bash: line 97: $'\E[?1': command not found
/bin/bash: line 97: $'2c\E[?1': command not found
/bin/bash: line 97: $'2c\E[?1': command not found
/bin/bash: line 97: $'2c\E[?': command not found
rm key
rm secret.docx.gpg
ls -alih
total 40K
2624184 drwxr-xr-x 3 fpetry fpetry 4.0K Dec 17 13:32 .
2621441 drwxr-xr-x 5 root   root   4.0K Dec 17 13:06 ..
2631209 -rw------- 1 fpetry fpetry   42 Dec 17 13:07 .bash_history
2627663 -rw-r--r-- 1 fpetry fpetry  220 Dec 17 13:06 .bash_logout
2631208 -rw-r--r-- 1 fpetry fpetry 3.7K Dec 17 13:06 .bashrc
2631219 drwx------ 2 fpetry fpetry 4.0K Dec 17 13:31 .gnupg
2631221 -rw------- 1 fpetry fpetry   33 Dec 17 13:24 .lesshst
2627664 -rw-r--r-- 1 fpetry fpetry  675 Dec 17 13:06 .profile
2631216 -rw-r--r-- 1 fpetry fpetry 4.0K Dec 17 13:17 secret.docx
2631218 -rw------- 1 fpetry fpetry  908 Dec 17 13:21 .viminfo
rm -rf .gnupg
ls -alih
total 36K
2624184 drwxr-xr-x 2 fpetry fpetry 4.0K Dec 17 13:32 .
2621441 drwxr-xr-x 5 root   root   4.0K Dec 17 13:06 ..
2631209 -rw------- 1 fpetry fpetry   42 Dec 17 13:07 .bash_history
2627663 -rw-r--r-- 1 fpetry fpetry  220 Dec 17 13:06 .bash_logout
2631208 -rw-r--r-- 1 fpetry fpetry 3.7K Dec 17 13:06 .bashrc
2631221 -rw------- 1 fpetry fpetry   33 Dec 17 13:24 .lesshst
2627664 -rw-r--r-- 1 fpetry fpetry  675 Dec 17 13:06 .profile
2631216 -rw-r--r-- 1 fpetry fpetry 4.0K Dec 17 13:17 secret.docx
2631218 -rw------- 1 fpetry fpetry  908 Dec 17 13:21 .viminfo
exit

keyをインポートし、暗号化データを復号する。

$ gpg --import key
gpg: ディレクトリ「/home/ctf/.gnupg」ができました
gpg: 新しい構成ファイル「/home/ctf/.gnupg/gpg.conf」ができました
gpg: *警告*: 「/home/ctf/.gnupg/gpg.conf」のオプションは起動している間、有効になりません
gpg: 鍵リング「/home/ctf/.gnupg/secring.gpg」ができました
gpg: 鍵リング「/home/ctf/.gnupg/pubring.gpg」ができました
gpg: /home/ctf/.gnupg/trustdb.gpg: 信用データベースができました
gpg: 鍵D0D8161F: 公開鍵"operator from hell <team@kitctf.de>"をインポートしました
gpg: 鍵D0D8161F: 秘密鍵をインポートしました
gpg: 鍵D0D8161F:"operator from hell <team@kitctf.de>"変更なし
gpg: 処理数の合計: 2
gpg:               インポート: 1  (RSA: 1)
gpg:              変更なし: 1
gpg:       秘密鍵の読み込み: 1
gpg:   秘密鍵のインポート: 1

$ gpg secret.docx.gpg
gpg: 2048-ビットRSA鍵, ID BF30A26A, 日付2016-12-11に暗号化されました
      "operator from hell <team@kitctf.de>"

secret.docxが復号でき、ファイルを開いてみるとフラグが書いてある。
f:id:satou-y:20170105224849p:plain

33C3_g00d_d1s3ct1on_sk1llz_h0mie

3DSCTF Writeup

CTF writeup

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

Hot Sun? (CRYPTO 100)

シーザー暗号。http://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipher
でROT14にして復号する。

3DS{th1s_r0t_1s_n0t_s0_H0t}

Results does not matter!!! (PROG 100)

演算の図が与えられているので、FLAGの値を求める。逆算すればよい。

0b10101111101(= 334453 ^ 0b1010001111100001000) :上側のXOR演算
0b10100111001(= 1337) :最終結果

上側のXOR演算とANDで最終結果になるものは次の値。

0b1?1?01110?1(*1)

0b00100111110(= 318) とXORして(*1)になるものは次の値。

0b1?0?00001?1(*2)

0b01000000000(0x200) とORして(*2)になるものは次の値。

0b1?0?00001?1

この条件を満たすもので最小値は次の値。

1029(=0b10000000101)

SHA256('1029')を計算する。

3DS{d9a5223b761c375d1263e6e57ebec42d3e0fe3f6f283488d2eb204fb6ff17ee5}

Excaliflag (STEGO 100)

pngファイルが与えられている。StegSolveで開いてみると、Blueのビットにフラグが隠れていた。
f:id:satou-y:20170103124143p:plain

3DS{Gr4b_Only_th1s_B1ts}

base3200 (MISC 100)

Base64エンコードを複数回行っていると思われる。例外が発生するまでデコードする。

import base64

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

i = 1
while True:
    print 'Try %d times' % i
    try:
        data = base64.b64decode(data)
    except:
        break
    i+= 1

print data
3DS{B453_64_L00p_50}

Crypt or Encode? (MISC 200)

いくつかの文字をこのシステムでエンコードして、そのデータをBase64デコードして比較してみる。

平文:0123456789
暗号文:YGJkZmhqbG5wcg==
暗号文のBase64デコードデータ:'`bdfhjlnpr'

平文:ABCDEFGHIJKLMNOPQRSTUVWXYZ
暗号文:goSGiIqMjpCSlJaYmpyeoKKkpqiqrK6wsrQ=
暗号文のBase64デコードデータ:
'\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4'

平文:abcdefghijklmnopqrstuvwxyz
暗号文:wsTGyMrMztDS1NbY2tze4OLk5ujq7O7w8vQ=
暗号文のBase64デコードデータ:
'\xc2\xc4\xc6\xc8\xca\xcc\xce\xd0\xd2\xd4\xd6\xd8\xda\xdc\xde\xe0\xe2\xe4\xe6\xe8\xea\xec\xee\xf0\xf2\xf4'

暗号文をBase64デコードして、ASCIIコードを半分にしたものを文字にしていけば復号できそう。

enc = 'Zoim9tRgkNy+iGBmvrLeqr6MaGLY+g=='

b64_plain = enc.decode('base64')

flag = ''
for i in range(len(b64_plain)):
    code = ord(b64_plain[i]) / 2
    flag += chr(code)

print flag
3DS{j0Hn_D03_YoU_F41l}

Different and Notorious Alignment (PROG 200)

最初に聞かれるタイプの数値はそのまま提示されたものと同じ数値を答えればよい。あとは文字の違う箇所の数を答えていく。

#!/usr/bin/env python
import socket
import re

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.175.35.248', 8001))

data = s.recv(2048)
print data
pattern1 = 'To receive the first pair type (.+):'
m = re.search(pattern1, data)
s.sendall(m.group(1) + '\n')

for i in range(1, 101):
    data = s.recv(1024)
    print data,
    pattern2 = 'Sample 01\: (.+) - Sample 02\: (.+)'
    m = re.search(pattern2, data)
    s1 = m.group(1)
    s2 = m.group(2)
    count = 0
    if len(s1) < len(s2):
        LEN = len(s1)
        DIFF = len(s2) - len(s1)
    else:
        LEN = len(s2)
        DIFF = len(s1) - len(s2)
    for i in range(LEN):
        if s1[i] != s2[i]:
            count += 1
    count += DIFF
    print count
    s.sendall(str(count) + '\n')

data = s.recv(256)
print data
3DS{Y0u_4ch13v3d_h4mm1ng_D1st4nc3}

We also have memes! (STEGO 300)

画像の中に文字データとしてフラグを隠している。そのロジックはスクリプトとして提示されている。スクリプトからpは0~5、offsetは1~h(=5000)-255の範囲であることまでわかったので、ブルートフォースでフラグが"3DS{"で始まるものを探す。

from PIL import Image

pre_flag = '3DS{'

def get_pixel(t, x1, y1):
    if t == 0:
        r, g, b = img.getpixel((x1, y1))
    elif t == 1: 
        r, b, g = img.getpixel((x1, y1))
    elif t == 2:
        g, r, b = img.getpixel((x1, y1))
    elif t == 3: 
        g, b, r = img.getpixel((x1, y1))
    elif t == 4:
        b, r, g = img.getpixel((x1, y1))
    elif t == 5: 
        b, g, r = img.getpixel((x1, y1))
    return r, g, b

img = Image.open('output.png').convert('RGB')
h, w = img.size

found = 0
for p in range(6):
    for offset in range(1, h - 255 + 1):
        LEN, x, y = get_pixel(0, 0, 0)
        flag = ''
        for i in range(LEN):
            r, g, b = get_pixel(p, x + offset, y + offset)
            if i < len(pre_flag):
                if chr(r) != pre_flag[i]:
                    break
            else:
               found = 1
            flag += chr(r)
            x = g
            y = b
        if found == 1:
            break
    if found == 1:
        break

print flag
3DS{w0w_aw3s0me_scr1pt}

Return of the Notorious Alignment (PROG 300)

部分文字列で共通する文字列の最大長を答える問題。

#!/usr/bin/env python
import socket
import re

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('209.190.1.131', 9002))

data = s.recv(2048)
print data
pattern1 = 'To receive the first pair type (.+):'
m = re.search(pattern1, data)
s.sendall(m.group(1) + '\n')

for i in range(1, 101):
    data = s.recv(2048)
    print data,
    pattern2 = 'Sample 01\: (.+) - Sample 02\: (.+)'
    m = re.search(pattern2, data)
    s1 = m.group(1)
    s2 = m.group(2)
    if len(s1) < len(s2):
        s_s = s1
        s_l = s2
    else:
        s_s = s2
        s_l = s1
    found = 0
    for l in range(len(s_s), 0, -1):
        for i in range(len(s_s) - l + 1):
            if s_s[i:i+l] in s_l:
                found = 1
                ans = l
                break
        if found == 1:
            break
    if found == 0:
        ans = 0
    print ans
    s.sendall(str(ans) + '\n')

data = s.recv(256)
print data
3DS{C0mp4ris0n_0f_substr1ngs_1s_c00l}

Fibonacci Calls (PROG 400)

何回関数が呼ばれるかを答える問題。回数はG(N) = G(N-1) + G(N-2) + 2、G(0) = 0、 G(1) = 0の漸化式になるので、それを使って最初に想定するNの範囲で計算結果をメモリ上に保存しておき、聞かれたときに取り出せるようにする。

#!/usr/bin/env python
import socket
import re

dic = {}
dic[0] = 0
dic[1] = 0
for i in range(2, 1000):
    dic[i] = dic[i-1] + dic[i-2] + 2

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('54.175.35.248', 8000))

data = s.recv(2048)
print data
pattern1 = 'To start the challenge inform the number (.+):'
m = re.search(pattern1, data)
s.sendall(m.group(1) + '\n')
data = s.recv(256)
print data

for i in range(1, 101):
    data = s.recv(256)
    print data,
    pattern2 = 'Stage (.+) -> N = (.+)\n'
    m = re.search(pattern2, data)
    count = int(str(dic[int(m.group(2))])[-3:])
    print count
    s.sendall(str(count) + '\n')
    data = s.recv(256)
    print data

data = s.recv(256)
print data
3DS{g00d4lgorithmsC4nSaveYourTime}