この大会は2022/4/16 1:00(JST)~2022/4/18 1:00(JST)に開催されました。
今回もチームで参戦。結果は4100点で425チーム中6位でした。
自分で解けた問題をWriteupとして書いておきます。
Seek (Rev 100)
添付のflag.txtは空になっている。添付のc言語のソースファイルの処理では、flag.txtを読み、ファイルの位置の文字をチェックしている。
何行も以下の形式でチェックしているので、それを抽出し、flag.txtの内容を復元する。
fseek(fp,<位置>,SEEK_SET);c=fgetc(fp);if(c != <ASCIIコード>){oops();}
#!/usr/bin/env python3 import re with open('seek.c', 'r') as f: lines = f.read().splitlines()[19:746] pattern = 'fseek\(fp,(\d+),SEEK_SET\);c=fgetc\(fp\);if\(c != (\d+)\)\{oops\(\);\}' msg = [''] * 727 for line in lines: m = re.match(pattern, line) index = int(m.group(1)) char = chr(int(m.group(2))) msg[index] = char msg = ''.join(msg) print(msg)
実行結果は以下の通り。
_______ ______ .___________. _______ ___ _______ ______ __ __ .__ __. _______ ___ | \ / || || ____| / /| ____| / __ \ | | | | | \ | | | \ \ \ | .--. | ,----'`---| |----`| |__ | | | |__ | | | | | | | | | \| | | .--. | | | | | | | | | | | __| / / | __| | | | | | | | | | . ` | | | | | \ \ | '--' | `----. | | | | \ \ | | | `--' | | `--' | | |\ | | '--' | / / |_______/ \______| |__| |__| | | |__| \______/ \______/ |__| \__| |_______/ | | \__\ /__/
DCTF{FOUND}
MACdonalds 1 (Crypto 200)
サーバの処理概要は以下の通り。
・self.forgeries = 0 ・self.tagged = False ・self.key = get_random_bytes(16) ・self.tagged_message = '' ・以下繰り返し ・data: jsonデータ入力 ・req_json: dataをjsonデータとして格納 ・req_json['action']が'tag'の場合 ・self.taggedがFalseの場合 ・self.tagged_messageにreq_json['message']をセット ・self.taggedにTrueをセット ・req_json['message']をhexデコードしたものをtag関数実行・表示 ・mask = bytes([0] * 16) ・messageの長さが16の倍数でない場合は、パディング ・各blockに対して以下繰り返し ・mask: maskとblockのXORをAES-ECB暗号化 ・maskの16進数表記を返却 ・req_json['action']が'verify'の場合 ・req_json['message']とreq_json['tag']の組み合わせが正しい場合フラグが表示される。
tagは一度しかアクションできない。verifyでは、tagで確認したメッセージについては認証OKとならない。tagの結果から算出する必要がある。
1ブロックのみの平文のtagは以下のようなイメージで算出される。
平文1ブロック目 ^ ([0] * 16) --(AES暗号)--> 暗号1ブロック目(=tag)
2ブロックの平文のtagは以下のようなイメージで算出される。
平文1ブロック目 ^ ([0] * 16) --(AES暗号)--> 暗号1ブロック目 平文2ブロック目 ^ 暗号1ブロック目 --(AES暗号)--> 暗号2ブロック目(=tag)
平文2ブロック目 ^ 暗号1ブロック目 = 平文1ブロック目となるような平文2ブロック目を指定すればtagは同じになる。以上のことをスクリプトにして実行する。
#!/usr/bin/python3 import socket import json from Crypto.Util.strxor import strxor def pad(message): temp = bytearray(message) if len(message) % 16: num_missing = 16 - (len(message) % 16) for _ in range(num_missing): temp.append(0) return temp HOST = "51.124.222.205" PORT = 13372 # Open a connection to the challenger with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((HOST, PORT)) # Send a message to the challenger and get the tag tag_obj = { 'action': 'tag', 'message': bytes('Hello World', encoding='utf-8').hex() } print(json.dumps(tag_obj)) s.sendall(bytes(json.dumps(tag_obj), encoding='utf-8')) tag = s.recv(1024).decode() print(tag) m2 = strxor(pad(bytes('Hello World', encoding='utf-8')), bytes.fromhex(tag)) message = pad(bytes('Hello World', encoding='utf-8')) + m2 tag_obj = { 'action': 'verify', 'message': message.hex(), 'tag': tag } print(json.dumps(tag_obj)) s.sendall(bytes(json.dumps(tag_obj), encoding='utf-8')) flag = s.recv(1024).decode() print(flag)
実行結果は以下の通り。
{"action": "tag", "message": "48656c6c6f20576f726c64"} 6c5790b632ee2947b1c5bd795b25503a {"action": "verify", "message": "48656c6c6f20576f726c6400000000002432fcda5dce7e28c3a9d9795b25503a", "tag": "6c5790b632ee2947b1c5bd795b25503a"} dctf{Paper_is_technically_made_out_of_sugar.}
dctf{Paper_is_technically_made_out_of_sugar.}
MACdonalds 2 (Crypto 300)
サーバの処理概要は以下の通り。
・self.forgeries = 0 ・self.tagged = False ・self.key = get_random_bytes(16) ・self.tagged_message = [] ・self.iv = get_random_bytes(16) ・以下繰り返し ・data: jsonデータ入力 ・req_json: dataをjsonデータとして格納 ・req_json['action']が'tag'の場合 ・self.taggedがFalseの場合 ・req_json['message']の長さが32バイト以下の場合 ・self.tagged_messageにreq_json['message']を追加 ・self.taggedにTrueをセット ・req_json['message']をhexデコードしたものをself.ivを使ってtag関数実行・表示 ・messageの長さが16の倍数でない場合は、パディング ・self.ivと、self.ivとblockのXORをAES-ECB暗号化したものの16進数表記を返却 ・self.tagged_messageにself.ivを追加 ・req_json['action']が'verify'の場合 ・req_json['message']とreq_json['tag']の組み合わせが正しい場合フラグが表示される。
tagは一度しかアクションできない。verifyでは、tagで確認したメッセージについては認証OKとならない。tagの結果から算出する必要がある。
平文Aのtagは以下のようなイメージで算出される。
平文A ^ iv1(=tag[0]) --(AES暗号)--> 暗号A(=tag[1])
平文Bも同じtag[1]にするためには、以下の条件が必要
平文A ^ iv1 = 平文B ^ iv2
以上のことをスクリプトにして実行する。
#!/usr/bin/python3 import socket import json from Crypto.Util.strxor import strxor def pad(message): temp = bytearray(message) if len(message) % 16: num_missing = 16 - (len(message) % 16) for _ in range(num_missing): temp.append(0) return temp HOST = "51.124.222.205" PORT = 13373 # Open a connection to the challenger with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((HOST, PORT)) # Send a message to the challenger and get the tag tag_obj = { 'action': 'tag', 'message': bytes('Hello World', encoding='utf-8').hex() } print(json.dumps(tag_obj)) s.sendall(bytes(json.dumps(tag_obj), encoding='utf-8')) tag = s.recv(1024).decode() print(tag) tag_json = json.loads(tag) iv1 = bytes.fromhex(tag_json['iv']) ct = bytes.fromhex(tag_json['ct']) message = bytes('Hello World!!!!!', encoding='utf-8') xor_data = strxor(pad(bytes('Hello World', encoding='utf-8')), iv1) iv2 = strxor(xor_data, message) tag_obj = { 'action': 'verify', 'message': message.hex(), 'tag': [iv2.hex(), ct.hex()] } print(json.dumps(tag_obj)) s.sendall(bytes(json.dumps(tag_obj), encoding='utf-8')) flag = s.recv(1024).decode() print(flag)
実行結果は以下の通り。
{"action": "tag", "message": "48656c6c6f20576f726c64"} {"iv": "554881b00326c77f7bafc90ad897527e", "ct": "26213ce1549bd1e418c01e05ace6aa1c"} {"action": "verify", "message": "48656c6c6f20576f726c642121212121", "tag": ["554881b00326c77f7bafc92bf9b6735f", "26213ce1549bd1e418c01e05ace6aa1c"]} dctf{ECB_is_the_ice_cream_machine_of_crypto.}
dctf{ECB_is_the_ice_cream_machine_of_crypto.}
Snailtime (Crypto 400)
サーバの処理概要は以下の通り。
・TARGET = 10 ・MAX = 10 ・N = 512 ・key: 4つの整数固定値のタプル ・count = 0 ・lookups = 0 ・C = MyCrypt(key) ・(self.n, self.g, self.h, self.x) = key ・self.lookup = [pow(self.g, -(2**i), self.n) for i in range(N)] ・C.n, C.gを表示 ・m = new_num(C) ・m: 1以上N-1以下のランダム整数値 ・ct = C.encrypt(m,exp=True) ・m = pow(2, m) ・r: 1以上pow(2,N)-1以下のランダム整数値 ・(pow(self.g, m, self.n) * pow(self.h, r, self.n)) % nを返却 ・ctを表示 ・mを返却 ・以下繰り返し ・op: メニュー選択 ・op == "1"の場合 ・n: 数値入力 ・n == mの場合 ・count: 1プラス ・count == TARGETの場合、フラグが表示される。 ・m = new_num(C) ・op == "2"の場合 ・lookups == MAXの場合 ・メニュー選択に戻る(このメニューはもう使えない) ・ct: 数値入力 ・pt = C.decrypt(ct) ・a = pow(ct, self.x, self.n) ・a == ctの場合、-1を返却 ・x = 0 ・e = 1 ・以下N回繰り返し ・pow(a, pow(2,N-i-1), self.n)が1でない場合 ・x: eプラス ・a = (a * self.lookup[i]) % self.n ・e: 2倍 ・xを返却 ・n: ptの2進数に1が含まれている数 ・nが256より大きい場合、"Thats one fat number."と表示 ・nが256以下の場合、"Eh, could be bigger."と表示 ・lookups: 1プラス
非常にわかりにくくコードが書かれているが、2のメニューは使用する必要はない。復号方法のコードはほぼ書かれており、その結果が2の何乗なのかがmの値になる。
あとはこのことを元に10回正解すればフラグが表示される。
#!/usr/bin/env python3 import socket import sympy def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) def decrypt(c, x, n): a = pow(c, x, n) y = 0 e = 1 for i in range(N): if pow(a, pow(2, N - i - 1), n) != 1: y += e a = (a * lookup[i]) % n e *= 2 return sympy.factorint(y)[2] N = 512 key = (1406745126430834211368439581427586552128513839368079375330777422350279010233921137101818450726988691168057262732590043941337227908029133975607524811099227565909552352445605144707215821110896806246996893529617429480181978275309159546378644943189838293023417359936637918158730858640390260572101852546621557080006885599631146311721451331859138297506121887787830325952441708634953348555768257126236741528355472633852552203653607703853172417814273926846522222899266871676816812119260729815492523759602496987964348605786989031714342204638679831604162373164470163182293721312107165701819445214483716237099450544614974539548198879711577259046399009099059074121716448365481422270130752107511758789011194744135899404901773436027732204863189984525085762750748955124164661344679706185466081110635241274044828067943979807155807734417834245987985856846297320515363064556415983787996822585199472909391214500400444166487063524093463852220417, 251866275144832804117904650340467630327307547943294624162209655756270474616461710900607819308591438275651230688003685366068819577019929011011295545508703008591857050628219284845515392790910741084753577414622807247270754762645744764876490428295621665384055415418169341078308493172308733595420124097494677194540909701109028540473029950111640772713847356903605994653403284524882942147938696272647334727153364783235667527051798321928751045255353667018547182541937144110088746969503093966522873124410190902718072885783072296015671501983300880465302176711365804392810324971758586422217953992618331675795569781401468259934658957480197964961765768947303650692905269349733121910054679242628384198257734418028748045690138687732945938842986119237008185398476030495662774786539266858488404701340179841538824890075144003341024405656120021006077527899583999969175371696313982716472581754564152173971431839109213808103672177137270194321293, 64483553273707701082069119474864761484140198779195205191703146328739249301059109834572879488427582977522752237968398074099234477007409347567853933386826721350256480514485971352082469112757173139860892967355208302212485705530355135722912097053805880953171949024722427667555620087032862452781768079296554995158815516828876567603012394267057043832426850055913400184738634011058897940770332793740052856097541437613719435073303700983399040651216693590347070762778435854836393343091049891939791695541625011428952697702074527974632446661775684242393743906007656648372656188229156821538851404002436023678629327262167916731577511021273973949460144971677960025602180358558582819051788340354961452773935908279347186712893939560790345719422007545257161759661122195919915290844338488580083220257144546652115017067417618577246400854456902784137631613746604771821308217617307667192441237878580298928009539089335672831178451077104170896368, 563319099256293902032388749750654192984464733635672492304301190365077376009372065959315472009535709705316690524690985053255280177975172547678109541453117178384086871012637820496164079588145248956284229006337403549473552689324499153965206786653940143576427832191594039413565022201664029290442473764023702613866104286160734416775865036413816060437076891210506338740457628013484721477061815104356120378702637640673855794011483177921108210990626777852511385576013825) (n, g, h, x) = key lookup = [pow(g, -(2**i), n) for i in range(N)] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('20.229.71.147', 1339)) for _ in range(2): data = recvuntil(s, b'\n').rstrip() print(data) for _ in range(10): data = recvuntil(s, b'\n').rstrip() print(data) ct = int(data.split(' ')[-1]) m = decrypt(ct, x, n) data = recvuntil(s, b'> ') print(data + '1') s.sendall(b'1\n') data = recvuntil(s, b'> ') print(data + str(m)) s.sendall(str(m).encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
C.n = 1406745126430834211368439581427586552128513839368079375330777422350279010233921137101818450726988691168057262732590043941337227908029133975607524811099227565909552352445605144707215821110896806246996893529617429480181978275309159546378644943189838293023417359936637918158730858640390260572101852546621557080006885599631146311721451331859138297506121887787830325952441708634953348555768257126236741528355472633852552203653607703853172417814273926846522222899266871676816812119260729815492523759602496987964348605786989031714342204638679831604162373164470163182293721312107165701819445214483716237099450544614974539548198879711577259046399009099059074121716448365481422270130752107511758789011194744135899404901773436027732204863189984525085762750748955124164661344679706185466081110635241274044828067943979807155807734417834245987985856846297320515363064556415983787996822585199472909391214500400444166487063524093463852220417 C.g = 251866275144832804117904650340467630327307547943294624162209655756270474616461710900607819308591438275651230688003685366068819577019929011011295545508703008591857050628219284845515392790910741084753577414622807247270754762645744764876490428295621665384055415418169341078308493172308733595420124097494677194540909701109028540473029950111640772713847356903605994653403284524882942147938696272647334727153364783235667527051798321928751045255353667018547182541937144110088746969503093966522873124410190902718072885783072296015671501983300880465302176711365804392810324971758586422217953992618331675795569781401468259934658957480197964961765768947303650692905269349733121910054679242628384198257734418028748045690138687732945938842986119237008185398476030495662774786539266858488404701340179841538824890075144003341024405656120021006077527899583999969175371696313982716472581754564152173971431839109213808103672177137270194321293 ct = 892497945412208607315937517659542570841531715664467865742761125833977632783459557180914688220613301954988139450451739628608818229187484466681090097043894555931542273513597259682232362507045458074525051791598871039573428443875554094900800342914656650896480391677237245824145017792975072594666037536424982445508437276900843796849520672592907735194436488158712623223139161656032941686698394507241621552229986978588294576299446574929547473126517533631491883267867997896890305221505026700838618768386098585509638436980615756664811298979058321814967411113155964992416439553434241185826639159070957830181564121878754233315739852457447641040612703454225425291732445621216215127897084454308205991647706453486255259737185616326785223493272529522105649997518167188701700079921025553797155349779186082884123923059068384392596873642740127923826173838645025003293365750167908591696866942281601769482114860297292351626157976324577911982723 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 58 Correct, onto the next one. ct = 58296834181878781106678272887893299142646845419880846015975911886550872318837112642495457100137884924723293930168166885431957288755392082245527256849704094244937182982369908381743702125615278873959756814502057619311377250539928283001662545696079418710302308433022951066935880542205747426133516234258211427211359883331882258353304441646284918080647385748114914994103292437658407701946842754661883980353736387365929750600488853227033243758158789504351087444184717507290261678350031682411716421100588177231654240457577253307612309069198500506700047988196075792753606520070971129133673667390398989888346377472868667532492037224017677904798945929569258460113929701492185623470227578909026241442789878119539842624642478310163497796312291713234133827636941219118637931805147949424842991255446575315212057199354261594203872841238870934175582079653060550363565791178475159610116844851893855455219737174767600231623456399134908384234 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 395 Correct, onto the next one. ct = 130291870676262389143202394987141072637921504168477510982649959210079000941809713510079769230895582751324545381223520083991570472755271811856522200472571283871524633695745031841646242893213960783100392942067040500695253273539966682588916607511813300430500049088992357782698767439151546976374244010854587315994906732593359715584268498319885435200771113040328139709341756139239202331276743723179058814674070196927552530307562429224659603846931018008858058227649064860419436207575436822824797734450407018997413509799531781793313170382913666145506052802994286639202057467958140317089212156468246331648196751259736331031544550948097867788775492744346302826544801016418006777168987064142162896253953148344014674156965922115076997438020460209189666328525909096525131806433835215740904958558312189019257710036511157278781738012701032979882641031269854130055083884837716583236072445131059329232444876086837904373021607085828951369307 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 284 Correct, onto the next one. ct = 32683554714774524382167563410908457799859895697200090605813545123410352372154784864591118931372895074482607993552674561719329177538312173600706880038739889906488991541403925952565433110713432426214904740274257495845657630453552809300186724759025929379212840175275996727196804236785613466093943184089138446028061531513992520649145278440756352385536973652416433162740093095344497046523449833530226716860832665506213171348263627601873392393840212459170651995917208843153789724205398863231546051810334335570734444821677790194981645149087091672976981666390643898292688055227362105139850277726763374180747534396394689151275090322602600865778412875032419345054534398126900095434932557532739481269309410784782368705456238182841236932800684080969424274588098823509595922037331637009483759776659261812494764577035218686102847503088376584667303278357472846194449508098324658117429820271673565866332838405004495175532178632293431307566 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 195 Correct, onto the next one. ct = 963129330020860682116033934976577406299452583047761447056186133243546156335631631747065614833903123986150716711631045814121693432407938517060718626050729234496751549656427509109264605263146493287732886056254108498342909555991002272817140670650452796310125204041577405994894020690464936402053823412421715446401479824184038252489914986981359573555579485270315628049664875921889476800021664941061591867895882770852619926561305287149662851966701880669877416631893658366033938162470374695117008084964645956385585238363342352910287999696951397361430021053516503971019846216225357160300536497498202315670639152356041400339692722646239008193913148790022544746058149034250684674265115184064900262372638440135925568761950988350979020639649114918244616238283257354672296050790822247383629997280126643803712049665925080830016159572671935544123444713130876639557016434409982305867104145405285096243772127587270298975974850751970280745386 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 19 Correct, onto the next one. ct = 290944265381311193856606958572445108945292566585254983747492944627762832512767015892853965487122625951305895514461452933215983141455845695276747018447704176231357288360964407015647357736219449869043920525825900509050411463270573971075550249621539458914663945454418623045968183107432874050581856258989855345642336417676259897222215385385983773928598947176871564945435493052492220169297277942186198981987486278068502590165469517925092397954834397640322345081854197264841244967585373096381433005240746896907425138452926787678420177754747040990552857040846685507400406834109275129490730218972408162290363115178682222829411143944792173740616281353940116275160669016381908193714489932588707657585028097708069936521310854532376911188560611691634420821943808767216061125061344554892441767580755689314855044007531888131967973670844076255374421446837462025809797797167868029957152770165538215433203660708538826326852415983750698421206 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 469 Correct, onto the next one. ct = 519120726358120522593732657743868275452287949006017744797334753555286810987654453202289918545927713320685641812601469251528390853316796169452296753788436197839664078675009003124521455136485056719122219019896338665442702928539587601492970497709966652013050814685408740511274607694205468691722896246089196887665437209845405516482918605780714534010560215737232928403698413713533284371182553873630659760489591919270816722775243850878205641763525348363185309450797947282519841166757493994665121911201416373844700490819236105187849746120723379618311177765398472710337049070938429083786086905914404890294860199331487557408966160343375125424245794531046330159018425596021484183130069038004070103187087131564024985842490383574547826491197180119384408829297145688013496169921224038874380624483634211789497882174812737392537284209187081298135805810387458551389092242266048934817776760620425709923467214196921866202858613048804269489709 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 170 Correct, onto the next one. ct = 258608240605907790056040152217126564046011008047440324128824718831331429917283399793278019052647514124770190849540057910816160903978809369949746827065389286200521635759188028842325575558598658374214680568187031368146249073619777994085627896878769220763614212472265111674078223238064926133306191572486328772412038351075225987226366728290684713689987854933410450011316228637158897172438001194795156703056306914217775220352198360944455579069157487339403252668026007418297860476128814371952947308899636451796220372572703240685845110644138793540188047364855626100366972420196550481217892857657084378962118490944490858287153428259317291084589946151629305593144846130760249537780082692897139002304893992721316208968994054670197978444712709191069894904368673300256869411362123192246038803006175809495193168420462803968859985870470499837279171051590602808164474902819258033252874996305537966660214765157908011372105256351135121455758 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 144 Correct, onto the next one. ct = 551316316220067811587308361314873337803862027439865911012547727632670357818873890568019380452419703760457149255241399747935732892679741816423831801743579946238313796380950048891957579940969452444711721594956225247995848400693386536574045631557244618528761872097665402069953593381165183452643153822428602906108195466256162176467686182850077709627095172067773190473342333346736637661860427220007492564291260377705486664090418007182804530543095965369128783362761461525346000359195705570031243794110039257976534655415725069640840039296851038760385592004015776379946351340508715882617102195647395962790702106578766106221975030855900368947293695167613984499684401479248730417393502536541650911307556776617569540647807211928668065124697766401653896119299706412087101995740053390104984761188899101878560327360294454457059834673719718348255591650421287166709564052203296127302892112952929032777507877002468526628991260970253965945468 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 295 Correct, onto the next one. ct = 763942693330246267478927112356204285610683007522140184575558016689697740068826237038023462721064325105405287354310550728551509633260408479264371989327385316671012282954688511704154248434774691253214692851679548590413757829090181204634450357456911009600969023735013134852871412206636825737807833032887955025609616214927121669694034275579967928714877445143341852944699914803868035162016176615519079912976318791447055927039037805017410253423586396419195734077737022950998120436852668833288295842819192486476181398491795461842270134636408143767629112601060488252256029238922361286293125254613172969707193565631942269172275441533410511981845139107909775761531291986310716375178899749850629348785260779915796450299663919714365275961648872256252261233165450701080046381940744595221816863933203728793467788394129592573855803714458882781179752617915389595352242214749510515711194122720264989602588260198432124355318899961239709698243 Options: 1 - Guess number. 2 - Send ciphertext. > 1 What number did i encrypt? > 145 Correct, here is your flag: dctf{1_r3fus3_t0_us3_sm4113r_numb3r5}
dctf{1_r3fus3_t0_us3_sm4113r_numb3r5}