Rustで数値シミュレーションをする際に使用しているライブラリ(クレート)の紹介

この記事はTUT Advent Calendar 2017の18日目の記事です。

概要

普段私はRustを使ってシミュレータを作成しているのですが、そこでお世話になっているライブラリ(クレート)を簡単に紹介します。
今回紹介するライブラリ(用途)は以下の2つです。

  • rayon (データ並列化)
  • statrs (様々な確率分布に従う乱数生成)

rayon

すでにいくつかの記事で紹介されていますが、rayonによって主に以下の処理を簡潔に行うことができます。両者とも、Work stealingと呼ばれる方法で実現されているそうです。

  • スレッドによる並列処理
  • 再帰関数の分割処理

スレッドによる並列処理

rayonでは、Parallel Iteratorの導入によって通常のイテレータに対する関数(mapなど)の処理を並列化することができます。D言語でいうstd.parallelismに似ているかもしれません。 ただし、Rustのシステムによって並列時の安全性は保証されています。つまり、標準ライブラリのスレッド同様、Sendトレイト、Syncトレイトの制約によってコンパイル時に検査が行われます。

iter関数やinto_iter関数が実装されている型は基本的にParallel Iteratorに変換することができ、以下のような対応関係を持ちます。

コード例は以下のとおりです。

extern crate rayon;
use rayon::prelude::*;

fn main() {
    (0..100)
    .into_par_iter()
    .map(|i| i * 2)
    .for_each(|x| println!("{}",x));
// 200未満の偶数が出力される
}

大変便利ですが、Parallel Iteratorに対してcollect::<Vec<_>>()のようなことはできず、 あらかじめ格納先のベクタをミュータブルとして宣言したのち、collect_into関数を用いて格納する必要があります。

コード例は以下のとおりです。

extern crate rayon;
use rayon::prelude::*;

fn main() {
    let mut even_vec = vec![0;100];
    (0..100)
    .into_par_iter()
    .map(|i| i * 2)
    .collect_into(&mut even_vec);
// 200未満の偶数がeven_vecに格納される
}

並列処理時のスレッド数は自動的に決定されますが、スレッド数を能動的に設定したい場合は、num_threads関数によって設定可能です。
また、実行時にスレッド数を設定したい場合は、環境変数RAYON_NUM_THREADSの値を設定してから実行することで対応できます。

再帰関数の分割処理

join関数によって、再帰関数を効率的に並列処理します。
rayonのGithubリポジトリの例が簡潔であるため、引用します。 コード例は、並列化したクイックソートのようです。

fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    rayon::join(|| quick_sort(lo), || quick_sort(hi));
}

リポジトリのREADMEによれば、

Note though that calling join is very different from just spawning two threads in terms of performance. 
This is because join does not guarantee that the two closures will run in parallel. 
If all of your CPUs are already busy with other work, Rayon will instead opt to run them sequentially. 
The call to join is designed to have very low overhead in that case, so that you can safely call it even with very small workloads (as in the example above).

とのことですので、join関数の引数のクロージャを、可能なら並列処理し、CPUの負荷が高い場合は逐次的に処理するよう、うまくスケジューリングされる(?)ようです。

statrs

statrsはRustにおける統計的な数値計算のためのクレートで、特に私はdistributionモジュールを頻繁に利用しています。distributionモジュールを利用することで、各種確率分布に従う乱数を容易に生成することができます。
ただし、rust statrsで検索すると検索エンジンが変に気を利かせて別の検索ワードを推奨してくるので注意です。

離散型分布、連続型分布問わず様々な分布に対応しており、以下の分布ごとに構造体が定義されています(非常に多い)。また、分布の期待値、分散を返す関数が各分布に実装されており、離散型確率分布に対しては確率質量関数の値、連続型確率分布に対しては確率密度関数の値を返す関数が実装されています。

