2020年12月3の21:30 - 12月4日21:30 で行われていた、Shakti CTF 2020の [Crypto] 分野のwriteupです。
※まとめはこちら tech.kusuwada.com
Ancient Warfare
Do you know how people from Caeser's time used to send encrypted messages?
Try to get the flag : funxgvpgs{byq3e_1f_a0g_nyj4lf_gu3_o3gg3e!}
これはrot13かな?cyberchefに突っ込んでみます
ビンゴ!
flag: shaktictf{old3r_1s_n0t_alw4ys_th3_b3tt3r!}
Easy Encoding
Joan knows this is breakable. Do you know how?
01001110 01111010 01001101 00110010 01001111 01000100 01011001 01111000 01001110 01101101 01001001 00110011 01001110 01000100 01011001 00110101 01001110 01101010 01001101 00110011 01001110 01000100 01011001 00110010 01001110 00110010 01001001 00110001 01001110 01111010 01001101 00110000 01001110 01111010 01001001 00110010 01011010 01000100 01010101 00110001 01001110 01111010 01000001 00110001 01011010 01101010 01010001 01111010 01001110 01101010 01100111 01111010 01001110 01000100 01011010 01101010 01001110 01101101 01001101 01111010 01001101 01111010 01011010 01101100 01001110 01101010 01100011 01111010 01001101 01111010 01100100 01101011
Author : 4lph4
binだ。2進数から16進数 -> Ascii encodeをしてみる。でもcyberchefに投げる。
2進数からAsciiにするとbase64っぽい文字列になるので、base64 decode, hexっぽい文字列になるのでhex -> ascii変換でflagが出ました。
flag : shaktictf{W4rmUp_Ch4ll3ng3}
3,2,1..Go
Introducing our theme woman : "Joan Clarke!" Cipher : WEQEXFTUXQHVOUFPSVLPTORHAFBQE
Looks like I found something I shouldn't have. Seperate the words by underscores('_ ') and submit everything in lowercase around the flag format
Author : ph03n1x
config.jpg
が配布されます。
めっちゃ見にくいけど、MACHINE TYPE
が読み取れたのと、UIが dCode.fr っぽかったので dcode MACHINE TYPE
でググったら出てきた。
Enigma Machine Cipher - Decoder, Encoder, Solver, Translator
Enigma Machine というやつらしい。エニグマだ!
設定をconfig.jpg通りにやると、英文っぽいのが出てきたので、flag formatに入れると
YOUHAVECRACKEDTHEENIGMAGENIUS
-> shaktictf{you_have_cracked_the_enigma_genius}
Rail Mail
Joan received a secret mail from her friend, upon looking into it, she found that it contains an encrypted text and sum of key and offset. She is clueless what to do. Help her get the message.
Author : 4lph4
mail.txt
が配布される。
Ciphertext: aAknhk{w_319stf333o!itsmpG}c0_ Key + Offset = 11
問題文からして、数値のkeyとoffsetが設定される暗号らしい。こないだなんかやったな?
HousePlantCTFでちょうどやったやつだ!
Rail Fence Cipher Decode
今回の問題のほうが全然ヒントないから、これやってなかったら解けなかったと思う。今回もcyberchefのお世話になった。
keyとoffsetが足して11になるように順に入れていくと、key=5, offset=6 でflagが出た。
flag: shaktictf{Aw3s0m3_k33p_Go1n9!}
SimpleRSA [Easy]
Here's the secret message from Joan to you. Break it and Read it.
Author : 4lph4
enc.txt
が配布されます。
Here's a simple RSA challenge for you. n = 6823097956559906304718047559434503772935670794168872682087986860491266565197938988585578012131795379682740793915178580560097648572207445450501957620442660379247761L e = 65537 c = 484661494807973176484841550022162356056969394230726278907827156279573785417739620605749085238379352332325669223692676583758711843467179784519220209212809010990483
eは大きすぎず小さすぎず、特に他に気になる点もないので、n
を因数分解してみます。
まず factordb.com にかけると
724804277 9413710946631053481929229233058876904137902588796220199578081215560027062585806165966619995720300336586922201502376869335302844207978432570013597781850093
この2つに分解してくれました。
桁数が違いすぎるけど、これで復元を試みます。
from Crypto.Util.number import inverse from Crypto.Util.number import long_to_bytes import gmpy # for pow n = 6823097956559906304718047559434503772935670794168872682087986860491266565197938988585578012131795379682740793915178580560097648572207445450501957620442660379247761 e = 65537 c = 484661494807973176484841550022162356056969394230726278907827156279573785417739620605749085238379352332325669223692676583758711843467179784519220209212809010990483 p = 724804277 q = 9413710946631053481929229233058876904137902588796220199578081215560027062585806165966619995720300336586922201502376869335302844207978432570013597781850093 d = inverse(e, (p-1)*(q-1)) m = pow(c, d, n) print(long_to_bytes(m))
実行結果
$ python solve_rsa.py b'shaktictf{Gr3a7-g01ng-g1rl-Y4yyy!!}'
あら、解けてしまった!
XOR
Joan worked at Bletchley Park in the section known as Hut 8 and quickly became the only female practitioner of Banburismus, a cryptanalytic process developed by Alan Turing to break German ciphers. He came up with the idea when he noticed that every german message ended up with the same word “Heil Hitler!” . In other words the ciphertexts though different, they definitely knew that every text would end with the same plaintext
Can you use the analogy to get the flag here?
Author : ph03n1x
cipher.txt
とchall.py
が配布されます。
from itertools import cycle from time import time from hashlib import md5 from secret import flag import os def xor(a,b): return ''.join(chr(ord(i)^ord(j)) for i,j in zip(a,cycle(b))) def hashit(x) : return md5(x).hexdigest() def generatekey(sz) : return os.urandom(sz) def encrypt(m) : return xor("Message : " + m + ":e.o.m" ,generatekey(28)) if __name__ == "__main__" : f = open("cipher.txt","w") f.write(encrypt(flag)) f.close()
flag暗号文を Message : {flag}:e.o.m
という形式にて、ランダムな28byteのkey(短ければ繰り返す)とxorして出力しているみたいです。
最初の10文字とflag format,最後の7文字がわかっているので、randomのほうが大体計算できそう。
with open('cipher.txt', 'rb') as f: cipher = f.read() prefix = b'Message : shaktictf{' foot = b'}:e.o.m' key = [] for i in range(20): key.append(prefix[i] ^ cipher[i]) key_foot = [] for i in range(len(foot)): key_foot.append(foot[i] ^ cipher[len(cipher)-(len(foot)-i)]) # blute force last one key for n in range(0xff): key_full = key + [n] + key_foot flag = '' for i in range(len(cipher)): flag += chr(cipher[i] ^ key_full[i%len(key_full)]) print(flag)
既知文字が1つ足りなかったので、全部出してそれっぽいのを投げるやつをやった。
$ python test.py Message : shaktictf{û0r_c4n_b3_a_sh4dy_s0m3t1m3s}:e.o.m (略) Message : shaktictf{x0r_c4n_b3_a_sh4dy_s0m3t1m3s}:e.o.m Message : shaktictf{X0r_c4n_b3_a_sh4dy_s0m3t1m3s!}:e.o.m
正直、試行錯誤している間にx0r
かX0r
だと思ったのですが、xor
の方ばかりflagに投げてこんでいてfailerを量産してしまった…。X0r
のほうが正解でした。文字数でわかっただろうに。
Simple Hash
The 'Government Code and Cypher School' was founded with a single purpose: that of breaking the German Enigma Code, which they thought to be non-reversible. But later it was broken by her and her team.
Hashes are said to be reversible too. Do you think you can reverse this hash though?
Author : 4lph4
challenge.py
とparams.txt
が配布されます。
import hashlib from secret import flag import string chars = list(string.ascii_lowercase + string.digits) m = hashlib.md5() assert len(flag) == 5 assert all(c in chars for c in flag) m.update("shaktictf{" + flag + "}") print m.hexdigest()
hash: cb7a53dd721f4ca90b8fd3dbdabeda5a
これはflagの未知の部分が5文字なこと、使われる可能性のある文字種別が明記されていることから、bruteforceでhashを計算するのが想定解と判断。着手した時間も遅かったので間に合うかわからないけど、とりあえず書いて回し始めた。
import hashlib import string from itertools import product given_hash = 'cb7a53dd721f4ca90b8fd3dbdabeda5a' chars = list(string.ascii_lowercase + string.digits) for candidate in product(chars, repeat=5): try_string = "shaktictf{" + ''.join(candidate) + "}" print(try_string.encode()) m = hashlib.md5() m.update(try_string.encode()) if given_hash == m.hexdigest(): print(try_string) break
刺さった!
$ python solve.py b'shaktictf{aaaaa}' ... b'shaktictf{sup3p}' b'shaktictf{sup3q}' b'shaktictf{sup3r}' shaktictf{sup3r}
感想
Crypto分野、古典暗号もあると一気に楽しくなる人なので、今回の大会もめちゃめちゃ楽しかった!一つ残ってしまったけど、これは逆にさっぱりわからなかったので今の実力出しきれた感じでよかった👍