seccamp2016 DAY4

6-C 車載LAN上を流れるメッセージの解析

車載LANであるCANネットワークに接続し,そこを流れるパケットをキャプチャ解析して遊びました.
今回の機材は安価で手に入れられるということなので,問題のない範囲で遊びたいと思います.

7-A ID連携基礎

今回のセキュリティ・キャンプのなかでは非常に高いレイヤの話でした.具体的にはHTTPより上のレイヤでした.
非常に残念ながら最後まで演習をする時間がありませんでしたが,とても興味が湧いたのでまた演習したいと思います.
Burp使えるようになりたい.

企業プレゼンテーション

AAとかtwitterアカウントとかコミケのブースとか紹介されました.
質問の時間も多くとっていただきました.インターンシップの話なんかは良い情報を聞きました.

グループワーク

今日はチューターさんが「寝ろ」と言わずにデブ活している……
一部の方には「夜は自分の部屋にいなkくぁwせdrftg……
徹夜つらい……
徹夜つらい……
徹夜つらい……

今日の飯テロ

朝ごはん

昼ごはん

夜ごはん


謎ごはん


seccamp2016 DAY3

いろはす

室内でもいろはすが無限に増え続けている件について.

3-B フィジカル・リバースエンジニアリング入門

JTAGまで行けなくてとても残念でした.
法を破らない範囲で楽しく分解調査をしていきたいと思いました.

4-C オンラインゲームアタック&ディフェンスチャレンジ

ほぼすべて演習という感じの講義でしたが,なかなかにつらかったです.僕の仕事は強い人を観察することということなので色々と様子を見ていたのですが,本当に強いですね…….
jsはインターンで扱わないといけないので,これから頑張っていきたい所存.あとWebSocketもとても手軽に扱えそうなので,是非触ってみたいです.

5-C サーバに対する攻撃とその影響度を調べてディスカッションする講義

唐突な差し入れで受講者の心を鷲掴みにする川口先生素敵でした!!

一番目の発表者がスライド40枚分作ってきていて,できる人はこんなにいっぱい調べられるんだなあと驚きました.
僕は問題点2個だけピックアップしてプレゼンしました.
模範解答の発表では色々と納得の行く調査をしていて,やはり本業の方はすごいなあという感想を抱きました.

企業プレゼン

DNPさんのプレゼンを聞きに行きました.
「TAME Range」というサーバセキュリティの演習環境を開発されているそうです.印刷業のメーカーからしては全然イメージできないジャンルでしたが,色々な紹介を聞くことができました.

グループワーク

すすめています(白目)

今日の飯テロ



seccamp2016 DAY2

おはようございます

今日から(と言っても書いてるのは翌日の朝ですが)専門講義が始まりました.
とてもわくわくしながら朝ごはんを食べていました.

1・2F 作って学ぶ低レイヤネットワーク

午前

坂井講師作のpkt-toolsの使い方を学習した後,
0806 0001 0800 0406 0002
この凶悪なパケットを送りまくったり,
超簡易型リピーターの暴走っぷりを眺めたり,
頑張ってICMPパケットを作ったり,
pkt-toolsを改造したり,
幕張に閉じ込められているのに運動会を始めたりしました.
(ちなみに運動会は これ を使いました.カッコイイですね)

※8/30追記
講義では隔離されたネットワークの中のみでパケットを送信しました.運動会をやりたいと思われた方は,必ず外部のネットワークから隔離するようにしてください.

午後

午後は,なんと変態改造を施したArduinoのGPIOポートをそのままLANケーブルにつなぎ(!?),ARPパケットを送ってみようという実習でした.
自作したLANケーブルというのがこちら

これは帰ってから自分で試してみたい! と思いました.
「イーサネットコントローラの言いなりにはならないぞ!」

※8/30追記

CTF

僕はこのチームで出場しました.
他のメンバーは気付かずのうちにこのチーム名に決定したようでしたが,

Perlはいいぞ

結果は10位200点.
まあ残念でしたが,うんうん唸っているのがとても楽しかったので,またチャレンジしたいと思いました.

そういえば生の友利奈緒さんを二人目撃することができたので幸せでした.

今日の飯テロ

seccamp2016 DAY1

はじまりました

セキュリティ・キャンプが始まっちゃいました.

頑張っていこうと思います.

開講

荷物を預けたら名刺交換です.
数えたら今日だけで51枚の名刺+2枚のステッカーをいただきました.みていてとても楽しいですね.
デレステマシンを覚えて頂いてる方が数人いらっしゃって,とてもうれしかったです.

そういえばいきなり会場のアクセスポイントが楽しいことになっていました.

共通講義

スーツのおじさまのお話が終わった後,楽な格好のおじさんのお話が始まりました.はじめの「セキュリティ基礎」ではいきなりグループワークで,応募フォームの問題点のあら捜しをしました.自己紹介から入ったのですが,うちのグループはみなさんVim使いでEmacserが一人もいませんでしたつらいかなしい.
(Emacserのお友達を切実に募集しています)
こういった話が普通に通じてしまうコミュニティが大学にはとても少なく,楽しかったです.

その後は,キャンプのためだけに来ていただいたと言う,福森さんの講義でした.
ただ単に力をつけるだけではダメだと痛感し,「技術」とは何なのか考えさせられた講義でした.

他にも色々あった気がしますが朝ごはんを食べたいので一旦投稿してしまいます.

本日の飯テロ

本日のお部屋情報

普通に快適でした.

ArchLinux道、始めます!

この記事は2016年1月の下書きに加筆修正したものです.

今更感のあるこの記事について

ついにArchLinuxに手を出してしまいました(2016年1月頃の発言)。
手持ちのPCはこんな感じになってます。

  • Win7 + ArchLinux デスクトップ
  • Win10 + Ubuntu14.04 ノート → Win10 + ArchLinux ノート (Ubuntuアップデート失敗のため,乗り換えました)
  • Ubuntu12.04 サーバー

せっかくなので次のインストールの為にも,セットアップ手順を残しておきます。
OSのインストールに関しては情報がたくさん見つかったので,省略します。
主に次の記事を参考にさせていただきました.
ビギナーズガイド | ArchWiki
Arch Linuxインストール | 普段使いのArch Linux
今回の記事では,デスクトップ環境の導入からとりあえずのPC環境にするまでをまとめます。

デスクトップ環境の導入

今回はデスクトップ環境としてGDM+Cinnamonを選択しました。

1
sudo pacman -S gdm cinnamon

パッケージなど

いれないと死んでしまうパッケージ

1
2
3
4
5
6
7
8
9
sudo
gnome-terminal #端末,Ubuntuの標準
alsa-utils #音の再生には必須
bzip2
make
git
zsh #シェルはzshを愛用しています
emacs #迷ったらEmacsを
mikutter #ツイ廃さん御用達

日本語関係

emacs-mozcを使う場合,FcitxではなくiBusを使う必要があります.