さらに、sample関数(rand::Rngトレイトを実装する乱数生成器を引数)の実装によって、各分布に従う乱数を生成可能です。 rand::Rngトレイトを実装している乱数生成器であればよいため、StdRngやThreadRng、XorShiftなど様々なものに対応しています。

  • 離散型確率分布
    • ベルヌーイ分布
    • 二項分布
    • カテゴリカル分布(Categorical Distribution)
    • 離散一様分布
    • 幾何分布
    • 超幾何分布
    • 多項分布
    • ポワソン分布
  • 連続型確率分布
    • ベータ分布
    • コーシー分布
    • カイ分布
    • カイ2乗分布
    • ディリクレ分布
    • アーラン分布
    • 指数分布
    • F(Fisher-Snedecor)分布
    • ガンマ分布
    • 逆ガンマ分布
    • 対数正規分布
    • 正規分布
    • パレート分布
    • t分布
    • 三角分布
    • 連続一様分布
    • ワイブル分布

本記事ではdistributionモジュールにのみ着目しましたが、他のモジュールにてベータ関数やエラー関数などの複雑な関数の値を計算する関数も用意されているようです。

まとめ

rayonやstatrsは、数値シミュレーションをするうえで、大変有用です。並列処理により計算時間を削減することができ、randクレートでは対応していない様々な確率分布に従う乱数生成を行うことで様々なシミュレーションが可能です。
また、Rustはコンパイラが大変優秀なので、コンパイル時の検査のおかげでシミュレーション実行時のエラーがなく、重宝しています。その一方で、コンパイルを通すのは大変ですが。

私の身の回りでもRustが流行ればいいな、と思うこの頃です。

apt-get dist-upgradeで無線LANに接続できなくなった

概要

Raspbian jessie on Raspberry Pi (1st)の環境で、apt-get dist-upgradeを実行したら無線LANに接続できなくなったので、その解決(?)までの過程を記事に残します。

問題

dist-upgrade実行後に、

  • Raspberry Piが設定した固定IPではなくなる
  • そもそもwlan0にIPが割り振られなくなる

といった問題が発生しました。

解決まで

IPが降られなくなる

$ dmesg

でログを確認してみると、wpa_supplicantがCTRL-EVENT-DISCONNECTEDというエラーで異常終了している様子。

$ cat /etc/wpa_supplicant/wpa_supplicant.conf  

で設定を見てみると、先頭に下記の謎の設定が自動的に追加されていました。

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

この設定を削除して元のwpa_supplicant.confに戻すと、無線LANに接続できました。

固定IPでなくなる

dhcpcd.confを覗いてみると、設定が初期値に戻されていたので、以前と同様に設定を行うことで固定IPの設定も難なくできました。
dist-upgradeの途中で設定ファイル群を更新したことが原因のようです。

まとめ

dist-upgradeの途中で設定を更新するときは要注意。

TDD challenge #1 に参加してきました

概要

2017年8月18日に株式会社ミクシィ 渋谷本社にて開催されたTDD challengeに参加してきました。

このワークショップは、テスト駆動開発(TDD: Test Driven Development)の講義と、ペアプログラミングの形式をとった実習から構成されていて、講義と演習を交互に行うものでした。

当日の流れ

開始前

11:00より受付とのことだったので、あらかじめ場所を確認しておいて、定刻どおりに受付まで行いました。
JR渋谷駅のすぐ近くだったので、迷わずに済みました。

各種設定(演習用)

予め決められたペアで演習を行いました。パートナーの方と共通して使用できる言語がJavaしかなかったので、使用言語はJavaとしました。

全体としては、Javaを使用するペアが多数でしたが、他にもRubyPythonなどを使用するペアもあって、多種多様でした。
とはいえ、私たちのペアは両者ともにしばらくJavaを書いていなかったので、些か不安でした。

講義

なぜTDDが必要なのか、どのような状況でTDDがその威力を発揮するのか、TDDを始めるにあたって意識すべきことは何か、といった点に重点を置いた講義だったように感じました。

TDDでは、その名にあるとおり、

  1. テストを書く
  2. テストを失敗させる
  3. (テストを通すように)実装する

