簡易CTF競技可視化システム
(EasySaucer)
Windows版を追加しました(バージョン1.13)
■ 概要
簡易CTF用(EasyCTF)
用の簡単な可視化システムです.
FreeBSDやCentOSなどのいわゆるPC-UNIX,もしくはWindowsで動作します.
作者があまりデザインセンスが無いので,なんかデザイン的にどうなのかなと
思っています(笑).
好きに改造して使ってください.
FreeBSD/CentOS/ラズベリーパイ2/Windows7で動作を確認してあります.
UFOみたいなのをイメージして作ってみました.
- Saucer-1.0 (2015/04/12)
- 動かすことを優先して即席で作ったためかなり荒削りです.
- 手抜きな部分もまだいっぱいありますが,
とりあえず動くようになったのでリリースします.
- Saucer-1.1 (2015/04/15)
- mkreport.pl
- パラメータ修正
- 回答済みリストが正常に扱われていなかった問題の修正
- 情報が連続して送信される場合に,ユーザが分散するようにする
- リプレイ時の速度調整オプション(-speed)を追加
- 早送り時の誤答抑制用に-omitオプションを追加
- reporter.plとsaucerを同一機で動作させた場合にreporter.plの負荷が
集中してsaucerの動作が1秒おきに遅くなる問題を軽減させるために,
sleep()の位置を分散させて負荷のタイミングを分散する
- ファイルアクセスを軽減する
- クライアントモードでの動作(-hostオプション)を追加
- saucer
- 円盤の3次元方向への回転機能を追加
- パターンを追加
- いくつかバグ修正や細かい修正など
- Saucer-1.2 (2015/04/19)
- 円盤のパターン生成を別ファイル化
- 円盤のパターンを追加
- lib.[ch] → vector.[ch] に変更
- j,lのキーバインドを逆にする
- Saucer-1.3 (2015/05/03)
- f,dによる回転速度の調整を追加
- x,zによる自動モードの調整を追加
- テクスチャによるユーザ名表示を追加 (フォントはオリジナル)
- Saucer-1.4 (2015/05/11)
- 8x8,16x16フォントを追加
- Makefileでのフォント指定を可能にする
- 'a'で描画パターンをバックする
- 字間の自動調整を追加
- 16x16フォントを標準にする
- Saucer-1.5 (2015/05/12)
- Saucer-1.6 (2015/05/24)
- reporter.pl のコネクション切断チェックが誤動作する場合のある問題を修正.
- reporter.pl にfork()しないモードを追加.(-single)
- サーバモード時にクライアントからの再接続を可能にする.
- ユーザ名に空白を入れられるように,シングルクォート・ダブルクォートでの
文字列指定を可能にする.
- セクタとトラックの役割を逆にする.
- Saucer-1.7 (2015/05/28)
- テクスチャでのスコアの表示を追加
- テクスチャでのジャンルの表示を追加
- 円盤数,トラック数,セクタ数の初期値を変更
- テクスチャ表示時の補間方法を変更
- '1','2'での円盤配置のスケール変更を追加
- 色を調整
- CLEAR受信の繰り返しで重複してスコアが計上される問題を修正
- Saucer-1.8 (2015/06/13)
- ユーザ名・ジャンルの漢字表示に対応
- ユーザ名・ジャンルでバックスラッシュによるエスケープを可能にする
- Saucer-1.9 (2015/06/29)
- ソケットのclose()もれを修正
- -udp/-uによるUDP接続を追加
- Saucer-1.9.1 (2015/07/02)
- バッファにデータが残っている状態でコネクションが切断されると,
残ったデータが処理されない問題を修正
- Saucer-1.10 (2015/07/02)
- -multi/-mによるマルチ接続モードを追加(複数の同時接続を受け付ける)
- Saucer-1.10.1 (2015/07/03)
- コネクションの終端に\nが存在しない場合に,処理されないデータがバッファ
上に残ってしまい,ソケットのオブジェクトが削除されずに残ってしまう
問題を修正
- Saucer-1.11 (2015/08/04)
- Saucer-1.12 (2015/08/05)
- サーバモード時のbind()するホスト名指定を可能にする
- Saucer-1.13 (2016/03/10)
Saucer-1.13 (Windows版) (2016/03/10)
- Windowsに対応 (MinGWでビルドできます)
- 円盤の配置をパラメータ調整可能にする('3','4'でパラメータを増減)
- 光源の位置をオブジェクトの直上から視点に移動し,画面を明るくする
- reporter.plのクライアント動作時にホスト名指定が効いていない問題を修正 (-cオプションを追加)
- Saucer-1.14 (2018/10/27)
Saucer-1.14 (Windows版) (2018/10/27)
- 円盤の位置をスコアでソートする
- 円盤の移動パターンに加速度を導入して滑らかにし,回転などの動作を追加
- 一部の環境でテクスチャが正常に表示されない問題を修正
(glFlush()によるフラッシュを追加)
- glBindTexture()によりテクスチャをバインドし,毎回の画像データのロードを
削減するお試しコードを追加
(ただしうまく動作せず,現状無効(USE_BIND_TEXTURE))
■ 注意点
動かすことを優先して即席で作ったため現時点でかなり荒削りで,
ものすごく手抜きです.
様々な問題があるかもしれません.セキュリティ的な脆弱性などもあるかも
しれません.(TCPでのサーバ動作や通信を行います)
自由に使って構いませんが,損害など出ても作者は責任はとれません.
各自の責任の下で利用してください.
EasyCTFと同様に,とにかくシンプルな作りなので,
自分でいろいろ改造したり,実験したり,
機能追加するためのベースとして使うといいでしょう.
■ 機能
競技ユーザごとに,円盤が出ます.
円盤内は,半径と角度ごとに,ブロックに分割されています
(ハードディスクのトラックとセクタのようなイメージ).
それぞれのブロックが問題に相当します.ブロックには最初は青い壁が立っていて,
問題に挑戦すると白の小さい板が飛んできて壁にぶつかります.
板が飛んできている間は壁が赤や紫になります.板がぶつかると破片が飛び散ります.
正答だと壁がゆっくり倒れて緑色になります.
同じジャンルの問題は同じ角度に割り当てられます.つまりあるジャンルの問題を
全問正解すると,緑のピザのピースのような形ができることになります.
ジャンルごとのレーダーチャートのような感じになります.
(注意:saucer-1.6から,半径と角度の役割が逆になりました.saucer-1.5以前は,あるジャンルの問題を全問正解すると緑の輪になります)
ジャンルごとの問題数が一致していることが理想ですが,そうでなくても構いません.
問題数が足りなくて空いたブロックは,回答されない状態で残るだけです.
(つまり,そのジャンルは全問正解しても完全なピザのピースにならない)
が,全ジャンルの問題数が一致していれば,全問正解で円盤が緑一面になって
きれいでわかりやすいです.
動作中にユーザ追加やジャンル&問題追加(EasyCTFのlist.txtへの問題追加)
などがあった場合にも,動的に追随します.
例えば動作中にユーザ追加されると円盤が増えていきますし,
問題が追加されるとトラックが細く多くなります.
■ とりあえず見てみたいときには
サーバへの接続無しでのスタンドアロンの状態でも動作します.
とりあえずサーバ連携無しに,どんなものかパッと見てみたいという人向けです.
makeでビルドして,./saucer をオプション無しで起動してください.
起動したら以下のキーを押して,いろいろ動作を見てみてください.
■ 操作方法
可視化システム上で,以下のキー操作ができます.
- s ... 円盤のパターンを組み変え(20種類あります)
- i,j,k,l,u,o ... 視点を移動
- r ... 疑似的に正答を行う
- e ... 疑似的に誤答を行う
- t ... 疑似的にトラック数の追加を行う (つまり,輪が細くなる)
- g ... 疑似的にセクタ数の追加を行う (つまり,角度が細かくなり円に近くなる)
- b ... 疑似的に円盤の追加を行う (つまり,円盤が増える)
- q ... 終了
(以下はSaucer-1.3から追加)
- d,f ... 回転速度を変更
- x,z ... 自動解答のレートを変更
(以下はSaucer-1.4から追加)
(以下はSaucer-1.7から追加)
(以下はSaucer-1.13から追加)
■ 使うための準備
OpenGLとGLUTを使っています.
以下のようにして,freeglutをインストールしておきます.
# yum install freeglut-devel (CentOSの例)
$ sudo apt-get install freeglut3-dev (Ubuntuの例)
SaucerをダウンロードしてZIPを展開します.
展開するとscriptsというディレクトリに reporter.pl というスクリプトがあります.
これは,情報を送信するためのサーバとして使います.
ZIPの展開ディレクトリでmakeを実行してsaucerをビルドします.
■ Windows版の使いかた
ビルドに以下のツール・ライブラリを利用しています.
ライブラリ類はZIPファイルに同包していますので,ライセンスなどはそちらを
参照してください.
Windows版のZIPファイルを展開すると saucer.exe という実行ファイルがあるので,
とりあえずそれをダブルクリックして起動できます.
実際に使う場合にはパラメータ指定が必要なので,コマンドプロンプトから
引数指定して起動するか,ショートカットを作成して引数指定してください.
■ サンプルデータで動かしてみる
EasyCTFと連携してちゃんと動かしてみる前に,とりあえず競技だとどんな感じなのか,
サンプルデータで動かして見てみる方法についてです.
以下に,後述する疑似データの生成スクリプトで生成した
サンプルデータがあるのでダウンロードします.
(ただしサンプルとして,激し目(笑)にパラメータ調整しています)
サンプルデータ(7分程度)
上記データをダウンロードしたら解凍します.
「sample-result」というディレクトリが生成されるので,
Saucerに付属のreporter.plを以下のようにディレクトリ指定して起動します.
$ ./reporter.pl -d sample-result -replay
実行するとSaucer可視化システムからの接続待ちになります.
(注意:reporter.plはポート(デフォルトでは12345)を開けて,
認証無しで接続受け付けします.インターネットに接続されているような
サーバで安易に起動しないように注意してください)
次にSaucer可視化システムをmakeでビルドして,以下のようにして起動して
サーバに接続します.
$ ./saucer -h <reporter.plを起動したサーバのホスト名もしくはIPアドレス>
■ ちゃんとした使いかた
可視化システム(Saucer)には reporter.pl というスクリプトが付属しています.
このスクリプトが,EasyCTFのCGIのフォルダからユーザ情報や問題の回答情報を
読んで,それを送信するサーバをやってくれます.
で,Saucer可視化システムは reporter.pl に接続して,もらった情報を
円盤のグラフィックで表示します.
このため手順としては,以下のようになります.
EasyCTF起動 → reporter.plを起動してサーバ起動
→ Saucer可視化システムを起動してサーバに接続
具体的には以下のような感じです.
- EasyCTFをインストールして起動 (これについてはEasyCTFのほうを参照)
- EasyCTFを起動しているシステム上で,reporter.pl を以下のようにして起動
$ ./reporter.pl -d <EasyCTFのCGIのディレクトリ>
(例えばCentOSなら以下のような感じ)
$ ./reporter.pl -d /var/www/cgi-bin/easyctf
※ ポート番号はデフォルトで12345になっています.
他のアプリとぶつかるようなら-pオプションで変更できます.
(注意:reporter.plはポート(デフォルトでは12345)を開けて,
認証無しで接続受け付けします.インターネットに接続されているような
サーバで安易に起動しないように注意してください)
- Saucer可視化システムを以下のようにして起動する.
$ ./saucer -h <reporter.plを起動したサーバ名もしくはIPアドレス>
※ ポート番号はデフォルトで12345になっています.
変更が必要なら,やはり-pオプションで変更できます.
reporter.plは複数のSaucer可視化システムからの接続を受け付けます.
Saucer可視化システム側をいったん終了して再接続したりすることもできます.
■ リプレイモード
reporter.plは通常起動だと,現時点で存在している回答情報を一気に送り,
あとは新しい回答が出るたびに送る,という動作をします.
つまり動作中にreporter.plやSaucer可視化システムを再起動し再接続した場合には,
現在の状態まで早送りで一気に進められ,それ以降はリアルタイムで動作することに
なります.これは競技中に再起動や再接続をすることを想定しています.
reporter.plを -replay というオプションで起動すると,
現時点で存在している回答情報(と,新たに追加されていく回答情報)を,
回答されたときの時間のインターバルをおいて送ります.
これは競技後に,競技の状況を再現するのに使えます.
ちなみにreporter.plにSaucer可視化システムを接続した状態でreporter.plを
終了した場合(つまりセッションが切断された場合)には,
Saucer可視化システムは終了せずにそのまま動き続けます
(ただしサーバからの情報送信が無いので,何も情報が得られず
ただ動き続けるだけです).
なのでreporter.plを再起動した場合には,Saucer可視化システムを手動で終了&
再起動する必要があります.
これは競技中にreporter.plを再起動したいが,Saucer可視化システムは
(プロジェクタなどでギャラリーに見せているため)別のタイミングで再起動したい,
という状況を想定しています.
■ 実行時オプション
■ reporter.pl
- {-dir|-d} <dir> ... ディレクトリ指定
- {-port|-p} <port> ... ポート番号指定
- {-quiet|-q} ... 標準出力へのログ出力をしない
- {-replay|-r} ... リプレイモード
(以下はSaucer-1.1から追加)
- {-host|-h} <hostname> ... クライアントモードで動作(サーバのホスト名を指定し,自身がクライアントとしてサーバに接続する) → Saucer-1.12までは機能していなかったため,Saucer-1.13で仕様変更しました.サーバ動作時にはbind()するホスト名,-cでのクライアント動作時には接続するサーバのホスト名を指定します.
- {-omit|-o} ... 再接続時の早送りの時間節約のために,誤回答情報を省略して早送りする.(早送り後は通常動作する)
- {-speed|-s} <rate> ... リプレイモード時の再生速度 (1で通常,2で倍速,0.5で半速)
(以下はSaucer-1.6から追加)
- -single ... fork()しないでひとつのクライアントからの接続のみ受け付ける
(以下はSaucer-1.13から追加)
- {-client|-c} ... クライアントモードで起動(-hostで指定したサーバに,クライアントとして接続しにいく) ※ -hostを指定しただけではクライアントモードにならないように仕様変更したので注意
■ Saucer可視化システム
- {-host|-h} <hostname> ... クライアント動作時の,サーバのホスト名(もしくはIPアドレス)を指定 → Saucer-1.12より,サーバ動作時にはbind()するホスト名になるよう機能追加した
- {-port|-p} <port> ... ポート番号指定
- {-server|-s} ... サーバモードで起動 (デバッグ用.後述)
- -alone ... 強制スタンドアロンモード(サーバへの接続を行わない)
- -saucer-num ... 起動時の円盤の数
- -track-num ... 起動時のトラック数
- -sector-num ... 起動時のセクタ数
(以下はSaucer-1.3から追加)
- -auto-rate <port> ... 自動解答のレート指定
(以下はSaucer-1.8から追加)
- -kanji <filename> ... 漢字フォントファイルを指定
(以下はSaucer-1.9から追加)
(以下はSaucer-1.10から追加)
- {-multi|-m} ... マルチ接続モード(複数の同時接続を受け付ける)
(以下はSaucer-1.12から追加)
- {-host|-h} <hostname> ... クライアント動作時のホスト名指定の従来オプションだが,サーバ動作時にはbind()するホスト名になるよう機能追加した
■ ユーザ名・ジャンルの漢字表示
ユーザ名とジャンルは漢字を利用できます.ただし漢字の利用時には,
以下のようにしてフォントファイルの作成と指定が必要です.
(フォントファイルを指定しない場合,漢字部分は表示されません)
まず,漢字フォントのBDFファイルが必要です.これは pcf2bdf というコマンドで,
PCFファイルから変換することができます.PCFファイルはX11のものが利用できます.
以下はFreeBSDでの例です.
% pcf2bdf /usr/local/lib/X11/fonts/local/jiskan16-2000-1.pcf.gz > kanji.bdf
次に,BDFファイルを添付のスクリプトでフォントファイル(独自形式)に変換します.
% ./saucer-1.8/scripts/bdf2sfont.pl kanji.bdf > kanji.sfont
生成したフォントファイルを-kanjiオプションで指定して,saucerを起動します.
% ./saucer -kanji kanji.sfont
USERコマンドによるユーザ情報の送信時とQUESTIONコマンドによる問題情報の送信時
に,ユーザ名/ジャンルに漢字が指定されたときに,
漢字で表示するようになります.(漢字コードはUTF-8のみです)
■ 疑似的なXXの追加
「操作方法」のところにありますが,キーボードからの操作により円盤の数などを
疑似的に増加させることができます.
サーバに接続しての実際の動作中に,上記の「疑似的なXXの追加」を行っても,
実害はありません.
例えば「b」を押すと円盤が追加されますが,その円盤は,
(対応するユーザがいないので)何も回答されない状態で動き続けます.
その後に実際にユーザ追加された場合には,すでに追加されている
(が,対応するユーザがいない状態の)余っている円盤がそのユーザに
割り当てられます.
もちろんそのような余った円盤が無い場合には,その都度円盤が増えます.
ジャンルや問題についても,そのような感じで動作します.
ただ当然ながら実際のユーザやジャンル数とは食い違うことになって見栄えは
悪くなるので,競技中に間違ってキー操作してしまってあーやっちまったと思った
場合には,Saucer可視化システムを終了させて再起動&再接続するといいでしょう.
■ 疑似データの作成
実際に競技しないと動作を見ることができないというのでは不便なので,
疑似的に競技データを作成するスクリプトを添付してあります.
reporter.plと同じディレクトリに,mksample.pl というスクリプトがあります.
以下のようにして実行することで,EasyCTFのユーザ情報と問題情報を読み込んで,
競技者の回答情報を疑似的に生成していきます.
$ ./mksample.pl -d <EasyCTFのCGIのディレクトリ>
(例えばCentOSなら以下のような感じ)
$ ./mksample.pl -d /var/www/cgi-bin/easyctf
mksample.pl を動作させている状態で,そのディレクトリ指定で reporter.pl を
起動すれば,生成データをSaucer可視化システムに送信することができます.
mksample.plは以下の実行時オプションを指定できます.
- {-dir|-d} <dir> ... ディレクトリ指定
- {-speed|-s} <パーセント> ... 問題回答(でも誤答)の確率
- {-rate|-r} <パーセント> ... 正答の確率
- {-quiet|-q} ... 標準出力へのログ出力をしない
■ 通信内容
reporter.pl と Saucer可視化システムは,TCPでの通信を行います.
通信内容はテキストです.
このためtelnetで接続してのデバッグが可能です.
(reporter.plにtelnetで接続するとわかります)
これは reporter.pl 側の通信系のデバッグに使えます.
またSaucer可視化システムは,-sオプションでサーバモードで起動することが
できます.
サーバモードで起動すると,自身が接続にいくのでなく,他からの接続を待ちます.
つまりSaucer可視化システムをサーバモードで起動し,そこにtelnetで接続して
コマンドを手動で発行することで,Saucer可視化システムを操作することができます.
これはSaucer可視化システム側の通信系のデバッグに使えます.
■ 通信フォーマット
reporter.pl → Saucerに,以下の4種類の情報を送信します.
ユーザ情報
(書式)
USER <ユーザID> <ユーザ名> (ユーザIDはユニークな文字列なら何でもいい)
(ユーザ名に空白など入れたい場合には "" でくくることができます)
(バックスラッシュでエスケープします)
(漢字はUTF-8で指定し,-kanji オプションでフォントファイルを指定します)
(例)
USER 0001 TestUser
USER 0002 "Sample User"
USER 0003 "\"Sample User 2\""
USER 0004 "漢字の名前"
問題情報
(書式)
QUESTION <問題ID> <ジャンル> <スコア> (問題IDはユニークな文字列なら何でもいい)
(ジャンルはBinaryとかWebとか)
(ジャンルはユーザ名と同様に "" やバックスラッシュによるエスケープ,漢字が使えます)
(例)
QUESTION Q001 Binary 100
QUESTION Q002 Web 200
QUESTION Q003 "Genre Web" 300
QUESTION Q004 "バイナリ" 400
回答したけど不正解だったときの情報
(書式)
REPLY <ユーザID> <問題ID> <時刻> (時刻はtime()の値)
(例)
REPLY 0001 Q001 1432476751
正答したときの情報
(書式)
CLEAR <ユーザID> <問題ID> <時刻> (時刻はtime()の値)
(例)
CLEAR 0001 Q001 1432476751
■ スクリーンショット集
(Saucer-1.1から追加)
(Saucer-1.3から追加)