その他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
nemo #シンプルで使い勝手の良いファイラ
eog #gnomeの画像ビューワです
evince #pdfなどのドキュメントビューワです
firefox
flashplugin
jre7-openjdk
asunder #CDのリッピングツール
vlc
mplayer #メディアプレーヤー
gnome-mplayer #mplayerのフロントエンド.無難に使いやすい
filezilla
libreoffice
shutter #スクリーンショットツール
vim

トラブルシュート

今回次のような問題が発生しました。
合わせて対処法もまとめておきます。

  • 日本語キーボードが使えない
    デスクトップ環境であれば簡単でした.
    設定画面を開き,キーボード > レイアウトから,レイアウトを日本語にします.

  • Cinnamonの設定が開けない
    Cinnamonの設定をGUIで行うには次のパッケージが必要だそうです。

    1
    sudo pacman -S cinnamon-settings
  • mozcが起動しない
    まずキー割り当てを見直してみてください.
    iBusのキー割り当て,mozcのキー割り当ての2種類があります.
    僕の場合,iBusには一切割り当てず,mozcのモード切替に全角半角キーを割り当てています.

  • 通知領域にmozcアイコンが表示されない
    まだ原因がわかっていません.ごめんなさい.

  • CapsLockをCtrlキーとして使いたい
    デスクトップ環境であれば簡単でした.
    設定画面を開き,キーボード > レイアウト > オプションから,CapsLockをCtrlとして使う設定を有効化できます.

  • プライベートIPアドレスを固定する
    Ubuntuに比べて少しややこしくなっていました.
    こちらの記事を参考に設定しました.
    Arch Linuxで固定IP設定にはまる | netanote.com

  • Cinnamonが起動しなくなった,Cinnamonのアイコンが表示されなくなった
    Gnome-shell 3.2.2 updated: extension and tray icons missing | Arch Linux Forums

ArchLinuxでBlu-rayを再生する

エンバンデビュー!

先日,初めてBlu-ray,いわゆる円盤を購入しました.

とりあえずいつものArchWikiより,Blu-rayについての記事を見ながら再生環境を整えようとしました.
しかし,方法1を試しても鍵の認証ができない,方法2はそもそも鍵データが古すぎる……,ということで嘆いていました.ああ,心待ちにしていた円盤が再生できない…….
どうやら,今回買った円盤はAACS v46だそうで,この方法は古すぎるようです.

と,そこに素晴らしい記事が舞い込んできました.
対Blu-ray用決戦部隊、通称MakeMKV

詳しくはこちらの記事を参照してください.
簡単に言うと,

一般的に使われているライブラリの代わりにMakeMKVで使われてるライブラリを使うことで,VLCでBDの再生ができる

ということです.
MakeMKVというのはBlu-rayのリッピングツールであるため,取り扱いにはくれぐれも注意してください.

というわけで,ArchLinuxの場合はユーザーリポジトリに入っているようなので

1
yaourt -S makemkv-libaacs

を実行し,VLCを起動し,Blu-rayディスクを再生しようとすると……,

参考にしたサイトの管理者の方,本当にありがとうございました.

ただし,メニューには対応していないようでした…….どうにかできないのでしょうか.

余談

今回の再生環境や,Windowsの怪しいフリーソフトでの再生時には,映像が乱れたり画面が止まったりすることが何度かありました.PowerDVDなどの純正ソフトで再生したときにはこんなことなかった気がします.
何が違うのでしょうか……?
きれいに再生する方法をご存知の方,教えてください.

dアニメストアはいいぞ

アニメ好きな人たちへ

dアニメストア はご存知でしょうか?
アニメ番組の配信サイトです.最近特に頑張っています.もともとはドコモの契約者のみに提供されていたサービスらしいですが,今は誰でも入会できるようになっています.
その魅力をまとめ,沼に落とそうみなさんにおすすめしようと思います.

dアニメストアとは

値段

公式サイトにこんな文言がありました.(アクセス日:2016年6月6日)

月額400円(税抜)で約1,600作品、 約30,000話のアニメが見放題!
ドコモじゃなくてもOK! 初回31日間は無料で見放題!

え,まって,すごくないですか?
月額400円でほぼすべての作品が見放題.一部有料作品(レンタル販売という扱い)がありますが,現時点で13作品だけです.2016年6月6日早朝段階で全作品数は1673作品でした.つまり,1660作品が見放題というわけですね,すごい.

配信作品

一番の問題はどんなアニメが配信されているかということですね.
例えば2016年春アニメを例に挙げると,残念ながらすべての作品が配信されているわけではないです.僕が見ようとしたアニメだけでも,

  • 甲鉄城のカバネリ
  • 彼女と彼女の猫 -Everything Flows-
  • ばくおん!!

は配信されていませんでした.
また,最新作の配信についても,配信日程が遅いものも見受けられます.Re:ゼロから始める異世界生活はテレビ放映の2週間後に配信されています…….もちろん,TV放映の翌日に配信される作品も多々ありますよ.

ではdアニメストアがどういった作品を多く置いているかについてです.
例えばノイタミナ作品は多く配信されています.僕だけがいない街や,PSYCHO-PASSなど,話題を呼んだ作品が見放題です.もちろん,有名なタイトルも多く配信されています.個人的イチオシですが,電脳コイルが配信されています.良いアニメだよほんとに.
昔のアニメも揃っているようです.アルプスの少女ハイジ,パーマン,おそ松くん(おそ松さんじゃないですよ),他にも新世紀エヴァンゲリオンも配信中です.
劇場版も配信作がそろっています.図書館戦争,あの花,花咲くいろは,雲のむこう、約束の場所,などなど.たまこラブストーリーは配信されていませんでした……残念!
他にも,ショートアニメもラインナップがそろっています.ゆるめいつ全シリーズや,あいまいみー(残念ながら1期のみ)が配信中.

独自のサービス

面白い配信サービスも展開されています.
例えば,アニソン配信です.なんとフルサイズの楽曲にムービーがついて配信されているのです.例えばGod knows,ガーネット,紅蓮の弓矢,などなど,全124曲のラインナップになっています.

また,dアニメストアはリクエストが可能です.観たいけど配信されていない作品は,是非リクエストを入れましょう.毎月のように新規作品が配信されているので,いつか配信開始されるかもしれません(一方で,しばしば配信終了もされています.また,復活することもよくあります).

他のサービスと比較して