の順で開発を行います。リファクタリングは最後、つまりテストが通っている前提で行うべき、とのことでした。 特に、TDDにおいて意識すべきことやメリットが次節の演習で大きく効いていた印象を受けました。

演習

講義の合間合間に複数の課題が発表されて、要求された仕様を満たすようにペアでTDDによる実装を行います。

一見実装が楽に思える仕様でも、TDDを意識して、テストを先に完成させることに重点を置きました。 私たちのペアはJavaを使用したので、テストフレームワークとしてJUnitを採用しました。
両者ともにJUnitは未経験だったため、講師の方々に助けて頂きながら試行錯誤しました。

演習の前半ではつい実装の方に手を伸ばしてしまいそうになっていましたが、後半ではテストを書くことに多くの時間を割くようになっていました。
各課題ともに1~2時間程度(正確に測ったわけではないのでそれ以上の可能性もある)の時間が設けられていましたが、テストの作製に時間を要したこともあって、すべての課題を完成させることはできませんでした。

しかし、テストを作成するにあたって、テストがコード自体(クラスなど)の設計に直結しているように感じて、テストを完成させたあとの実装は想像以上に速く行うことができたように思いました。

その他

エンジニアの方々とともに昼食をいただきました。8月18日が「お米の日」(「米」を分解すると八 十八 になることから。米寿の由来と同様?)ということで、釜めしをいただきました。お茶漬け用の出汁もあり、二重の楽しみがあって大変おいしくいただきました。

食事中にはエンジニアの方と研究の話題や普段のコーディング、プログラミング言語全般など、様々なお話をさせていただいて、大変有意義な時間となりました。

まとめ

普段私はプロジェクト(もしくはオブジェクト指向としてのクラス)を設計するとき、必要なメソッド群を脳内で雑に実装を始める、といったことをしていたのですが、実際はそれはTDDに直結していて、そのまま置き換えられるように感じました。
TDDではテストがそのまま実装される関数群を網羅していて、かつテストケースとして期待する振る舞いを記述することから、むしろ仕様がテストに表れている印象を受けました。
期待される動作がテストに書かれているため、実装の際に混乱することを抑制することができ、実装をスムーズに行うことができたように思います。

言語によってテストフレームワークは異なりますが、幸い普段私が使用する言語は優秀なフレームワークが整っているようなので、今後TDDを活用していきたい、と強く感じたワークショップとなりました。

最後になりますが、ワークショップを通して丁寧に指導してくださった講師の皆様、本当にありがとうございました。 また、参加者の皆さん、お疲れ様でした。

Phoenix on Raspberry Pi の導入メモ

プログラミング言語ElixirのWebフレームワークである「Phoenix」をRaspberry Pi 1 に導入してみましたが、いたるところで詰まったのでメモしておきます。

# 目標 Raspberry Pi Model BにPhoenixを導入する。

今時何で初代を使っているのだろう。。

問題1

「Elixir Phoenix」などのワードで検索すると、多くの記事で以下のような導入方法が紹介されています。

qiita.com

この記事におけるPhoenixの導入方法を試みると、まずmix local.hexの実行の時点で失敗しました。エラー文の画像はありませんが、以下のような内容です。
Phoenixの導入のためにはhexは必須ではありませんが、mix archive ~の部分も同様のエラーで失敗します。

stackoverflow.com

エラー文から察するに、SSLが有効になっていないことが原因のようです。 opensslが入っていることを確認したうえでErlang VMの再導入を試みましたが、無駄のようです。

そこで、Erlang VMソースコードからビルドすることを試みます。Erlang VMをビルドしてSSLを有効にする方法は以下の記事を始めとして多くの記事で紹介されているように、kerlというバージョンマネージャを使用すれば容易に行うことができますが、コンパイルオプションが曲者でした。

qiita.com

紆余曲折あり、私の環境ではオプションを以下のようにすることでようやくSSLが有効になりました。

