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を使う際に多用した機能について述べます。
gnuplotでCSVファイルを用いる際は、あらかじめ、
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では文字列内の変数展開が可能ですので、ファイル名の指定が容易に可能です。
まとめ
bashとgnuplotを用いることで、簡単なデータ整理を行うことができます。
個人的には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つのlibcに対してシェルを起動するよう、ROPガジェットを構成する×4
2つのlibcに対して1つのプログラムで両方ともシェルが起動できるようにROPガジェットを構成する
3つのlibcに対して1つのプログラムで(以下略
4つ(以下略
キャンプが始まる前までは全く未知の分野で、理解できるか大変不安でした。講義が始まってひととおり説明を受け、実際にROPガジェットを探して組み合わせ始めると、途端に楽しくなって、1つROPが完成できたときには大変興奮しました。
私はlibcに対してシェルを起動するプログラムを2つまで作ることができました。ほかの方の中には複数のlibcに対して同時に起動するものを作成できた方もいました。
講義を受けるまで不安が多かったのですが、講義後にはとても気持ちよく、引き続き勉強したくなりました。 この講義はスケジュールの都合上、他の講義より時間が短く、物足りなさも感じました。
DAY4
専門(6)
現在の自動車には数十のECU(制御コンピュータ)や、またセンサやアクチュエーターが搭載されており、それぞれCANやLINなどの通信ネットワークで結ばれてい ます。 今回は、CANの実験用ネットワークとECUのシミュレータを用意し、そこにELM327 を使ったアダプタで各人のPCからCANバスにアクセスし、流れているメッセージを受信し解析する方法を、LinuxとPythonの環境を使ったハンズオン形式で行う予定です。
この講義では、CANのパケットを受信して、その内容をフォーマットに基づいて解析する、といったことを行いました。
CANのデータフォーマットについても丁寧に解説いただき、スクリプトを組んで実際にデータが解析できて大変面白かったです。
また、CANのデータフォーマットとその意味について説明があり、個人的には「なるほど…!!」と感動しました。
専門(7)
組込み/IoTシステムに搭載される組込みリアルタイムOSと通信ミドルウェアの仕組みについて、実機による演習を通して学んでいただきます。汎用システムとは 異なる、組込み/IoTシステムの世界を、ソフトウェアを中心に知ることができます。
普段マイコンをOSなしの環境下でプログラムを組む私にとっては、組込み用リアルタイムOSはまるで別の世界でした。
ふたを開けてみれば、形は違えどまるで通常のOSのようなスタイルでプログラムを組むことができて、大変便利だと感じました。
一方で組み込み特有の事情に起因する違いもあって、新鮮でした。
DAY5
グループワーク発表
私のグループは「小規模企業におけるセキュリティ対策」について考察しました。発表まで(ほとんど前日)に調査、考察をする中で、他のグループのテーマとも深く関わりがあるように思えてきて、「もともとそのような意図からこのグループワークは始まったのでは・・・?」と思いながら資料を作成しました。
実際に他のグループの発表を聞きながら自分のチームの発表を終えると、(冷静に考えれば容易にわかることかもしれないけれど)内容をうまく絞ることができていなかった、と反省しました。
他のグループの発表を聞きながら、その発想はなかった、と思うことも多々あって、個人的によい刺激になったと思います。
キャンプを終えて
セキュリティ・キャンプの5日間は本当に濃く、(感覚的に)短いものでした。
参加者の皆さん、チューター、講師の皆さんには大変感謝しております。本当にありがとうございました。
その他
食事
おいしい。
夜
夜でも外が明るかったので、明るいと寝付けない私にとってはなかなか辛かった。
gnuplotでpdf出力できなかったのでメモ(OSX,El Capitan)
OSXのHomebrewでインストールしたgnuplotでpdf出力ができなかったのでその解決策をメモ。
OSXのHomebrewは大変便利なので、
$ brew install gnuplot
とするだけでターミナル上でgnuplotを動かすことができます。
…が、これだけだとpdf出力ができないようです。
pdf出力可能かどうかは
$ gnuplot > set terminal
と実行することでわかります。
解決策は、「pdf出力をサポートするようにインストールオプションを追加する」です。
(brew info 等でインストールオプションは調べられるそうです)
したがって、一度gnuplotをアンインストールしてからオプションを追加して再インストールする必要があります。
pdf出力をサポートするためのインストールオプションは
"--pdf"とのことなので、以下のように実行することでpdf出力ができるようになりました。
$ brew uninstall gnuplot $ brew install --pdf gnuplot
Raspbian Jessieで静的IP
Raspsberry PiでIPアドレスを静的にする方法がWheezyとJessieで異なる(?)のでここに記します。
これまでは/etc/network/interfacesに記載する方法をとっていました。
(おそらくそのような記事が多数)
Jessieから、/etc/dhcpcd.confに追記しなければならないようです。
interface インターフェース名(eth0など) static ip_address=アドレス static routers=ゲートウェイ static domain_name_servers=DNSサーバアドレス
/etc/network/interfacesはデフォルトのままで、dhcpcd.confを編集するのみでIPアドレスを固定することができました。 無線LANを用いる場合のwpa_supplicant.conf周りの設定はWheezyとJessie間で変更はない模様です。
スタート
後の自分のためも兼ねていろいろ書いた方がいいと思って作ってみました。