大手アニメ配信サイトであるバンダイチャンネルに,バンダイチャンネルのおすすめポイントがまとめられていました.ここ.この表を見ながら確認していきましょう.

  1. 作品数自体はdアニメストアのほうが少ないですが,見放題作品数はおよそ1.5倍もあります.
  2. ガンダムシリーズは一部有料配信なんですよね…….こればかりはバンダイチャンネルに劣ります.仕方ない.
  3. 最新作の追加はリアルタイムで通知が来ます.しかも最新作の追加更新は毎日12時に行われています.
  4. 特撮は扱っていなかったはずです.まあ”アニメ”ストアなので……
  5. 自動連続再生に対応しています.
  6. 途中で再生を停止した場合,次回再生時には続きから再生します.この情報はアカウントごとに保存されているため,再生するデバイスを変えても再生位置は変わりません.
  7. PC版の場合,シークバーにサムネイル表示されていました.
  8. 視聴履歴はもちろん,気になるリストや,マイリスト機能が用意されています.
  9. アニメごとに口コミが見られるわけではありませんが,1シーズンに1回,おすすめアニメ投票が行われています.
  10. ファンがオススメアニメを公開はできません.その代わり,ユーザーへのおすすめアニメが公式から紹介されます.他にも,ジャンル別のアニメ特集が組まれています.
  11. 全話視聴したら”Complete”って書かれます……,別にエンブレムとかはいらないと思う.
  12. 決済手段はクレジットのみです.
  13. 対応デバイスはWin,Mac,Android,iOSです.しかし,GoogleChrome(Chromium)ブラウザを使えばLinuxからも視聴ができました!(これが言いたいがためにブログ更新したと言っても過言ではない)
  14. レベルなんて概念はありません.
  15. 動画の画質は3〜4種類用意されており,再生時に選択可能です(Edge,Chromeを除く).
  16. 会員限定のプレゼント企画が毎月開催されています.
  17. 月額料金の支払いごとにdポイントが貯まるようです.
  18. 特典……そんなのあったっけ.
  19. 過去ライブの配信はされているようです.
  20. iOSとAndroidは専用アプリがあります.使い勝手は問題ないと思っています.

結論

dアニメストアはいいぞ.最新作を一番乗りで観たい! という人にはあまりオススメできませんが,過去作品をゆっくり観たいという人にはとてもオススメです.

ちなみに,僕は基本的にdアニメストアでアニメを観て,配信されていない作品はAmazonビデオ(AmazonStudentなので年額1900円)で観ています.それでも配信されていない作品などはDMM月額レンタルで借りることにしています.割れ,ダメ,絶対!

それではみなさん,dアニメストアで楽しいアニメライフを!

セキュリティ・キャンプ2016に応募した

応募した

セキュリティキャンプに応募しました.
年齢制限があるので今年で最後です.
悔いのないように頑張って原稿を書き上げました.
さらに悔いの残らないようにブログに掲載しておきます.
合否結果は6月中旬までお待ちください.
※2016年6月14日追記 残念ながら参加見送りとなりました
※2016年6月16日追記 欠員補充により参加できることになりました

共通問題1

この設問は省略します.

あなたが今まで作ってきたものにはどのようなものがありますか? いくつでもいいので、ありったけ自慢してください。

reminder,思い継ぎ語り,タニタンv1.0・v1.1,迷路自動取得ソフト,マイクロマウスタイマー,タニタンv2.0H,STM32 writer,デレステ自動演奏機,について超簡単にまとめました.

それをどのように作りましたか?ソフトウェアの場合にはどんな言語で作ったのか、どんなライブラリを使ったのかなども教えてください。

それぞれ数文でまとめました.

開発記のブログなどあれば、それも教えてください。コンテストなどに出品したことがあれば、それも教えてください。

省略します.

共通問題2

あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?(例えば、C言語プログラムを複数ファイルに分割する方法)

近年で一番印象的だった壁はマングリングです.
組み込みで,初めてC++での開発をしようとしたときの話です.割り込みに関する部分のプログラムを追加したところ,定義しているはずの関数が見つからないというリンカエラーが発生しました.プログラムの見直しや構造の見直しなどいろいろと試してみたのですが,2週間ほど何もわからずに苦しんでいました.開発はC++ですが,自動生成されるファイルは一部がC言語やアセンブリで書かれていたため,これらのファイルの間でマズいことが起きているのではないかと考えましたが,具体的に何が悪いのかわかりませんでした.また,所属していたサークルにC++で開発をしている人がおらず,身近に解決手段を聞ける相手がいませんでした.

また、その壁を乗り越えるために取った解決法を具体的に教えてください。(例えば、知人に勧められた「○○」という書籍を読んだ)

マングリングに悩まされていた問題ですが,たまたま大学に来られていたサークルOBの人にプログラムを見てもらい,マングリングではないかとアドバイスを受けました.ひとまず対処法を検索し,C++はコンパイルの際にシンボル名が変わることが原因であるため,シンボル名が変わらないように対策すれば良いことがわかりました.
原因はわかりましたが,実際にどのようなことが起こっているか確認したかったので,簡単なプログラムを作成して実験してみました.作成したのは次のコードです.

1
2
3
4
5
6
int test_func(){
return 0;
}
int main(){
return test_func();
}

これをmainc.c,maincpp.cppの2つのファイルに分けて保存し,gccとrx-elf-gcc(Renesas RXシリーズマイコン用のコンパイラ)の2種類でコンパイルし,その中身を解析してみました.実行したコマンドは次の通りです.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ gcc mainc.c -o gccmainc.o
$ g++ maincpp.cpp -o gccmaincpp.o
$ rx-elf-gcc mainc.c -o rxmainc.o
$ rx-elf-g++ maincpp.cpp -o rxmaincpp.o

$ objdump -x gccmainc.o
(中略)
SYMBOL TABLE:
(中略)
0000000000000000 g F .text 000000000000000b test_func
(後略)

$ objdump -x gccmaincpp.o
(中略)
SYMBOL TABLE:
(中略)
0000000000000000 g F .text 000000000000000b _Z9test_funcv
(後略)

$ rx-elf-objdump -x rxmainc.o
(中略)
SYMBOL TABLE:
(中略)
00000000 g F P 0000000f _test_func
(後略)

$ rx-elf-objdump -x rxmaincpp.o
(中略)
SYMBOL TABLE:
(中略)
00000000 g F P 0000000f __Z9test_funcv
(後略)

これらの実行結果から,C++で実装された関数のシンボルがマングルされていることを確認しました.また,コンパイラによって関数の頭に”_”がついたりつかなかったりするということも確認しました.
ここで,先ほど調べた解決法を試してみました.次のコードをmaindemangle.cppとして保存し,コンパイルした後に解析してみました.

1
2
3
4
5
6
7
8
9
extern "C" {
int test_func(){
return 0;
}
}