KERL_CONFIGURE_OPTIONS="--enable-dynamic-ssl-lib --with-ssl=/usr/bin/ --disable-hipe --enable-smp-support --enable-threads --enable-kernel-poll --disable-native-libs --without-javac"

このオプションでビルドした場合、初代Raspberry Piのスペックでは数時間から半日ほど時間を要しました。

問題2

Erlang VMソースコードからビルドし、Elixirの環境を導入します。 Elixirの環境は、

$ apt-get install elixir

で問題ありませんでした。
導入後、

$ mix phoenix.new phoenix_sample
$ cd phoenix_sample
$ mix phoenix.server

とすることで導入完了の予定でしたが、ここで別の問題が発生しました。mix phoenix.serverの実行中に行われるnpm installでエラーが発生し、失敗する、というものでした。

ここでnpmのバージョンを調べると、

$ npm --version

v0.14.21という、古すぎるバージョンであることが判明したため、以下の記事に則ってnpm(及びnode)のアップデートを行い、

qiita.com

再び

$ mix phoenix.server

とすることで解決できました。

導入成功

導入後、初回起動時はコンパイルが多く、ある程度時間を要しましたが、実際にブラウザからアクセスでき、同時にログ出力も確認されました。
ログの応答速度から察するに、初代Raspberry Piにとってはある程度の速度が出ている・・・のか?というところです。

f:id:je6bmq:20170131213245p:plain f:id:je6bmq:20170131213322p:plain

CTF for ビギナーズ Finalに参加しました(感想+Write up)

Outline

初CTF(at セキュリティ・キャンプ2016)以来、CTFに興味があったのでCTF for ビギナーズ FINALに参加してきました。

2016.seccon.jp

午前中から昼過ぎまでWeb、Forensics、Binaryについての講義が行われ、最後に参加者全員でCTFを行いました。 今回のCTFは初の400人規模のCTFとのことで、独特の雰囲気だったことを覚えています。。 このCTFは講義の復習+αのような内容で、難しくも楽しかったです。

私が解けた問題は以下の通りです。 f:id:je6bmq:20170130210532p:plain

Webの「もぐもぐ」問題、Forensicsの「あけてみよう」問題、Binaryの「HiddenFlag」問題は今思うとあと1歩で解くことができたような(気がする)問題だったので、悔しい限りです。
後でちゃんと解こうと思います。

以降、Write upです。

Write up

スクリーンショットの撮り忘れにより、(特にWebの)情報量が少ないことをお許しください。 また、フラグの形式はctf4b{文字列}です。

Web

Classical Injection

フォームに' OR 1=1を入力すると、フラグが表示されました。

(講義中で「もっとも単純なインジェクションの1つです」のような話があったような・・・?)

May the extensions be with you.

提示されたURLを開くと、「あなたは管理者(admin)ではない」(曖昧)といったメッセージが表示されており、問題から、ブラウザの拡張機能を使用すればよいのでは?と想像しました。

演習環境のブラウザ(Chrome)には、EditThisCookieという拡張機能があり、Cookieの値を参照、変更することができるため、使用してみると、admin(といった名前)のCookiefalseの値を持っていることが確認できました。

そこで、この値をtrueに変更し、リロードするとフラグが表示されました。

Forensics

みつけてみよう

与えられたpcapファイルをWiresharkで開いて、パケットの統計(Packet Hierarchy)を見ると、以下のようにHTTPでいくつかパケットが飛んでいることが分かりました。

f:id:je6bmq:20170130213953p:plain

これらのパケットを眺めていると、無数のctf4b{}の文字が。
そこで、Wiresharkのフィルタリング機能でframe matches "ctf4b"とすると、フラグが出てきました。
正規表現で検索するなど、より理論的な解法は多々あるかと思われる)

Binary

復習

2つのセクションのアセンブリの処理を追った結果得られる最終的なeaxの値を"_(アンダーバー)"で結合したものをフラグとする、といった問題でした。

1つ目のセクションではeaxの初期値を3として、8倍したあと、3を引き、さらに2を足す、といった処理をしていたので、最終的なeaxの値は23となったと思います。

