34C3 CTF 参戦

この大会は2017/12/28 5:00(JST)~2017/12/30 5:00(JST)に開催されました。
今回もチームで参戦。結果は35点で187チーム中178位でした。
今回は自分が得点した問題は1問もありませんでした。
あまりにも難しすぎる!
暗号の一番簡単と思われる問題は該当するオンラインツールを見つけることができたにも関わらず、使い方やフラグに結び付くようなデータを探し出すことができず、フラグを見つけ出せませんでした。Writeupで勉強するしかないですね。

3DSCTF Writeup

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

How to submit a flag (TUTORIAL)

問題文にフラグが書かれている。

3DS{mY_F1rsT_fL4G}

Capo Di Tutti Capi (CRYPTO)

$ nc capoditutticapi01.3dsctf.org 8001

                +++     3DSCTF - Capo Di Tutti Capi     +++

 [+] One year after the death of the one of the most famous members of the
     mafia, the FBI found a notebook with a few weird annotations.
 
 [+] Trying to use the same strategy as the last time, all the FBI experts
     failed to translate the book. Look if you have some luck! 

 [+] Type start to read the first note: start
     Openning the book...

 [+] Page 1/10 [c, r, p]: [HGZBMEDSYKPVJCTQOLRWAUFIXN, 18, FQVKFMF SKDWBFMP DIVFE KFYJHKF FQVKFMF PDBJVHDEP]
     The answer is:

何をやっているかよくわからないので、何パターンか試してみる。

 [+] Page 1/10 [c, r, p]: [ZYVATFLKNDRUMEGJOHPIXBCQWS, 2, MLLH ZOCI KIRLJFX TEOXL, ACB MLLH ZOCI LJLGRLX TEOXLI]

 [+] Page 1/10 [c, r, p]: [SOJDTUEHZXVNQLKCRMGWABYPFI, 19, PRQVPUP ZVHATPUN HFQPE VPXLOVP PRQVPUP NHTLQOHEN]

 [+] Page 1/10 [c, r, p]: [TZPFCNDWBHYSXOGEJIURKAMLQV, 2, TJM CPE FD RYCH QYAHJMA XEJQYEB HJQ AJ FD IJQDRWMO FMA TJM CPEEJA FD IJQDRWMO QYAHJMA GJEDT]

 [+] Page 1/10 [c, r, p]: [WPZRYXAOLIJEMGHQUNDSBCVTKF, 4, TEL XLVT OLILNVL YJYMNVT TEL TCLYAELCDKV MV TCLYAELCZ]

 [+] Page 1/10 [c, r, p]: [CWKSLJGVEQHXAOYURIZFNPDBTM, 6, MOH VCTYFHTT NX MOH ZGXYG YT VCTYFHTT]

3個目のパラメータは換字式暗号の暗号文と推測して、quipqiupで復号してみる。

暗号:TJM CPE FD RYCH QYAHJMA XEJQYEB HJQ AJ FD IJQDRWMO FMA TJM CPEEJA FD IJQDRWMO QYAHJMA GJEDT
平文:YOU CAN BE RICH WITHOUT SNOWING HOW TO BE POWERFUL BUT YOU CANNOT BE POWERFUL WITHOUT MONEY

1個目のパラメータは換字テーブルのようだ。

平文:ABCDEFGHIJKLMNOPQRSTUVWXYZ
暗号:TZPFCNDWBHYSXOGEJIURKAMLQV

数値はシフト数のことかもしれない。

C: (C+2)E->C
H: (H+2)J->H
T: (Y+2)A->T

一致するので、推測通り!
変換テーブルに従い元に戻した後、数字分だけマイナス方向にシフトすれば復号できる。

import socket
import re
import string

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('capoditutticapi01.3dsctf.org', 8001))

data = s.recv(1024)
print data + 'start'
s.sendall('start\n')
data = s.recv(1024)
print data

for i in range(10):
    data = s.recv(1024)
    print data

    pattern = '\[c, r, p\]: \[(.+)]'
    m = re.search(pattern, data)
    elems = m.group(1).split(', ', 2)
    tbl = elems[0]
    shift = int(elems[1])
    enc = elems[2]

    ans = ''
    for i in range(len(enc)):
        if enc[i] in string.uppercase:
            idx = tbl.index(enc[i])
            ans += string.uppercase[(idx - shift) % 26]
        else:
            ans += enc[i]
    print ans
    s.sendall(ans + '\n')
    data = s.recv(1024)
    print data

実行結果は次の通り。

                +++     3DSCTF - Capo Di Tutti Capi     +++

 [+] One year after the death of the one of the most famous members of the
     mafia, the FBI found a notebook with a few weird annotations.
 
 [+] Trying to use the same strategy as the last time, all the FBI experts
     failed to translate the book. Look if you have some luck! 

 [+] Type start to read the first note: start
     Openning the book...


 [+] Page 1/10 [c, r, p]: [LHKJBMIQGEUXYNSOTRWPZDFCAV, 10, JRS IAHDN XSDACTK JA JRS VUJWSCJ FUC]
     The answer is: 
THE WORLD BELONGS TO THE PATIENT MAN
 [+] Correct!


 [+] Page 2/10 [c, r, p]: [TCMDJUQHYIZGWKVPFNLAEOBRSX, 2, OIQ DQEO UQHQPEQ MYMZPEO OIQ OAQMJIQAFBE ZE OAQMJIQAT]
     The answer is: 
THE BEST DEFENSE AGAINST THE TREACHEROUS IS TREACHERY
 [+] Correct!


 [+] Page 3/10 [c, r, p]: [YBZQMHGFRSOVWNTJUXDACPIEKL, 15, AWRGABA MGQUYABF QCRAZ GAHSEGA AWRGABA FQYSREQZF]
     The answer is: 
EXTREME PROBLEMS OFTEN REQUIRE EXTREME SOLUTIONS
 [+] Correct!


 [+] Page 4/10 [c, r, p]: [GMHBRAUPXKQVNTFEOWZDLJISCY, 3, BXIPL B CVAIWLM, JQBLZPO MWSL TOVXP]
     The answer is: 
AFTER A VICTORY, SHARPEN YOUR KNIFE
 [+] Correct!


 [+] Page 5/10 [c, r, p]: [APYRHGVONFKUSMECWLQXITDJZB, 15, IRV HXCLX NR VXJTY, WX VXCQM IRV UCV]
     The answer is: 
FOR PEACE TO REIGN, BE READY FOR WAR
 [+] Correct!


 [+] Page 6/10 [c, r, p]: [KRDTCVOHWLPAMNQUEFGBZIJXSY, 2, ILO TOZI SDK IE OUIOB EJB TJZPUOZZ PZ IE TO TEBU PUIE PI]
     The answer is: 
THE BEST WAY TO ENTER OUR BUSINESS IS TO BE BORN INTO IT
 [+] Correct!


 [+] Page 7/10 [c, r, p]: [MSKLAONWEQGYRIPDFUZXVBJTCH, 11, AZD ROLXCDLL HF AZD TYFXY XL ROLXCDLL]
     The answer is: 
THE BUSINESS OF THE MAFIA IS BUSINESS
 [+] Correct!


 [+] Page 8/10 [c, r, p]: [XSCMNUPQKAYWZJOBFTRLVHGIDE, 18, IPA QGRVG WP AGXDU, LG AGRHF IPA ORA]
     The answer is: 
FOR PEACE TO REIGN, BE READY FOR WAR
 [+] Correct!


 [+] Page 9/10 [c, r, p]: [DAORHQVZCUMIYSLXNGPKFJEBTW, 26, UFRVHP, IDETHGP DSR XLICKCOCDSP ZDJH D ICOHSPH KL PKHDI EH RLSK SHHR LSH]
     The answer is: 
JUDGES, LAWYERS AND POLITICIANS HAVE A LICENSE TO STEAL WE DONT NEED ONE
 [+] Correct!


 [+] Page 10/10 [c, r, p]: [FHQXZWOEDKYABNSLMIVTUPJRGC, 14, LVEEVW BQDW VHVFJVO QKVWVOEJFSEV BQDW OEDXJIJEB EPSH BQDW OPWVYIHVOO]
     The answer is: 
BETTER YOUR ENEMIES OVERESTIMATE YOUR STUPIDITY THAN YOUR SHREWDNESS
 [+] Correct!

 [+] Cool, the flag is: 3DS{k33p_y0Ur_fr13nDs_cl0S3_AND_y0uR_fL4Gs_cLOs3R}
3DS{k33p_y0Ur_fr13nDs_cl0S3_AND_y0uR_fL4Gs_cLOs3R}

Xesar (CRYPTO)

Base64デコードしたデータをファイルに保存する。
https://wiremask.eu/tools/xor-cracker/でXOR鍵のあたりをつけ、調整したXOR鍵で復号する。

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

cipher = data.decode('base64')

key = 'MOIIIGKEMK'

plain = ''
for i in range(len(cipher)):
    plain += chr(ord(cipher[i]) ^ ord(key[i%len(key)]))

print plain

復号結果は次の通り。

LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPISCING ELIT. MAURIS MATTIS RISUS EU SUSCIPIT CONSEQUAT. DONEC CONGUE DAPIBUS IPSUM, A IMPERDIET EST RUTRUM ID. DONEC NON IPSUM EGET ORCI VIVERRA PORTA. SED SAGITTIS IPSUM NEC LACUS SUSCIPIT CONVALLIS. NULLA IMPERDIET NISI UT DICTUM SUSCIPIT. DUIS AC SAGITTIS LOREM. PELLENTESQUE HABITANT MORBI TRISTIQUE SENECTUS ET NETUS ET MALESUADA FAMES AC TURPIS EGESTAS. PROIN BLANDIT NEQUE QUIS MAURIS MAXIMUS, VEL PRETIUM NISI PORTA. INTEGER NEC SUSCIPIT URNA.FUSCE IN PHARETRA LACUS. FUSCE FEUGIAT AC IPSUM ET MOLESTIE. SUSPENDISSE NEC ENIM A MASSA ACCUMSAN BLANDIT. SUSPENDISSE CONVALLIS ORCI SIT AMET IPSUM CONSEQUAT, VEL ALIQUAM ENIM FEUGIAT. INTEGER SED CONDIMENTUM DOLOR, VITAE CURSUS NULLA. VIVAMUS EGET NUNC A MI PLACERAT IMPERDIET. NULLAM EST JUSTO, ALIQUET RHONCUS ORCI SODALES, PULVINAR VEHICULA DOLOR. VIVAMUS RHONCUS DIGNISSIM ARCU EU PHARETRA. SUSPENDISSE ET DOLOR ODIO. CURABITUR IMPERDIET LECTUS SIT AMET LACINIA VEHICULA. FUSCE DIAM NISI, GRAVIDA ET SEMPER SED, ELEIFEND UT MI.MAURIS SODALES PURUS EFFICITUR NISL CURSUS, AT TEMPOR PURUS PULVINAR. INTEGER ULTRICIES, IPSUM NEC LUCTUS CONSEQUAT, MAURIS EX TEMPUS MASSA, NON MALESUADA LIGULA TORTOR UT MASSA. SUSPENDISSE VEHICULA NEQUE VITAE LECTUS CONSEQUAT, QUIS CONGUE ANTE VOLUTPAT. INTEGER SEMPER RUTRUM MAGNA, SIT AMET TRISTIQUE MAGNA. ALIQUAM ERAT VOLUTPAT. IN NON SOLLICITUDIN MI. MAECENAS VEHICULA AUGUE PURUS, A TINCIDUNT DOLOR FAUCIBUS SIT AMET. NULLAM BLANDIT EFFICITUR SAPIEN IN LAOREET. CRAS VOLUTPAT NEQUE MAGNA, VOLUTPAT CONSEQUAT LOREM FERMENTUM EU. ETIAM ET LUCTUS METUS. NULLA AT METUS TELLUS. PELLENTESQUE RISUS IPSUM, PORTA SIT AMET POSUERE ID, PHARETRA NON RISUS. QUISQUE EGET EST VEHICULA, TINCIDUNT URNA AT, MOLESTIE MI. SED UT SEM ALIQUAM, TINCIDUNT DIAM SED, PORTTITOR ORCI. SED QUIS BLANDIT SEM. MAECENAS EST PURUS, VOLUTPAT SIT AMET DUI EU, MATTIS AUCTOR ELIT.CRAS NEC PURUS SIT AMET URNA PLACERAT FEUGIAT. NULLAM DICTUM LIBERO ET ANTE GRAVIDA, LAOREET FACILISIS URNA EUISMOD. ETIAM ET QUAM AC NIBH ACCUMSAN MOLESTIE. VIVAMUS MOLESTIE EST QUIS SCELERISQUE IACULIS. IN VEL ERAT NEQUE. NULLAM SAGITTIS NEC TELLUS ET PLACERAT. MAURIS MOLESTIE SAPIEN SIT AMET SAPIEN PLACERAT, EGET VEHICULA NULLA DICTUM. NAM PURUS LECTUS, TRISTIQUE NEC BLANDIT SED, VEHICULA VITAE NULLA. ALIQUAM ERAT VOLUTPAT. QUISQUE DICTUM ELEMENTUM FELIS FEUGIAT TEMPUS. INTEGER ACCUMSAN RISUS EGET MAXIMUS EUISMOD. PELLENTESQUE HABITANT MORBI TRISTIQUE SENECTUS ET NETUS ET MALESUADA FAMES AC TURPIS EGESTAS. VIVAMUS BLANDIT, NISL ID CURSUS MOLESTIE, VELIT PURUS MATTIS LIGULA, SIT AMET ELEMENTUM AUGUE NISL VEL TORTOR. PROIN QUIS ULTRICES NISL. CURABITUR SEMPER NULLA NON ERAT PLACERAT, AT RUTRUM TELLUS PELLENTESQUE. AENEAN PELLENTESQUE ULLAMCORPER TELLUS, SOLLICITUDIN PORTTITOR LACUS CONDIMENTUM EU.UT NEC DUI MOLLIS EX VIVERRA CONVALLIS. SUSPENDISSE IN ANTE NON DIAM ULLAMCORPER VARIUS EU AC ODIO. DONEC ORCI VELIT, LUCTUS AC LECTUS QUIS, BIBENDUM ALIQUET DOLOR. AENEAN QUAM TURPIS, PLACERAT SED ALIQUAM NON, PLACERAT QUIS LIGULA. MAURIS AC ANTE PORTTITOR LEO TINCIDUNT POSUERE. VESTIBULUM MOLLIS ID NULLA EGET TRISTIQUE. MAECENAS VIVERRA LACUS AUCTOR LIGULA POSUERE, EU SUSCIPIT EX HENDRERIT.ETIAM EFFICITUR VESTIBULUM DOLOR, NON PORTTITOR LECTUS PHARETRA VEL. MAURIS PHARETRA ELEIFEND SCELERISQUE. PELLENTESQUE PORTA SEM LEO, NEC TEMPOR URNA SEMPER SED. SED DOLOR EX, PRETIUM VEL ENIM SED. THE FLAG IS 3DS{1_H4V3_50M3_CR1P70_5K1LL5}

最後にフラグが書いてある。

3DS{1_H4V3_50M3_CR1P70_5K1LL5}

Escape from Arkham I (CRYPTO)

the_joker.keyを内容をBase64をデコードする。空白行を詰めると、以下のようになる。

HA HA HA HA HA HA HA HA HA HA HA HA HA HA HA
WHAT A JOKE!
You thought that it would be so easy?
You ain't no Batsy!!!! He's a true detective! You are just... hmmm... alive, and I don't know why...
Really, really funny....
In fact, let's play a game since this is all a big joke.... 
The master key was ciphered using aes-256-cbc on OpenSSL 1.1.0g 2 Nov 2017
Enjoy your tail chasing, because when Batsy arrives, I'll not be here!!
HA HA HA HA HA HA HA HA HA HA HA HA HA HA HA

master.keyはAESで暗号されているようだ。ファイルの先頭にSalted__の文字列があるのでSaltも付けたAES暗号のようだ。
問題に書かれている16進数をデコードする。

>>> '5368616d6972'.decode('hex')
'Shamir'

Shamirの秘密分散法の問題であることを示していると推測できる。
https://github.com/jqueiroz/python-sslibのライブラリを使って分散された秘密情報を取得する。

#!/usr/bin/env python3
from sslib import shamir

DIR = 'arkham\\'
key_files = ['bane.key', 'dr_hugo_strange.key', 'harley_queen.key',
    'hush.key', 'killer_croc.key', 'poison_ivy.key', 'scarecrow.key',
    'the_penguin.key', 'the_riddler.key', 'two_face.key']

def read_key_file(fname):
    with open(fname, 'r') as f:
        data = f.read()
    data = data.replace('(', '')
    data = data.replace(')', '')
    data = data.split(', ')
    return data[0], int(data[1]), int(data[2])

shares = []
for i in range(10):
    idx, data, n = read_key_file(DIR + key_files[i])
    h_data = '%x' % (data % n)
    if len(h_data) % 2 != 0:
        h_data = '0' + h_data
    shares.append(idx + '-' + h_data)

s_data = {'required_shares': 4}
s_data['prime_mod'] = '%x' % n
s_data['shares'] = shares

dec = shamir.recover_secret(shamir.from_hex(s_data)).decode('ascii')
print(dec)

この結果、hy_so_crypto?_ha_ha_ha_ha という文字列が取れた。これでmaster.keyを復号してみる。

$ openssl enc -d -aes-256-cbc -salt -pass pass:hy_so_crypto?_ha_ha_ha_ha -in master.key -out decrypted
bad decrypt
140081836168864:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539:

うまくいかない。hy_so_crypto?_ha_ha_ha_haの hy って何だろうと思い、改めてthe_joker.keyのデコード結果を見る。whyのwが削れてしまったのかもしれない。パスワードにwを付けて再度復号してみる。

$ openssl enc -d -aes-256-cbc -salt -pass pass:why_so_crypto?_ha_ha_ha_ha -in master.key -out decrypted

復号に成功した!

$ file decrypted
decrypted: PNG image data, 300 x 30, 8-bit/color RGBA, non-interlaced
$ mv decrypted flag.png

f:id:satou-y:20171231111832p:plain
復号したPNGファイルを見るとフラグが書かれていた。

3DS{Sh4m1r_S4b3_S3p4r4r_S3gr3d0s}

InCTF Writeup

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

Sanity Check (Misc 1)

freenodeで#bi0s-ctfに入る。

    :
21:12 *topic : Welcome to InCTF, https://ctf.inctf.in/ | Flag for Sanity check inctf{w3lc0me_t0_inctf}
inctf{w3lc0me_t0_inctf}

Multi Layer RSA (Crypto 100)

encryption_keyの各要素の乗算結果をeと考えれば、RSA暗号になる。eが非常に大きい値になるので、Wiener Attackで復号する。

from fractions import Fraction

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')

def continued_fractions(n,e):
    cf = [0]
    while e != 0:
        cf.append(int(n/e))
        N = n
        n = e
        e = N%e
    return cf

def calcKD(cf):
    kd = list()
    for i in range(1,len(cf)+1):
        tmp = Fraction(0)
        for j in cf[1:i][::-1]:
            tmp = 1/(tmp+j)
        kd.append((tmp.numerator,tmp.denominator))
    return kd

def int_sqrt(n):
    def f(prev):
        while True:
            m = (prev + n/prev)/2
            if m >= prev:
                return prev
            prev = m
    return f(n)

def calcPQ(a,b):
    if a*a < 4*b or a < 0:
        return None
    c = int_sqrt(a*a-4*b)
    p = (a + c) /2
    q = (a - c) /2
    if p + q == a and p * q == b:
        return (p,q)
    else:
        return None

def wiener(n,e):
    kd = calcKD(continued_fractions(n,e))
    for (k,d) in kd:
        if k == 0:
            continue
        if (e*d-1) % k != 0:
            continue
        phin = (e*d-1) / k
        if phin >= n:
            continue
        ans = calcPQ(n-phin+1,n)
        if ans is None:
            continue
        return (ans[0],ans[1])

with open('ciphertext.txt', 'r') as f:
    c = int(f.read(), 16)

with open('modulus.txt', 'r') as f:
    n = int(f.read().split(' = ')[1])

encryption_keys = [34961, 3617491, 68962801, 293200159531, 1191694878666066510321450623792489136756229172407332230462797663298426983932272792657383336660801913848162204216417540955677965706955404313949733712340714861638106185597684745174398501025724130404133569866642454996521744281284226124355987843894614599718553178595963014434904833]

e = 1
for i in encryption_keys:
    e *= i

p, q = wiener(n, e)