int main(){
return test_func();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ g++ maindemangle.cpp -o gccmaindemangle.o
$ rx-elf-g++ maindemangle.cpp -o gccmaindemangle.o

$ objdump -x maindemangle.o
(中略)
SYMBOL TABLE:
(中略)
00000000004004a6 g F .text 000000000000000b test_func
(後略)

$ rx-elf-objdump -x maindemangle.o
(中略)
SYMBOL TABLE:
(中略)
fff40168 g F .text 0000000f _test_func
(後略)

無事にシンボルをCと同じ名前にすることができました.
これらを踏まえてプログラムを修正したところ,無事にリンカエラーが解消しました.

その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?

マングリングによるエラーに悩んでいる人がいるとしたら,まずは自分のブログなどを紹介し,解決法を教えます.解決した後に,objdumpという便利なツールがあるということを教え,自分のプログラムを解析させます.
いきなり解決法を提示するというのには理由があります.私は今ソフトウェアだけでなく「ものづくり」をしていますが,やはり物が動かなくてはモチベーションも続きません.そのため,はじめはできるだけ解決を優先し,モチベーションを高めてあげることが重要だと考えています.
しかし,解決法の提示だけではあくまで一つの対処法を学んだだけに過ぎません.今後のことを考えると,解決へ至るプロセスや,調査方法などにも触れさせるべきだと思います.次に似たような問題に直面したときに,自力で解決できるようにすべきだからです.
今回の例では,objdumpでシンボルを確認することで,マングリングを目で見ることができます.それだけでなく,シンボル以外にも様々な情報を得ることができることに気づくことができます.何気なく動かしていた自分のプログラムが,実は様々なライブラリやソフトウェアなどによって支えられていて初めて動いていることを知ることは,コンピュータに強い興味を抱かせる理由の一つとなりました.初心者には,プログラムの内部を見てみることで新しい興味を抱き,単にトラブルの解決法を知るだけでなく,より多くの知識を広げていってほしいと考えています.

共通問題3

あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

すべての講義を受けたいのですが,そういうわけにもいかないので,2つだけピックアップして述べます.

  1. 6-C 車載LAN上を流れるメッセージの解析
    昨年,驚くべき脆弱性情報を目にしました.CVE-2015-5611,クライスラー社の車がインターネットを通じて遠隔操作され,ブレーキやハンドル操作まで乗っ取られるという脆弱性です.これまではインターネットとは程遠い存在だった車が,近距離ネットワークを構築したり,インターネットに接続したりするように開発が進められています.制御も複雑化しており,複数のECUと複数のセンサなどが通信しあって動作しています.このような技術の進歩は喜ぶべきことですが,同時に強い恐れを抱いています.なぜなら,人の命を預かる車が乗っ取られたときの被害が,あまりに甚大であるからです.自動車は,これまではセキュリティと無縁だと思っていましたが,これからのセキュリティ問題に大きく関わってくるキーワードであると思っています.そこで,車に関わるこの講義に興味を惹かれました.
    今回の講義はCANの通信解析ということですが,CANにもセキュリティ上の問題が指摘されています.盗聴はもちろん,なりすましや不正メッセージの送信なども行えるということを知りました.CANにはエンジンやブレーキなどを制御するECUも接続されているため,攻撃を受けると致命的な問題が発生します.私はこれまで,動作の確認という意味でSPIバス通信の解析をしたことはありますが,攻撃やその防御策を考える意図で解析をしたことはありません.バスに対する攻撃と防御を学ぶ第一歩としてこの講義を受講したいです.
    攻撃されたときの深刻性は,自動車はもちろん大きなものでありますが,他の機械でも大きな問題となる可能性があります.私はこの講義を受講して攻撃者や防御者という立場での解析法を学び,将来技術者となったときに万全のセキュリティ対策を施せるようになりたいです.

  2. 3-A Webアプリケーションの脆弱性の評価と発見
    この講義を受けたいと思った理由は2つあります.
    まず1つ目ですが,より幅広い分野の技術者がWebアプリケーションのセキュリティについて学ぶ必要があると考えているからです.近年流行しているIoTにより,あらゆるデバイスがインターネットに接続するようになってきました.このため,多くのサーバやWebアプリケーションを用意する必要があります.サーバやWebアプリケーションが増えるということは,それだけ攻撃の対象が増えることを意味します.したがって,ソフトウェアのみならず,ハードウェアを扱う技術者にとっても,Webアプリケーションに関するセキュリティ知識が必須であると考えます.
    次に2つ目の理由ですが,脆弱性やその対策法について,より実践的な経験を得たいと思っているからです.私は自宅にサーバを設置していくつかのサービスを運用しています.運営する上で,書籍を読みセキュリティ対策について勉強をしてきたつもりです.基本的な知識や,代表的な攻撃の手法,その対策法など,これまで知らなかったことを学ぶことができました.しかし,新たな脆弱性を発見するためには何をすべきかわかっていません.この講義を受講して,脆弱性の検出プロセスや,そもそも脆弱性が発生する根本的な原因を学びたいと考えています.

Webアプリケーションのセキュリティはどのような分野においても必要不可欠だと思います.私は将来どんな職種になるかわかりませんがここで得た知識は必ず役に立ちますし,仕事を通して社会利益に貢献したいです.また将来の仕事以外でも,趣味での開発やブログ等での情報発信は今後も引き続き行っていくつもりです.ここで得た知識を元に,よい技術者としての発信を続けていきたいと思っています.以上の理由から,私はこの講義を受講したいです.

あなたがセキュリティ・キャンプでやりたいことは何ですか?身につけたいものは何ですか?(複数可)自由に答えてください。

このセキュリティキャンプでやりたいことは,主に2つあります.

  1. セキュリティに対する意欲を,今後も伸ばしていきたいと思っています.そのため,セキュリティへの意欲が高い学生の方々や専門の講師の方々と知り合い,技術的な交流をしたいです.
    私は大学入学前からコンピュータネットワークに強い興味があり,入学時には応用情報技術者試験に合格しました.しかし,大学には情報・セキュリティに関する活動を行っているクラブ・サークルがなかったため,ロボット製作をメイン活動としているサークルに入部しました.このサークルに入部したことは自分にとってプラスとなりました.サークルOBには全国トップクラスの技術力を持っている方々がいらっしゃり,現在も著名企業でご活躍されています.こういった方々と知り合い,頻繁にお話を聞くことができるようになったため,ハードウェアについての知識を多く得ることができました.これまではソフトウェア一本でしたが,ハードウェアや組み込み系に強い人々と交流することがいい刺激となり,ハードについても強い興味が出てきました.
    一方で,私はネットワークやセキュリティについて話し合える知り合いがほしいと常々思っています.近年ではIoTといったワードをよく聞きますが,ハードウェアとネットワークはもはや切り離せない関係にあり,同時にセキュリティは必要不可欠です.私は,今はハードをメインに活動していますが,元々はネットワークに興味があり勉強をしてきました.いずれの領域においてもセキュリティは共通して重要な要素です.したがって,ハード面のみならずソフト面でも強い意欲を伸ばしていくために,このキャンプに参加し,ソフトウェアやセキュリティに強い関心がある人たちと知り合い,互いに刺激し合えるような関係を作りたいと思っています.

  2. セキュリティについて,適切な指導を受けて力を伸ばしたいです.
    私はこれまでずっと,独学で勉強をしてきました.残念ながらソフトウェアやセキュリティに強い知り合いがおらず,本やインターネットで調べて得た知識を吸収してきただけです.自力で勉強することは大切なことですが,これだけではだめだとも思っています.独学では,手を動かして課題に取り組んだ際にフィードバックを得ることができません.また,最新のセキュリティについても,書籍ではなかなか得ることができません.セキュリティの分野で活躍されているプロの方々からの指導を受けることで,このような知見を得たいと考えています.同時に,セキュリティ問題に取り組む姿勢や考え方なども吸収したいです.

選択問題1

ローカル変数はスタック領域に,mallocを使った動的なメモリ確保はヒープ領域にメモリが確保されることは予め知っていましたが,今回のプログラムにはなんの違和感も感じませんでした.そこで,まずは与えられたプログラムを手元の環境で実行してみました.
ただし今回の実行環境は次の通りであり,以降の問題でも特筆していなければこの環境で動作させています.

1
2
3
4
$ uname -a
Linux arch_thinkpad 4.5.1-1-ARCH #1 SMP PREEMPT Thu Apr 14 19:19:32 CEST 2016 x86_64 GNU/Linux
$ gcc --version
gcc (GCC) 5.3.0

実行結果は次の通りです.

1
2
3
$ ./1-1
hoge address = 0x7ffe049bf300
fuga address = 0x1038010

fuga addressが明らかに違うことが判明しました.そこで,mallocの動作を調べることにしました.
manでmallocについての情報を見ると,mallocは内部でsbrkを用いてヒープからメモリを割り当てていることがわかりました.また同時に,MMAP_THRESHOLDバイトより大きな領域を確保する場合,glibcのmallocは代わりにmmapを用いることがわかりました.sbrkとmmapでどの領域からメモリを確保しているのか,実際に試してみました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(){
int fp = open("/dev/zero", O_RDONLY);
void* p1;
void* p2;
if((p1 = mmap(NULL, 1, PROT_WRITE, MAP_PRIVATE, fp, 0)) == MAP_FAILED) printf("ERROR\n");
p2 = sbrk(1);
printf("mmap: %p\n", p1);
printf("sbrk: %p\n", p2);
return 0;
}

このプログラムは,p1にmmapでメモリを割り当て,p2にsbrkでメモリを割り当て,それぞれのアドレスを表示するプログラムです.
実行結果は次の通りです.

1
2
3
$ ./1-3
mmap: 0x7f39b4c2c000
sbrk: 0x157f000

この結果から,sbrkとmmapでは確保されるメモリ領域が異なることが判明しました.手元で課題のコードを動作させたときのfuga addressが,このプログラムのsbrkで確保したアドレスに似通っているため,実は内部でsbrkが呼ばれていたのではないかと考えました.
mallocのmanページをもう少し読むと,malloptを使ってMMAP_THRESHOLDが変更可能であると書かれていました.そこで,課題のコードを少し書き換え,MMAP_THRESHOLDを0,つまり常にmmapを使うようにコードを変更してみました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main(int argc, char **argv){
char c;
int hoge[10];
int *fuga;
mallopt( M_MMAP_THRESHOLD, 0 );
fuga = malloc(1);
printf("hoge address = %p\n", hoge);
printf("fuga address = %p\n", fuga);
free(fuga);
return 0;
}

このコードの実行結果は次の通りです.

1
2
3
$ ./1-4
hoge address = 0x7ffd8c819780
fuga address = 0x7fde0b040010

課題文中の実行結果と似た出力となりました.また,今回コード中で指定したMMAP_THRESHOLDを,環境変数で指定できることがわかったので,実行してみました.出力結果は省略しますが,次のコマンドを順に実行すると,先ほどと同様の出力が得られました.なおプログラム実行後に環境変数は通常の値に戻しておきました.

1
2
3
$ export MALLOC_MMAP_THRESHOLD_=0
$ ./1-1
$ export MALLOC_MMAP_THRESHOLD_=131072

これらの結果から,課題文中の実行結果は,何らかの理由で環境変数MALLOC_MMAPTHRESHOLDが0になっている環境で実行されたのではないかと考えます.この環境では,割当を解除したメモリ空間を将来的な割当に再利用できなくなるため,不効率である可能性があります.

選択問題4

次のコードをC言語で作成しました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct packet{
char Magic [2];
char Source[20];
char Destination[20];
uint32_t DataLength;
char* Data;
} __attribute__((packed));

int strcmp_upper(const char* s1, const char* s2){
int i=0;
while(toupper(s1[i]) == toupper(s2[i])){
if(s1[i++] == '\0') return 0;
}
return 1;
}

int chk1(struct packet* p){
if(strncmp(p->Magic, "RH", 2) == 0) return 1;
else return 0;
}

int chk2(struct packet* p){
if(!strcmp_upper(p->Source, "rise-san")) return 1;
if(!strcmp_upper(p->Source, "cocoa-san")) return 1;
return 0;
}

int chk3(struct packet* p){
if(!strcmp_upper(p->Destination, "Chino-chan")) return 1;
if(!strcmp_upper(p->Destination, "Chino")) return 1;
return 0;
}

int chk4(struct packet* p){
if((!strcmp(p->Source, "cocoa-san"))&&(!strcmp(p->Destination, "Chino"))) return 0;
return 1;
}

int chk5(struct packet* p){
if(strstr(p->Data, "BlueMountain") != NULL) return 1;
if(strstr(p->Data, "Columbia") != NULL) return 1;
if(strstr(p->Data, "OriginalBlend") != NULL) return 1;
return 0;
}

int chk6(struct packet* p){
if(strstr(p->Data, "DandySoda") != NULL) return 0;
if(strstr(p->Data, "FrozenEvergreen") != NULL) return 0;
return 1;
}

uint32_t convEndian(uint32_t t){
uint32_t ret = 0;
ret = (t<<24)&0xFF000000;
ret |= (t<<8)&0x00FF0000;
ret |= (t>>8)&0x0000FF00;
ret |= (t>>24)&0x000000FF;
return ret;
}

int readPacket(FILE* fp, struct packet* p){
if(fread(p, 1, 46, fp) != 46) return 0;
p->DataLength = convEndian(p->DataLength);
if(p->Data != NULL){
free(p->Data);
p->Data = NULL;
}
p->Data = malloc((size_t)(p->DataLength)+1);
memset(p->Data, 0, p->DataLength+1);
if(fread(p->Data, 1, p->DataLength, fp) != p->DataLength) return 0;
return 1;
}

int main(){
struct packet* p = malloc(sizeof(struct packet));
memset(p, 0, 50);
p->Data = NULL;
FILE* fp = fopen("pyonpyon.rh", "r");
while(readPacket(fp, p)){
if(chk1(p)&&chk2(p)&&chk3(p)&&chk4(p)&&chk5(p)&&chk6(p))
printf("PASS\n");
else
printf("REJECTED\n");
}
if(p->Data != NULL){
free(p->Data);
p->Data = NULL;
}
free(p);
fclose(fp);
return 0;
}

実行結果は次の通りとなりました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$ ./4-1c
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
PASS
REJECTED
PASS
PASS
PASS
REJECTED
REJECTED
PASS
PASS
PASS
REJECTED
REJECTED
REJECTED
PASS
PASS
PASS
REJECTED
REJECTED
REJECTED
REJECTED
PASS
PASS
PASS
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
PASS
PASS
PASS
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED

念の為バイナリを確認してみましたが,正しく動作しているようでした.

続いて,このプログラムが使用したメモリ使用量と動作時間(CPUサイクル)を測定しました.まずメモリ使用量ですが,/usr/bin/timeを用いて計測し,次のような結果となりました.

1
2
3
$ /usr/bin/time -f "%M KB" ./4-1c
(./4-1c実行結果は省略)
1350 KB

また動作時間については,rdtscp命令を利用して,消費したCPUサイクル数を計測することにしました.
提出したコードに次のようなコードを追加し,動作時間(CPUサイクル数)を測定しました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsigned long long rdtsc() {
unsigned long long ret;
__asm__ volatile ("rdtscp" : "=A" (ret));
return ret;
}

int main(){
struct packet* p;

unsigned long long st, et;
st = rdtsc();

p = malloc(sizeof(struct packet));
(中略)
fclose(fp);

et = rdtsc();
printf("%lld, %lld, %lld\n", st, et, et-st);

return 0;
}

このプログラムを実行すると,次の出力が得られました.

1
2
3
$ 4-1c-calc
(実行結果は省略)
3752867116, 3753241296, 374180

したがって,今回のプログラムのサイクル数が374180サイクルという実行結果を得られました.

選択問題5

はじめにJIS規格におけるOSの定義を示しておきます.
「プログラムの実行を制御するソフトウェアであって,資源割り振り,スケジューリング,入出力制御,データ管理などのサービスを提供するもの」
これを踏まえたうえで,組み込み開発での体験を元にした,自分なりの考えをまとめます.

私は,組み込みを始めるまではWindows向けのアプリケーションなどを作成していました.その時は,プログラムは慣れさえあれば簡単なものだと勘違いしていました.用意された関数を呼べば線を描画でき,画像も表示できます.関数を呼べばシリアルからデータを送信でき,時間待ちも簡単にできます.そんなに高度なことはしていませんでしたが,ハードについて全然知識を持ち合わせていなくても,このようなプログラムを書くことができていました.
大学に入り,組込み開発をするようになってから,この認識が大きく変わりました.普段の組込み開発ではOSは使用せず,いわゆるベアメタルでの開発をしています.プログラムは唯一のものしか無く,入出力制御は直接レジスタを操作し,データ管理のシステムは自分で整備します.私個人は,このようなプログラムを作ることは楽しいと感じています.直接レジスタを操作し,直接マイコンを操作しているように思うからです.同時に,これまでのプログラミングに関しての知識は,まったくの不十分であることも実感しました.例えば,C言語でLinux向けのアプリケーションを書く時のことを考えます.1秒待ちたい場合は,”sleep(1);”と書くだけで時間を待つことができます.一方,組み込みで1秒の時間待ちをしたい場合,自分で専用の関数を作る必要があります(もちろん標準で用意されている場合もありますが).このときには,マイコン周辺回路の一つであるタイマを利用する必要があります.タイマのレジスタを設定し,割り込み周期を設定し,種々の設定を行い,タイマをスタートさせる.これだけの長い処理を書くことで初めて時間待ちができるようになります.当然,設定するためには相応のハードウェアの知識が必要となります.
先ほどの例で,Linuxアプリケーションでは”sleep(1);”だけで良いと書きました.これはC標準ライブラリに用意されているから使えるわけですが,その根本にはOSが関わっています.ハードウェアを強く意識させること無く,シグナルという概念を使ってプログラムを作ることができるようになっています.OSの機能の,一番大きな役割ではないかと考えます.

つまり,OSとは
「低レベルの操作を統括し抽象化することにより,ユーザーには低レベル操作を意識させることなくプログラムの開発を進められるようにする仕組み」
であると考えます.

選択問題8

問題文を見た時,とても不思議なコードだと感じました.objdumpは何度も使ったことがありますが,これほどpushqが連続した逆アセンブル結果を見たことがなかったからです.
いくつか気になるところがあったので,次の点に注意しながらプログラムを解析していくことにしました.

  1. 0x4000a2で64bit長のデータをスタックに格納している.何か重要なデータかもしれない.
  2. 0x400110で,このプログラム中唯一比較演算をしている.
  3. 0x400129に,このプログラム中唯一の分岐命令がある.

複雑な動作をしているため,問題文と同じプログラムを作成して検証してみることにしました.8-5.sというファイルにアセンブリコードを保存しています.ただし,0x400129のjne命令でのジャンプ先アドレスを問題文と同じようにできませんでした.そのためジャンプ先アドレスを変更しています.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ as -march=corei7 8-5.s -o 8-5.o
$ ld 8-5.o -o 8-5_run
$ objdump -d 8-5_run
8-5_run: ファイル形式 elf64-x86-64
セクション .text の逆アセンブル:
0000000000400078 <_start>:
400078: 90 nop
400079: 90 nop
40007a: 90 nop
40007b: 90 nop
40007c: 90 nop
40007d: 90 nop
40007e: eb 00 jmp 400080 <main>
0000000000400080 <main>:
400080: 68 19 01 40 00 pushq $0x400119
400085: 6a 01 pushq $0x1
400087: 68 06 01 40 00 pushq $0x400106
(中略)
400126: 48 ff c9 dec %rcx
400129: 0f 85 01 00 00 00 jne 400130 <main+0xb0>
40012f: c3 retq
400130: 41 5a pop %r10
400132: c3 retq

このプログラムをgdbを使って実行しました.

1
2
3
4
5
6
$ gdb 8-5_run -q
Reading symbols from 8-5_run...done.
(gdb) run
Starting program: /home/nonoho/ownCloud/Event/SecurityCamp2016/8-5_run
12345678
[Inferior 1 (process 8199) exited with code 01]

おそらくsyscallで標準入力を読んでいると予想されるので,”12345678”を入力しました.ステータスが1で終了しているので,何か問題があったのではないかと考えられます.

続いて,ステップ実行をしてどのようにプログラムが進んでいるのかを確かめてみます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ gdb 8-5_run -q
Reading symbols from 8-5_run...done.
(gdb) start
Temporary breakpoint 1 at 0x400080: file 8-5.s, line 13.
Starting program: /home/nonoho/ownCloud/Event/SecurityCamp2016/8-5_run
Temporary breakpoint 1, main () at 8-5.s:13
13 push $0x400119
(gdb) set logging on
main () at 8-5.s:14
14 push $0x1
(gdb) si
(以降siを繰り返す)
(gdb) si
main () at 8-5.s:61
61 syscall
(gdb)
[Inferior 1 (process 8750) exited with code 01]

出力されたgdb.txtファイルを見ながら,プログラムの流れを予想してみました.ただし,ここに掲載したログは見やすさのために,不要な行を飛ばしています.

  1. はじめはスタックにデータを格納しているだけです.ただし注意すべきことがあります.今回の場合,スタックに格納されるのは8バイト単位です.したがって,pushqを実行するたびにスタックポインタ(%rsp)は8ずつ小さい値を指すようになります.
    13 push $0x400119
    14 push $0x1
    15 push $0x400106
    (中略)
    41 push $0x400106
    42 push $0x0
    43 push $0x400102
  2. 次に,0x400101に到達したときの動作を考えます.ret命令が実行された時,スタック最上位に格納されているアドレスにジャンプし,スタックポインタを8バイト増やします.したがって,今回はスタック最上位の0x400102にジャンプすることになります.
    44 ret
  3. 続いてレジスタにデータを格納し,システムコールを呼び出しています.この時,システムコール番号を%raxに,引数を順に%rdi,%rsi,%rdx,%r10に格納します.では,今回はどのシステムコールが呼び出されたかを確認します.

    main () at 8-5.s:61
    61 syscall
    (gdb) i r
    rax 0x0 0
    rbx 0x0 0
    rcx 0x0 0
    rdx 0x8 8
    rsi 0x7fffffffdfd8 140737488347096
    rdi 0x0 0
    rbp 0x0 0x0
    rsp 0x7fffffffdff8 0x7fffffffdff8
    r8 0x0 0
    r9 0x0 0
    r10 0x0 0
    r11 0x0 0
    r12 0x0 0
    r13 0x0 0
    r14 0x0 0
    r15 0x0 0
    rip 0x400119 0x400119
    eflags 0x202 [ IF ]
    cs 0x33 51
    ss 0x2b 43
    ds 0x0 0
    es 0x0 0
    fs 0x0 0
    gs 0x0 0

    %raxに0が入っているため,予想通りreadが呼ばれています.readの引数は,ssize_t read(int fd, void *buf, size_t count);となっています.したがって,ファイルディスクリプタは0(stdin),格納先の先頭アドレスは0x7fffffffdfd8,読み出すバイト数は8バイトであることがわかります.

  4. 続いて,次の命令が実行されました.
    62 ret
    51 pop %rbp
    52 ret
    53 pop %rcx
    54 ret
    このときの%rcxの値は7になっていることを確認しました.
  5. この後,次の命令が8回実行されていました.
    59 xorb $0x55,(%rsi,%rcx,1)
    60 ret
    68 dec %rcx
    69 jne 0x400130
    71 pop %r10
    72 ret
    55 add %rbp,%rsp
    56 ret
    %rcxをデクリメントし,0になるまで繰り返しているようです.また,1回ループするごとにxor演算をしています.この動作をメモリダンプして確認しました.
    確認時には次の命令を実行しました.
    (gdb) x/128 (0x7fffffffe0a0-(128*4))
    ただし,文字数と見やすさの都合で,ここには該当箇所のみ記載します.

    1) xor実行前
    0x7fffffffdfc0: 0x0040011c 0x00000000 0x35343332 0x0a383736
    2) xor1回実行後
    0x7fffffffdfc0: 0x0040011c 0x00000000 0x35343332 0x5f383736
    3) xor2回実行後
    0x7fffffffdfc0: 0x0040011c 0x00000000 0x35343332 0x5f6d3736
    4) xor8回実行後
    0x7fffffffdfc0: 0x0040011c 0x00000000 0x60616667 0x5f6d6263

    この結果から,先程のシステムコールで入力した値の,すべてのバイトを,0x55との排他的論理和をとっていることがわかりました.

  6. 最後に,次の命令が実行されてプログラムが終了していました.
    49 pop %rdi
    50 ret
    45 pop %rax
    46 ret
    57 cmp %rax,(%rsi)
    58 ret
    45 pop %rax
    46 ret
    69 jne 0x400130
    71 pop %r10
    72 ret
    49 pop %rdi
    50 ret
    61 syscall
    cmp命令実行前の,レジスタの値とメモリダンプを確認しました.

    (gdb) i r
    rax 0x63391a67251b1536 7149774913733858614
    rbx 0x0 0
    rcx 0x0 0
    rdx 0x8 8
    rsi 0x7fffffffdfc8 140737488347080
    rdi 0x0 0
    rbp 0xffffffffffffffe0 0xffffffffffffffe0
    rsp 0x7fffffffe058 0x7fffffffe058
    r8 0x0 0
    r9 0x0 0
    r10 0x400102 4194562
    r11 0x302 770
    r12 0x0 0
    r13 0x0 0
    r14 0x0 0
    r15 0x0 0
    rip 0x400110 0x400110
    eflags 0x202 [ IF ]
    cs 0x33 51
    ss 0x2b 43
    ds 0x0 0
    es 0x0 0
    fs 0x0 0
    gs 0x0 0

    %raxの値と,%rsiの指すメモリ内容を比較しています.この時,%rsiの指すアドレスには次の値が入っていることが,先ほどのダンプ結果からわかっています.
    0x7fffffffdfc8: 0x60616667 0x5f6d6263
    この値は,プログラム実行時に入力した値を,0x5555555555555555でxor演算した値と等価です.今回は,入力した”12345678”と予めセットされている値が一致しなかったため,ステータスコード1で終了しました.そこで,2つの値が一致するような入力値を求めると,”c@Np2Ol6”であることがわかりました.

