Questcon CTF Writeup

この大会は2023/10/27 13:30(JST)~2023/10/29 13:30(JST)に開催されました。
今回は個人で参戦。結果は1417点で445チーム中40位でした。
1問だけ解けず残念です。
自分で解けた問題をWriteupとして書いておきます。

Guidelines of the Caribbean (Misc)

ルールのページを見ると、一番最後にこう書いてある。

Thanks for reading rules, your flag: REDACTED.

HTMLソースを見ると以下のようになっていた。

<li>🤫 Thanks for reading rules, your flag: REDACTED.<span style="display: none">QUESTCON{C0d3Break3r_Rul35_Expl0r3r}</span>
QUESTCON{C0d3Break3r_Rul35_Expl0r3r}

Pirate's Port Paradox (Misc)

まず、それぞれ対応する標準のポート番号を書き出していく。

WHOIS: 43
QOTD: 17
CHARGEN: 19
XFER: 82
ECHO: 7
DCE: 135
NNTP: 119
NSCA: 5667

式に当てはめ計算する。

>>> ((((43 + 17) * 19) - 82) % 7) * (135 + 119) * 5667
1439418
QUESTCON{1439418}

Hexa Pirate's Code (Misc)

1つだけsaveファイルがある。

cc53495bb42e4f6563b68cdbdd5e4c2a9119b498b488f53c0f281d751a368f19.save

そのsave拡張子が付かないファイルcc53495bb42e4f6563b68cdbdd5e4c2a9119b498b488f53c0f281d751a368f19に以下のコードがある。

    if (!String.Equals(pass, "5155455354434f4e7b426c34636b42333472645f4d616c773472335f50697234"+"7433737d-0000-0000-000000000000")) {

hexデコードする。

$ echo 5155455354434f4e7b426c34636b42333472645f4d616c773472335f506972347433737d | xxd -r -p
QUESTCON{Bl4ckB34rd_Malw4r3_Pir4t3s}
QUESTCON{Bl4ckB34rd_Malw4r3_Pir4t3s}

Cursed Treasure (Web)

リンクは以下のようになっている。

https://questcon-cursed-treasure.chals.io/maps.php?id=e25388fde8290dc286a6164fa2d97e551b53498dcbf7bc378eb1f178
https://questcon-cursed-treasure.chals.io/maps.php?id=58b2aaa0bfae7acc021b3260e941117b529b2e69de878fd7d45c61a9
https://questcon-cursed-treasure.chals.io/maps.php?id=271f93f45e9b4067327ed5c8cd30a034730aaace4382803c3e1d6c2f

CrackStationでidの値をクラックしてみる。

e25388fde8290dc286a6164fa2d97e551b53498dcbf7bc378eb1f178 -> (sha224) 1
58b2aaa0bfae7acc021b3260e941117b529b2e69de878fd7d45c61a9 -> (sha224) 2
271f93f45e9b4067327ed5c8cd30a034730aaace4382803c3e1d6c2f -> (sha224) 4

https://miniwebtool.com/ja/sha224-hash-generator/で"3"のsha224を算出する。

3 -> 4cfc3a1811fe40afa401b25ef7fa0379f1f7c1930a04f8755d678474

https://questcon-cursed-treasure.chals.io/maps.php?id=4cfc3a1811fe40afa401b25ef7fa0379f1f7c1930a04f8755d678474にアクセスする。
Usernameに"Barbossa"を入力してVerifyすると、フラグが表示された。

QUESTCON{Th3_Pir4t3s_0f_Th3_Car1bb34n_Arr_Th3_B3st!}

Web Explorer's Journey

以下のように表示される。

Your flag is:
1021089710312384101115116957010897103125

script.jsを見ると、以下のように書いてある。

let flag = "flag{Test_Flag}";
let encryptedFlag = "";
function encodeFlag() {
  for (let i = 0; i < flag.length; i++) {
    encryptedFlag += flag.charCodeAt(i);
  }
}

encodeFlag();
document.getElementById("flag").innerHTML = encryptedFlag;

HTMLソースを見ると、以下のように書いてある。

      <div id="flag">
        81856983846779781238751669551888076488251829549839552875183487751125
      </div>

適度に区切ってデコードする。

>>> s = '81 85 69 83 84 67 79 78 123 87 51 66 95 51 88 80 76 48 82 51 82 95 49 83 95 52 87 51 83 48 77 51 125'
>>> ''.join([chr(int(c)) for c in s.split(' ')])
'QUESTCON{W3B_3XPL0R3R_1S_4W3S0M3}'
QUESTCON{W3B_3XPL0R3R_1S_4W3S0M3}

Island of Hidden Bounty (Forensic)

$ stegseek blackperl.jpg dict/rockyou.txt
StegSeek 0.6 - https://github.com/RickdeJager/StegSeek

[i] Found passphrase: "password"
[i] Original filename: "hidden_treasure.txt".
[i] Extracting to "blackperl.jpg.out".

$ cat blackperl.jpg.out
https://hiddenbounty.netlify.app

https://hiddenbounty.netlify.appにアクセスするが、特にあやしいものはない。
https://hiddenbounty.netlify.app/robots.txtにアクセスする。

User-agent: *
Disallow: /HiddenInMist.html

https://hiddenbounty.netlify.app/HiddenInMist.htmlにアクセスすると、フラグが書いてあった。

QUESTCON{X_M4rk5Th3Digit4lTr34sur3}

Isla de Muerta's Secrets (Forensic)

HTTPでフィルタリングすると、以下の情報をPOSTしていることがわかる。

Discover the clandestine chest's whereabouts on Isla de Muerta.
30.089251341863626, -114.54361624717956

このPOSTのパケットの送信元のIPアドレスは以下の通り。

192.168.0.129
QUESTCON{192.168.0.129}

Head Jack Sparrow (Forensic)

pngのフォーマットだが、ヘッダ4バイトと、IHDRのチャンク名が壊れているので、修正する。修正した画像の右下にフラグが書いてあった。

QUESTCON{P1RaT3s_Ha13s_PNG_F1l3}

Mystery (Stego)

steghideでパスフレーズなしで秘密情報を抽出する。

$ steghide extract -sf pirate.jpg           
Enter passphrase: 
wrote extracted data to "mystery".

$ file mystery              
mystery: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=4], progressive, precision 8, 360x360, components 1
$ mv mystery mystery.jpg