flag = decrypt(p, q, e, c)
print flag
inctf{w13n3r's_4774ck_s0lv3d_17_4ll_r1gh7?}

RSA 1s fun (Crypto 150)

eの値が互いに素になっていなく、最大公約数が3になっていることから、以下のように考える。

c1 = pow(flag, 3*3, n)
c2 = pow(flag, 3*41, n)

ここで平文をflag**3と考え、Common Modulus Attackを行う。復号した値の3乗根を取れば、最終的には復号できる。

import gmpy

def commom_modules_attack(c1, c2, e1, e2, n):
    gcd, s1, s2 = gmpy.gcdext(e1, e2)
    if s1 < 0:
        s1 = -s1
        c1 = gmpy.invert(c1, n)
    elif s2 < 0:
        s2 = -s2
        c2 = gmpy.invert(c2, n)
 
    v = pow(c1, s1, n)
    w = pow(c2, s2, n)
    x = (v * w) % n
    return x

with open('ciphertext.txt', 'r') as f:
    lines = f.readlines()

with open('modulus.txt', 'r') as f:
    n = int(f.read().split(' = ')[1])

c1 = int(lines[0].strip().split(':  ')[1])
c2 = int(lines[1].strip().split(':  ')[1])
e1 = 9 / 3
e2 = 123 / 3

m = commom_modules_attack(c1, c2, e1, e2, n)
m = gmpy.root(m, 3)[0]
flag = ('%x' % m).decode('hex')
print flag
inctf{n07_s0_e4sy_70_expl01t_7h1s_RSA_orIsIt?}

Crafted RSA (Crypto 200)

p, qそれぞれの素数の生成の範囲が決まっていることから、近い数値であると推測し、Fermat法で素因数分解し、復号する。

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

with open('ciphertext.txt', 'r') as f:
    c = int(f.read(), 16)

with open('modulus.txt', 'r') as f:
    n = int(f.read().split(':  ')[1])

e = 2**16 + 1

p, q = fermat(n)

phi = (p - 1) * (q - 1)

x = 0
while True:
    if (phi * x + 1) % e == 0:
        d = (phi * x + 1) / e
        break
    x = x + 1

m = pow(c, d, n)

flag = ('%x' % m).decode('hex')
print flag
inctf{1_7h0ugh7_17_c4n_0nly_b3_s0lv3d_by_F3rm4t's_F4ct0r1s4710n}

WhiteHat Grand Prix 2017 Writeup

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

Bonus (Misc 1)

slackで#whitehat_anouncementチャネルに入ると、フラグのお知らせがあった。

WhiteHat{bc0b6353ab20df0fb7bc7a89e57cdc3ace54cb1f}

Welcome (Misc 10)

動画を見てると最後の方で16進表記で記載されている文字列がある。
f:id:satou-y:20171224211517p:plain

>>> '5768697465'.decode('hex')
'White'
>>> '486174'.decode('hex')
'Hat'
>>> '7b57656c636f6d65'.decode('hex')
'{Welcome'
>>> '5f746f5f477261'.decode('hex')
'_to_Gra'
>>> '6e645f507269787d'.decode('hex')
'nd_Prix}'

結合すると、WhiteHat{Welcome_to_Grand_Prix} となる。

$ echo -n Welcome_to_Grand_Prix | sha1sum
e75e376bd57142ab77e1c47e0dc9470627deb68d  -
WhiteHat{e75e376bd57142ab77e1c47e0dc9470627deb68d}

Secure_token (Crypto 100)

以下のように暗号化される。

入力:メッセージ文字列の16進表記
msg = {"a": メッセージ文字列, "flag": keyのmd5}
cipher = msgのAES暗号の16進表記

平文は「{"a": 」という形式であると考え、ブロック暗号であることを利用してパディング文字数を調整しながら、先頭からフラグを探り当てる。以下のようなことを繰り返すイメージ。

{"a": "########<FLAG>
{"a": "########<FLAG1文字目をBFで回す>

{"a": "#######<FLAG>
{"a": "#######F<FLAG2文字目をBFで回す>

  :
import socket
import string

header = '{"a": "'
def query(s, text, cont):
    data = s.recv(1024)
    data = s.recv(1024)
    send_data = text.encode('hex')
    s.sendall(send_data + '\n')
    data = s.recv(1024)
    recv_data = data[12:].strip().decode('hex')
    data = s.recv(1024)
    s.sendall(cont + '\n')
    return recv_data

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('secure-token.grandprix.whitehatvn.com', 3333))

flag = ''
while True:
    padding = '#' * ((- len(header + flag) - 1) % 16)
    size = len(header + padding + flag) + 1
    correct = query(s, padding, 'y')[0:size]
    for c in string.printable:
        try_str = query(s, padding + flag + c, 'y')[0:size]
        if try_str == correct:
            flag += c
            print c,
            break

    if flag[-1:] == '}':
        query(s, 'fin', 'n')[0:size]
        break

print ''
print flag

実行結果は次の通りとなる。

" ,   " f l a g " :   " c 7 3 6 6 4 5 6 8 e 1 7 c d 0 e 3 d 5 b 0 8 4 d a 0 7 c 3 f 5 f " }
", "flag": "c73664568e17cd0e3d5b084da07c3f5f"}
$ echo -n c73664568e17cd0e3d5b084da07c3f5f | sha1sum
328fe20bc7c47d8a11c3c8810c0a9985e6262332  -
WhiteHat{328fe20bc7c47d8a11c3c8810c0a9985e6262332}

0x00ctf-2017 Writeup

この大会は2017/12/16 2:30(JST)~2017/12/17 2:30(JST)に開催されました。
今回もチームで参戦。結果は320点で196チーム中11位でした。
自分で解けた問題をWriteupとして書いておきます。
・・参加賞の問題だけですが。

Turing Test (Intro 20)

http://irc.0x00sec.orgから channel: #0x00ctf に入る。

05:29:29ⓘ 0x00ctf 2017 | Sign up now! | flag: 0x00CTF{im_not_a_bot}
0x00CTF{im_not_a_bot}

SECCON 2017 Online CTF Writeup

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

Vigenere3d (Crypto 100)

問題はこうなっている。

----- Vigenere3d.py
import sys
def _l(idx, s):
    return s[idx:] + s[:idx]
def main(p, k1, k2):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
    t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
    i1 = 0
    i2 = 0
    c = ""
    for a in p:
        c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
        i1 = (i1 + 1) % len(k1)
        i2 = (i2 + 1) % len(k2)
    return c
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
-----
$ python Vigenere3d.py SECCON{**************************} **************
POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9

2次元の変換文字列のため、キーは1通りとは限らないが、正しいもののうち1つ選択できれば、復号できる。先頭7文字の平文がSECCON{になることからキー14文字全てを求めることができる。キーを見つけたら、ブルートフォースで求めるのが早そうなので、そのようなコードで復号できる。

enc = 'POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9'
dec1 = 'SECCON{'
dec2 = '}'

def _l(idx, s):
    return s[idx:] + s[:idx]

def encrypt(a, k1, k2, index):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
    t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
    return t[s.find(a)][s.find(k1[index%len(k1)])][s.find(k2[index%len(k2)])]

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]

key1 = ''
key2 = ''
for i in range(len(dec1)):
    index1 = s.find(dec1[i])
    found = False
    for j in range(len(s)):
        for k in range(len(s)):
            if t[index1][j][k] == enc[i]:
                key1 += s[j]
                key2 += s[k]
                found = True
                break
        if found:
            break

key = key1 + key2[::-1]

flag = ''
for i in range(34):
    for j in range(len(s)):
        if encrypt(s[j], key, key[::-1], i) == enc[i]:
            flag += s[j]
            break

print flag
SECCON{Welc0me_to_SECCON_CTF_2017}

Powerful_Shell (Binary 300)

ps1のコードが与えられているが、難読化されている。ps1のコードの主要部分のみデコードする。

import re

skip_ptn1 = '$ECCON="";'
skip_ptn2 = 'Write-Progress'
skip_ptn3 = '{"D`eb`u`g`g`in`g is `pr`o`h`ib`it`e`d";Exit}'
ptn1 = '\$ECCON\+\=\[char\]\((.+)\);'
ptn2 = '\$ECCON\+\=\[char\]\(\[int\]\[Math\]::sqrt\(\[Math\]::pow\((.+),2\)\)\);'

with open('powerful_shell.ps1', 'r') as f:
    lines = f.readlines()

codes = ''
for line in lines:
    line = line.strip()
    code = ''
    if line == skip_ptn1:
        pass
    elif line.startswith(skip_ptn2):
        pass
    elif skip_ptn3 in line:
        pass
    else:
        m = re.search(ptn2, line)
        if m is None:
            m = re.search(ptn1, line)
            code = chr(eval(m.group(1)))
        else:
            code = chr(eval(m.group(1)))
    codes += code

print codes

デコード結果は次のようになる。

$ErrorActionPreference = "ContinueSilently"

[console]::BackgroundColor = "black";[console]::ForegroundColor = "white";cls;Set-Alias -Name x -Value Write-Host;$host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size 95,25;$host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.Size 95,25;$host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size 95,25;$host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.Size 95,25;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 12 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 0 -n;x '  ' -b 15 -n;x;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x '  ' -b 15 -n;x;x;



<# Host Check #>

Write-Host -b 00 -f 15 Checking Host... Please wait... -n

Try{

	If ((Get-EventLog -LogName Security | Where EventID -Eq 4624).Length -Lt 1000) {

		Write-Host "This host is too fresh!"

		Exit

	}

}Catch{

	Write-Host "Failed: No admin rights!"

	Exit

}

Write-Host "Check passed"



$keytone=@{'a'=261.63}

$pk='a'

ForEach($k in ('w','s','e','d','f','t','g','y','h','u','j','k')){

	$keytone+=@{$k=$keytone[$pk]*[math]::pow(2,1/12)};$pk=$k	

}

Write-Host -b 00 -f 15 "Play the secret melody."



Write-Host -b 15 -f 00 -n '   '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '   |   '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 '   |    ' 

Write-Host -b 15 -f 00 -n '   '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '   |   '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n '   '

Write-Host -b 15 -f 00 '   |    ' 

Write-Host -b 15 -f 00 -n '   '

Write-Host -b 00 -f 15 -n ' w '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n ' e '

Write-Host -b 15 -f 00 -n '   |   '

Write-Host -b 00 -f 15 -n ' t '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n ' y '

Write-Host -b 15 -f 00 -n '  '

Write-Host -b 00 -f 15 -n ' u '

Write-Host -b 15 -f 00 '   |    ' 

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00  '    '

Write-Host -b 15 -f 00 -n '  a |'

Write-Host -b 15 -f 00 -n '  s |'

Write-Host -b 15 -f 00 -n '  d |'

Write-Host -b 15 -f 00 -n '  f |'

Write-Host -b 15 -f 00 -n '  g |'

Write-Host -b 15 -f 00 -n '  h |'

Write-Host -b 15 -f 00 -n '  j |'

Write-Host -b 15 -f 00  '  k '

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00 -n '    |'

Write-Host -b 15 -f 00  '    '

Write-Host

$stage1=@();$f="";

While($stage1.length -lt 14){

	$key=(Get-Host).ui.RawUI.ReadKey("NoEcho,IncludeKeyDown")

	$k=[String]$key.Character

	$f+=$k;

	If($keytone.Contains($k)){

		$stage1+=[math]::floor($keytone[$k])

		[console]::beep($keytone[$k],500)

	}

}

$secret=@(440,440,493,440,440,493,440,493,523,493,440,493,440,349)

If($secret.length -eq $stage1.length){

	For ($i=1; $i -le $secret.length; $i++) {

		If($secret[$i] -ne $stage1[$i]){

			Exit

		}

	}

	x "Correct. Move to the next stage."

}

$text=@"

YkwRUxVXQ05DQ1NOE1sVVU4TUxdTThBBFVdDTUwTURVTThMqFldDQUwdUxVRTBNEFVdAQUwRUxtT

TBEzFVdDQU8RUxdTbEwTNxVVQUNOEFEVUUwdQBVXQ0NOE1EWUUwRQRtVQ0FME1EVUU8RThdVTUNM

EVMVUUwRFxdVQUNCE1MXU2JOE0gWV0oxSk1KTEIoExdBSDBOE0MVO0NKTkAoERVDSTFKThNNFUwR

FBVINUFJTkAqExtBSjFKTBEoF08RVRdKO0NKTldKMUwRQBc1QUo7SlNgTBNRFVdJSEZCSkJAKBEV

QUgzSE8RQxdMHTMVSDVDSExCKxEVQ0o9SkwRQxVOE0IWSDVBSkJAKBEVQUgzThBXFTdDRExAKhMV

Q0oxTxEzFzVNSkxVSjNOE0EWN0NITE4oExdBSjFMEUUXNUNTbEwTURVVSExCKxEVQ0o9SkwRQxVO

EzEWSDVBSkJAKBEVQUgzThAxFTdDREwTURVKMUpOECoVThNPFUo3U0pOE0gWThNEFUITQBdDTBFK

F08RQBdMHRQVQUwTSBVOEEIVThNPFUNOE0oXTBFDF0wRQRtDTBFKFU4TQxZOExYVTUwTSBVMEUEX

TxFOF0NCE0oXTBNCFU4QQRVBTB1KFU4TThdMESsXQ04TRBVMEUMVThNXFk4TQRVNTBNIFUwRFBdP

EUEXQ0ITShdME0EVThBXFU4TWxVDThNKF0wRMBdMETUbQ0wRShVOE0MWThMqFU1ME0gVTBFDF08R

QxdMHUMVQUwTSBVOEEEVThNNFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNGF0wTKhVBTxFK

F0wdMxVOEzUXQ04QSBVOE0AVTBFVFUFMEUkXTBFDG0wTQRVMETMXQE4TSBVCE0MXTBNBFU4QQRVB

TB1KFU4TQxdMEVYXTBEUG0NMEUoVThNBFk4TQRVCEygXQ0wRShdPEUMXTB1DFU4TQBdDThBIFU4T

SBVMESgVQUwRSRdMEUYbTBMWFUNOE0gWThNCFUITFBdDTBFKF08RQxdMHUMVThNVF0NOEEgVThNN

FUwRQxVOE0IWQUwRShtME0EVTBFVF08RQxdDQhNKF0wTQRVOEEEVThM9FUNOE0oXTBFFF0wRKBtD

TBFKFU4TQRZOE0EVQhNAF0NMEUoXTxFDF0wdVRVOEzMXQ04QSBVOE00VTBFVFU4TQRZBTBFKG0wT

RBVMESgXQE4TSBVCE0MXTBNBFU4QKhVBTB1KFU4TFBdMEUIXQ04TRBVMEUMVThNBFk4TNxVNTBNI

FUwRQxdPEUMXTB01FUFME0gVThBBFU4TTRVMERQVQUwRSRdMEUMbTBNBFUwRQxdAThNIFUITQxdM

E0EVThAxFUFMHUoVThNDF0wRVhdMEVUbQ0wRShVOE0QWThMWFU1ME0gVTBFDF08RRhdDQhNKF0wT

QRVOEFcVQUwdShVOE0EXTBFFF0NOE0QVTBFDFU4TVxZOEyoVTUwTSBVMETMXTxFVF0NCE0oXTBNE

FU4QQhVBTB1KFU4TQBdMERcXQ04TRBVMEUAVThNDFkFMEUobTBNCFUwRQRdAThNIFUITQRdMExYV

QU8RShdMHUEVThNOF0NOEEgVThNIFUwRKBVBTBFJF0wRMxtMEzcVQ04TSBZOE0EVQhNVF0wTQRVB

TxFKF0wdQxVOE0MXTBFFF0NOE0QVTBFGFU4TKhZBTBFKG0wTRBVMERQXQE4TSBVCE04XTBNXFUFP

EUoXTB0zFU4TThdDThBIFU4TTRVMEUMVThMWFkFMEUobTBNCFUwRFBdAThNIFUITQxdME0EVThAx

FUFMHUoVThNGF0wRQxdDThNEFUwRQRVOEyoWQUwRShtMEzcVTBFDF0BOE0gVQhMzF0wTFhVBTxFK

F0wdMxVOExQXQ04QSBVOE0gVTBEUFUFMEUkXTBEzG0wTQRVDThNIFk4TQRVCEygXTBNEFUFPEUoX

TB1DFU4TRhdDThBIFU4TTRVMEVUVQUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdM

HTMVQUwTSBVOEEEVThNbFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwd

ShVOEzMXTBE2F0NOE0QVTBFBFU4TKhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsV

Q04TShdMEUAXTBFDG0wTQhVDThNIFk4TRBVCEygXQ0wRShdPEUYXTB0UFUFME0gVThBDFU4TTRVD

ThNKF0wRQBdMEUMbTBNBFUNOE0gWThNBFUITQxdME0EVQU8RShdMHUMVThNVF0wRVhdDThNEFUwR

RhVOEyoWQUwRShtME0MVTBEzF0BOE0gVQhNDF0wTQRVOEEEVQUwdShVOExQXTBFNF0NOE0QVTBFG

FU4TRBZBTBFKG0wTRBVMERQXQE4TSBVCEzUXTBMWFUFPEUoXTB1DFU4TRhdDThBIFU4TTRVMEVUV

QUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdMHTMVQUwTSBVOEEEVThNbFUwRNRVB

TBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwdShVOEzMXTBE2F0NOE0QVTBFBFU4T

KhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsVQ04TShdMEUAXTBFDG0wTQhVDThNI

Fk4TRBVCEygXQ0wRShdPEUYXTB0zFUFME0gVThBMFU4TSBVDThNKF0wRQxdMERQbQ0wRShVOE0IW

ThNDFU1ME0gVTBFAF08RQRdDQhNKF0wTQxVOEBYVQUwdShVOE0EXTBFNF0NOE0QVTBFDFU4TKhZO

E0QVTUwTSBVMEUYXTxFAF0NCE0oXTBNCFU4QFhVBTB1KFU4TQBdMEUIXQ04TRBVMEUAVThNDFkFM

EUobTBNDFUwRFBdAThNIFUITQRdME0wVQU8RShdMHUMVThMoF0wRNhdDThNEFUwRRhVOEzEWQUwR

ShtME0EVTBFGF0BOE0gVQhNDF0wTVxVBTxFKF0wdQxVOEygXTBE2FxROE10VShZOTBFTF2E=

"@



$plain=@()

$byteString = [System.Convert]::FromBase64String($text)

$xordData = $(for ($i = 0; $i -lt $byteString.length; ) {

	for ($j = 0; $j -lt $f.length; $j++) {

		$plain+=$byteString[$i] -bxor $f[$j]

		$i++

		if ($i -ge $byteString.Length) {

			$j = $f.length

		}

	}

})

iex([System.Text.Encoding]::ASCII.GetString($plain))

変数の値を標準出力させながら、まず$fの値を確認する。途中、ピアノの画面でキーに対応するstage1の値はそれぞれ以下のようになっていることがわかる。

a 261
w 277
s 293
e 311
d 329
f 349
t 370
g 392
y 415
h 440
u 466
j 493
k 523

つまりsecretの値から文字列がわかり、hhjhhjhjkjhjhf が$fの値であることがわかる。そのあと、Base64文字列をデコードしたものと$fのXORをとる。

b64 = '''
YkwRUxVXQ05DQ1NOE1sVVU4TUxdTThBBFVdDTUwTURVTThMqFldDQUwdUxVRTBNEFVdAQUwRUxtT
TBEzFVdDQU8RUxdTbEwTNxVVQUNOEFEVUUwdQBVXQ0NOE1EWUUwRQRtVQ0FME1EVUU8RThdVTUNM
EVMVUUwRFxdVQUNCE1MXU2JOE0gWV0oxSk1KTEIoExdBSDBOE0MVO0NKTkAoERVDSTFKThNNFUwR
FBVINUFJTkAqExtBSjFKTBEoF08RVRdKO0NKTldKMUwRQBc1QUo7SlNgTBNRFVdJSEZCSkJAKBEV
QUgzSE8RQxdMHTMVSDVDSExCKxEVQ0o9SkwRQxVOE0IWSDVBSkJAKBEVQUgzThBXFTdDRExAKhMV
Q0oxTxEzFzVNSkxVSjNOE0EWN0NITE4oExdBSjFMEUUXNUNTbEwTURVVSExCKxEVQ0o9SkwRQxVO
EzEWSDVBSkJAKBEVQUgzThAxFTdDREwTURVKMUpOECoVThNPFUo3U0pOE0gWThNEFUITQBdDTBFK
F08RQBdMHRQVQUwTSBVOEEIVThNPFUNOE0oXTBFDF0wRQRtDTBFKFU4TQxZOExYVTUwTSBVMEUEX
TxFOF0NCE0oXTBNCFU4QQRVBTB1KFU4TThdMESsXQ04TRBVMEUMVThNXFk4TQRVNTBNIFUwRFBdP
EUEXQ0ITShdME0EVThBXFU4TWxVDThNKF0wRMBdMETUbQ0wRShVOE0MWThMqFU1ME0gVTBFDF08R
QxdMHUMVQUwTSBVOEEEVThNNFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNGF0wTKhVBTxFK
F0wdMxVOEzUXQ04QSBVOE0AVTBFVFUFMEUkXTBFDG0wTQRVMETMXQE4TSBVCE0MXTBNBFU4QQRVB
TB1KFU4TQxdMEVYXTBEUG0NMEUoVThNBFk4TQRVCEygXQ0wRShdPEUMXTB1DFU4TQBdDThBIFU4T
SBVMESgVQUwRSRdMEUYbTBMWFUNOE0gWThNCFUITFBdDTBFKF08RQxdMHUMVThNVF0NOEEgVThNN
FUwRQxVOE0IWQUwRShtME0EVTBFVF08RQxdDQhNKF0wTQRVOEEEVThM9FUNOE0oXTBFFF0wRKBtD
TBFKFU4TQRZOE0EVQhNAF0NMEUoXTxFDF0wdVRVOEzMXQ04QSBVOE00VTBFVFU4TQRZBTBFKG0wT
RBVMESgXQE4TSBVCE0MXTBNBFU4QKhVBTB1KFU4TFBdMEUIXQ04TRBVMEUMVThNBFk4TNxVNTBNI
FUwRQxdPEUMXTB01FUFME0gVThBBFU4TTRVMERQVQUwRSRdMEUMbTBNBFUwRQxdAThNIFUITQxdM
E0EVThAxFUFMHUoVThNDF0wRVhdMEVUbQ0wRShVOE0QWThMWFU1ME0gVTBFDF08RRhdDQhNKF0wT
QRVOEFcVQUwdShVOE0EXTBFFF0NOE0QVTBFDFU4TVxZOEyoVTUwTSBVMETMXTxFVF0NCE0oXTBNE
FU4QQhVBTB1KFU4TQBdMERcXQ04TRBVMEUAVThNDFkFMEUobTBNCFUwRQRdAThNIFUITQRdMExYV
QU8RShdMHUEVThNOF0NOEEgVThNIFUwRKBVBTBFJF0wRMxtMEzcVQ04TSBZOE0EVQhNVF0wTQRVB
TxFKF0wdQxVOE0MXTBFFF0NOE0QVTBFGFU4TKhZBTBFKG0wTRBVMERQXQE4TSBVCE04XTBNXFUFP
EUoXTB0zFU4TThdDThBIFU4TTRVMEUMVThMWFkFMEUobTBNCFUwRFBdAThNIFUITQxdME0EVThAx
FUFMHUoVThNGF0wRQxdDThNEFUwRQRVOEyoWQUwRShtMEzcVTBFDF0BOE0gVQhMzF0wTFhVBTxFK
F0wdMxVOExQXQ04QSBVOE0gVTBEUFUFMEUkXTBEzG0wTQRVDThNIFk4TQRVCEygXTBNEFUFPEUoX
TB1DFU4TRhdDThBIFU4TTRVMEVUVQUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdM
HTMVQUwTSBVOEEEVThNbFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwd
ShVOEzMXTBE2F0NOE0QVTBFBFU4TKhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsV
Q04TShdMEUAXTBFDG0wTQhVDThNIFk4TRBVCEygXQ0wRShdPEUYXTB0UFUFME0gVThBDFU4TTRVD
ThNKF0wRQBdMEUMbTBNBFUNOE0gWThNBFUITQxdME0EVQU8RShdMHUMVThNVF0wRVhdDThNEFUwR
RhVOEyoWQUwRShtME0MVTBEzF0BOE0gVQhNDF0wTQRVOEEEVQUwdShVOExQXTBFNF0NOE0QVTBFG
FU4TRBZBTBFKG0wTRBVMERQXQE4TSBVCEzUXTBMWFUFPEUoXTB1DFU4TRhdDThBIFU4TTRVMEVUV
QUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdMHTMVQUwTSBVOEEEVThNbFUwRNRVB
TBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwdShVOEzMXTBE2F0NOE0QVTBFBFU4T
KhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsVQ04TShdMEUAXTBFDG0wTQhVDThNI
Fk4TRBVCEygXQ0wRShdPEUYXTB0zFUFME0gVThBMFU4TSBVDThNKF0wRQxdMERQbQ0wRShVOE0IW
ThNDFU1ME0gVTBFAF08RQRdDQhNKF0wTQxVOEBYVQUwdShVOE0EXTBFNF0NOE0QVTBFDFU4TKhZO
E0QVTUwTSBVMEUYXTxFAF0NCE0oXTBNCFU4QFhVBTB1KFU4TQBdMEUIXQ04TRBVMEUAVThNDFkFM
EUobTBNDFUwRFBdAThNIFUITQRdME0wVQU8RShdMHUMVThMoF0wRNhdDThNEFUwRRhVOEzEWQUwR
ShtME0EVTBFGF0BOE0gVQhNDF0wTVxVBTxFKF0wdQxVOEygXTBE2FxROE10VShZOTBFTF2E=
'''

byteString = b64.decode('base64')
key = 'hhjhhjhjkjhjhf'

dec = ''
for i in range(len(byteString)):
    dec += chr(ord(byteString[i]) ^ ord(key[i%len(key)]))
print dec

復号結果は次のようになる。

${;}=+$();${=}=${;};${+}=++${;};${@}=++${;};${.}=++${;};${[}=++${;};
${]}=++${;};${(}=++${;};${)}=++${;};${&}=++${;};${|}=++${;};
${"}="["+"$(@{})"[${)}]+"$(@{})"["${+}${|}"]+"$(@{})"["${@}${=}"]+"$?"[${+}]+"]";
${;}="".("$(@{})"["${+}${[}"]+"$(@{})"["${+}${(}"]+"$(@{})"[${=}]+"$(@{})"[${[}]+"$?"[${+}]+"$(@{})"[${.}]);
${;}="$(@{})"["${+}${[}"]+"$(@{})"[${[}]+"${;}"["${@}${)}"];"${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${(}${+}+${"}${&}${@}+${"}${+}${=}${+}+${"}${|}${)}+${"}${+}${=}${=}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${[}${]}+${"}${&}${=}+${"}${+}${+}${[}+${"}${+}${+}${+}+${"}${+}${=}${|}+${"}${+}${+}${@}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${(}${|}+${"}${+}${+}${=}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${+}${+}${[}+${"}${.}${@}+${"}${+}${+}${(}+${"}${+}${=}${[}+${"}${+}${=}${+}+${"}${.}${@}+${"}${+}${+}${@}+${"}${|}${)}+${"}${+}${+}${]}+${"}${+}${+}${]}+${"}${+}${+}${|}+${"}${+}${+}${+}+${"}${+}${+}${[}+${"}${+}${=}${=}+${"}${.}${|}+${"}${+}${.}+${"}${+}${=}+${"}${)}${.}+${"}${+}${=}${@}+${"}${[}${=}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${.}${@}+${"}${[}${]}+${"}${+}${=}${+}+${"}${+}${+}${.}+${"}${.}${@}+${"}${.}${|}+${"}${&}${=}+${"}${[}${&}+${"}${+}${+}${|}+${"}${(}${|}+${"}${+}${+}${[}+${"}${.}${(}+${"}${)}${@}+${"}${]}${+}+${"}${[}${|}+${"}${[}${|}+${"}${.}${|}+${"}${[}${+}+${"}${+}${@}${.}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${)}${+}+${"}${+}${+}${+}+${"}${+}${+}${+}+${"}${+}${=}${=}+${"}${.}${@}+${"}${)}${[}+${"}${+}${+}${+}+${"}${|}${&}+${"}${.}${.}+${"}${.}${|}+${"}${]}${|}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${[}+${"}${&}${.}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${.}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${]}+${"}${.}${[}+${"}${+}${.}+${"}${+}${=}+${"}${+}${@}${]}|${;}"|&${;}

これも変数を標準出力させながら確認し、最後の部分は以下のようになる。

[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]61+[CHar]82+[CHar]101+[CHar]97+[CHar]100+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]45+[CHar]80+[CHar]114+[CHar]111+[CHar]109+[CHar]112+[CHar]116+[CHar]32+[CHar]39+[CHar]69+[CHar]110+[CHar]116+[CHar]101+[CHar]114+[CHar]32+[CHar]116+[CHar]104+[CHar]101+[CHar]32+[CHar]112+[CHar]97+[CHar]115+[CHar]115+[CHar]119+[CHar]111+[CHar]114+[CHar]100+[CHar]39+[CHar]13+[CHar]10+[CHar]73+[CHar]102+[CHar]40+[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]32+[CHar]45+[CHar]101+[CHar]113+[CHar]32+[CHar]39+[CHar]80+[CHar]48+[CHar]119+[CHar]69+[CHar]114+[CHar]36+[CHar]72+[CHar]51+[CHar]49+[CHar]49+[CHar]39+[CHar]41+[CHar]123+[CHar]13+[CHar]10+[CHar]9+[CHar]87+[CHar]114+[CHar]105+[CHar]116+[CHar]101+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]39+[CHar]71+[CHar]111+[CHar]111+[CHar]100+[CHar]32+[CHar]74+[CHar]111+[CHar]98+[CHar]33+[CHar]39+[CHar]59+[CHar]13+[CHar]10+[CHar]9+[CHar]87+[CHar]114+[CHar]105+[CHar]116+[CHar]101+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]34+[CHar]83+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]123+[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]125+[CHar]34+[CHar]13+[CHar]10+[CHar]125|string Insert(int startIndex, string value)

数値部分のみASCIIコードとしてデコードすると、以下のようになる。

$ECCON=Read-Host -Prompt 'Enter the password'
If($ECCON -eq 'P0wEr$H311'){
        Write-Host 'Good Job!';
        Write-Host "SECCON{$ECCON}"
}
SECCON{P0wEr$H311}

Ps and Qs (Crypto 200)

まず2つの公開鍵を見てみる。

$ openssl rsa -pubin -text < pub1.pub
Public-Key: (4096 bit)
Modulus:
    00:cf:cf:bb:ee:a7:df:14:3a:8a:c2:08:b1:aa:1d:
    2f:86:54:5a:c4:cb:58:8c:94:a3:fb:1c:14:ad:91:
    a4:f0:b9:36:15:7c:5a:4b:86:9c:18:a8:b8:64:f4:
    72:6b:f8:fc:dc:02:0c:b4:10:42:ba:c9:67:84:ab:
    7d:03:f9:37:49:47:ef:b0:bc:3d:66:58:31:97:43:
    40:15:9f:fc:3d:b7:c8:e7:4b:63:90:fd:a6:ee:c3:
    0b:81:c6:ff:62:4e:8d:3f:5b:17:bf:b7:a5:c7:ff:
    d8:ec:f4:e6:51:8b:39:3a:be:fd:dd:0f:ae:ba:43:
    08:74:6b:a6:3f:81:06:b5:9d:7e:05:89:43:a0:01:
    31:a7:d4:e5:38:c4:64:b2:70:57:76:47:ed:bc:47:
    8c:c1:ce:95:85:ef:e8:77:30:5b:3a:7c:2e:7c:44:
    db:54:75:ed:da:dc:34:5a:2c:90:a9:46:77:1c:ac:
    0a:45:4c:db:cb:46:1f:28:40:e7:61:3c:83:e9:ce:
    cc:94:03:7f:a0:9b:b9:da:a3:f1:80:56:2c:01:df:
    0b:e6:c5:1f:0c:06:e8:f0:e2:d6:e1:a5:e5:0d:0a:
    28:c3:88:11:40:77:0a:9f:45:93:41:46:b7:f3:59:
    b9:39:ce:23:f0:fa:50:7a:6f:4e:45:45:71:43:09:
    52:00:3c:20:f1:d9:7a:67:14:0b:6e:5f:cb:fb:3b:
    37:6e:4e:24:96:9a:eb:1d:48:9c:fc:72:af:4f:15:
    a4:78:8a:1a:a9:7c:89:75:6d:1d:4d:94:aa:47:e7:
    cd:3a:81:ae:cb:92:44:8c:c9:2c:77:d2:ef:57:6a:
    a0:db:c1:35:08:62:ac:cd:da:dd:bc:e8:03:57:f0:
    cd:5b:85:4d:d0:f8:c4:62:7f:e4:b7:18:b2:4e:cf:
    e1:1e:d2:4c:3b:e2:2f:00:64:3b:be:d4:ee:5e:34:
    5a:f1:76:e5:b7:6d:23:a2:f8:0e:0e:c6:f3:4e:57:
    18:c6:2a:70:fe:55:70:c2:8b:80:7b:44:f2:2e:ad:
    eb:d9:b5:ff:90:6f:6a:85:be:88:c0:c8:f6:e5:f8:
    80:a5:1f:17:f8:4d:b1:c2:ee:fe:a8:af:34:04:04:
    44:ce:d1:a3:7d:f0:e4:f5:f7:2c:c3:f5:0b:7e:42:
    7c:8c:2d:8b:61:86:ea:d7:62:f0:c4:44:b3:ca:3a:
    01:03:ed:12:a9:3b:ce:9c:ae:74:79:a2:29:eb:bc:
    0a:64:8e:aa:6f:97:e5:05:1a:66:eb:09:eb:d7:34:
    8e:92:f7:5f:12:5e:bd:c3:67:e2:a7:d1:da:77:59:
    d4:1f:ae:2e:26:35:bf:4b:7a:7f:91:be:ca:b3:ac:
    7d:05:bd
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz8+77qffFDqKwgixqh0v
hlRaxMtYjJSj+xwUrZGk8Lk2FXxaS4acGKi4ZPRya/j83AIMtBBCuslnhKt9A/k3
SUfvsLw9Zlgxl0NAFZ/8PbfI50tjkP2m7sMLgcb/Yk6NP1sXv7elx//Y7PTmUYs5
Or793Q+uukMIdGumP4EGtZ1+BYlDoAExp9TlOMRksnBXdkftvEeMwc6Vhe/odzBb
OnwufETbVHXt2tw0WiyQqUZ3HKwKRUzby0YfKEDnYTyD6c7MlAN/oJu52qPxgFYs
Ad8L5sUfDAbo8OLW4aXlDQoow4gRQHcKn0WTQUa381m5Oc4j8PpQem9ORUVxQwlS
ADwg8dl6ZxQLbl/L+zs3bk4klprrHUic/HKvTxWkeIoaqXyJdW0dTZSqR+fNOoGu
y5JEjMksd9LvV2qg28E1CGKszdrdvOgDV/DNW4VN0PjEYn/ktxiyTs/hHtJMO+Iv
AGQ7vtTuXjRa8Xblt20jovgODsbzTlcYxipw/lVwwouAe0TyLq3r2bX/kG9qhb6I
wMj25fiApR8X+E2xwu7+qK80BAREztGjffDk9fcsw/ULfkJ8jC2LYYbq12LwxESz
yjoBA+0SqTvOnK50eaIp67wKZI6qb5flBRpm6wnr1zSOkvdfEl69w2fip9Had1nU
H64uJjW/S3p/kb7Ks6x9Bb0CAwEAAQ==
-----END PUBLIC KEY-----

$ openssl rsa -pubin -text < pub2.pub
Public-Key: (4096 bit)
Modulus:
    00:bb:33:cc:7f:cc:8e:ca:f3:bf:9e:d9:5c:58:37:
    92:e1:ec:6b:80:ee:87:5e:c2:06:4d:bc:f0:75:95:
    c8:34:49:23:bf:53:65:24:d4:e0:a7:55:74:c7:79:
    8c:73:b1:97:dd:2b:1b:42:05:4b:1e:49:cb:45:fb:
    f0:4e:6f:11:4c:f8:a3:65:c3:df:36:45:52:4f:77:
    82:68:03:8a:3f:a2:68:02:e9:d1:ed:bf:bb:5e:df:
    b5:a0:c3:75:37:0d:7f:10:f5:7d:ab:bd:4f:77:1d:
    ad:36:32:f0:1b:9b:ce:10:48:99:66:ee:88:2d:ab:
    17:a3:3b:78:6a:a5:f7:31:65:a5:40:51:30:0b:1d:
    f9:28:03:92:a3:ed:e9:d3:fc:9c:4d:8a:6a:06:35:
    1f:6e:f3:59:8e:8d:e2:b3:9d:3b:19:af:64:a1:71:
    6c:d1:58:26:c3:f2:4c:b1:3d:eb:72:2c:3a:03:ef:
    1d:2b:e2:d0:a5:a6:e2:10:ff:5d:01:83:67:be:3b:
    f9:9e:a2:6b:a0:06:e5:16:4a:4d:d5:5a:ab:cd:44:
    9d:e5:ce:18:64:82:5d:c1:60:e5:0d:50:9e:b0:e6:
    fe:72:3e:f1:82:68:1e:dd:b9:40:84:b8:3e:c9:e2:
    e9:43:e8:7c:b8:75:09:ab:0f:d9:b1:ca:22:c1:ce:
    af:f3:9f:ca:cf:67:29:fc:0e:05:78:67:0d:87:d7:
    f0:f9:cc:be:09:cb:3e:12:ce:b8:95:57:2a:99:79:
    d1:0b:fd:bf:af:a2:60:56:8d:8d:b1:84:be:12:b3:
    e3:19:3e:07:72:9c:e3:c1:d9:cd:82:83:ed:69:83:
    a0:63:88:03:6a:0a:70:29:4f:23:39:29:44:77:82:
    80:e7:de:9f:60:16:3a:81:50:e3:0f:f4:a4:ea:02:
    79:2c:be:83:05:ba:a2:e9:9a:fe:51:e1:7d:af:c5:
    6b:e0:d3:84:14:7b:cd:38:e9:d1:29:34:ec:71:26:
    22:21:77:73:a4:b3:85:1a:9b:0c:6c:7c:3e:01:f6:
    11:1a:1e:1a:55:7f:4e:2a:e4:a2:47:ce:9b:75:cc:
    cc:b1:81:98:25:f3:05:4a:a1:c0:55:bd:3e:23:40:
    09:3a:e2:ef:1d:0f:a5:a1:76:82:5e:fd:f7:95:07:
    02:7f:51:04:08:00:09:14:2f:0d:43:e2:f1:0c:fa:
    d2:20:81:3b:bb:90:14:d4:f4:32:5e:da:c5:38:fb:
    5e:82:b7:53:e2:ad:3b:24:60:7d:73:80:aa:64:fc:
    b9:8b:59:ea:8b:5a:73:6b:80:93:83:24:8c:ec:e0:
    b1:72:55:ea:55:9e:90:12:7f:77:8a:f6:d7:e8:a6:
    6d:ad:91
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuzPMf8yOyvO/ntlcWDeS
4exrgO6HXsIGTbzwdZXINEkjv1NlJNTgp1V0x3mMc7GX3SsbQgVLHknLRfvwTm8R
TPijZcPfNkVST3eCaAOKP6JoAunR7b+7Xt+1oMN1Nw1/EPV9q71Pdx2tNjLwG5vO
EEiZZu6ILasXozt4aqX3MWWlQFEwCx35KAOSo+3p0/ycTYpqBjUfbvNZjo3is507
Ga9koXFs0Vgmw/JMsT3rciw6A+8dK+LQpabiEP9dAYNnvjv5nqJroAblFkpN1Vqr
zUSd5c4YZIJdwWDlDVCesOb+cj7xgmge3blAhLg+yeLpQ+h8uHUJqw/Zscoiwc6v
85/Kz2cp/A4FeGcNh9fw+cy+Ccs+Es64lVcqmXnRC/2/r6JgVo2NsYS+ErPjGT4H
cpzjwdnNgoPtaYOgY4gDagpwKU8jOSlEd4KA596fYBY6gVDjD/Sk6gJ5LL6DBbqi
6Zr+UeF9r8Vr4NOEFHvNOOnRKTTscSYiIXdzpLOFGpsMbHw+AfYRGh4aVX9OKuSi
R86bdczMsYGYJfMFSqHAVb0+I0AJOuLvHQ+loXaCXv33lQcCf1EECAAJFC8NQ+Lx
DPrSIIE7u5AU1PQyXtrFOPtegrdT4q07JGB9c4CqZPy5i1nqi1pza4CTgySM7OCx
clXqVZ6QEn93ivbX6KZtrZECAwEAAQ==
-----END PUBLIC KEY-----

2つあるので、共通の素数がないかプログラムで探してみる。

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

n1 = 0x00cfcfbbeea7df143a8ac208b1aa1d2f86545ac4cb588c94a3fb1c14ad91a4f0b936157c5a4b869c18a8b864f4726bf8fcdc020cb41042bac96784ab7d03f9374947efb0bc3d665831974340159ffc3db7c8e74b6390fda6eec30b81c6ff624e8d3f5b17bfb7a5c7ffd8ecf4e6518b393abefddd0faeba4308746ba63f8106b59d7e058943a00131a7d4e538c464b270577647edbc478cc1ce9585efe877305b3a7c2e7c44db5475eddadc345a2c90a946771cac0a454cdbcb461f2840e7613c83e9cecc94037fa09bb9daa3f180562c01df0be6c51f0c06e8f0e2d6e1a5e50d0a28c3881140770a9f45934146b7f359b939ce23f0fa507a6f4e454571430952003c20f1d97a67140b6e5fcbfb3b376e4e24969aeb1d489cfc72af4f15a4788a1aa97c89756d1d4d94aa47e7cd3a81aecb92448cc92c77d2ef576aa0dbc1350862accddaddbce80357f0cd5b854dd0f8c4627fe4b718b24ecfe11ed24c3be22f00643bbed4ee5e345af176e5b76d23a2f80e0ec6f34e5718c62a70fe5570c28b807b44f22eadebd9b5ff906f6a85be88c0c8f6e5f880a51f17f84db1c2eefea8af34040444ced1a37df0e4f5f72cc3f50b7e427c8c2d8b6186ead762f0c444b3ca3a0103ed12a93bce9cae7479a229ebbc0a648eaa6f97e5051a66eb09ebd7348e92f75f125ebdc367e2a7d1da7759d41fae2e2635bf4b7a7f91becab3ac7d05bd
n2 = 0x00bb33cc7fcc8ecaf3bf9ed95c583792e1ec6b80ee875ec2064dbcf07595c8344923bf536524d4e0a75574c7798c73b197dd2b1b42054b1e49cb45fbf04e6f114cf8a365c3df3645524f778268038a3fa26802e9d1edbfbb5edfb5a0c375370d7f10f57dabbd4f771dad3632f01b9bce10489966ee882dab17a33b786aa5f73165a54051300b1df9280392a3ede9d3fc9c4d8a6a06351f6ef3598e8de2b39d3b19af64a1716cd15826c3f24cb13deb722c3a03ef1d2be2d0a5a6e210ff5d018367be3bf99ea26ba006e5164a4dd55aabcd449de5ce1864825dc160e50d509eb0e6fe723ef182681eddb94084b83ec9e2e943e87cb87509ab0fd9b1ca22c1ceaff39fcacf6729fc0e0578670d87d7f0f9ccbe09cb3e12ceb895572a9979d10bfdbfafa260568d8db184be12b3e3193e07729ce3c1d9cd8283ed6983a06388036a0a70294f23392944778280e7de9f60163a8150e30ff4a4ea02792cbe8305baa2e99afe51e17dafc56be0d384147bcd38e9d12934ec712622217773a4b3851a9b0c6c7c3e01f6111a1e1a557f4e2ae4a247ce9b75ccccb1819825f3054aa1c055bd3e2340093ae2ef1d0fa5a176825efdf79507027f5104080009142f0d43e2f10cfad220813bbb9014d4f4325edac538fb5e82b753e2ad3b24607d7380aa64fcb98b59ea8b5a736b809383248cece0b17255ea559e90127f778af6d7e8a66dad91
e = 65537

p = egcd(n1, n2)[0]
q1 = n1 / p
q2 = n2 / p
print 'p =', p
print 'q1 =', q1
print 'q2 =', q2

共通の素数pとq1, q2の値がわかる。

p = 28491351268021265385526651386538607807309659986276688343064670073891013400825164415230601338782473025742402049394830630675805725885088430112149497869242346184436501498250656252478654366186925359496427622140658107345546543257713919694302487049954761322101254188444207888427451979864984635323522901072705782835553010119115529960199616134426518090324707055730908978182075401070044276443957929403874512391698813306139691898167549756758189122432373003019206630611377319244160315312008084214038516008026804548925876733577843139353697227433645926176332422253880445694249081777712571005410284034477749618735562684652311433029
q1 = 29756285957217824990174038832451778402099067307810847648290595785058431646976908322304147959112427140159792888914923236200167490011201811250432742134955076467161512399957077313964630071141735504154569672191460389697633956438555548934921730829103416692214221897316036431719854727062122070711252924237859981650839082127947619246716311728507350521260831762017879211408671194883521699107885995227760052190268561172377288494647487407578357795768368061699760835305355222313206649747987980403480055830409354654506995090037005532480704961830183236922268938782515705140754745094708066416483123932606937140087049605071066540057
q2 = 26805289271497618288824957409840900087921737364247062017954653095350605996401170903273670545713193946727301443779225655009185442124301303618802469003843741958147267024677868793805932449329658920982848063484688700333399204106733149230481527426171610107889681875992617647315539302047794058437648908212645971211176786957517731494723729889354075435764097658602139780143569337636457452893386690938522392609685556109416233805154149262663416050814684714850213550063231110089787491540944945712297710844735930977234970373826519042470046867137186054740672979017101637673890382547484646195101031561338945685511605286410830656477

n1(=p*q1), e, cの方で復号する。まず秘密鍵を生成する。

$ rsatool.py -f PEM -o sec1.key -p 28491351268021265385526651386538607807309659986276688343064670073891013400825164415230601338782473025742402049394830630675805725885088430112149497869242346184436501498250656252478654366186925359496427622140658107345546543257713919694302487049954761322101254188444207888427451979864984635323522901072705782835553010119115529960199616134426518090324707055730908978182075401070044276443957929403874512391698813306139691898167549756758189122432373003019206630611377319244160315312008084214038516008026804548925876733577843139353697227433645926176332422253880445694249081777712571005410284034477749618735562684652311433029 -q 29756285957217824990174038832451778402099067307810847648290595785058431646976908322304147959112427140159792888914923236200167490011201811250432742134955076467161512399957077313964630071141735504154569672191460389697633956438555548934921730829103416692214221897316036431719854727062122070711252924237859981650839082127947619246716311728507350521260831762017879211408671194883521699107885995227760052190268561172377288494647487407578357795768368061699760835305355222313206649747987980403480055830409354654506995090037005532480704961830183236922268938782515705140754745094708066416483123932606937140087049605071066540057
Using (p, q) to initialise RSA instance

n =
cfcfbbeea7df143a8ac208b1aa1d2f86545ac4cb588c94a3fb1c14ad91a4f0b936157c5a4b869c18
a8b864f4726bf8fcdc020cb41042bac96784ab7d03f9374947efb0bc3d665831974340159ffc3db7
c8e74b6390fda6eec30b81c6ff624e8d3f5b17bfb7a5c7ffd8ecf4e6518b393abefddd0faeba4308
746ba63f8106b59d7e058943a00131a7d4e538c464b270577647edbc478cc1ce9585efe877305b3a
7c2e7c44db5475eddadc345a2c90a946771cac0a454cdbcb461f2840e7613c83e9cecc94037fa09b
b9daa3f180562c01df0be6c51f0c06e8f0e2d6e1a5e50d0a28c3881140770a9f45934146b7f359b9
39ce23f0fa507a6f4e454571430952003c20f1d97a67140b6e5fcbfb3b376e4e24969aeb1d489cfc
72af4f15a4788a1aa97c89756d1d4d94aa47e7cd3a81aecb92448cc92c77d2ef576aa0dbc1350862
accddaddbce80357f0cd5b854dd0f8c4627fe4b718b24ecfe11ed24c3be22f00643bbed4ee5e345a
f176e5b76d23a2f80e0ec6f34e5718c62a70fe5570c28b807b44f22eadebd9b5ff906f6a85be88c0
c8f6e5f880a51f17f84db1c2eefea8af34040444ced1a37df0e4f5f72cc3f50b7e427c8c2d8b6186
ead762f0c444b3ca3a0103ed12a93bce9cae7479a229ebbc0a648eaa6f97e5051a66eb09ebd7348e
92f75f125ebdc367e2a7d1da7759d41fae2e2635bf4b7a7f91becab3ac7d05bd

e = 65537 (0x10001)

d =
cc151d61f6189d3c14d31348af60b4307e9d1990fda829bd94b8f211b6ebbdc0963da97edf9715ab
1ddee0be33b497b473b7cb93f6382249f2d096bd526ea7fdde98a4ff68691f09ac9c4dce2eecc00b
c2506b781f870b2e85fbc1fa95098d4d27c024e591cc4c4a9555b7f88c7266c4ab9692477977d0a6
f7f654311f5c607587b296280475c7b723dbecd0ea7756de7df98b9e90c1c9ff405665d1ed635ee4
63da1f0e5c3b69092b1b808a6223bb29c9862dea743e53c820582ee6f69446a2e1b5c6b14172505f
3eb95ab1ac30744d6e27b8fd334d5367e6514f6810cc8deec133ad680be01c5d682d82389a2471a3
f701dbc8277b6b91edd317ac708231b4e634dcc024e8d79767139277fe6198a1df09cd3d7743d43e
906b083944c82cc663b70bcf8589eb6534f78d46a4df5e21029482e33a6fe86676b1ffbbad380dc8
a77eb3e667f131c856754a364ae8b369f9eaa0903b3a4a73327eddbe6bddbbf59d79839fe65980ef
2d6f9cfa0b4c5069fa84902c5ab97a8ddfe4b4ec912bbabefc27b8f8d5e554e3671814a73cc2a7d1
19430abddce1a33dc463f5291a1b6da01ab56ad17d3713d099c7fa9de7df39d6c37f10cb35dcdc33
3241798a70a44e9d2666bac0c5cd96eb1f0345bbaaca33fe16f80b4862ca690880a7466b15989d67
dbb19fa4511269b8112e83e4bc41e38d585036ee35798dd4c5c6a4a07cf10561

p =
e1b1e9fa3b5075f426eb220a9aa8d7a674219045ae500e0a45dc40b71ecd6ff56317efa5ada5d48d
49a5e83d6f6042c35c5dd06d2a182cdd6d15f0588ab429b7a001943c7dd83a14818c172be911841f
f4ce430646c0a3bb877d07a50306da67a02d3042edb1169740f7e30a1e3aed163afbb4ffed13b8dd
d29b5567231026ca5c38994dd0920e04965625153e06140e03358b758f7d2d49e12e9eb246f65715
05920cbeb1537d2996ea4453b5018348bbd6c80f5ebe640f97a8cc74b1c20ca6d33f96f0699b852b
ab50027f8bd704cf088ac6db47c7d6d8ed0416d0b61e9d7ebfb94e31bcc84368d37914af9539b8d3
0fe35bba367a64b278c3353fa0f24f45

q =
ebb716a60ff65464c67bb9cee4e093f5da8c9054c22e2e8f62bbe56d4d80dec018818d2a21f824ac
112b8482d068a2e4a2e98ed85dd4478cb5d8534593a6ac2c950d4db398706a0bdefc77e77098d91d
e9f666daea5d3b18e17b418a9cef85719def74b8f378181e170ceda51e0a0c2ea2b1774582534aaf
95e0d978d365c3117d843c03d3f585ab471823d74a072754eae5b047b3a10b83affe00b865ab306b
5822cca155632148830a952ae7e9115324c95c0ea68a20831fe27851b3db7681bbb577f37b5eab7e
1541c5a014af83360a187d621f4b285e80af618358fcc1f025bf448ee619868eb18a5a972e09e99f
604591437c2732bd993cd68ebb76a819

Saving PEM as sec1.key

この秘密鍵で復号する。

$ openssl rsautl -decrypt -inkey sec1.key < cipher 
SECCON{1234567890ABCDEF}
SECCON{1234567890ABCDEF}

Very smooth (Crypto 300)

No.30のパケットから証明書をエクスポートし、証明書(公開鍵)の内容を見てみる。

$ openssl x509 -in SRL.cer -text -pubkey -inform DER
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 11640506567126718943 (0xa18b630c7b3099df)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, ST=Kawasaki, O=SRL
        Validity
            Not Before: Oct  8 02:47:17 2017 GMT
            Not After : Oct  8 02:47:17 2018 GMT
        Subject: C=JP, ST=Kawasaki, O=SRL
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:d5:46:aa:82:5c:f6:1d:e9:77:65:f4:64:fb:fe:
                    48:89:ad:8b:f2:f2:5a:21:75:d0:2c:8b:6f:2a:c0:
                    c5:c2:7b:67:03:5a:ec:19:2b:37:41:dd:1f:4d:12:
                    75:31:b0:7a:b0:12:eb:86:24:1c:09:c0:81:49:9e:
                    69:ef:5a:ea:c7:8d:c6:23:0d:47:5d:a7:ee:17:f0:
                    2f:63:b6:f0:9a:2d:38:1d:f9:b6:92:8e:8d:9e:07:
                    47:fe:ba:24:8b:ff:df:f8:9c:df:af:47:71:65:89:
                    19:b6:98:1c:9e:14:28:e9:a5:34:25:ca:2a:31:0a:
                    a6:d7:60:83:31:18:ee:0d:71
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         78:92:11:fb:6c:e1:7a:f7:2a:33:b8:8b:08:a7:f7:5b:de:cf:
         62:0b:a0:ed:be:d0:69:88:38:93:94:9d:05:41:73:bd:7e:b3:
         32:ec:8e:10:bc:3a:62:b0:56:c7:c1:3f:60:66:a7:be:b9:46:
         f7:46:22:6a:f3:5a:25:d5:66:94:57:0e:fc:b5:16:33:05:1c:
         6f:f5:85:74:57:a4:a0:c6:ce:4f:fd:64:53:94:a9:83:b8:96:
         bf:5b:a7:ee:8b:1e:48:a7:d2:43:06:0e:4f:5a:86:62:69:05:
         e2:c0:bd:4e:89:c9:af:04:4a:77:a2:34:86:6a:b8:d2:3b:32:
         b7:39
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVRqqCXPYd6Xdl9GT7/kiJrYvy
8lohddAsi28qwMXCe2cDWuwZKzdB3R9NEnUxsHqwEuuGJBwJwIFJnmnvWurHjcYj
DUddp+4X8C9jtvCaLTgd+baSjo2eB0f+uiSL/9/4nN+vR3FliRm2mByeFCjppTQl
yioxCqbXYIMxGO4NcQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIB0zCCATwCCQChi2MMezCZ3zANBgkqhkiG9w0BAQsFADAuMQswCQYDVQQGEwJK
UDERMA8GA1UECAwIS2F3YXNha2kxDDAKBgNVBAoMA1NSTDAeFw0xNzEwMDgwMjQ3
MTdaFw0xODEwMDgwMjQ3MTdaMC4xCzAJBgNVBAYTAkpQMREwDwYDVQQIDAhLYXdh
c2FraTEMMAoGA1UECgwDU1JMMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV
RqqCXPYd6Xdl9GT7/kiJrYvy8lohddAsi28qwMXCe2cDWuwZKzdB3R9NEnUxsHqw
EuuGJBwJwIFJnmnvWurHjcYjDUddp+4X8C9jtvCaLTgd+baSjo2eB0f+uiSL/9/4
nN+vR3FliRm2mByeFCjppTQlyioxCqbXYIMxGO4NcQIDAQABMA0GCSqGSIb3DQEB
CwUAA4GBAHiSEfts4Xr3KjO4iwin91vez2ILoO2+0GmIOJOUnQVBc71+szLsjhC8
OmKwVsfBP2Bmp765RvdGImrzWiXVZpRXDvy1FjMFHG/1hXRXpKDGzk/9ZFOUqYO4
lr9bp+6LHkin0kMGDk9ahmJpBeLAvU6Jya8ESneiNIZquNI7Mrc5
-----END CERTIFICATE-----
n = 0x00d546aa825cf61de97765f464fbfe4889ad8bf2f25a2175d02c8b6f2ac0c5c27b67035aec192b3741dd1f4d127531b07ab012eb86241c09c081499e69ef5aeac78dc6230d475da7ee17f02f63b6f09a2d381df9b6928e8d9e0747feba248bffdff89cdfaf4771658919b6981c9e1428e9a53425ca2a310aa6d760833118ee0d71

nの素因数分解をしようと、factordbを使ったり、Fermat法や小さい素数から除算を行ったり、msieveやsageを使ったりしたが、うまくいかない。いろいろ調べた中に、Pollard's p-1 factoringというものがあったので、試してみる。
https://github.com/ralphleon/Python-Algorithms/blob/master/Cryptology/pollard.pyを参考に素因数分解するプログラムを作成する。

from math import floor

def gcd(a, b):
    while b != 0:
        t = b
        b = a % b
        a = t
    return a

def factor(n, b):
    a = 2
    for j in range(2, b):
        a = a**j % n

    d = gcd(a - 1, n)
    if 1 < d < n:
        return d
    else:
        return -1

def pollards_p1_factor(n):
    s = 2
    d = -1

    while s < n and d == -1:
        s += 1
        d = factor(n, s)
        print "Round %i = %i" % (s, d)

    if d == -1:
        print 'No Factor could be found ...'
        return -1
    else:
        print '%i has a factor of %i, with b = %i' % (n, d, s)
        return d

n = 0x00d546aa825cf61de97765f464fbfe4889ad8bf2f25a2175d02c8b6f2ac0c5c27b67035aec192b3741dd1f4d127531b07ab012eb86241c09c081499e69ef5aeac78dc6230d475da7ee17f02f63b6f09a2d381df9b6928e8d9e0747feba248bffdff89cdfaf4771658919b6981c9e1428e9a53425ca2a310aa6d760833118ee0d71
p = pollards_p1_factor(n)
q = n / p

print 'p =', p
print 'q =', q

しばらく処理に時間がかかるが、素因数分解できて、次の2つの素数が得られる。

p = 11807485231629132025602991324007150366908229752508016230400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
q = 12684117323636134264468162714319298445454220244413621344524758865071052169170753552224766744798369054498758364258656141800253652826603727552918575175830897

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

$ rsatool.py -f PEM -o secret.key -p 11807485231629132025602991324007150366908229752508016230400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 -q 12684117323636134264468162714319298445454220244413621344524758865071052169170753552224766744798369054498758364258656141800253652826603727552918575175830897
Using (p, q) to initialise RSA instance

n =
d546aa825cf61de97765f464fbfe4889ad8bf2f25a2175d02c8b6f2ac0c5c27b67035aec192b3741
dd1f4d127531b07ab012eb86241c09c081499e69ef5aeac78dc6230d475da7ee17f02f63b6f09a2d
381df9b6928e8d9e0747feba248bffdff89cdfaf4771658919b6981c9e1428e9a53425ca2a310aa6
d760833118ee0d71

e = 65537 (0x10001)

d =
3d0dbab810f69fbf7adfa3e3d8c3856e6c50f8de69f0d43220de55978e91ce47d7487d99c2e6bd2d
cca82e3f0f6f870ec822d26b9720b3a5f91ce30d7e68af76a5002e3026ebb3f987c6920e5a558985
5147876b83e2dc5a07d8672563a631855f677779ba3bae90bfff0000ffff0000ffff0000ffff0000
ffff0000ffff0001

p =
e171c91c9e775f06802d83cbf21643a137b576a582e1fee5bbe1566ba5c532400717dfaa2122229c
440000000000000000000000000000000000000000000001

q =
f22eac8b5af91a65f035441b93d722269b1b807932bcc74efda85c1d2b8f35b79e7d6a3813f6f71b
15b6981c9e1428e9a53425ca2a310aa6d760833118ee0d71

Saving PEM as secret.key

この秘密鍵Wiresharkに設定して復号すると、index.htmlは以下のようになっていることがわかる。

<html>
<head><title>Very smooth</title></head>
<body>
<h1>
Answer: One of these primes is very smooth.
</h1>
</body>
</html>
SECCON{One of these primes is very smooth.}

Takoma Park CTF Writeup

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

Sanity Check (Slightly More Trivial 1)

問題に書かれているフラグを記載するだけ。

tpctf{this-is-a-flag}

Zalgo (Slightly More Trivial 2)

問題にフラグが書いてあるが、見にくい。文字をコピーした後に、通常のASCII文字を拾えばよい。

tpctf{he_comes}

trivial rev (Slightly More Trivial 2)

実行するだけ。

tpctf{ez_pz}

trivial rsa (Slightly More Trivial 3)

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

65561 = 53 * 1237

あとは通常通りRSA暗号の復号方法で復号する。

n = 65561
e = 65537
c = 27830
p = 53
q = 1237

phi = (p - 1) * (q - 1)

x = 0
while True:
    if (phi * x + 1) % e == 0:
        d = (phi * x + 1) / e
        break
    x = x + 1

m = pow(c, d, n)

flag =  'tpctf{%d}' % m
print flag
tpctf{31337}

trivial stego (Slightly More Trivial 3)

添付のPNGファイルのIENDチャンクの後ろにフラグがある。

tpctf{steg!}

trivial arithmetic (Slightly More Trivial 4)

pythonで計算してみる。

>python
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1+0.2
0.30000000000000004
tpctf{0.30000000000000004}

Ads (Web 20)

ソースからリンクしているファイルを見てみる。
https://tpctf.com/static/user.cssにフラグが書いてある。

tpctf{thx_4_n0_adb1ock}

Demo File (Forensics 90)

添付のdocxファイルを解凍し、demo\word\mediaにある画像を調べる。image4.pngのIENDチャンクの後ろにかなり大きいサイズの文字列が入っていて、ダミーフラグが大量にある。正規表現を使いプログラムでダミーフラグを取り除いていく。最終的なコードは以下の通り。

import re

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

data = data.replace('TPCTF stands for Teaching Primary Care Trust Flag. ', '')
data = re.sub(r'The flag isn\'t TPCTF{[a-z:)]+}\. ', '', data)
data = data.replace('Clarence Lam is a TPCTF organizer. He is also a TPCTF disorganizer. ', '')
data = re.sub(r'TPCTF stands for T[a-z]+ P[a-z]+ Capture The Flag, and it was made by current and former T[a-z]+ P[a-z]+ students. ', '', data)
data = re.sub(r'TPCTF stands for T[a-z]+ P[a-z]+ Cat The Flag.txt, where participants around the world attempt to \'cat flag.txt\' and get something like TPCTF{[a-z:)]+}. Of course, that isn\'t the flag. ', '', data)
data = re.sub(r'TPCTF{[a-z:)]+} is not the flag. ', '', data)
data = re.sub(r'TPCTF stands for T[a-z]+ Paper Capture The Flag, and it was made by current and former T[a-z]+ Paper students. ', '', data)
data = re.sub(r'Some of Clarence Lam\'s nicknames are Calvin, clam, clam~, c-lam, and TPCTF{[a-z:)]+}. Actually, the last one isn\'t true. ', '', data)
data = re.sub(r'Clarence Lam has a flag that he doesn\'t want anyone to find out about. It\'s not TPCTF{[a-z:)]+} though. ', '', data)
data = re.sub(r'Clarence Lam is a TPCTF organizer and he thinks the flag is TPCTF{[a-z:)]+} but it isn\'t. ', '', data)
data = re.sub(r'Fun fact: TPCTF{[a-z:)]+} is a fake flag. ', '', data)
data = re.sub(r'Fun fact: TPCTF{[a-z:)]+} starts with TPCTF. ', '', data)
data = re.sub(r'Fun fact: TPCTF{[a-z:)]+} has 18 letters in between the braces. ', '', data)
data = re.sub(r'Fun fact: All the letters in TPCTF{[a-z:)]+} are lowercase except for the TPCTF at the start. ', '', data)
data = re.sub(r'Clarence Lam is a TPCTF organizer and he doesn\'t like strings of text like TPCTF{[a-z:)]+}. ', '', data)
data = re.sub(r'Clarence Lam is a TPCTF organizer and his least favorite string is TPCTF{[a-z:)]+}. ', '', data)
data = re.sub(r'Clarence Lam is part of a group that organized TPCTF and the flag is not quite TPCTF{[a-z:)]+}. ', '', data)
data = re.sub(r'Clarence Lam is a TPCTF organizer and favorite string is TPCTF{[a-z:)]+}. ', '', data)
data = data.replace('Just kidding! ', '')
data = re.sub(r'The flag TPCTF{[a-z:)]+} isn\'t actually real. ', '', data)
data = re.sub(r'Clarence Lam writes TPCTF problems, some of which contain flags, such as TPCTF{[a-z:)]+}. This isn\'t a real flag. ', '', data)
data = re.sub(r'The flag TPCTF{[a-z:)]+} isn\'t actually real. ', '', data)
data = re.sub(r'Clarence Lam wrote a few problems for TPCTF and his least favorite string of text isn\'t not TPCTF{[a-z:)]+}. ', '', data)
data = re.sub(r'Did you know that Clarence Lam\'s favorite command is TPCTF{[a-z:)]+}\'; DROP TABLE flags; -- \? Of course you didn\'t. It\'s not true! ', '', data)
data = re.sub(r'Clarence Lam is a TPCTF organizer and the flag isn\'t TPCTF{[a-z:)]+}. ', '', data)

print data

最後に残ったメッセージは以下の通り。

Clarence Lam is a TPCTF organizer and his favorite string is TPCTF{ohnoivebeendocxxed}.
TPCTF{ohnoivebeendocxxed}

Bad Restaurant (Crypto 5)

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

tpctf{all_roads_lead_to_rome}

768 (Crypto 30)

nを素因数分解する。

p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917

あとはRSA暗号の通常通り、復号する。

n = 0xCAD984557C97E039431A226AD727F0C6D43EF3D418469F1B375049B229843EE9F83B1F97738AC274F5F61F401F21F1913E4B64BB31B55A38D398C0DFED00B1392F0889711C44B359E7976C617FCC734F06E3E95C26476091B52F462E79413DB5
e = 0x10001
c = 0x3F808414886E7C91F1D78AEB7EF920D2C9294AC384DCBB1A48032E8CAB79131AB3C1852896EEEECB5BA055AE77BBB619741FDE4D01AAC7D56F4E44508A8FC81A86DDB929A112AA80C4A7221B3C651E14E2D701B52E295152813CD9EFB4B51CB
p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917

phi = (p - 1) * (q - 1)

x = 0
while True:
    if (phi * x + 1) % e == 0:
        d = (phi * x + 1) / e
        break
    x = x + 1

m = pow(c, d, n)

flag = ('%x' % m).decode('hex')
print flag

復号結果は次の通り。

It appears that you have managed to solve the challenge.
Flag is tpctf{omg_b1c_m0dulus}.
tpctf{omg_b1c_m0dulus}

That's not latin... (Misc 10)

フラグが書かれているが、eだけ全角になっているので、半角にする。

tpctf{nev3r_7h15_3z}

Not Quite LSD (Steganography 30)

添付のPNGファイルをStegSolveで開き、Data ExtractでRGBのLSBのみチェックをつけるとフラグが表示される。
f:id:satou-y:20171210214310p:plain

TPCTF{1sB_i5_K00l}

Woah! (Steganography 40)

添付のPNGファイルのIENDチェンクの後ろに以下の文字列がある。

c=23273044714507614583919107642780731232409437015529456693716961465133831310123918470882082327335507219289041144186168765420579209702030715438341449893348841695639896994241125

素因数分解してみる。

c=2855076403049907408196032392213367306890430676224579762045^3

RSA暗号のnが大きく、eが3で小さいパターンの復号の問題とみて、復号する。

>>> ('%x' % 2855076403049907408196032392213367306890430676224579762045).decode('hex')
'tpctf{rs4_and_st3g0_w0w}'
tpctf{rs4_and_st3g0_w0w}