ここまでを踏まえて,もう一度プログラムを動作させてみます.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ gdb ./8-5_run -q
Reading symbols from ./8-5_run...done.
(gdb) run
Starting program: /home/nonoho/ownCloud/Event/SecurityCamp2016/8-5_run
12345678
[Inferior 1 (process 13998) exited with code 01]

$ gdb ./8-5_run -q
Reading symbols from ./8-5_run...done.
(gdb) run
Starting program: /home/nonoho/ownCloud/Event/SecurityCamp2016/8-5_run
c@Np2Ol6
[Inferior 1 (process 14003) exited normally]

“c@Np2Ol6”を入力すると,ステータスコードが0で終了しました.

以上の調査より,このプログラムは,パスワード”c@Np2Ol6”を認証するプログラムであると考えられます.
このプログラムについての個人的な感想ですが,このプログラムは難読化のためにあえて読みづらいコードにしているのではないかと感じました.あわせて,認証するパスワードもxor演算を施しておくことで,解析しづらくしているのではないかと思います.

Apacheでletsencryptを使う

Let’s Encryptとは

Let’s Encryptは無料で使えるSSL認証局です.
Let’s Encryptで証明書を取得し,Apacheで動作させるまでの方法を書き残しておきます.

動作環境は,

  • Ubuntu 12.04
  • Apache 2.4.12

