この大会は2022/4/30 6:00(JST)~2022/5/1 6:00(JST)に開催されました。
今回もチームで参戦。結果は11939点で436チーム中7位でした。
自分で解けた問題をWriteupとして書いておきます。
Join the Discord (Misc)
Discordに入り、#rulesチャネルのメッセージを見ると、フラグが書いてあった。
PCTF{y0ur3_t34ring_m3_4p4rt_1isa}
Apples (Misc)
$ file apples apples: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a9d726b38f66c296b53ef882a4f40732348f7dcb, for GNU/Linux 3.2.0, not stripped $ ltrace ./apples printf("Please enter the password: ") = 27 fgets(Please enter the password: a "a\n", 1024, 0x7f1f77d5ba00) = 0x7fff74e87d70 strcmp("a\n", "apples\n") = -102 puts("Sorry, that password was wrong!!"...Sorry, that password was wrong!!! ) = 34 +++ exited (status 0) +++ $ ./apples Please enter the password: apples You're right! The correct password was apples! You deserve some apples as a reward!
apples_rewardが生成された。
$ file apples_reward apples_reward: ASCII text, with very long lines, with no line terminators
内容はbase64文字列。デコードすると、jpgになったので、問題にある通り、steghideで情報を抽出する。パスワードには"apples"を指定する。
$ steghide extract -sf flag.jpg -p apples wrote extracted data to "data.txt". $ cat data.txt pctf{@pples_tast3_amaz\!ng666}
そのままではフラグが通らなかったので、"\"をエスケープ文字として、省略する。
pctf{@pples_tast3_amaz!ng666}
String Cheese (Reverse Engineering)
$ strings cheese | grep PCTF PCTF{d0nt_string_m3_410ng_b3_my_v413ntin3}
PCTF{d0nt_string_m3_410ng_b3_my_v413ntin3}
PeeWhySea (Reverse Engineering)
Python3.9のpycのようだが、デコンパイルツールはPython3.8以下しかサポートしていない。ヘッダの1バイトのみ変更し、Python3.8のpycヘッダにする。
61 -> 55
pycをデコンパイルする。
$ uncompyle6 flag-checker.pyc # uncompyle6 version 3.8.0 # Python bytecode 3.8.0 (3413) # Decompiled from: Python 3.6.9 (default, Mar 15 2022, 13:55:28) # [GCC 8.4.0] # Embedded file name: ./flag-checker.py # Compiled at: 2022-03-29 07:35:26 # Size of source mod 2**32: 318 bytes import sys if len(sys.argv) != 2: print('One argument required') sys.exit() else: arg = sys.argv[1] key = 'ABCDEFGHIJKLMNOP' encode = ''.join(['{:02x}'.format(ord(a) ^ ord(b)) for a, b in zip(arg, key)]) if encode == '110117023e3273237a157f133d372c2d': print('You have the correct flag!') else: print('Wrong flag') # okay decompiling flag-checker.pyc
keyとのXORの16進表記が'110117023e3273237a157f133d372c2d'であるので、XORで復号する。
#!/usr/bin/env python3 enc = bytes.fromhex('110117023e3273237a157f133d372c2d') key = b'ABCDEFGHIJKLMNOP' flag = ''.join([chr(a ^ b) for a, b in zip(enc, key)]) print(flag)
PCTF{t4k3_4_pyc}
Inspector Clouseau (Web)
HTMLソースを見たら、コメントにフラグが書いてあった。
PCTF{i_w0u1d_1ik3_t0_buy_4_h4mburg3r}
Rock and Roll (Web)
ブラウザでアクセスすると、https://www.youtube.com/watch?v=dQw4w9WgXcQにリダイレクトされる。
リダイレクトせずにHTTPヘッダを確認する。
$ curl http://chal2.pctf.competitivecyber.club:49399/ -v * Trying 34.205.133.141... * TCP_NODELAY set * Connected to chal2.pctf.competitivecyber.club (34.205.133.141) port 49399 (#0) > GET / HTTP/1.1 > Host: chal2.pctf.competitivecyber.club:49399 > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Server: Werkzeug/2.1.1 Python/3.10.4 < Date: Sat, 30 Apr 2022 03:09:07 GMT < Content-Type: text/html; charset=utf-8 < link: <style.css>; rel=stylesheet; < flag: PCTF{r1Ck_D0wn_7h3_r0ll} < Refresh: 5; url=https://www.youtube.com/watch?v=dQw4w9WgXcQ < Content-Length: 0 < * Connection #0 to host chal2.pctf.competitivecyber.club left intact
PCTF{r1Ck_D0wn_7h3_r0ll}
Apocalypse Security - 1 (Web)
ログイン画面で、以下を入力し、ログインする。
Username: ' or 1=1 -- - Password: a
ログイン成功し、フラグが表示された。
PCTF{SQLI_iS_3@sy}
Spongebob (Web)
`ls -la`と入力してみる。
totAL 476 dr-Xr-XR-x 1 rOot wwW-Data 4096 ApR 29 23:43 . drWXr-xR-x 1 RooT RoOT 4096 aPr 20 11:18 .. -RW-RW-r-- 1 roOT www-DATA 29 apR 26 20:34 .DOCKErIGnoRE -R--r--R-- 1 ROot WWW-dATA 453875 aPr 26 20:31 FlAG-aS98Dc6rnv3P948R7aSP98FDYNp.JPG -r--r--r-- 1 ROOt Www-DATa 293 aPr 26 20:31 INdex.hTML -r--R--r-- 1 rOoT wwW-daTA 118 ApR 26 20:31 maiN.PHp -r--R--r-- 1 roOT wwW-dATa 437 APR 26 20:31 MemeteXT.py
大文字か小文字化は不明だが、すべて小文字として以下のURLにアクセスすると、画像にフラグが書いてあった。
http://chal1.pctf.competitivecyber.club:10009/flag-as98dc6rnv3p948r7asp98fdynp.jpg
PctF{SPoNGebob_LOokiNG_ThIcC}
Locked (Web)
サブディレクトリを探ってみると、http://chal1.pctf.competitivecyber.club:10017/admin/にアクセスできた。HTMLソースを確認し、リンクされているmain.jsを確認してみると、以下のような記述があった。
var thing = atob(atob(atob("VERKR2EySlhiSFZNTUVaTVUydFNWRk5yV2t4U1JrNUxWRVZHVkZKcE9YSmpNbmhyWVcxYWRtRlhSbXRqTWxsMVpFaG9NQT09")));
$ echo VERKR2EySlhiSFZNTUVaTVUydFNWRk5yV2t4U1JrNUxWRVZHVkZKcE9YSmpNbmhyWVcxYWRtRlhSbXRqTWxsMVpFaG9NQT09 | base64 -d | base64 -d | base64 -d /admin/AKJDSJFKDSJLASF/ksldjfoiadsf.txt
http://chal1.pctf.competitivecyber.club:10017/admin/AKJDSJFKDSJLASF/ksldjfoiadsf.txtにアクセスすると、以下のように書かれていた。
https://pastebin.com/F21q9Eu8
https://pastebin.com/F21q9Eu8にアクセスすると、フラグが記載されていた。
pctf{Th3_W3bsite_w@s_UnL0cK3d}
Apocalypse Security - 2 (Web)
ログイン画面で、以下を入力し、ログインしてみる。
Username: ' or 1=1 -- - Password: a
「SQL injection Deteced: or」と表示された。"or"は使えないようだ。
次に以下を入力して、ログインしてみる。
Username: ' union select 'admin', 'pass' -- - Password: a
「SQL injection Deteced: admin」と表示された。"admin"は使えないようだ。
次に以下を入力して、ログインしてみる。
Username: ' union select 'a', 'a' -- - Password: a
ログイン成功し、フラグが表示された。
PCTF{f1l7ers_n0t_s3cur3}
Apocalypse Security - 3 (Web)
今度は'admin'でログインする必要がある。ただし、'or', 'and', 'admin'は使えない。
文字列を連結するように、以下を入力して、ログインしてみる。
Username: ' union select 'ad' || 'min', 'a' -- - Password: a
ログイン成功し、フラグが表示された。
PCTF{w0rld_0f_sQl_8kdw7}
Base64 Times 10 (Crypto)
10回base64デコードする。
#!/usr/bin/env python3 import base64 with open('cipher.txt', 'r') as f: data = f.read() for _ in range(10): data = base64.b64decode(data) flag = data.decode() print(flag)
pctf{0bfusc@tion_1s_n0t_3ncrypt10n}
The Order (Crypto)
Cistercian numerals。https://en.wikipedia.org/wiki/Cistercian_numeralsを見ながら、デコードする。
6811 1112 5195 1101 1710 9985 1114 9511 5121 1151 1651 1093 3
ASCIIコードの文字になるよう切りながらデコードする、
#!/usr/bin/env python3 enc = '6811 1112 5195 1101 1710 9985 1114 9511 5121 1151 1651 1093 3' enc = enc.replace(' ', '') flag = '' code = '' for c in enc: code += c if int(code) > 32 and int(code) < 127: flag += chr(int(code)) code = '' flag = 'PCTF{%s}' % flag print(flag)
PCTF{Dop3_numb3r_syst3m!}
No Postcode Envy (Crypto)
RM4SCC。https://en.wikipedia.org/wiki/RM4SCCを参考にデコードする。
OHLORDEK
PCTF{OHLORDEK}
TwoFifty (Crypto)
p = 33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711 q = 64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367
あとはそのまま通常通り復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * n = 2140324650240744961264423072839333563008614715144755017797754920881418023447140136643345519095804679610992851872470914587687396261921557363047454770520805119056493106687691590019759405693457452230589325976697471681738069364894699871578494975937497937 e = 65537 c = 1374140457838957379493712264664046131145058468396958574281359672603632278570608567064112242671498606710440678399100851664468278477790512915780318592408890478262161233349656479275652165724092531743704926961399610549341692938259957133256408358261191631 p = 33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711 q = 64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367 assert n == p * q phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
復号結果は以下の通り。
this_s3miprim3_t00k_2700_CPU_c0r3_y34rs_t0_cr4ck
PCTF{this_s3miprim3_t00k_2700_CPU_c0r3_y34rs_t0_cr4ck}
Cowsay (Crypto)
https://wiremask.eu/tools/xor-cracker/でクラックする。鍵長38で鍵がフラグになることがわかる。
PCTF{this_is_4_sup3r_i(p0rt4nt_bin4ry}
CorruptAAAAd (Crypto)
base64デコードしてPEM形式からDER形式にデータを変換する。あとはDER形式が以下のようになっていることから、n, e, dを取り出す。
RSAPrivateKey ::= SEQUENCE { version Version, modulus INTEGER, -- n publicExponent INTEGER, -- e privateExponent INTEGER, -- d prime1 INTEGER, -- p prime2 INTEGER, -- q exponent1 INTEGER, -- d mod (p-1) exponent2 INTEGER, -- d mod (q-1) coefficient INTEGER, -- (inverse of q) mod p otherPrimeInfos OtherPrimeInfos OPTIONAL }
あとはこのまま復号し、フラグ部分を取り出す。
#!/usr/bin/env python3 from base64 import * from Crypto.Util.number import * with open('corrupted-privkey.pem', 'r') as f: data = ''.join(f.read().splitlines()[1:-1]).encode() data = b64decode(data) n = int(data[0x00b:0x10c].hex(), 16) e = int(data[0x10e:0x111].hex(), 16) d = int(data[0x115:0x215].hex(), 16) with open('encryptedmessage.enc', 'rb') as f: c = bytes_to_long(f.read()) m = pow(c, d, n) msg = long_to_bytes(m) index_begin = msg.index(b'PCTF') index_end = msg.index(b'}', index_begin) flag = msg[index_begin:index_end + 1].decode() print(flag)
PCTF{g1mm3_th3_e}
Merkle-Derkle (Crypto)
サーバの処理概要は以下の通り。
・letters: 英大小文字 ・secret: 15~35文字の英大小文字 ■/ (GET) ・クッキーのauthが設定されていない場合 ・new_user() ・user = "admin=False" ・data = secret + user ・mac: dataのsha1ダイジェスト(hex) ・cookie_val: userの16進数表記 + "." + mac →authに設定 ・クッキーのauthが設定されている場合 ・admin = validate(<クッキーのauthの値>) ・user: "."の前のhexデコード ・data = secret + user ・cookie_mac: "."の後ろ ・dataのsha1ダイジェスト(hex)とcookie_macが一致していたら"="区切りの最後の値を返す。 ・adminがTrueの場合、adminページを表示
クッキーのauthに以下が設定されていた。
61646d696e3d46616c7365.9451921a06a1d53d48e56d40f206ae2928e57f72
Hash Length Extension Attackで設定すべきクッキーを取得する。
既知文字列:admin=False 既知ハッシュ:Cookieから取得 ※上記の場合、9451921a06a1d53d48e56d40f206ae2928e57f72 追加文字列:=True
secretの全パターンの長さの場合のクッキーの値を列挙する。
#!/usr/bin/env python3 import hashpumpy cookie_val = '61646d696e3d46616c7365.9451921a06a1d53d48e56d40f206ae2928e57f72' known_str = bytes.fromhex(cookie_val.split('.')[0]).decode() known_hash = cookie_val.split('.')[1] add_data = '=True' for secret_len in range(15, 36): h, d = hashpumpy.hashpump(known_hash, known_str, add_data, secret_len) auth_val = d.hex() + '.' + h print(auth_val)
列挙した結果は以下の通り。
61646d696e3d46616c736580000000000000000000000000000000000000000000000000000000000000000000000000d03d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000000000000000000000000000000000000d83d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000000000000000000000000000000000000e03d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000000000000000000000000000000000000e83d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000000000000000000000000000000f03d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000000000000000000000000000000f83d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000000000000000000000000000001003d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000000000000000000000001083d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000000000000000000000001103d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000000000000000000000001183d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000000000000000001203d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000000000000000001283d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000000000000000001303d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000000000001383d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000000000001403d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000000000001483d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000000000001503d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000000000001583d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c736580000000000000000000000000000000000001603d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c7365800000000000000000000000000000000001683d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a 61646d696e3d46616c73658000000000000000000000000000000001703d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a
順にクッキーに設定して、リロードする。
以下をクッキーのauthに設定したときにフラグが表示された。
61646d696e3d46616c7365800000000000000000000000000000000000000000000000000001203d54727565.8f725aa1575d90691cbe2e84f8671cd054dd480a
PCTF{c4p4c10us_3xtr3m1s}