2つ目のセクションでは、ループのインデックスが1から5まで増加する計5回のループ中に、毎回eaxに対してループインデックスが乗算されるような挙動に思えたため、5の階乗、つまり120が得られ、

ctf4b{23_120}

をsubmitした結果通ったと思います。
アセンブリのファイルが手元になく、曖昧さが大きいです)

bashとgnuplot (時々awk)でデータ整理!

この記事はTUT Advent Calendar 2016の22日目の記事です。

本年度の私は、いろいろなデータをCSVファイルで吐かせて、そのデータ整理を行っていました。
データ整理の際、表計算ソフトが重い、そこまで面倒なことはさせない、といった場合のデータ整理でしたら、シェルスクリプトgnuplot(時々awk)でこなすことができます。
特に最近ではbash on Windowsの登場でWindowsでもbashスクリプトを書くことが可能になりましたので、お勧めしたいと思います。(表計算ソフトが重かったりしますし。。)

以降、今年1年で私が得られた知見について書き連ねていきます。 大まかな流れは以下の通りです。

  • 統計処理
  • ファイル整理
  • グラフ化

統計処理

統計処理として、今回取り上げるのは平均分散最大値(最小値)です。
今回は、CSVファイル(hoge.csv)が以下のような構成をしていることを想定します。

キー(サンプル番号やx軸に対応するもの), データ

つまり、ファイルの2列目を使用したい場合です。

平均

bashで平均値を求めたい場合は、awkを使用して1行で書くことができます。平均値meanは、以下のコードで求めることができます。
awkのオプション、-Fでファイルのデリミタ(区切り文字)である","を指定しています。

mean=$(cat hoge.csv | awk -F,  '{m+=$2} END{print m/NR;}')

awkのオプション、-Fでファイルのデリミタ(区切り文字)である","を指定し、ファイル中の2列目($2)の総和をとり、行数(NR)で割るのみです。

分散

先ほど求めた平均値meanを用いて、分散varianceは容易に求めることができます。

mean=$(cat hoge.csv | awk -F,  '{m+=$2} END{print m/NR;}')
variance=$(cat hoge.csv | awk -F,  "{m+=(\$2-${mean})^2} END{print m/NR;}")

meanの例とは異なり、awkの引数をダブルクォートで囲んでいます。これにより、列数を指定する$はエスケープが必要ですが、代わりにbashの変数展開を用いることができますので、分散を楽に求めることができます。(もっと楽な方法があるかもしれません)

最大値(最小値)

最大値は、awkを用いて次のコードで求めることができます。

max=$(cat hoge.csv | awk '{if(m<$2) m=$2} END{print m}')

最小値はこのコードの不等号を入れ替えるだけで求めることができます。

ただし、hoge.csvの2列目がすべて0の場合、結果として空の文字が返ってくるようです。(比較に失敗し続ける?) そのため、awkのBEGINセクションで初期値を与えてあげるのが無難化と思われます。

ファイル整理

ファイル整理として、例えばファイルの分離にはheadやtailコマンドで行うことができ、ファイルの結合にはcatコマンドでファイルを全て指定することで行うことができます。

本記事で着目するのは、ファイルの列結合です。

catコマンドで行うことができるのはファイルを縦に結合する場合です。ファイルを列で結合するには、joinコマンドを用います。
例えばhoge.csvの同様のファイル形式を持つfuga.csvがある場合、その2つのファイルを同一キーで列結合するには、以下のコマンドで行うことができます。

join -t, hoge.csv fuga.csv >> hogefuga.csv

デリミタを-tオプションで指定し、標準出力に結果が出力されるため、結合後ファイル(hogefuga.csv)に記録します。
joinコマンドはデフォルトでは1列目をキーに、2列目をデータとして処理します。 キーとなる列とデータ列を明示的に指定する場合は、それぞれ-1、-2オプションによって列番号を指定することで処理が可能です。