証明書の取得

クライアントの導入

githubからクライアントを持ってきて,依存関係の確認などを行います.
3行目でヘルプを確認していますが,このときに依存関係の確認・更新などを行うようです.

1
2
3
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
sudo ./letsencrypt-auto --help

証明書の取得

今回,証明書はサブドメインごとに取得します.
なお,80番ポートを使うので動作中のApacheは停止しておきます.

1
2
3
sudo service apache2 stop
./letsencrypt-auto certonly --standalone -d www.taniho.net
./letsencrypt-auto certonly --standalone -d blog.taniho.net

初回はメールアドレスなどを入力させるダイアログが出てくるので,いい感じに入力していきます.

IMPORTANT NOTES:

  • Congratulations! Your certificate and chain have been saved at
    /etc/letsencrypt/live/(ドメイン)/fullchain.pem. Your
    cert will expire on (有効期限). To obtain a new version of the
    certificate in the future, simply run Let’s Encrypt again.

この画面が出れば取得完了です.
見れば解ると思いますが,Let’s Encryptで取得した証明書は有効期限が90日しかありません.
証明書の更新は次のコマンドを打つことで行えます.
また,更新後にApacheを再起動する必要があります.

1
letsencrypt-auto renew --force-renew

今回取得した証明書は,/etc/letsencrypt/live/(ドメイン)/の中に入っています.

