好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

Shakti CTF 2020 writeup [Crypto]

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が出ました。

f:id:kusuwada:20201206080731p:plain

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が配布されます。

f:id:kusuwada:20201206080812j:plain

めっちゃ見にくいけど、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のお世話になった。

f:id:kusuwada:20201206080940p:plain

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.txtchall.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

正直、試行錯誤している間にx0rX0rだと思ったのですが、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.pyparams.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分野、古典暗号もあると一気に楽しくなる人なので、今回の大会もめちゃめちゃ楽しかった!一つ残ってしまったけど、これは逆にさっぱりわからなかったので今の実力出しきれた感じでよかった👍