ただし、このjoinコマンドは同時に2ファイルのみを結合可能という制約がありますので、3ファイル以上を結合したい場合はmktempコマンドなどで一時ファイルを生成してから順番に結合する必要があります。

グラフ化

gnuplotを使う際に多用した機能について述べます。
gnuplotCSVファイルを用いる際は、あらかじめ、

set datafile separator ","

とすることで、読み込むファイルのデリミタを","に指定します。

プロット時の簡単な数値処理

グラフを描画する際、ちょっとした規格化や簡単な単位調整等が必要な場合があります。つまり、ある列のすべての値に対して同じ演算を施したい場合、gnuplotで描画する場合に処理を行うことができます。

通常、hoge.csvの1列目を第1軸に、2列目を第2軸として描画を行う場合、以下のようなコマンドをgnuplotでは実行します。

plot "hoge.csv" using 1:2 

例えばデータを1000倍して表示したい場合、以下のようなコマンドを実行します。

plot "hoge.csv" using 1:($2*1000) 

関数近似

gnuplotでは、関数近似も容易に行うことができます。
例えばhoge.csvの1列目をx軸、2列目をy軸の値として

y=ax2+bx+c

の式で近似したい場合は、以下のコマンドを実行します。

f(x)=a*x**2+b*x+c
fit f(x) "hoge.csv" using 1:2 via a,b,c

このコマンドでは、f(x)としてフィッティング先の関数を、via以降で最適化するパラメータを列挙する必要があります。
フィッティング結果(係数の値、誤差)は、標準出力に出力されるとともに、logファイルが生成され、そこに書き込まれます。

文字列

複数のcsvファイルを同時に描画したい場合があるかと思います。 gnuplotではsprintf関数をサポートしているため、以下のような構文を用いることができます。

i=3
s(n)=sprintf("hoge_n%d.csv",n)
s(i)
# s(i) equals to hoge_n3.csv

また、gnuplot version 5.0以降では、描画時ループ構文をサポートしましたので、以下のような構文を用いることができます。

plot for[i=1:10] s(i) using 1:2

gnuplotではスクリプトファイルを作成し、gnuplot内でloadコマンドを実行することでコマンドをまとめて実行することができますが、 文字列処理や使用ファイル数が煩雑になる場合、bashスクリプトgnuplotスクリプトファイルを自動生成することも手です。

bashでは文字列内の変数展開が可能ですので、ファイル名の指定が容易に可能です。

まとめ

bashgnuplotを用いることで、簡単なデータ整理を行うことができます。

個人的にはjoinコマンドにより、表計算ソフトでの負担が大きく減るように思います。

明日のAdvent Calendarは・・・?

明日23日目のAdvent Calendarは@emaxserさんの担当です。「何か頑張る」とのことなので何やら楽しみです。
無理しない程度に頑張っていただきたいです。

セキュリティ・キャンプ2016全国大会に参加しました

8月9日~13日の4泊5日にわたって開催されたセキュリティ・キャンプ全国大会2016に参加してきました。
大変短く、楽しくハイテンションに過ごすことができた5日間だったので、ハイテンションのままに書き連ねておきます。

講義時間割 内容
1・2-F 作って学ぶ低レイヤーネットワーク
3-C 脆弱性検出実践(ファジング技術と脆弱性報告)
4-C オンラインゲームアタック&ディフェンスチャレンジ
5-D みんなでクールなROPガジェットを探そうぜ
6-C 車載LAN上を流れるメッセージの解析
7-B 組み込みリアルタイムOSとIoTシステム演習

DAY1

会場到着まで

事情により参加が遅れたため、多くの方と同時に交流できるチャンスの1つを逃してしまうというところから私のセキュリティ・キャンプは始まりました。
遅れて参加した私にも到着早々話しかけてくださった方に本当に感謝感謝です。

特別講義

サイバーディフェンス研究所の福森さん、日本サイバー犯罪対策センター(JC3)の間仁田さんによる講義が行われました。