Apacheの設定

とりあえず

Apache2.4.8以降では,それ以前と設定の仕方が変わっているので気をつけてください.
とりあえず,https://blog.taniho.net/にアクセスできるように設定してみます.

1
2
3
4
5
6
7
8
9
10
11
<VirtualHost *:443> 
ServerName www.hoge.net
DocumentRoot /var/www/html

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/blog.taniho.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/blog.taniho.net/privkey.pem
</VirtualHost>

1
sudo service apache2 restart

設定を有効化する

/etc/apache2/site-availableにsite設定を書いたら,次のコマンドで有効化,無効化することができます.

1
2
a2ensite (設定ファイル名)
a2dissite (設定ファイル名)

同様に,Apacheのモジュールを有効化・無効化させる場合は次のコマンドを使います.

1
2
a2enmod (モジュール名)
a2dismod (モジュール名)

今回はmod_sslを有効化する必要があるので,次のコマンドを叩いておきます.

1
a2enmod ssl

httpに来たアクセスをhttpsにリダイレクトさせる

必ずhttpsでアクセスさせたい場合や,その逆の場合もあると思います.
ひとまず,http://blog.taniho.net/にアクセスされた場合にhttpsに転送する設定をまとめておきます.
VirtualHost設定の中に次の内容を書きます.

