この大会は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
この大会は2017/2/3 19:00(JST)~2017/2/6 19:00(JST)に開催されました。
今回もチームで参戦。結果は2040点で1029チーム中63位でした。
自分で解けた問題をWriteupとして書いておきます。
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}
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}
公開鍵と暗号化データを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}
計算問題を解いていくだけ。
#!/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}
画像のステガノグラフィの問題。いろいろ試したみたが、なかなかうまくいかなかった。PythonのSteganographyライブラリを使ったら、簡単にフラグを抽出できた。
from steganography.steganography import Steganography secret_text = Steganography.decode('cat_with_secrets.png') print secret_text
ALEXCTF{CATS_HIDE_SECRETS_DONT_THEY}
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}
この大会は2017/2/4 20:30(JST)~2017/2/5 18:00(JST)に開催されました。
今回もチームで参戦。結果は570点で275チーム中8位でした。
自分で解けた問題をWriteupとして書いておきます。
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}
添付の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)
ファイルを開くと黒い塗りつぶし箇所がある。
画像コピーで切り出すと、フラグが見える。
BITSCTF{save_the_kid}
先頭が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}
暗号文は"&"が間に入っているのが目立つ。"&"と" "(スペース)の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}
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)
復号すると画像ファイルにフラグが書かれている。
BITSCTF{p_en_gee}
この大会は2017/1/21 18:00(JST)~2017/1/23 6:00(JST)に開催されました。
今回もチームで参戦。結果は450点で339チーム中51位でした。
自分で解けた問題をWriteupとして書いておきます。
暗号学者の誕生した年を答えていくクイズ。
いろんな問題パターンを辞書にして答えていくスクリプトにした。
辞書にないものは答えられず、完全に対応したスクリプトではない。
#!/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}
この大会は2016/12/28 5:00(JST)~2016/12/30 5:00(JST)に開催されました。
今回もチームで参戦。結果は1275点で278チーム中39位でした。
自分で解けた問題をWriteupとして書いておきます。
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ン・@ナサゥト偽。イ・UW%・耀カ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」SF|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エ欧>,ヌLJbea廟ヘ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ヤ ・0JeeXp陂・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が復号でき、ファイルを開いてみるとフラグが書いてある。
33C3_g00d_d1s3ct1on_sk1llz_h0mie
この大会は2016/12/17 11:00(JST)~2016/12/24 11:00(JST)に開催されました。
今回もチームで参戦。結果は6402点で536チーム中12位でした。
自分で解けた問題をWriteupとして書いておきます。
シーザー暗号。http://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipher
でROT14にして復号する。
3DS{th1s_r0t_1s_n0t_s0_H0t}
演算の図が与えられているので、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}
pngファイルが与えられている。StegSolveで開いてみると、Blueのビットにフラグが隠れていた。
3DS{Gr4b_Only_th1s_B1ts}
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}
いくつかの文字をこのシステムでエンコードして、そのデータを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}
最初に聞かれるタイプの数値はそのまま提示されたものと同じ数値を答えればよい。あとは文字の違う箇所の数を答えていく。
#!/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}
画像の中に文字データとしてフラグを隠している。そのロジックはスクリプトとして提示されている。スクリプトから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}
部分文字列で共通する文字列の最大長を答える問題。
#!/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}
何回関数が呼ばれるかを答える問題。回数は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}