福森さんの講義では技術とは何か、技術を何に使うのかを考える機会になりました。
間仁田さんの講義では、犯罪とは何か、セキュリティに関する犯罪をどのように複数の機関で解決するか、といったことを考えさせられました。

DAY2

専門(1)、専門(2)

概要:前半でPC上でパケットを生成やキャプチャーするプログラムを自作することにより、パケットの構成を理解します。後半でArduinoのデジタ ル出力のみを使って10BASE-Tのフレームシーケンスを実際に送出する演習を行います。

この講義で、前半ではOSI参照モデルにおける2層のレベルでパケットに触れ、後半では1層のレベルでパケットに触れて講義が行われました。
ここではARPパケットに着目して、ARPを手元のツールで送受信を行ったり、 Arduinoのボードからパケットを送信する、といったことを行いました。 特に、普段マイコンで遊ぶことの多い私には、ArduinoからEthernetフレームが送信できていることが大変新鮮でした。
また、用いたツールに関連付けて、ARPついて起こりうる攻撃手法(ARP Spoofing)にも触れられて、大変興味深い講義でした。

午前8時30分から午後5時30分まで1日中演習を行っていたのですが、楽しくてあっという間でした。

CTF

今回のセキュリティ・キャンプにおけるCTFは、Raspberry Piを舞台にFlagを集め、得点を競うというものでした。

私は今回が初CTFでした。
まずRaspberry Piが舞台ということで、まず適当にポートスキャンした結果SSHとHTTPに加えて2つ怪しげにポートが空いていたので、そのあたりはWebあたりに強いチームメイトにお任せしました。
Raspberry Piの初期ユーザとパスワードは体が覚えていたのでSSH接続を試みた結果あっさりログイン出来てフラグがあったので驚きました。

その後はチームメイトに助言をもらいながらRaspberry Piに保存されていたバイナリの解析を行いました。
1つはどうやら引数の値からFlagの値を計算していたようで、解析すると連立方程式の解がFlagに対応することがわかりました。
連立方程式を手計算で解くと解が一意に定まらないことがわかったので、正しいFlagを求めるために 解の組み合わせをできるだけ多く試すスクリプトを書いて総当たり的にFlagを計算しました。
出力されたそれらしい値を提出すると整数解の最小の組み合わせ(基本ベクトル)がそのままFlagを生成していたらしく、正攻法とは言えないかもしれませんが総じて2問分の得点だけチームに貢献できてよかったです。

私がこれらのことをやっている間に、チームメイトが他の問題(Web系などなど)を攻めて得点につなげてくれていて、なんと私のグループは優勝できました!
チームメイトに感謝感謝、と言いながら、ひとえにCTFと言っても様々な形(問題形式)があるのだなぁ、と思い、とても興味がわきました。

DAY3

専門(3)

脆弱性検出に使われるセキュリティテスト「ファジング」や、これまでに学んだ事を活かして IoT 機器を始めとした製品に対して脆弱性発見に挑戦していただきます。そこから検証コード作成を含めた脆弱性報告の仕方についても実践していただきます。

この講義では、実際の製品に対して ファジングを行ってその結果を観察しました。

実際に脆弱性が発見された、といったことはなかったのですが、実際にツールがファジングに使っているデータが興味深いデータばかりでした。

専門(4)

オンラインゲームのプログラムなどによる自動プレイは、不正行為として禁止されているケースがほとんどです。しかし、不正行為自体はなくならず、近年では、自動化のみならずチートなどの行為も横行しており、対策に追われることも少なくありません。本講義では、オンラインWebゲームを運営する側とプレイする側に分かれて、運営側と攻撃側を体験します。

講義で使用されたゲームについてはこちらに詳しく書かれています。
講義は前半と後半に分けられ、私はプレイヤー側と運営側の両方を担当することができました。

プレイヤー側では、自分がゲームをプレイしやすいようにするためのコントローラが完成直前で時間切れになったため悔しい思いをしました。
サーバ側では、サーバのログを逐次見ながら、明らかに人為的なものではない(プログラムで実行されたような)挙動が発生した際に逐次対応できるよう努めました。