1
2
3
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*) https://blog.taniho.net$1 [R,L]

参考

CentOS 7 + Apache 2.4 で Let’s Encrypt の証明書を導入する手順
Let’s Encrypt サーバー証明書の取得と自動更新設定メモ
apacheでhttpへのアクセスをhttpsへ自動リダイレクトする

e2studioを用いてGCC(C++)で開発する

目的

ルネサスが提供しているRX用C++コンパイラはなかなかに使えないので,お手軽にC++11を使える方法を考えます。
ルネサスが公式サポートしている,KPIT GNU Toolse2studioで使えるようにします。

環境を整える

KPIT GNU Toolsの入手

KPIT GNU Tools公式サイトでユーザー登録を行う必要があります。
パスワードの発行に少し時間がかかる可能性があるので,予め済ませておきましょう。

ログインして,使うマイコンのコンパイラ(今回の場合GNURX v12.xx Windows Tool Chain (ELF))をダウンロード,インストールします。
※4/26追記 バージョン違いだったようです。最新版をインストールしてください。

e2studioの入手

e2studioをダウンロード,インストールしておきます。
KPIT GNU Toolsがインストール済みであれば,初めての起動の際に何か聞かれるので,Toolchainを登録しておきましょう。

プロジェクトの作り方

e2studioの使い方は省略します。
基本的にはルネサス公式のコンパイラを使う場合と同じように,新規C++プロジェクトを作成します。
ただし,利用するツールチェインを”KPIT GNURX-ELF Toolchain”にします。
その他はいい感じに設定を進めていきます。

C++11を使えるようにする

このままではC++98のままなので,C++11を使えるように設定しておきます。

メニューバーの「プロジェクト」->「プロパティ」を開き,
「C/C++ビルド」->「設定」を選びます。
「ツール設定」の中の「Compiler」->「その他」の画面で,
ユーザー定義オプションに”-std=c++11”を追加しておきましょう。
これでC++11が使えるようになります。

余談ですが,KPIT GNU ToolsはまだC++14に対応していないようです。

動かしてみて

動いた

時間が無く十分な検証ができていませんが,次のコードが正しく動作しました。

1
2
3
4
5
6
7
8
9
#include "iodefine.h"
#include <array>
using namespace std;
int main(){
array<int, 1> a = {123};
if(a.at(0) == 123) (LED点灯);
while(true);
return 0;
}

わからん

ビルドは通るし,プログラムも動作しているようですが,なぜか”-std=c++11フラグをつけるのならrx-elf-g++を使えよ!”という警告が出ます。
確かにrx-elf-gccで動かしているので,そりゃそうだと思ってコマンドをrx-elf-g++に変更するとコンパイルができなくなりました。

また,コンパイルは通っているのにe2studioのシンタックスチェックでシンボルが見つからないよ! というエラー表示が出てしまいます。
とりあえず動いているので問題はなさそうですが,うーん……

※4/26追記 シンタックスチェックを無効化すればいいとの意見をいただきました。
参考に設定方法を掲載しておきます。
Window>設定>C>コード解析 「シンボルが解決されません」「メソッドが解決されません」のチェックを外す

C++/C++11を始めよう

本を読んでください
としか言わないのは悲しいので,Miceでも使ってもらえそうな(とっつきの良さそうな)C++の新機能をリストアップします。
毎度のごとく,自分で詳しく調べなおしてください。

C++03

変数の定義位置

C言語でははじめに変数宣言をする必要がありましたが,C++では好きなところで変数宣言ができます。
すごく便利なのが次のコード

1
for (int i=0; i<100; ++i) hoge();

namespace

名前空間が使えます。
別の名前空間に属していれば,名前の重複が起こりません。
モジュールごとに名前空間を分けるようにすれば,命名力不足に悩まされる心配もありません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
namespace A{
int hoge = 0;
}
namespace B{
int hoge = 1;
}
int main(){
std::cout << hoge << endl; // hogeは存在しない
std::cout << A::hoge << endl; // 0
std::cout << B::hoge << endl; // 1
using namespace A;
std::cout << hoge << endl; // 0
}

vector

可変長配列です。
つまり配列の長さを自由に伸び縮みさせられる配列です。

1
2
3
4
5
6
7
8
#include <vector>
using namespace std;
int main(){
vector<int> hoge = {0, 1, 2};
hoge.at(1); //1
hoge.push_back(3);
hoge.at(3); //3
}

pair

これまでいちいち構造体で作っていたpairが標準で用意されるようになりました。

1
2
3
4
5
6
7
8
#include <utility>
using namespace std;
int main(){
pair<int, int> p1(10, 20);
p1.first + p1.second; // 30
pair<float, const char*> p2(1.3f, "abc");
return 0;
}

C++11

auto

自動型推論と呼ばれる機能です。
要するに型を”auto”としておけば自動でいい感じにしてくれます。

C流

1
2
3
4
5
6
7
8
9
#include <stdio.h>
void func(int t){
printf("Value: %d\n", t);
}
int main(){
void (*f)(int) = &func;
f(123);
return 0;
}

C++11流

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
void func(int t){
cout << "Value: " << t << endl;
}
int main(){
auto f = &func;
f(123);
return 0;
}

array

より安全に使える配列です。
あわせて,下のサンプルではrange-based forという技も使っています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <array>
using namespace std;
int main(){
array<int, 10> a = {};
for(auto ite = a.begin(); ite != a.end(); ++ite){
static int j = 0;
*ite = j++;
}
for(auto i: a){
cout << i << endl;
}
return 0;
}

enum class

C言語にも列挙型がありましたが,C++11で使い勝手が良くなりました。
列挙型のサイズを規定でき,スコープ演算子でアクセスするようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
using namespace std;
enum class N : unsigned char{
N1,
N2 = 100,
N3,
N4,
};
int main(){
N1; // 存在しない
N::N1; // 0
N::N4; // 102
return 0;
}

最後に

これだけでも十分便利そうなC++ですが,C++の底力はこんなもんじゃあないので,頑張って勉強していきたいところです。