この大会は2022/3/5 18:30(JST)~2022/3/6 18:30(JST)に開催されました。
今回もチームで参戦。結果は 6979点で302チーム中15位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (easypeasy)
問題にフラグが書いてあった。
CTF{Welcome}
Join our discord (easypeasy)
Discordに入り、#you-should-come-hereチャネルのメッセージを見ると、フラグが書いてあった。
CTF{Welcome_to_ectf22}
whatisthis (Misc)
zipを解凍し、展開されたpngファイルを見たが、pngの形式にはなっていない。
$ file whatisthis.png
whatisthis.png: POSIX tar archive
$ mv whatisthis.png whatisthis.tar
$ tar xf whatisthis.tar
中身を見てみると、各ディレクトリに以下のような構成になっている。
・json ・layer.tar ・VERSION
各layer.tarを解凍・展開してみていく。
a4ddd19c83968edda65f7205efc664cab87fe1522d7bec7252384aa259f37b39\layer.tarを展開すると、a4ddd19c83968edda65f7205efc664cab87fe1522d7bec7252384aa259f37b39\layer\etc\m\m\nothing.txtにフラグが書いてある。
CTF{D0cker_ent3r5_the_p4rty}
Not really random (Misc)
2022/3/1 00:00:00のUNIXTIMEからブルートフォースで同じ乱数が出るseedを探し、フラグを出力する。
import random import time import hashlib seed = 1646060400 while True: random.seed(seed, version=2) rand = random.random() if rand == 0.33567959567961436: break seed += 1 while True: rand = random.random() has = hashlib.sha256(str(rand).encode()).hexdigest() flag = f"CTF{{{has}}}" if "7a2" in has: print(flag) break else: print(f"Bad random value: {rand}")
実行結果は以下の通り。
Bad random value: 0.8913897703358419 Bad random value: 0.3032054069265432 Bad random value: 0.6860829464688437 Bad random value: 0.2658087107328536 Bad random value: 0.8903005048882441 Bad random value: 0.914630909612433 Bad random value: 0.9688578899818961 Bad random value: 0.7925090397955323 Bad random value: 0.10136501216336935 Bad random value: 0.568451491382639 Bad random value: 0.16898065821921437 Bad random value: 0.5541712073794856 Bad random value: 0.029926361216790154 Bad random value: 0.18218590474521223 Bad random value: 0.49713845657579536 Bad random value: 0.7631162105077507 Bad random value: 0.7386939443532723 Bad random value: 0.5815609491717452 Bad random value: 0.5905894610211082 Bad random value: 0.09018146469820387 CTF{a13a806d175841731b24a01e9af240bc81750967542550a4b3bb77a29a9d291b}
CTF{a13a806d175841731b24a01e9af240bc81750967542550a4b3bb77a29a9d291b}
Packman 1 (RE-pwn)
$ strings chall | grep CTF CTF{ee_lo_p3ll3t_kh4o}
CTF{ee_lo_p3ll3t_kh4o}
Lost Password (RE-pwn)
$ strings main | grep CTF CTF{HaC
Ghidraでデコンパイルする。
undefined8 main(int param_1,long param_2) { int iVar1; long in_FS_OFFSET; int local_3c; int local_38 [4]; undefined4 local_28; undefined4 local_24; undefined4 local_20; undefined4 local_1c; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_38[0] = 0x9e; local_38[1] = 0x86; local_38[2] = 0xa5; local_38[3] = 0xb2; local_28 = 0xa0; local_24 = 0xb4; local_20 = 0xa1; local_1c = 0xd0; if (param_1 == 2) { printf("Checking %s\n",*(undefined8 *)(param_2 + 8)); iVar1 = strcmp(*(char **)(param_2 + 8),""); if (iVar1 == 0) { for (local_3c = 0; local_3c < 8; local_3c = local_3c + 1) { putchar(local_38[local_3c] + -0x53); } } else { puts("WRONG!"); } } else { puts("What you doin?? Need Argument"); } if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) { return 0; } /* WARNING: Subroutine does not return */ __stack_chk_fail(); }
引数に"mingw.exe"を指定すれば良さそう。
$ ./main mingw.exe
Checking mingw.exe
K3R_MaN}
CTF{HaCK3R_MaN}
You're too blind to see (Web)
HTMLソースを見ると、スクリプトにこう書いてある。
function generateHash(plainText) { var md = forge.md.sha256.create(); md.start(); md.update(plainText, "utf8"); var hashText = md.digest().toHex(); return hashText; } : function checkLogDetails() { var username = document.getElementById("Uname").value; var password = document.getElementById("Pass").value; if (username == "Rick Astley" && generateHash(password) == "1b638a7a9a56a4485ebd95816d1d8abf0576cdbf39854c6dd5cb47c3c53f48be") { redirect_site = 'redirect'+ password + '.html'; window.open(redirect_site, '_blank'); } else { window.open('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); } }
以下を入力できればよい。
username: Rick Astley passwordのsha256: 1b638a7a9a56a4485ebd95816d1d8abf0576cdbf39854c6dd5cb47c3c53f48be
またコメントにこう書いてある。
<!-- bmV2ZXJnb25uYWxldHlvdWRvd24wMTIyQGdtYWlsLmNvbSBrbm93cyB0aGUgcGFzc3dvcmQ -->
$ echo bmV2ZXJnb25uYWxldHlvdWRvd24wMTIyQGdtYWlsLmNvbSBrbm93cyB0aGUgcGFzc3dvcmQ= | base64 -d nevergonnaletyoudown0122@gmail.com knows the password
nevergonnaletyoudown0122@gmail.comにメールで連絡をしたら、以下のメッセージが返ってきた。
never_gonna_say_goodbye
$ echo -n never_gonna_say_goodbye | sha256sum 1b638a7a9a56a4485ebd95816d1d8abf0576cdbf39854c6dd5cb47c3c53f48be -
ハッシュが一致した。以下の情報でログインしてみると、フラグが表示された。
username: Rick Astley password: never_gonna_say_goodbye
CTF{W3r3_N0_57r4N63r5_70_10V3}
Hack the Auth (Web)
HTMLソースを見ると、スクリプトのこう書いてある。
var userAuthentication = function() { var username = document.getElementsByName('username')[0].value; var password = document.getElementsByName('password')[0].value; var hash = sha256(password); if(hash === "dfbec338b51c5643ba481625e1075236d3a9a07fbd6393763f253e99024958a4" && username === "admin") { window.location = "./q1?username=admin&password=" + password; } else { alert("Invalid username or password"); } };
以下を入力できればよい。
username: admin passwordのsha256: dfbec338b51c5643ba481625e1075236d3a9a07fbd6393763f253e99024958a4
CrackStationでクラックする。
Thisismypassword
以下の情報でログインすることができる。
username: admin password: Thisismypassword
ログインすると、このようなメッセージが表示される。
Congrats! You got the admin password!
クッキーのHack-the-Authキーにフラグが設定されていた。
CTF%7BSHA256_AND_WEB%7D
CTF{SHA256_AND_WEB}
Favourite Website (Web)
このページを12893422回目に閲覧したときにフラグが表示されるようだ。リロードすると、回数が増えていく。
Cookieを見ると、_gata~_gatoまでbase64文字列が設定されている。これを見ていくと、_gatjに回数を含むデータが含まれていた。
$ echo c3RpbGwgY2Fubm90IHNvbHZlIHRoaXMgdGFzaz90aW1lcz0wMDAwMDAwMSZpZD0xNzhiNzI2Mi1kNTIzLTQyMDktYjY0OS0yMTIyZDBmMzFmZDk3 | base64 -d still cannot solve this task?times=00000001&id=178b7262-d523-4209-b649-2122d0f31fd97
timesに12893422を設定する。
$ echo -n "still cannot solve this task?times=12893422&id=178b7262-d523-4209-b649-2122d0f31fd97" | base64 c3RpbGwgY2Fubm90IHNvbHZlIHRoaXMgdGFzaz90aW1lcz0xMjg5MzQyMiZpZD0xNzhiNzI2Mi1k NTIzLTQyMDktYjY0OS0yMTIyZDBmMzFmZDk3
Cookieの_gatjに以下を設定する。
c3RpbGwgY2Fubm90IHNvbHZlIHRoaXMgdGFzaz90aW1lcz0xMjg5MzQyMiZpZD0xNzhiNzI2Mi1kNTIzLTQyMDktYjY0OS0yMTIyZDBmMzFmZDk3
リロードしてみると、フラグが表示された。
Congrats! You got the flag: CTF{C@@kie$_@re_the_be$t}
CTF{C@@kie$_@re_the_be$t}
THE CAT KNOWS THE CULPRIT (Forensics)
$ exiftool clue.jfif ExifTool Version Number : 10.80 File Name : clue.jfif Directory : . File Size : 113 kB File Modification Date/Time : 2022:03:05 18:47:32+09:00 File Access Date/Time : 2022:03:05 18:47:43+09:00 File Inode Change Date/Time : 2022:03:05 18:47:32+09:00 File Permissions : rwxrwxrwx File Type : JPEG File Type Extension : jpg MIME Type : image/jpeg JFIF Version : 1.01 Resolution Unit : None X Resolution : 1 Y Resolution : 1 Comment : CTF{It_1s_D0UG_JUdY} Image Width : 1400 Image Height : 1400 Encoding Process : Baseline DCT, Huffman coding Bits Per Sample : 8 Color Components : 3 Y Cb Cr Sub Sampling : YCbCr4:4:4 (1 1) Image Size : 1400x1400 Megapixels : 2.0
Commentにフラグが設定されていた。
CTF{It_1s_D0UG_JUdY}
Father's Day Dilemma (Forensics)
index.htmlを見ると、スペースによる不自然なインデントがある。問題には、以下のことが書いてある。
・数が好きなドットとダッシュの2人の子供がいた。 ・彼らは8より大きい数字しか好きではなかった。 ・ドットは数字の10を見つけるために使っていた。 ・ダッシュは数字の12を見つけるために使っていた。
このことから、
.--. .--- -.-. --- --- .-..
デコードする。
PJCOOL
CTF{PJCOOL}
I can do this all day. (Forensics)
ファイルがたくさんあるので、grepで検索する。
$ grep -rl CTF ./icandothisallday/ ./icandothisallday/Pip_the_Troll.txt $ cat ./icandothisallday/Pip_the_Troll.txt Okay. Okay. Ready.CTF{d3cry471ng_nu3l34r_c0d35} strings * | grep <word> would've been faster
CTF{d3cry471ng_nu3l34r_c0d35}
Heavens and Earth (Forensics)
jpgの後ろにzipがくっついている。zipを切り出し解凍すると、2つのpngファイルが展開される。各ピクセルでXORをしてみる。
from PIL import Image img1 = Image.open('earth.png').convert('RGB') img2 = Image.open('heavens.png').convert('RGB') w, h = img1.size output_img = Image.new('RGB', (w, h), (255, 255, 255)) for y in range(0, h): for x in range(0, w): r1, g1, b1 = img1.getpixel((x, y)) r2, g2, b2 = img2.getpixel((x, y)) output_img.putpixel((x, y), (r1 ^ r2, g1 ^ g2, b1 ^ b2)) output_img.save('flag.png')
実行した結果、文字が現れる。
J__B0NWBCU13L
Rail Fence Cipherと推測し、https://www.dcode.fr/rail-fence-cipherで復号する。
J _ _ B 0 N W B C U 1 3 L
J01N_W3B_CLUB
CTF{J01N_W3B_CLUB}
Save Our Souls! (Forensics)
wavの先頭4バイトが壊れているので、"RIFF"に修正する。Audacityで開き、スペクトログラムを見ると、メッセージが現れた。
WE-NEED-REINFORCEMENTS
CTF{WE-NEED-REINFORCEMENTS}
TVA's Trap (Crypto)
改行やスペースを除くとbase64文字列になるので、8回デコードする。
#!/usr/bin/env/ python3 import base64 with open('8-6-4.txt', 'r') as f: data = f.read() data = data.replace('\n', '').replace(' ', '') for _ in range(8): data = base64.b64decode(data) flag = data.decode() print(flag)
CTF{w3c-ctf-z0z2_3ry9t0}
Shakespeare and Encoding (Crypto)
2進数コードをデコードし、ASCIIコードで-1方向にシフトする。
#!/usr/bin/env python3 codes = '01000100 01010101 01000111 01111100 01011010 00110001 01010110 00101110 01110101 01110000 01110000 00101110 01000011 01110011 01110110 00110010 01110110 01010100 01111110' codes = codes.split(' ') msg = '' for code in codes: msg += chr(int(code, 2) - 1) print(msg)
CTF{Y0U-too-Bru1uS}
Locked Out (Crypto)
aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xRDBtTkp0YThkRFRDY2VCREkycG9YS3AyYlJhMEcya0Ivdmlldz91c3A9c2hhcmluZw==
$ echo aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xRDBtTkp0YThkRFRDY2VCREkycG9YS3AyYlJhMEcya0Ivdmlldz91c3A9c2hhcmluZw== | base64 -d https://drive.google.com/file/d/1D0mNJta8dDTCceBDI2poXKp2bRa0G2kB/view?usp=sharing
base64デコードしたらGoogleドライブのURLになったので、アクセスしてファイルをダウンロードする。
そのファイルには2進数で8桁ごとにスペースで区切られているデータが書いてあるので、デコードする。
#!/usr/bin/env python3 with open('USPatent4405829.txt', 'r') as f: codes = f.read().split(' ') msg = '' for code in codes: msg += chr(int(code, 2)) print(msg)
実行結果は以下の通り。
c = 7424699238646955201370695213431987671142812230143306867560482933056266299380926684689129315498363439046922143979269386180477235672715428337919573885741855 n = 14783703403657671882600600446061886156235531325852194800287001788765221084107631153330658325830443132164971084137462046607458019775851952933254941568056899 e = 0x10001
RSA暗号のパラメータになったので、nをfactordbで素因数分解してみる。
p = 121588253559534573498320028934517990374721243335397811413129137253981502291629 q = 121588253559534573498320028934517990374721243335397811413129137253981502291631
あとはそのまま通常通り復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * c = 7424699238646955201370695213431987671142812230143306867560482933056266299380926684689129315498363439046922143979269386180477235672715428337919573885741855 n = 14783703403657671882600600446061886156235531325852194800287001788765221084107631153330658325830443132164971084137462046607458019775851952933254941568056899 e = 0x10001 p = 121588253559534573498320028934517990374721243335397811413129137253981502291629 q = 121588253559534573498320028934517990374721243335397811413129137253981502291631 assert p * q == n phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
CTF{r0n_4D1_130N4rd}
climb the HILL (Crypto)
Hill暗号。文字列のテーブルは英小文字、数字、{}_の順番にして復号する。
#!/usr/bin/sage import string def decrypt(K, ct, alphabet): ct = [[alphabet.index(c)] for c in ct] C = matrix(Zmod(n), ct) P = K.inverse() * C pt = ''.join([alphabet[P[i][0]] for i in range(P.nrows())]) return pt alphabet = string.ascii_lowercase + string.digits + '{}_' ciphertext = 'z3{ryu0kdhhxwuph__oin4}{h5cn78y6a{obebxbh932j' n = len(alphabet) K = matrix(Zmod(n), [[6, 24, 11], [12, 13, 10], [20, 17, 15]]) flag = '' for i in range(0, len(ciphertext), 3): ct = ciphertext[i:i+3] pt = decrypt(K, ct, alphabet) flag += pt print(flag)
{y0u_h4ve_cl1m6ed_the_h1ll_here_1s_y0ur_fl4g}
CTF{y0u_h4ve_cl1m6ed_the_h1ll_here_1s_y0ur_fl4g}