セキュリティの脆弱性以外にも、攻撃者によっていかに攻撃を効率よくさせないか、といったようなことと関連があるのでは、と思いました。

専門(5)

本講義ではReturn-oriented programming(ROP)で利用可能なコード断片(ROPガジェット)を探索するツールを自作・利用していきます。

ROP に着目した講義で、ROPガジェットを見つけて構成するという講義でした。
講義では、libcのバイナリに対してシェルを起動することを目的に、ROPガジェットをツールを用いて探し、構成しました。
ここでは4つのlibcが用意され、次のことを行う、といった演習でした。

  1. 1つのlibcに対してシェルを起動するよう、ROPガジェットを構成する×4

  2. 2つのlibcに対して1つのプログラムで両方ともシェルが起動できるようにROPガジェットを構成する

  3. 3つのlibcに対して1つのプログラムで(以下略

  4. 4つ(以下略

キャンプが始まる前までは全く未知の分野で、理解できるか大変不安でした。講義が始まってひととおり説明を受け、実際にROPガジェットを探して組み合わせ始めると、途端に楽しくなって、1つROPが完成できたときには大変興奮しました。

私はlibcに対してシェルを起動するプログラムを2つまで作ることができました。ほかの方の中には複数のlibcに対して同時に起動するものを作成できた方もいました。

講義を受けるまで不安が多かったのですが、講義後にはとても気持ちよく、引き続き勉強したくなりました。 この講義はスケジュールの都合上、他の講義より時間が短く、物足りなさも感じました。

DAY4

専門(6)

現在の自動車には数十のECU(制御コンピュータ)や、またセンサやアクチュエーターが搭載されており、それぞれCANやLINなどの通信ネットワークで結ばれてい ます。 今回は、CANの実験用ネットワークとECUのシミュレータを用意し、そこにELM327 を使ったアダプタで各人のPCからCANバスにアクセスし、流れているメッセージを受信し解析する方法を、LinuxPythonの環境を使ったハンズオン形式で行う予定です。

この講義では、CANのパケットを受信して、その内容をフォーマットに基づいて解析する、といったことを行いました。
CANのデータフォーマットについても丁寧に解説いただき、スクリプトを組んで実際にデータが解析できて大変面白かったです。

また、CANのデータフォーマットとその意味について説明があり、個人的には「なるほど…!!」と感動しました。

専門(7)

組込み/IoTシステムに搭載される組込みリアルタイムOSと通信ミドルウェアの仕組みについて、実機による演習を通して学んでいただきます。汎用システムとは 異なる、組込み/IoTシステムの世界を、ソフトウェアを中心に知ることができます。

普段マイコンをOSなしの環境下でプログラムを組む私にとっては、組込み用リアルタイムOSはまるで別の世界でした。
ふたを開けてみれば、形は違えどまるで通常のOSのようなスタイルでプログラムを組むことができて、大変便利だと感じました。
一方で組み込み特有の事情に起因する違いもあって、新鮮でした。

DAY5

グループワーク発表

私のグループは「小規模企業におけるセキュリティ対策」について考察しました。発表まで(ほとんど前日)に調査、考察をする中で、他のグループのテーマとも深く関わりがあるように思えてきて、「もともとそのような意図からこのグループワークは始まったのでは・・・?」と思いながら資料を作成しました。

実際に他のグループの発表を聞きながら自分のチームの発表を終えると、(冷静に考えれば容易にわかることかもしれないけれど)内容をうまく絞ることができていなかった、と反省しました。
他のグループの発表を聞きながら、その発想はなかった、と思うことも多々あって、個人的によい刺激になったと思います。

キャンプを終えて

セキュリティ・キャンプの5日間は本当に濃く、(感覚的に)短いものでした。
参加者の皆さん、チューター、講師の皆さんには大変感謝しております。本当にありがとうございました。

その他

食事

おいしい。

夜でも外が明るかったので、明るいと寝付けない私にとってはなかなか辛かった。