この大会は2021/6/5 15:30(JST)~2021/6/7 15:30(JST)に開催されました。
今回もチームで参戦。結果は2602点で533チーム中46位でした。
自分で解けた問題をWriteupとして書いておきます。
check_flag (Reverse Engineering 100)
$ strings checkflag.exe | grep SHELL SHELL{bas1c_r3v}
SHELL{bas1c_r3v}
keygen (Reverse Engineering 200)
チェックしている文字を並べていく。
SHELL{s3nb0nzakur4_k4g3y05h1}
anonym (Web Security 100)
http://3.142.122.1:8887/robots.txtにアクセスすると、次のように書いてある。
User-agent: * Disallow: /yfhdgvs.txt
http://3.142.122.1:8887/yfhdgvs.txtにアクセスすると、フラグが書いてあった。
SHELL{n0_ro80t5_4llow3d_50886509749a98ef14ec2bc45c57958e}
Under Development (Web Security 100)
HTMLソースを見ると、コメントにこう書いてある。
<!--TODO: Develop auth, buy some cookies from the supermarket-->
クッキーにはprivilegeキーにdXNlcg%3D%3Dと設定されているので、base64デコードする。
$ echo dXNlcg== | base64 -d user
"admin"のbase64エンコードデータを設定してみる。
$ echo -n admin | base64 YWRtaW4=
YWRtaW4%3D をクッキーに設定する。
SHELL{0NLY_0R30_8e1a91a632ecaf2dd6026c943eb3ed1e}
Collide (Web Security 200)
shellパラメータの値のsha256とpwnパラメータの値のsha256で異なる文字列で衝突を発生させるようなコード。次にようなURLにして、パラメータに配列を使って、同じオブジェクト扱いにする。
http://3.142.122.1:9335/?shell[]=a&pwn[]=b
SHELL{1nj3ct_&_coll1d3_9d25f1cfdeb38a404b6e8584bec7a319}
login (Web Security 300)
http://3.142.122.1:8889/main.jsを見たらこう書いてある。
function checkIt() { var user = document.getElementById("username").value; var pass = document.getElementById("password").value; if (user != "din_djarin11") alert("Only for user: din_djarin11"); else { var s = Hash(pass); if (s == "9ef71a8cd681a813cfd377817e9a08e5") window.location = "./" + pass; else alert("Invalid login"); } }
Hashはmd5の処理になっている。9ef71a8cd681a813cfd377817e9a08e5をCrackStationでクラックすると、"ir0nm4n"であることがわかる。以下の情報でログインする。
Username: din_djarin11 Password: ir0nm4n
「login」をクリックしたら、ir0nm4nというファイルがダウンロードされ、このファイルにフラグが書いてあった。
SHELL{th1s_i5_th3_wa7_845ad42f4480104b698c1e168d29b739}
Hidden inside (Forensics 100)
jpgが添付されている。
$ zsteg mystic-fairy-girl-magical-dark-cgi-3840x2558-5287.jpg imagedata .. file: VAX-order 68k Blit mpx/mux executable b1,r,lsb,xy .. text: "NarUTO_Is_hokaGE"★ b1,abgr,msb,xy .. file: PGP\011Secret Sub-key - b2,r,msb,xy .. text: "z@(Z}v-J" b2,g,lsb,xy .. text: "'vV4Mc$v)7" b2,g,msb,xy .. text: "zA(Z}}-J" b3,bgr,msb,xy .. text: "F7JNF8qb" b3,abgr,msb,xy .. text: "g{6G|DGt6gs" b4,r,lsb,xy .. text: "c$UR%R$C#5D2%E#%C#\#$C$UU#EUU%DR'C3B5'CS" b4,r,msb,xy .. text: "\"Ll*\"bNd**" b4,g,lsb,xy .. text: "tEUTET5dDEUDEUDES4C5TEUU4UUVEVdGd4TE7SS" b4,rgb,lsb,xy .. text: "H$eWUrF#TWF" b4,bgr,lsb,xy .. text: "XBd'UuVBS'T" b4,rgba,lsb,xy .. text: "4o$o4o4oU"
SHELL{NarUTO_Is_hokaGE}
Cold Compress Inside (Forensics 200)
PNGファイルフォーマットの後に、ZIPが付いている。解凍して展開すると、以下の2つのファイルが入っている。
・o ・o.exe
$ ./o Hello, World! CRazy_MosQUIto_nEEDS_odoMOS
SHELL{CRazy_MosQUIto_nEEDS_odoMOS}
Hidden inside 2 (Forensics 200)
Stegsolveで開き、Extract ViewでGreenのLSBにチェックを入れると、PNGが見えた。エクスポートした画像にフラグが書いてあった。
RayMONd_redDINTON_is_nOt_iLLYA
SHELL{RayMONd_redDINTON_is_nOt_iLLYA}
encoder (Cryptography 100)
シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。
Rotation 7: SHELL{P1Z_W3AR_4_M45K}
SHELL{P1Z_W3AR_4_M45K}
EASY-RSA (Cryptography 100)
nをfactordbで素因数分解する。
n = 31415926535897932384626433832795028841 * 56129192858827520816193436882886842322337671
あとはそのまま復号する。
from Crypto.Util.number import * n = 1763350599372172240188600248087473321738860115540927328389207609428163138985769311 e = 65537 c = 33475248111421194902497742876885935310304862428980875522333303840565113662943528 p = 31415926535897932384626433832795028841 q = 56129192858827520816193436882886842322337671 phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m) print flag
shell{switchin_to_asymmetric}
Subsi (Cryptography 100)
換字式暗号でテーブルがわかっているので、元に戻す。
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ{}_1234567890' key = 'QWERTPOIUYASDFGLKJHZXCVMNB{}_1234567890' encrypted_msg = 'HITSS{5X65Z1ZXZ10F_E1LI3J}' flag = '' for i in encrypted_msg: index = key.index(i) flag += alpha[index] print flag
SHELL{5U65T1TUT10N_C1PH3R}
Algoric-Shift (Cryptography 100)
3つに分けて並べ直しているので、元に戻す。
ciphered_txt = 'HESL{LRAT5PN51010T_CNPH1R}3' li1 = [ciphered_txt[i] for i in range(0, len(ciphered_txt), 3)] li2 = [ciphered_txt[i] for i in range(1, len(ciphered_txt), 3)] li0 = [ciphered_txt[i] for i in range(2, len(ciphered_txt), 3)] flag = '' for i in range(len(li0)): flag += li0[i] flag += li1[i] flag += li2[i] print flag
SHELL{TRAN5P051T10N_C1PH3R}
haxxor (Cryptography 100)
フラグは"S"から始まることを前提に、XORキーを求め、復号する。
enc_str = '0x2-0x19-0x14-0x1d-0x1d-0x2a-0x9-0x61-0x3-0x62-0x15-0xe-0x60-0x5-0xe-0x19-0x4-0x19-0x2c' enc = [int(code, 16) for code in enc_str.split('-')] key = enc[0] ^ ord('S') flag = '' for i in range(len(enc)): flag += chr(enc[i] ^ key) print flag
SHELL{X0R3D_1T_HUH}
BruteforceRSA (Cryptography 200)
nをfactordbで素因数分解する。
p = 320163545884759912335372936276795190799 q = 329022220307104142121947724162904472797
あとはそのまま復号する。
from Crypto.Util.number import * import json with open('values.json', 'r') as f: data = json.load(f) e = data['e'] n = data['n'] c = data['enc_msg'] p = 320163545884759912335372936276795190799 q = 329022220307104142121947724162904472797 assert n == p * q phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m) print flag
shellctf{k3y_s1ze_m@tter$}
arc-cipher (Cryptography 200)
暗号の処理概要は以下の通り。
・k: keyのASCIIコードの配列 ・s: 0~255の配列 ・kを繰り返し、255要素分作成 ・key_new = key_stream(flag,key_sche(s,k)) →flagの長さだけに影響するので、keyはわかる ・flagとkey_newとXORをする。
key_newを求め暗号データとXORをとって復号する。
def key_sche(s, k): j = 0 for i in range(256): j = (j + s[i] + k[i]) % 256 temp = s[i] s[i] = s[j] s[j] = temp return s def key_stream(s, flag_len): ks = [] i = 0 j = 0 status = 1 while(status == 1): i = (i + 1) % 256 j = (j + s[i]) % 256 s[i], s[j] = s[j], s[i] t = (s[i] + s[j]) % 256 ks.append(s[t]) if len(ks) == flag_len: status = 0 return ks key = 'MANGEKYOU' s = [] k = [] for i in key: k.append(ord(i)) for i in range(0,256): s.append(i) if i >= len(key): k.append(k[i % len(key)]) hex_enc_txt = 'a7 f9 de 54 29 92 7f 61 9a 7a 5f f3 f4 1a 88 a1 8f ca 97 47' enc_list = [int(code, 16) for code in hex_enc_txt.split(' ')] key_new = key_stream(key_sche(s, k), len(enc_list)) flag = '' for i in range(len(enc_list)): flag += chr(enc_list[i] ^ key_new[i]) print flag
SHELL{S4SKU3_UCH1H4}
PowerRSA (Cryptography 500)
qはpの次の素数なので、近い数値。Fermat法で素因数分解し復号する。
import socket from Crypto.PublicKey import RSA from Crypto.Util.number import * def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) 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 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('34.92.214.217', 8887)) data = recvuntil(s, 'Encrypted Flag =') data += recvuntil(s, '\n').rstrip() print data pub_data = '\n'.join(data.split('\n')[1:-1]) pubkey = RSA.importKey(pub_data) n = pubkey.n e = pubkey.e c = int(data.split('\n')[-1].split(' ')[-1], 16) p, q = fermat(n) phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m) print flag
実行結果は以下の通り。
Public Key = -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA/WCAA3zWDqjWTHo3DLd0 gd0beYxANUEl9Qi7l5NH5nBe/z+KKLrZmJwJkWY4g+RSiQAkLBzOSdrJ0Sxr0TMo qj5CfcZmbEJS2OOIetVMnWUCQFkl54i7a5UA7KujiV9fFNz/Uoqz6MP/7FG8kaK/ xtxQy9Dsb1R0MvmZMJkVSViHBDqaAtoHFgd2R//clIcFl5/cA1qYXffvGwIkVKbQ UOXUsegrmqUr+xdc1cXqbEr+agcmJ8JGl/2gxixVie1lU7wi/gJ+YUh5ObPIlkdP +oGZU9/EmzJBDXQVJVlFjziUdAzPvTk1DeEUM7Vmkmm1b3ohQmWXlXyI3drRmN+V A5na05WKGjZd759y9/eHJzT5Sq/viPhnQGR9JcJX+ipRyFPdUuA6rln82pTF5lx/ tkEV/l2SyODQaucSd1K2a+2ggY2yekyi51EqlHRYO4yTbi/mNM7hLlaK88sSRtbk Lyvl+z+6YBuFK3GkDEJsgHZ02AIb+j3vHu/Cq0QJba5VyTbLHPzru2RNdE32/gKq 9Q6wsBZuNu8xGHRp6FlPYi1PZWMi17RykHMAdybFdbzQBCNlNIAtDoB8DaBcENdq +ek/RIBNiFTTo+DGoZb76+st75dhWlqSgwv1UTS7Xvexe4ylbzFg6qwMxzQBldKe z3fU0Jz1OViv8CmP2KPUvS0CAwEAAQ== -----END PUBLIC KEY----- Encrypted Flag = 0x5452995ea53f660d454d388f9fbffa64cb56125661d53bef63d765a5e009e91ad8ea1672a8c57d881dbd2d26d0cb2f7e78f5365530598874f1bb1d8088a07e01fba90b2229d4910e03b3c8b96d813e4fb3863e74365e0f67dbbc11fd9dfeb8a54113fb5c1ee0105411cc123e931562da8772c9b556bd2dff3822b331f605c3976a47d4c9acf155303d14bc745aeda985e5f4949ac59eec74a7a1063e629684a7bf303fb9b0dfb102ad6ce4982f2a9aa9f01d402006c7e32a247965a2649326eaaa20c141086ec134d5efdbef73c7ffd8df0fce752076e77b1e9241c077cf0115fc159b081123003a2a46e106dd9655fcede162f536c5edf743cdc92344cb53701d5680da7f9abc431a28bfb17718abac9099e8e3c5eb7e03ae918f35b473b27d9f2643e07d94ddbbe13e44e00b21fa5267d5c96780cf2bbb2eb8e46894b16ec7b645a3a5d63ac54e4f245c64a00259ffa313f60000bcbf0b2506ca403ea89ff1fbc2f03bf9abe55b72553e82a2686186f14b01661bb45add9e0b2e288534ddf702a8d395f59e7cbfabdf9f8c0fa41d40df0f922005faa538178beccc7ba8edb2ae45b232144f1d90e45198920506b0839768458eb6297170a55267393144adc10931d8a0506894195dd37b3f55d1ce5cf6b5fabe4bece7cdcb416326bbe91b4764f8c54d48b5310536227054c4481a6b88fd3afadf2eb7c6b9c3eb436aa7fb80 ��shell{entr0py_1s_th3_k3y_L9mlIsTtB557I/Nh4gqL87MxcugLIfZI}
shell{entr0py_1s_th3_k3y_L9mlIsTtB557I/Nh4gqL87MxcugLIfZI}
Puny Factors (Cryptography 500)
nが素数で復号の方法もコードに書かれているので、その通りに復号する。
import socket from Crypto.PublicKey import RSA from Crypto.Util.number import * def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('34.92.214.217', 8889)) data = recvuntil(s, 'c =') data += recvuntil(s, '\n').rstrip() print data pub_data = '\n'.join(data.split('\n')[:-1]) pubkey = RSA.importKey(pub_data) n = pubkey.n e = pubkey.e c = int(data.split('\n')[-1].split(' ')[-1]) phi = (n - 1) * (n - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m) print flag
実行結果は以下の通り。
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2nSjmSmkvJPpi1o84hPS UeLyokMny17+g9UPuDoZrAbnrl2xdhusBV9+8W9WDmhW6veAclKgMVd9/2x2ebgK Mf89KnK7AnmfNrVEJy8R3+NEXlyJKTSt/hKbXehjieG/4dxAhP0V2LFvVlEpmL4R YAtMFvS4Lo51RBmB6iPhDC/nKsIoPKzfvz2WfuIaAfcOnVz4vmXAp+TjsvLPW3+N 0g6iBSJx7B55rUwe0Y0ahwT/W8KUCVTouXwehk3b4nBjrOYdHSYpzuyw6SmDj+eN lPIHqCYSW2lZQmukAU3UYQUrr+NYMyXXQTyaKi7BVFgmVWerSYF+8oSmR6hFI1fb hg5duL7MtdBtEGqFQOMxqSnJa2RUvCd/nMYQKcTrrZkwMBFC2OEb31XTOhZSB37M 1CD94tlnI2oaFIsVconvjiIQZpc62CN8XhZ0oNcYpjKAq/d9c+/DPwxuA72IaVOD u8MbI164l96ublyymrjgP1YgCKVDbKURr6NPX4BRcfNnHo1sNdqe66inCnizYFq+ FVWfEvABgF3EInh4cM0aPZuQVqjn1AisIReRijalpIGs6BDDylwLcy+5XBPayhW4 DH/1sV6I24Mng0jTxUHCHfEmXyWUrv1kEju2fdvND5jhkMZD76/fjEVAy9qG2FYu BIJ7+T7fyoNJIEI7Ln0RbDUCAwEAAQ== -----END PUBLIC KEY----- c = 712650793884864492236401779887854343514338980705556904384583635379921781775791476359089644252586162352951567974333798735775383588441361100927769502157979122933682222602561758694634367391425931210068297806098529984861489065393067076196742811160719643775346750973746300835707143917750050508990844358252110207018069732320100976462811671896115206294125219396178012100388503993504857110924171621594485378878522142340674720671869066009771119465908286718532904550833630747962923189543986447609793111421899624049244649791213008567770802620331962848971176592431623309579517048519579740830776404007284730003387380930664176325343315736821834716194599111727905527790135786793309119990528975630001845350418976406958409400134357226290464043778780186385143533341800651386940304672672218721709658838907591564351116543227080347722097656330372969524593698876725199602929284402598366145317090493537920136983554290322114336668410829259304262718307634397027332448152021868502103300830439437806541409351876180207512373278480796300894865154181597920273151052886393212006388538339923681989883699825061737212980724577521727445453513638976649646711882473846961421608268818690023062626277577817118857821267729463466792740767849255815542697287582982566395816632 shellctf{pr1m3s_ar3_sup3r_int3re$tinG}
shellctf{pr1m3s_ar3_sup3r_int3re$tinG}
Vuln-AES (Cryptography 500)
暗号化は以下の文字列に対して行われる。パディングは長さが16の倍数の場合行われない。
[16-bytes] + [入力] + [flag]
フラグを1文字ずつはみ出させ、ブロック単位で暗号化したデータが一致するものを探すことを続けることによってフラグを割り出す。
$ nc 34.92.214.217 8885 Crewmate! enter your situation report: a xX+NDjg0X9tmJLobdQv9k9ds/4i9bLo8u6OoRjBMuldg6rjc+L5XlwAejtua+qoK $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aa xX+NDjg0X9tmJLobdQv9k0b0FVhqId3/a0bVJY6DW0f3xfscR3zfjDwfjiUWyAd7 $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaa xX+NDjg0X9tmJLobdQv9k2Rckh577ORwULBDkusPTDzydgpQE6Y6XTNE8EAJYj0X $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaa xX+NDjg0X9tmJLobdQv9kwIDub07Cuvooeb4r0qBYZdXANVJGF5XWUZtYaOp8R5R $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaa xX+NDjg0X9tmJLobdQv9k4yLxzWHDyrYSsvCBp9FyyB3CeHBUH8eopPhHFFTWYLP $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaa xX+NDjg0X9tmJLobdQv9k09ZEA+t4ZhMy+jT+T4XOk94KEhYfi3NHWY5aIclyLSu $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaa xX+NDjg0X9tmJLobdQv9k5GBwEvqG6CM9+6uoDmrQ0/0oUIaOYWdT9eiyrSVrU6n $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaa xX+NDjg0X9tmJLobdQv9k2Oso+o93pnbThKtFswQkyCHZfZapk8YdLtgwFJk6kls $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaa xX+NDjg0X9tmJLobdQv9k+2ltZKmKyrSOcHkZJM/mlSj9bdYMgopYPZohpXbkaOs $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaa xX+NDjg0X9tmJLobdQv9k/LQkrNK7YupRArfgwOhrvMZD+CsUsQXEa0aZVcsH5pq $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k/8KHf21mRN+RVk3pezy9qEh22WqGpMYPIsNyQyMRgqD $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k1ogVkj8E8TuHlXfa5NXsMvugb2sTfvfrBCBSOvexZ6L $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k2X2qXlJTJABFnkdpGYVqS3lbOXXgZh4ORmapkbU0pJ5 $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k6uJw5r5T1+MLtgzrH/prSIUnYCI5sIrshw0ZG6I6Cn3 $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k3AGFRiZTGeG8/XEsLctVgoQecf4yt/Ef7Oon84ND8+s $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k/AV/+SjM/eHGxK2+lZgigM83+M72twqaKyBgeUW2zjo $ nc 34.92.214.217 8885 Crewmate! enter your situation report: aaaaaaaaaaaaaaaaa xX+NDjg0X9tmJLobdQv9k/AV/+SjM/eHGxK2+lZgigPXbP+IvWy6PLujqEYwTLpXYOq43Pi+V5cAHo7bmvqqCg== →64バイト
フラグは以下のようなブロックの構成のイメージ。
0123456789abcdef ???????????????? XXXXXXXXXXXXXXXX FFFFFFFFFFFFFFFF
flagは16バイトであることがわかる。
0123456789abcdef ???????????????? XXXXXXXXXXXXXXXA XXXXXXXXXXXXXXXF FFFFFFFFFFFFFFFP
import socket import base64 def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) flag = '' for i in range(16): for code in range(32, 127): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('34.92.214.217', 8885)) try_pt = 'X' * (15 - i) + flag + chr(code) + 'X' * (15 - i) data = recvuntil(s, ': ') print data + try_pt s.sendall(try_pt + '\n') data = recvuntil(s, '\n').rstrip() print data try_ct = base64.b64decode(data) if try_ct[16:32] == try_ct[32:48]: flag += chr(code) break print flag
実行結果は以下の通り。
: Crewmate! enter your situation report: shell{kinda_susx xX+NDjg0X9tmJLobdQv9k67DKHeF54A/Dl4yLqvdeXc83+M72twqaKyBgeUW2zjo Crewmate! enter your situation report: shell{kinda_susy xX+NDjg0X9tmJLobdQv9k2GUUpmSt/pkv1mwX2MCxr883+M72twqaKyBgeUW2zjo Crewmate! enter your situation report: shell{kinda_susz xX+NDjg0X9tmJLobdQv9k9YBp9lWZiOWtrScZf0P5v083+M72twqaKyBgeUW2zjo Crewmate! enter your situation report: shell{kinda_sus{ xX+NDjg0X9tmJLobdQv9k/zabogRr3MjhFPzSiLZ9zY83+M72twqaKyBgeUW2zjo Crewmate! enter your situation report: shell{kinda_sus| xX+NDjg0X9tmJLobdQv9kzkXxh9nJyHpbyIhVXR7i9U83+M72twqaKyBgeUW2zjo Crewmate! enter your situation report: shell{kinda_sus} xX+NDjg0X9tmJLobdQv9kzzf4zva3CporIGB5RbbOOg83+M72twqaKyBgeUW2zjo shell{kinda_sus}
shell{kinda_sus}