抽出した画像には特に何も書かれていない。

$ exiftool mystery.jpg                                     
ExifTool Version Number         : 12.65
File Name                       : mystery.jpg
Directory                       : .
File Size                       : 17 kB
File Modification Date/Time     : 2023:10:27 13:49:38+09:00
File Access Date/Time           : 2023:10:27 13:52:22+09:00
File Inode Change Date/Time     : 2023:10:27 13:50:52+09:00
File Permissions                : -rwxrwx---
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : None
X Resolution                    : 1
Y Resolution                    : 1
Exif Byte Order                 : Big-endian (Motorola, MM)
Processing Software             : Hacker
Make                            : Alert
Camera Model Name               : Alert
Exif Version                    : 0230
Components Configuration        : Y, Cb, Cr, -
Flashpix Version                : 0100
Image Unique ID                 : UVVFU1RDT057TXk1dDNyeV8xc180dzNzMG1lIX0=
Image Width                     : 360
Image Height                    : 360
Encoding Process                : Progressive DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 1
Image Size                      : 360x360
Megapixels                      : 0.130

Image Unique IDにbase64文字列が設定されているので、デコードする。

$ echo UVVFU1RDT057TXk1dDNyeV8xc180dzNzMG1lIX0= | base64 -d
QUESTCON{My5t3ry_1s_4w3s0me!}
QUESTCON{My5t3ry_1s_4w3s0me!}

Mystery 2.0 (Stego)

$ zsteg another_mystery.png 
b1,g,lsb,xy         .. file: OpenPGP Public Key
b1,abgr,msb,xy      .. text: "}wwwwwww;"
b2,r,lsb,xy         .. text: "Y?*[*LkB"
b2,g,lsb,xy         .. text: "EAUUUUUUUU"
b2,b,msb,xy         .. text: "jUUv}VU}%c"
b2,rgba,lsb,xy      .. text: "QUESTCON{P1raT3s_Ar3_M7s!3rY}\n"
b2,abgr,msb,xy      .. text: "KKKKGOOO"
b3,rgb,lsb,xy       .. file: PGP Secret Sub-key -
b3,rgba,lsb,xy      .. file: PGP Secret Sub-key -
b4,r,msb,xy         .. text: ";3333333{"
b4,g,lsb,xy         .. text: "eDVeffffvfy"
b4,g,msb,xy         .. text: "ffffffffnfff"
b4,b,lsb,xy         .. text: "xweUgeeUwveUVx"
b4,b,msb,xy         .. text: "=33333333"
b4,rgb,lsb,xy       .. text: "bw%cEDcE"
b4,bgr,lsb,xy       .. text: "re%CdECT"
b4,rgba,lsb,xy      .. text: "%o4_Do4_"
QUESTCON{P1raT3s_Ar3_M7s!3rY}

Riddle of the Hidden Scrolls (Crypto)

CyberChefのMagicでヒントを見つける。
3とのXORでbase64文字列になりそう。その後base64デコードすると、フラグになった。

QUESTCON{D34d_M3n_T3ll_No_T4l3s}

Sparrow's Cryptographic Treasure (Crypto)

N, E, Cのパラメータがありので、RSA暗号と推測できる。
Nをfactordbで素因数分解する。

N = 857504083339712752489993810777 * 1029224947942998075080348647219

あとは通常通り復号する。

#!/usr/bin/env python3
from Crypto.Util.number import *

with open('Cryptographic_Treasure.txt', 'r') as f:
    params = f.read().splitlines()

N = int(params[0].split(' ')[-1])
E = int(params[1].split(' ')[-1])
C = int(params[2].split(' ')[-1])

p = 857504083339712752489993810777
q = 1029224947942998075080348647219

phi = (p - 1) * (q - 1)
d = inverse(E, phi)
m = pow(C, d, N)
flag = long_to_bytes(m).decode()
print(flag)
QUESTCON{1_HaT3_RS1}