task4233のめも

書きたいことをつらつらと

C言語のポインタとアドレスをアセンブリコードを用いて理解してみる

本記事はデジクリアドベントカレンダー2019の12/17用に書かれました。

TL;DR

  • 「アドレス」はデータが保存される場所
  • 「ポインタ」はアドレスを格納するための領域
  • ポインタ宣言はアドレスを格納するためのポインタ変数を宣言すること
  • 参照外しはポインタに格納されているアドレス先のデータを, 先頭アドレスと型情報を元に参照すること
  • アドレスを調整することで他の変数にもアクセスできる

もくじ

目標

本記事の目標は以下の3点です。

  1. 「アドレス」と「ポインタ」が何を表しているかを理解する
  2. ポインタ宣言と参照外しの違いを理解する
  3. キャストと参照外しを用いて別の変数にアクセスする

なお, タイトルにもある通り, 本記事ではC言語およびアセンブリコードを用います。なぜなら, アセンブリコードを読むことで実行時に何が起きているかが直感的に理解できるためです。

なお, アセンブリについては以下の記事を読むことを強くオススメします。 基礎知識やアセンブリの読み方, メモリやレジスタの仕組み等が詳しく書かれており, 非常にわかりやすいです。

qiita.com

1. 「アドレス」と「ポインタ」が何を表しているかを理解する

アドレス

データが保存される場所のことです。正しくは「メモリアドレス」といいます(長いので以後アドレスとします)。値を変数に格納したり, 正しく関数を呼び出したりできるのは, このアドレスがあるためです。

アドレスは1バイト単位でランダムアクセスすることが可能です。1バイトは一般に8ビットで, 10進数で0から255の値を格納することができます。それ以上の数を格納したい場合は, 複数のバイトをまとめて使用することで実現します。

ビットとバイトの違いが分からない方はこちらの記事が参考になるかもしれません。

さて, C言語ではこのアドレスを&変数名のように, &演算子(アドレス演算子) を用いて表現します。例えば, 変数aのアドレスが欲しい時は&aのように書くことで, その変数が格納されている先頭アドレスを取得できます。先述した通り, データが大きい時は複数のバイトに連なってデータが格納されるため, 連続しているうちの先頭のアドレスを変数のアドレスとしています

では, C言語のコード例を見てみましょう。 コードと実行結果はこちらから確認できます。

#include <stdio.h>

int main() {
  int num = 57;
  // 変数の値を表示
  printf("変数numの値は%d\n", num);
  // 変数のアドレスを表示
  printf("変数numのアドレスは%p\n", &num);
  return 0;
}

// 出力
// 変数numの値は57
// 変数numのアドレスは0x7ffd8e972c5c

変数の値とアドレスが正しく出力されていますね。 printf()関数の引数として, 前者はnumを, 後者は&numを使うことで, 正しく値が取得できていることがわかります。

では, 先ほどのコードをコンパイルしたアセンブリコードを見てみましょう。 コードはこちらから確認できます。 それぞれのコードの意味はコメントで加えておきました。

.LC0:
        ;「変数numの値は%d\n.string "\345\244\211\346\225\260num\343\201\256\345\200\244\343\201\257%d\n"
.LC1:
        ; 「変数numのアドレスは%p\n」
        .string "\345\244\211\346\225\260num\343\201\256\343\202\242\343\203\211\343\203\254\343\202\271\343\201\257%p\n"
main:
        push    rbp                     ; ベースポインタをスタックに積む
        mov     rbp, rsp                ; rspをベースポインタの所に持ってくる
        sub     rsp, 16                 ; rspをスタックトップに持ってくる
        mov     DWORD PTR [rbp-4], 57   ; rbp-4のアドレスからDWORD PTR(4バイト分)の領域に57という値を格納
        mov     eax, DWORD PTR [rbp-4]  ; rbp-4のアドレスからDWORD PTR(4バイト分)の領域にある値をeaxに格納
        mov     esi, eax                ; esiにeaxの値を格納(printf関数の引数)
        mov     edi, OFFSET FLAT:.LC0   ; ediに「変数numの値は%d\n」という文字列を格納(printf関数の引数)
        mov     eax, 0                  ; eaxに0を格納
        call    printf                  ; printf関数を呼び出す
        lea     rax, [rbp-4]            ; raxにrbp-4のアドレスを格納
        mov     rsi, rax                ; rsiにraxの値を格納(printf関数の引数)
        mov     edi, OFFSET FLAT:.LC1   ; ediに「変数numのアドレスは%p\n」という文字列を格納(printf関数の引数)
        mov     eax, 0                  ; eaxに0を格納
        call    printf                  ; printf関数を呼び出す
        mov     eax, 0                  ; eaxに0を格納
        leave                           ; high-level procedure exit
        ret                             ; return

ここで注目していただきたいのは, 変数numのを表示する時と変数numのアドレスを表示する時に使ったアセンブリ命令の違いです。

前者では以下のようにmovを使用しています。

mov     eax, DWORD PTR [rbp-4]  ; rbp-4のアドレスからDWORD PTR(4バイト分)の領域にある値をeaxに格納

movはMOVeのことです。Intel SDMの5.1.1 Data Transfer Instructionsによると, 汎用レジスタ間でデータを移動すると書かれています。したがって, 変数の値そのものに働きかけをしていることがわかります。

一方, 後者では以下のようにleaを使用しています。

lea     rax, [rbp-4]            ; raxにrbp-4のアドレスを格納

leaはLoad Effective Addressの略で, 直訳すると実行アドレスのロードのことです。Intel SDMでは5.1.13 Miscellaneous Instructionsに書かれています。したがって, 変数の実行アドレスを取得するという働きかけをしていることがわかります。

以上より, C言語アセンブリに以下のような対応付けができます。 なお, Cでの変数名はnumで, [rbp-4]から格納されているとします。

変数の値 変数のアドレス
C言語 num &num
アセンブリ mov rax, DWORD PTR [rbp-4] lea rax, [rbp-4]

ポインタ

変数や関数が格納されているアドレスを格納するための領域です。先ほど, アドレスの取得の仕方を紹介しましたが, 一般的な変数にアドレスは格納しません。そこで, このポインタを使用します。

C言語では, ポインタを書く際に*変数名のように, *を用いて表現します。この変数名は自由に宣言できますが, 他の変数名と重複してはいけません。

難しく考えることは無いです。ポインタはアドレスを格納するための領域です。

では, C言語のコードを見ていきましょう。 コードと実行結果はこちらから確認できます。

#include <stdio.h>

int main() {
  int num = 57;
  // ポインタに変数numのアドレスを格納
  int* ptr = &num;

  printf("変数numのアドレスは%p\n", ptr);
  return 0;
}

// 出力
// 変数numのアドレスは0x7ffd5324a174

アドレスが正しく出力されていることがわかります。

では, 先ほどのコードをコンパイルしたアセンブリコードを見てみましょう。 コードはこちらから確認できます。 それぞれのコードの意味はコメントで加えておきました。

.LC0:
        ; 「変数numのアドレスは%p\n」
        .string "\345\244\211\346\225\260num\343\201\256\343\202\242\343\203\211\343\203\254\343\202\271\343\201\257%p\n"
main:
        push    rbp                     ; ベースポインタをスタックに積む
        mov     rbp, rsp                ; rspをベースポインタの所に持ってくる
        sub     rsp, 16                 ; rspをスタックトップにセットする
        mov     DWORD PTR [rbp-12], 57  ; rbp-12のアドレスからDWORD PTR(4バイト分)の領域に57という値を格納
        lea     rax, [rbp-12]           ; rbp-12のアドレスをraxに格納
        mov     QWORD PTR [rbp-8], rax  ; raxの値をrbp-8からQWORD PTR(8バイト分)の領域に格納
        mov     rax, QWORD PTR [rbp-8]  ; rbp-8からQWORD PTR(8バイト分)の領域の値をraxに格納
        mov     rsi, rax                ; raxの値をrsiに格納
        mov     edi, OFFSET FLAT:.LC0   ; ediに「変数numのアドレスは%p\n」という文字列を格納
        mov     eax, 0                  ; eaxに0を格納
        call    printf                  ; printfを呼び出し
        mov     eax, 0                  ; eaxに0を格納
        leave                           ; high-level procedure exit
        ret                             ; return

ここで注目していただきたいのは, 以下の通り変数のアドレスを格納する際にDWORD PTR(4バイト分)ではなく, QWORD PTR(8バイト分)の領域を用いていることです。

       lea     rax, [rbp-12]           ; rbp-12のアドレスをraxに格納
       mov     QWORD PTR [rbp-8], rax  ; raxの値をrbp-8からQWORD PTR(8バイト分)の領域に格納

これは当然といえば当然なのですが, x86-64は64ビットのOSなので, アドレスは64ビット(8バイト)です。そのため, アドレスを格納するためには8バイトの領域が必要になり, このような命令を実行しています。

以上より, C言語アセンブリに以下のような対応付けができます。 なお, C言語での変数名はnumで[rbp-4]から格納されているとします。 そして, C言語でのポインタ名はptrとします。

変数の値 変数のアドレス 変数のポインタ
C言語 num &num ptr
アセンブリ mov rax, DWORD PTR [rbp-4] lea rax, [rbp-4] mov QWORD PTR [rbp-8], rax

まとめると, 「アドレス」はデータが保存される場所のこと, 「ポインタ」はアドレスを格納するための領域です。

2. ポインタ宣言と参照外しの違いを理解する

新たに「ポインタ宣言」と「参照外し」という言葉が出てきました。ポインタわからんという方はこの2つを区別できていないのではないかと考えています。そのため, ここでそれぞれの内容を述べておきます。

「ポインタ宣言」は, アドレスを格納するため変数を宣言することです。つまり, 先ほどポインタの説明で出てきたポインタの使い方は「ポインタ宣言」にあたります。

一方, 「参照外し」はポインタに格納されているアドレス先のデータを参照することです。 実際のC言語のコード例を見てみましょう。

#include <stdio.h>

int main() {
  int num = 57;
  // ポインタに変数numのアドレスを格納
  int* ptr = &num;

  // 参照外しにより, ptrのアドレスの先の値を取得
  int referred_num = *ptr;
  printf("%d\n", referred_num);
  return 0;
}

// 出力
// 57

参照外しによりptrが保持しているアドレス先に格納されている値を取得できていることがわかります。

では, このコードをコンパイルしたアセンブリコードを見てみましょう。 コードはこちらから確認できます。

.LC0:
        .string "%d\n"
main:
        push    rbp                      ; ベースポインタをスタックに積む
        mov     rbp, rsp                 ; rspをベースポインタの所に持ってくる
        sub     rsp, 16                  ; rspをスタックトップにセットする
        mov     DWORD PTR [rbp-16], 57   ; rbp-16のアドレスからDWORD PTR(4バイト分)の領域を確保して, 57を格納する
        lea     rax, [rbp-16]            ; rbp-16のアドレスをraxに格納
        mov     QWORD PTR [rbp-8], rax   ; raxの値をrbp-8からQWORD PTR(8バイト分)の領域に格納
        mov     rax, QWORD PTR [rbp-8]   ; rbp-8からQWORD PTR(8バイト分)の領域の値をraxに格納
        mov     eax, DWORD PTR [rax]     ; raxに格納されているアドレスからDWORD PTR(8バイト分)の領域の値をeaxに格納
        mov     DWORD PTR [rbp-12], eax  ; rbp-12からDWORD PTR(4バイト分)の領域にeaxの値を格納
        mov     eax, DWORD PTR [rbp-12]  ; rbp-12からDWORD PTR(4バイト分)の領域にある値をeaxに格納
        mov     esi, eax                 ; esiにeaxの値を格納
        mov     edi, OFFSET FLAT:.LC0    ; ediに「%d\n」を格納
        mov     eax, 0                   ; eaxに0を格納
        call    printf                   ; printf関数を呼び出し
        mov     eax, 0                   ; eaxに0を格納
        leave                            ; high-level procedure exit
        ret                              ; return

今回の参照外しに該当する部分は以下になります。

        mov     eax, DWORD PTR [rax]     ; raxに格納されているアドレスからDWORD PTR(8バイト分)の領域の値をeaxに格納

アセンブリでは[ ]で囲むと, 囲まれた値をアドレスとして認識し, そのアドレス上の値にアクセスします。したがって, 参照外しが正しく行われていることがアセンブリでも確認できました。

さらに, この参照外しは複数回行うことが可能です。 以下のこちらのコードを見てみましょう。

#include <stdio.h>

int main() {
  int num = 57;
  int* ptr = &num;
  int** ptr2 = &ptr;
  int*** ptr3 = &ptr2;
  int**** ptr4 = &ptr3;
  int***** ptr5 = &ptr4;

  int referred_num = *****ptr5;
  printf("%d\n", referred_num);
  return 0;
}

// 出力
// 57

なんとも仰々しいですが, 正しく実行できます。 これもコンパイルされたアセンブリを読めば簡単に理解できます。

.LC0:
        .string "%d\n"
main:
        push    rbp                     ; ベースポインタをスタックに積む
        mov     rbp, rsp                ; rspをベースポインタに持ってくる
        sub     rsp, 48                 ; rspをスタックトップにセットする
        mov     DWORD PTR [rbp-16], 57  ; rbp-16のアドレスからDWORD PTR(4バイト分)の領域に57を格納する
        lea     rax, [rbp-16]           ; raxにrbp-16のアドレスを格納
        mov     QWORD PTR [rbp-24], rax ; rbp-24のアドレスからQWORD PTR(8バイト分)の領域にraxの値を格納する
        lea     rax, [rbp-24]           ; raxにrbp-16のアドレスを格納
        mov     QWORD PTR [rbp-32], rax ; rbp-32のアドレスからQWORD PTR(8バイト分)の領域にraxの値を格納する
        lea     rax, [rbp-32]           ; raxにrbp-32のアドレスを格納
        mov     QWORD PTR [rbp-40], rax ; rbp-40のアドレスからQWORD PTR(8バイト分)の領域にraxの値を格納する
        lea     rax, [rbp-40]           ; raxにrbp-40のアドレスを格納
        mov     QWORD PTR [rbp-48], rax ; rbp-48のアドレスからQWORD PTR(8バイト分)の領域にraxの値を格納する
        lea     rax, [rbp-48]           ; raxにrbp-48のアドレスを格納
        mov     QWORD PTR [rbp-8], rax  ; rbp-8のアドレスからQWORD PTR(8バイト分)の領域にraxの値を格納する
        mov     rax, QWORD PTR [rbp-8]  ; rbp-8のアドレス先の値をraxに格納する
        mov     rax, QWORD PTR [rax]    ; raxのアドレス先の値をraxに格納する
        mov     rax, QWORD PTR [rax]    ; raxのアドレス先の値をraxに格納する
        mov     rax, QWORD PTR [rax]    ; raxのアドレス先の値をraxに格納する
        mov     rax, QWORD PTR [rax]    ; raxのアドレス先の値をraxに格納する
        mov     eax, DWORD PTR [rax]    ; raxのアドレス先の値をeaxに格納する
        mov     DWORD PTR [rbp-12], eax ; eaxの値をrbp-12のアドレスからDWORD PTR(4バイト分)の領域に格納する
        mov     eax, DWORD PTR [rbp-12] ; rbp-12のアドレスからDWORD PTR(4バイト分)の領域にある値をeaxに格納する
        mov     esi, eax                ; esiにeaxの値を格納する
        mov     edi, OFFSET FLAT:.LC0   ; ediに"%d\n"を格納する
        mov     eax, 0                  ; eaxに0を格納する
        call    printf                  ; printfを呼び出す
        mov     eax, 0                  ; eaxに0を格納する
        leave                 ; high-level procedure exit
        ret                             ; return

これを見れば,

int referred_num = *****ptr5;

という部分で,

mov     rax, QWORD PTR [rax] 

が複数回繰り返されて参照外しが行われていることが分かるはずです。

以上より, 「ポインタ宣言」は, アドレスを格納するため変数を宣言することであり,「参照外し」はポインタに格納されているアドレス先のデータを参照することであるとわかります。

3. キャストと参照外しを用いて別の変数にアクセスする

また新しい単語「キャスト」が出てきました。
「キャスト」とは, 変数を何の型で解釈するか指定する操作です。
キャストは(型名)を先頭に付与することで実現できます。
例えば, numという変数をlong型にキャストしたい場合は, (long)numと書けば良いです。

こちらのコードを見てください。

#include <stdio.h>

int main() {
  long num = 1;
  int num2 = 2;
  char num3 = '3';

  long* ptr = &num;
  int* ptr2 = &num2;
  char* ptr3 = &num3;

  printf(" ptr : %p\n", ptr);
  printf(" ptr2: %p\n", ptr2);
  printf(" ptr3: %p\n", ptr3);

  char* ptr4 = (char*)(ptr - 1) + 3;

  printf(" ptr4: %p\n", ptr4);
  printf("*ptr4: %c\n", *ptr4);
  
  return 0;
}

// 出力
//  ptr : 0x7ffce2e87928
//  ptr2: 0x7ffce2e87924
//  ptr3: 0x7ffce2e87923
//  ptr4: 0x7ffce2e87923
// *ptr4: 3

このコードを実行すると, 以下のような結果が得られます。

このコードで注目していただきたいことは, 以下の通りptrを利用してptr3のデータにアクセスできているということです。

 char* ptr4 = (char*)(ptr - 1) + 3;

アクセスする方法は単純で, ptrからptr3のアドレスを取得しているだけです。しかし, これコードの意味を理解するには内部で何がおきているのかを理解する必要があるはずです。

そのために, コンパイル後のアセンブリコードを確認します。 ここで, 簡単のためにprintf()関数を取り除いています。

main:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-40], 1
        mov     DWORD PTR [rbp-44], 2
        mov     BYTE PTR [rbp-45], 51
        lea     rax, [rbp-40]
        mov     QWORD PTR [rbp-8], rax
        lea     rax, [rbp-44]
        mov     QWORD PTR [rbp-16], rax
        lea     rax, [rbp-45]
        mov     QWORD PTR [rbp-24], rax
        mov     rax, QWORD PTR [rbp-8]
        sub     rax, 8
        add     rax, 3
        mov     QWORD PTR [rbp-32], rax
        mov     eax, 0
        pop     rbp
        ret

このうち, 注目していただきたいのは以下の4行です。

        mov     rax, QWORD PTR [rbp-8]      ; rbp-8からQWORD PTR(8バイト分)の領域にある値をraxに格納
        sub     rax, 8                      ; raxから8引く
        add     rax, 3                      ; raxに3を足す
        mov     QWORD PTR [rbp-32], rax     ; rbp-32からQWORD PTR(8バイト分)の領域にraxの値を格納

わざわざとった値に対して加減算を行っています。 これは, 今回の変数が以下のように積まれているためです。

アドレス番号 補足
0x0000fff0 num long(8バイト分)
0x0000ffec num2 int(4バイト分)
0x0000ffeb num3 char(1バイト分)

したがって, numのアドレスを持つポインタに8引いて3を足せばnumからでもnum3にアクセスできるわけです。 C言語のコードでは1しか引いていないのに8引かれているのは, ptrがlong型のポインタであるためです。long型は8バイトなので, -1しただけで8バイト分のアドレスを戻っています。

したがって, 同様に以下の場合でも正しくアクセスできますね。

// char型のポインタとしてキャストした上で5バイト分戻る
char* ptr4 = ((char*)ptr - 5);

つまり, ポインタでの参照外しをする際には, 先頭アドレスによって情報を読み取っているということです。

仮に先頭アドレスが正しくとも, 型が誤っていると正しくデータを取得できません。そのため, 型付き言語では変なキャストをするとwarningが出る訳です。

したがって, 先ほどの参照外しの説明は不十分です。 参照外しはポインタに格納されているアドレス先のデータを, 先頭アドレスと型情報を元に参照することと言った方がより正しいでしょう。

おわりに

ここまでお読みいただきありがとうございました。 本当はCコンパイラでアドレスとポインタを自作してその上で動かしたかったのですが, 時間が間に合いませんでした(演算子の定義等までは実装できました)。

本記事は参照外しとポインタ宣言が混同している方のために書いたつもりなんですが, 結果的に怪文書ができてしまった気がします。

なにはともあれ, ここまでお読みいただきありがとうございました。 変な部分があればマサカリを投げてください。 ありがとうございました。

学生LT #31 参加記録

TL;DR

  • 公開枠18組の概要と感想をまとめた
  • 5分間のLTをしてきた
  • LTの準備が不十分だった

もくじ

はじめに

本日(2019/12/08)に開催された学生LT#31に参加したので, その感想と反省を書きます。

学生LT#31の詳細は, connpassページをご覧ください。

student-lt.connpass.com

ライブ映像は公開されています。

https://youtu.be/cX13Wwa0Mds

以後, LT資料, および動画のリンクを載せていますが, 抜けがある場合はご指摘ください。よろしくお願いします。

当日の流れ

遅刻しました。

後述する解析に熱中しすぎて, 家を出る時間を超えてしまいました。

LT

us pycon参加録 by sakakendo

LT資料

docs.google.com

動画

https://youtu.be/cX13Wwa0Mds?t=2100

概要

Pycon2019に自費(?)で参加してきた話でした。

感想

海外カンファレンスに行ってみたいので, どこかのScholarshipに選出されたいものです。今の所MerkariさんのStepupgoで頑張っているので, GoCon出られると良いなと思っています。

Npurse使ってECサイト構築した話 by らいう

LT資料

docs.google.com

動画

https://youtu.be/cX13Wwa0Mds?t=2908

概要

タイトル通り, Mpurseを使ってECサイトを作った話でした。Mqurseの特徴についても触れられていました。

感想

大体の処理をMqurseに投げられるのは良さそうです。しかし, そのサービスに脆弱性が生まれた場合にどうなるのかを考えると怖そうです。

Kotlinで作ったJVMで動くCLIツールをGraalVMのnative imageでmacOS向けにバイナリ吐いてみた by マヤミト

動画

https://youtu.be/cX13Wwa0Mds?t=3524

概要

GraaVM上で, Kotlinコードをnative imageにコンパイルした話でした。JVMとの比較もしており, それぞれのメリット/デメリットも紹介していました。

感想

JVMもそこそこの速さですが, それよりも高速な実行時間というのは魅力的でした。

軽率にレイトレする by にー兄さん

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=3524

概要

古典的レイトレーシング(Ray Tracing)のアルゴリズム, Rayの生成と交差判定, ShadowRayによる可視判定等の理論について紹介していました。

感想

3DCGって出来る人すごいですよね。
以前レイトレは少し触れていたので, 古典的レイトレならもう少しわかりやすく話せたのではないかなという気がしました。BRDFでいえば, 「物体表面の点においてある方向から入射した光が, ある方向へ出射する割合」と言った方がわかりやすいと思いました。しかし, 割合というと[0, 1]のrangeを超えてしまう時に対応できないので難しいところです。ここ, 詳しい人に教えていただきたいです。

ref: BRDF range -- greater than 0...1 ?

ArduinoできらきらフルカラーLEDテープを光らせる話 by たかぴろ

動画

https://youtu.be/cX13Wwa0Mds?t=5004

概要

ArduinoでLチカして終わってしまう人が多いです。そんな中, フルカラーLEDテープを光らせる(制御)していました。

感想

Arduinoに触ってみたこともありましたが, たかぴろさんがおっしゃっていたように, 実践できるほどまでやっていませんでした。一貫して続けられるものを見つけたいものです。

RustでWebassemblyインタプリタを作った話 by tkr

LT資料

gitpitch.com

動画

https://youtu.be/cX13Wwa0Mds?t=5453

Agenda

感想

wasmを触ったことがなかったですが, アセンブリに対する抵抗感が薄くなった今, 触ってみたいと思いました。tkrさんは, 難しいことでも継続して続けている方だと感じていて, 凄いなと感じました。

遭難者を救うために学内Mapを作った話 by そうた

動画

https://youtu.be/cX13Wwa0Mds?t=6228

概要

Googleマップのような操作感, GPSで場所や距離のわかる, 企画の実施場所/時間がわかるWebマップを作った話でした。

感想

自作webpackLoaderという話がわからなかったので調べました。 入門者/初心者にもわかるwebpack 4の基礎によると, webpackは以下のように書かれています。

webpackは複数のファイルをまとめる処理(bundle your asset/image/scripts/styles)を行うツール

しかし, webpackはJavaScriptファイルのみをそのままの状態で扱う必要があるため, JavaScript以外のファイルをwebpack扱う場合には, Loaderを使用する必要があります。例えば, CSSならcss-loaderとstyle-loaderが必要になります。

「自作」というのは, JS以外のローダーも書いたということですかね?もしくはそれ以外に何かあるのでしょうか?

Webサービスをリリースした話 by Momiyama

動画

https://youtu.be/cX13Wwa0Mds?t=7140

概要

コミュニティーを一元化するためにWebサービスのプラットフォームを作成した話でした。アカウントの一元化, サービスの利用者が開発出来る仕組みを作成したとのこと。

感想

このLTを見ていて驚いたのが, 参加者が開発に参加できるというシステムでした。GitHubでそのサービスはありますが, PullRequestを送るのは怖いものです。そのため, 開発に参加することを一般化して開発に取り組みやすい環境づくりをしたのは画期的だと感じました。

大学祭のシステムを作ってみる->デスマーチの始まりだった by あべけんぴ

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=7435

概要

USB接続したレシートプリンタでQRコードを生成して使用した。前回の教訓を活かし, サイズを大きくしたとのこと。

感想

レシートプリンタは遠い所にあると考えていたのですが, SDKが公開されており, ドキュメントもしっかりしているらしいです。今の所使う予定はないですが, 頭の片隅においておきます。

話がまとまらなかったので本の紹介をします by kurogoma4D

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=7854

### 概要 ソーシャルメディア進化論という本の紹介。マスメディアが一方的に情報を提供していたた時代からSNSを用いて個の集合体が情報を提供できる時代になり, 色々変わったよねという話(多分)。

感想

「これからは個人の意見がより強くなっていくのでは?」という話については同意です。個が強くなりすぎて, 妄信的に個を信じ始める人間が出てきそうな気がしました。

Vtuberをしてみた by かよ

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=8425

概要

REALITYを運用して, 話す話がないので歯磨き音と咀嚼音で配信を始めたとのことです。その結果, 意外とファンがついたそうです。

感想

思い立ったらすぐ行動するということは大事ですね。同じ環境にいた時にスタートダッシュを切れた方が絶対に良いです。Vtuberは恥ずかしい気がしますが, 羞恥心を捨ててみるのも悪くないのかもしれません(私は踏み切れませんが)。

僕とpirkaと未踏ジュニア by 糸井主歩

動画

https://youtu.be/cX13Wwa0Mds?t=9045

概要

アイヌ語で美しいという意味を持つ, pirkaという会話をしながら成長していく人工知能技術を開発した話をしていました。pirkaのシステムについても触れていました。

感想

日本語の文を処理して入力する部分が為になりました。自然言語処理はあまり詳しくないので, アプローチを知る良い機会になりました。

色の役割、色の素敵な使い方 / Let's Do Color Design by Yuki Mihashi

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=10242

概要

カラーコーディネーター検定試験1級 第2分野(商品色彩)を受験して得た知見を共有していました。実践的な内容として具体例も複数含まれていました。

感想

率直に言って, 非常に見やすいスライドだと感じました。「明るい部分は黄み, 暗い部分の色は青みにすると自然な配色(ナチュラルカラー)になる」という部分がお手軽な知見だと感じました。今後意識していこうと思います。

Backdoorの調査と解析 by task4233

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=11294

概要

Backdoorの概要と, Discord ClientをBackdoor化するSpidey Botの解析結果を紹介していた。

感想

デモやコードを見せられなかったのが残念でした。スライドで補足しておいたので, もしよければご覧ください。

50言語でハノイの塔を書いてみた by しゅーまいくん

動画

https://youtu.be/cX13Wwa0Mds?t=11615

概要

タイトル通りです。50言語でハノイの塔の解法を実装していました。実装したリポジトリはこちら。 github.com

感想

ハノイの塔を再帰で書くとシンプルに書けるのは有名ですが, 50個もの言語で実装するというのには驚きました。 ハノイの塔の再帰的解法の証明はこちらがわかりやすいと思います。

www.tbasic.org

kaggle初参加記 by ゆきりん

LT資料

speakerdeck.com

動画

https://youtu.be/cX13Wwa0Mds?t=11983

概要

Kaggleに参加した話について, 実際に何をしたのか, どういう人と共に挑戦したのかという部分にも触れつつ話していました。

感想

Kaggleはよく分からなくて, 私はタイタニックだけやってやめてしまった人間なので, 続けているのは凄いと感じました。コミュニティがあるのは羨ましいです。

VRMアバターを作った作品制作 by やはぎ

動画

https://youtu.be/cX13Wwa0Mds?t=12469

概要

VRMアバターを使って文化祭で展示するライブ映像作品を作った話でした。動きはダンス部の動きをモーションキャプチャしてモデルにのせたそうです。実際にUnityを用いてデモもしていました。

感想

VRMという言葉が初耳だったので調べると, 「プラットフォーム非依存の3Dアバターファイルフォーマット」のことのようです。

vrm.dev

VRMにすることでプラットフォームに依存しない自由なVRアバターを作ることができるようです。Unityも詳しくないのでよくわかりませんでしたが, 実際に動いていて心踊る内容でした。

自己紹介LT by Masato Sugiyama

動画

https://youtu.be/cX13Wwa0Mds?t=12811

概要

自己紹介とのことで, Youtubeチャンネルを開設した話をしていました。Youtubeチャンネルの管理者画面ではどのような光景が見えているのかと言ったことや, 1人アドベントカレンダーの話もしていました。

感想

Youtubeの管理者画面では, いつ, どの程度の人数が動画を見てくれているのかが可視化できるんですね。このような情報を元に, 動画を改善していくことができるんですね。面白かったです。

行ったLTの反省

最も良くなかったこととして, 全体の流れが分かりづらかったということが挙げられます。理由はいくつかありますが, 最も大きい理由は計画性の無さだと思います。というのも, スライドが完成したのが直前で, ぶっつけ本番のLTだったんですよね。そのせいか, 心なし早口になっていたり, 指示語を多く使ったりと全体の流れが分かりづらいLTになってしまいました。

時間が押していたというのもありますが(動画で見たら4分しか話していなかった), 落ち着いて話せるようにLT前に一度資料を見返す余裕を作っておくべきだなと感じました。

次にLTをする際は意識します。

おわりに

以上が, 学生LT#31で発表された18個のLTでした。他にも懇親会で行われたものもあったのですが, 発表者の許諾を得ていないので今回は触れません。私の専門外の分野もいくつかあったので, そのジャンルを知る良い機会になりました。

学生LTのスタッフのみなさま, 会場を提供してくださったDMM様, ならびにLT枠のプレゼンターの方々, 聴講枠で聴きにきてくださった方々には本当に感謝です。

次の学生LTはin岡山だそうです。興味のある方は参加してみてはいかがでしょうか?

とある診断員とSecurity-JAWS #01 参加記録 および flaws.cloudのLevel4までのメモ

はじめに

2019年11月17日(金)に開催された, とある診断員とSecurity-JAWS #01というイベントに参加しました。 このイベントは, AWS固有のセキュリティをCTF形式で学べるhttp://flaws.cloud/を, ハンズオン形式で勉強するイベントでした。

このイベントがなければこのサービスの存在も知らなかった上に, 他の参加者と一緒に問題を解く機会が得られなかったので, いい機会になりました。

ちなみに, ハンズオンで使用された資料は公開されているのでリンクを貼っておきます。

www.slideshare.net

AWSのセキュリティどころか, AWS-CLIツールの使用もままならない状況だったので, 備忘録としてコマンドの使用法およびflaws.cloudの解法を載せていきます。

もくじ

環境

  • macOS Mojave version 10.14.6

AWS CLIについて

AWS CLIのcommand referenceは以下にあります。

docs.aws.amazon.com

command referenceは, まずサービス名を選択し, 次にコマンドを選択することでコマンドを一意に特定することができます。

例えば, ec2を選択すると, DescriptionとAvailable Commandsがあり, 使用できるコマンドの一覧が確認できます。そこで, 例としてdescribe-snapshot-attributeを選択すると, Description, Synopsis, Options, Examples, Outputがあり, コマンド自体について情報が確認できます。

ここでコマンドを実行したい場合は, ページ上部にある[ aws . サービス名 ]とSynopsisを連結して使用します。例えば, 先ほどのdescribe-snapshot-attributeで言えば, ページ上部に

[ aws . ec2 ]

の記載があり, Synopsisに

  describe-snapshot-attribute
--attribute <value>
--snapshot-id <value>
[--dry-run | --no-dry-run]
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]

とあるため, $ aws ec2 describe-snapshot-attribute --attribute <value> --snapshot-id <value>というコマンドを実行すれば良いことが分かります。

Level 1

概要

flaws.cloudにアクセスするとLevel 1があります。 書かれていることは以下の通りです。

  • 一連のレベルを通してAWSの一般的な間違いと落とし穴を学ぶ
  • AWS固有の問題をトピックとしている
  • 各問題でヒントが提供される
  • 全てが単一のAWSアカウントで実行される
  • 全てのチャレンジはflaws.cloudのサブドメインである
  • 最初のサブドメインを見つけられるか確認して

解法

まず, flaws.cloudがAWSのどのサービスを利用しているか確認します。これは, 使用しているAWSのサービスに応じて使用するCLIコマンドやURLで使用するために, 調査します。

これは, dignslookupで調査できます。好きなコマンドを使ってください。

$ dig flaws.cloud +short
52.218.228.218
$ dig -x 52.218.228.218 +short
s3-website-us-west-2.amazonaws.com.

正引きでドメインflaws.cloudに対応するIPアドレス52.218.228.218を取得し, 逆引きでそのIPアドレスに対応するドメインs3-website-us-west-2.amazonaws.com.を取得できました。したがって, awss3を使い, regionはus-west-2AWSサービスを利用していることが分かりました。

この結果を用いて, aws s3のリファレンスを確認し, ページ下部にAvailable Commandsがあります。ここでは, 全体を見るためにlsを使います。

$ aws s3 ls s3://flaws.cloud
2017-03-14 12:00:38       2575 hint1.html
2017-03-03 13:05:17       1707 hint2.html
2017-03-03 13:05:11       1101 hint3.html
2018-07-11 01:47:16       3082 index.html
2018-07-11 01:47:16      15979 logo.png
2017-02-27 10:59:28         46 robots.txt
2017-02-27 10:59:30       1051 secret-dd02c7c.html

ここで, 怪しそうなsecret-dd02c7c.htmlがあるので, ここにアクセスします。

http://flaws.cloud/secret-dd02c7c.html

学べたこと

AWSでは, 静的ファイルのホストに使用するなど, あらゆる種類の権限と機能を備えたS3バケットを設定できます。一方で, 多くの人が非常に緩い権限でそれらのファイルを公開しています。Webサーバのディレクトリ一覧を公開しないように, バケット一覧を公開するべきではありません。

hackeroneのレポートにおける実例

間違いを避けるために

デフォルトでは, S3バケットは作成時にprivateで安全です。

flaws.cloudでは, Webページとしてアクセスできるように,"Static Website Hosting"をOnにして, "s3:GetObject"権限を全員に許可しています。Webページとしてバケットを公開するならば, これで問題ありません。

しかし, flaw(欠陥)を紹介するために, "Everyone"を追加して"List"権限を付与しました。"Everyone"はインターネット上の全員を意味します。全員に対して"List"のアクセス許可があるため, http://flaws.cloud.s3.amazonaws.comにアクセスするだけで一覧を見ることができます。

Level 2

概要

http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloudにアクセスするとLevel 2があります。

書かれていることは以下の通りです。

  • 多少ひねっているものの, かなり似ている
  • 自分用のAWSアカウントが必要
  • 無料利用枠で良い

解法

AWSアカウントが必要なのでAWS CLIに設定します。設定にはaws configureを使います。

セットアップに関しては以下の記事か, google itしてください。

その後, Level 1と同じ流れで解いていきます。 digを使う際に, URLではなくドメイン名を入れる必要があることに注意してください。

$ dig level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud +short
52.218.232.75
$ dig -x 52.218.232.75 +short
s3-website-us-west-2.amazonaws.com.
$ aws s3 ls s3://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
2017-02-27 11:02:15      80751 everyone.png
2017-03-03 12:47:17       1433 hint1.html
2017-02-27 11:04:39       1035 hint2.html
2017-02-27 11:02:14       2786 index.html
2017-02-27 11:02:14         26 robots.txt
2017-02-27 11:02:15       1051 secret-e4443fc.html

ここで, 怪しそうなsecret-e4443fc.htmlがあるので, アクセスします。

http://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/secret-e4443fc.html

学べたこと

"Everyone"へのアクセス権限での公開と同様に, 人は誤って実際にはAWSアカウントを持っている全てのユーザを意味する"Any Authenticated AWS User"へのアクセス権限で公開してしまいます。これは, 自分のアカウントのユーザのみに公開していると誤解しているのかもしれません。

hackeroneのレポートにおける実例

間違いを避けるために

特定のAWSユーザに対して公開アクセス権限を付与してください。

Level 3

概要

http://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/にアクセスするとLevel 3があります。

書かれていることは以下の通りです。

  • 多少ひねっているものの, かなり似ている
  • 最初のAWS Keyを見つけよ
  • 見つければ他のバケットのリストを得られる

解法

かなり似ているらしいので今までと同じ流れで解いていきます。

$ dig level3-9afd3927f195e10225021a578e6f78df.flaws.cloud +short
52.218.230.26
$ dig -x 52.218.230.26 +short
s3-website-us-west-2.amazonaws.com.
$ aws s3 ls s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
                           PRE .git/
2017-02-27 09:14:33     123637 authenticated_users.png
2017-02-27 09:14:34       1552 hint1.html
2017-02-27 09:14:34       1426 hint2.html
2017-02-27 09:14:35       1247 hint3.html
2017-02-27 09:14:33       1035 hint4.html
2017-02-27 11:05:16       1703 index.html
2017-02-27 09:14:33         26 robots.txt

robots.txtがあるので中身を見ると, 以下のようになっています。

User-agent: *
Disallow: /

MDN web docs Robots.txtによると, 以下のように書かれています。

Robots.txt は通常、ウェブサイトのルートに配置されているファイルです。このファイルは、クローラーからウェブサイトへのアクセスを許可するか、禁止するかを決定します。

したがって, *(任意の)User-agentを許容し, TOP配下の全てのページをブロックしていることが分かります。

次に, .gitを解析します。 解析のために, cpを利用します。

$ aws s3 cp s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud ~/work/ --recursive
: 略
$ git branch
* master
$ git log --oneline
b64c8dc (HEAD -> master) Oops, accidentally added something I shouldn't have
f52ec03 first commit
$ git reset --hard HEAD^
HEAD is now at f52ec03 first commit
$ ls
access_keys.txt     hint2.html      index.html
authenticated_users.png hint3.html      robots.txt
hint1.html      hint4.html
$ cat access_keys.txt 
access_key AK**(略)
secret_access_key Od**(略)

ここで, Access Keyが得られたので登録します。素で$ aws configureを実行すると, 自分のAccess Keyが上書きされてしまうため, --profileオプションを利用したAccess Keyの使い分けを推奨します。また, digコマンドの結果でわかっているように, regionはus-west-2なので, それに倣ってus-west-2にします。

$ aws configure --profile level3
AWS Access Key ID [None]: AK**(略)
AWS Secret Access Key [None]: Od**(略)
Default region name [None]: us-west-2
Default output format [None]: json

その後, このaccess_keyを用いて中身を確認します。 保持しているバケットの一覧はlsで確認できます。

$ aws s3 ls --profile level3
2017-02-19 04:41:52 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud
2017-05-30 01:34:53 config-bucket-975426262029
2018-07-08 01:09:49 flaws-logs
2017-02-19 04:40:54 flaws.cloud
2017-02-24 14:15:42 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
2017-02-27 03:29:03 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
2017-02-27 03:49:31 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
2017-02-27 04:49:03 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud
2017-02-27 04:48:40 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
2017-02-27 05:07:13 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud

ここで, level4-から始まるドメイン名があるので, このドメイン名にアクセスします。

学べたこと

人はしばしばAWS Keyを漏洩し, Keyを取り消さずにミスを隠蔽しようとします。不適切な配置や漏洩した可能性がある任意のAWS Key(もしくはSecrets)を, あなたは常に無効にするべきです。Secretsに対して素早く, そして頻繁に権限を与えて直してください。

また, AWSの特定のバケットのみを一覧表示に含めないという制限はできません。そのため, いくつかのバケットを一覧表示する権限をとある人に与えたとすると, その人は全てのバケットを一覧表示することができます。バケットの中に何があるかは分かりませんが, バケットが存在することが分かります。

同様に, バケットは全ての顧客に対して一意でなくてはならないglobal namespaceを使用することに注意してください。したがって, もしmerger_with_company_Yといった秘密と思われる何かの名前のバケットを作成すると, そのバケットの存在を技術的に発見する可能性があります。

実例とケーススタディ

間違いを避けるために

もし誤って侵入, 保存, 共有, publicにされたと考えられる場合, 必ずSecretの権限を割り当て直してください。

Level 4

概要

http://level4-1156739cfb264ced6de514971a4bef68.flaws.cloud/にアクセスするとLevel4があります。

書かれていることは以下の通りです。

  • 次のレベルのために4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloudのEC2上で動いているWebページにアクセスする必要がある
  • nginxがセットアップされたすぐ後に, EC2のスナップショットが作成されたことを知っておくと役立つ

解法

4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloudにアクセスするとログインを求められます。Response HeaderのWWW-Authenticateを見るとBasic realm="Restricted Content"とあるため, これはBasic認証であることとnginxでserveされていることがわかります。

ここで, 問題文にあるnginxがセットアップされたすぐ後に, EC2のスナップショットが作成されたことを知っておくと役立つとのヒントから, EC2のスナップショットを得たいという発想になります。

aws ec2のAvailable Commandsを見ると, describe-snapshotsがあります。単純にコマンドを実行すると膨大な量のスナップショットが表示されたため, スナップショットに紐づけられているOwnerIdの数を確認しました。

$ aws ec2 describe-snapshots --profile level3 | grep "OwnerId" | wc -l
21541

これだけあってはスナッップショットを特定するのは難しいです。そこで, OwnerIdを指定することでスナップショットを特定します。OwnerIdはaws sts get-caller-identityで取得できます。このコマンドでは, userID, AWSのaccountID, ARN(AWS Resource Name)を取得できます。

$ aws sts get-caller-identity --profile level3
{
    "UserId": "AI**LC",
    "Account": "97**29",
    "Arn": "arn:aws:iam::97**29:user/backup"
}

取得したAcountIDを用いて, スナップショットを取得します。

$ aws ec2 describe-snapshots --owner-id 97**29 --profile level3
{
    "Snapshots": [
        {
            "Description": "",
            "Encrypted": false,
            "OwnerId": "97**29",
            "Progress": "100%",
            "SnapshotId": "snap-0b**89",
            "StartTime": "20**0Z",
            "State": "completed",
            "VolumeId": "vol-04*50",
            "VolumeSize": 8,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "fl**27"
                }
            ]
        }
    ]
}

SnapshotIdを取得できたので, パーミッションを確認します。パーミッションaws . ec2 describe-snapshot-attributeで取得できます。

$ aws ec2 describe-snapshot-attribute --snapshot-id snap-0b**89 --attribute createVolumePermission --profile level3
{
    "CreateVolumePermissions": [
        {
            "Group": "all"
        }
    ],
    "SnapshotId": "snap-0b49342abd1bdcb89"
}

Permissionは"Group": "all"なので, 自分のアカウントにスナップショットを作成します。

aws ec2 create-volume --availability-zone us-west-2b --region us-west-2 --snapshot-id snap-0b49342abd1bdcb89
{
    "AvailabilityZone": "us-west-2b",
    "CreateTime": "2019-12-17T05:23:09.000Z",
    "Encrypted": false,
    "Size": 8,
    "SnapshotId": "snap-0b**89",
    "State": "creating",
    "VolumeId": "vol-07**c5",
    "Iops": 100,
    "Tags": [],
    "VolumeType": "gp2"
}

この作成したインスタンスにesbをアタッチしてmountします。マウントした中身を見ると, setupNginx.shで.htpasswdに書き込みをしているようです。

ubuntu@ip-***-**-**-**:~$ cat /mnt/home/ubuntu/setupNginx.sh
htpasswd -b /etc/nginx/.htpasswd flaws nCP8xigdjpjyiXgJ7nJu7rw5Ro68iE8M

htpasswd -c -b /etc/httpd/conf/.htpasswd ユーザ名 パスワードの形式なので, 以下のように情報を抜き取れる

を入力してクリア。

学べたこと

AWSはEC2とデータベース(RDS)のスナップショットを作成できます。主な目的はバックアップを作成することですが, パスワードを忘れたとき人所有しているEC2にアクセスできるようにすることがあります。これは, 攻撃者に対しても同様です。

スナップショットは通常所有しているアカウントに生げんっされているため, 攻撃者はAWSキーにアクセスしてEC2の開始/停止等を行い, それを使用してEC2のスナップショットを作成して起動します。

おわりに

Level 5-6も終わっているのですが, 記事にする時間がなかったので今度更新します。冒頭で紹介した通り, 本イベントで使用された資料は公開されているので, flaws.cloudにチャレンジしてみてはいかがでしょうか?

CODE BLUE 2019 @TOKYO 学生スタッフ 参加記録

こんにちは。task4233(@task4233)です。

2019年10月29日-30日の2日間, ベルサール渋谷ガーデンで開催されたCODE BLUE 2019 @TOKYOに学生スタッフとして参加しました。 そこで, 来年以降参加される方をメインの対象として以下の3点を共有するために本記事を投稿します。

  • 本カンファレンスの概要
  • 学生スタッフの概要
  • 学生スタッフとしてお手伝いした感想

もくじ

CODE BLUEとは

公式のWebページによると, 以下のように書かれています。

CODE BLUEとは、世界トップクラスの情報セキュリティ専門家による最先端の講演と、国や言語の垣根を越えた情報交換・交流の機会を提供する国際会議です。

Talks(講演)では, 世界中から招へいされたセキュリティの専門家が講演をします。大半の講演が英語ですが, 同時通訳の日本語音声*1が無料で利用できます。講演では実際にデモとしてexploitする講演もありました。

本カンファレンスでは, Talks(講演)のみならず, オープンソースツールやプロジェクトを紹介するBluebox, CTF, Hardware Soldering VillageCapture The PacketといったWorkshopも催されていました。

学生スタッフとは

学生スタッフは公式のTwitterで, 以下のような文面でスタッフを募集していました。。

日交代で聴講したり、トップクラスのスピーカーに質問したり、企業で働く方々に直接話を聞いてリアルを学んだり、全国各地から来る学生と友だちになる、貴重な機会になるはず!

お手伝いするのは, 準備日の会場設営, 1日目もしくは2日目に割り当てられた業務およびカンファレンス終了後の片付けになります。 私が割り当てられた業務は同時通訳レシーバの貸し出し, 回収および清掃でした。

他の業務の役割はこの方の記事で説明されていたので共有します。

balius-1064.hatenablog.com

学生スタッフは業務が割り当てられていない間ならば自由にカンファレンスを楽しむことができます。私は1日目に業務が割り当てられたので, 2日目は講演を拝聴したりWorkshopに参加したりしました。

学生スタッフとしてお手伝いした感想

一言で言うと, 楽しめました

実は, 学生スタッフの統括を行った方々が再三再四おっしゃっていたことがありました。 それは「楽しみましょう」という言葉でした。 「楽しむ」と聞いて何を想像するでしょうか?

日本国語大辞典で「楽しむ」の意味を調べると, 以下のような意味がありました。

  • …の中に、あるいはその状態において、心の満足を感じる。
  • ある持続的な行為によって、心を快適にする。また、満足しながら、ある行為をする。
  • 将来に期待をかけることによって、心を希望で満たす

うまく言語化されているなと感じました。2単語を抜き出すとすれば, 「満足」と「希望」です。

これらの観点で言えば, 今回はかなり楽しめました。 なぜなら, 私の業務はMain Track会場内で完結する業務で, 併せて講演を拝聴できたためです。多少はメモを取ることもできたのでラッキーでした。また, 休憩室で数人のスピーカーとお話もできたのも学生スタッフで参加しなければ経験できなかったことなので満足しています。

また, 休憩中に学生スタッフ同士で話すことで, 初対面の人とは新しいコネクションを作り, 既に知り合っていた人とは更に深いコネクションを作ることもできました。特に, 普段のイベントでは話せないような, CODE BLUE CTFを運営したCTFチームのメンバーや会社のCTO*2といった, 普段のイベントでは話せないような方々と話せたので, またとない良い機会でした。イベントでは意外と英語が通じたのも少し自信に繋がりました。こういったコネクションが今後の活動で役に立つやもしれません。その点で言えば希望もあると言えるのではないでしょうか?*3

おわりに

以上が参加記録になります。

今回の学生スタッフを振り返ると, 直後だからか, 楽しかったという思いが強く残っています。 そのため, 関係者の皆様には感謝しかありません。

また, 講演は私の知識不足で完全に理解できている講演は殆どないと感じています。そのため, 今後はCODE BLUEのレポートに少しずつ目を通すつもりです。 レポートはTwitterのタグ#codeblue_jpや以下のリンク先を参照してください。このリンクは気づき次第更新するつもりです。

兎にも角にも, CODE BLUEは非常に楽しめたカンファレンスでした。来年度も縁があって参加できるようならば, スピーカーアテンドに挑戦するつもりです。 来年度も開催されると思うので, ぜひ参加してみてはいかがでしょうか?

*1:日本語から英語の同時通訳もありました

*2:名前は伏せたほうが良い気がしたので伏せておきます

*3:少しこじつけ感はありますが......

セキュリティ・ミニキャンプ in 山梨 2019 参加記

TL;DR

  • ミニキャンプの概要共有
  • ミニキャンプで得られた情報の整理

もくじ

はじめに

2019年9月29日(日)に開催されたセキュリティ・ミニキャンプ in 山梨 2019に参加しました。この記事の目的は, ミニキャンプの概要を共有することとミニキャンプ中に学んだことを私なりにまとめて共有することです。

大学の講義や教職課程の介護等体験などで忙しく, 公開までに2週間ほど経ってしまいましたが, なんとか公開できてよかったです。

セキュリティ・ミニキャンプとは

IPAによると以下のように書かれています。

 全国における情報セキュリティ人材の早期発掘と育成を目的に、各地で専門講義を実施しています。全国大会と比較して、期間が1日程度と短いことから「ミニキャンプ」とも称しています。対象は25歳以下の学生で、参加するには、応募課題を提出し、合格する必要があります。

期間は1日と短いですが, 内容は一般的な講義と比較して濃かったです。

詳しくは, 以下のリンクを参照してください。

専門講座: ミニキャン言語を作ってみよう!

講座概要

自作言語であるMC言語を実装する講座でした。 この言語は, フロントエンドでLLVM IRを出力するC++コードを採用し, バックエンドにLLVMを利用しています。

このおかげで, 私たち人間はC++コードを書くだけで, 最適化まで行われた実行形式のバイナリを入手することができます。

基本的に実装は事前課題*1で行い, 本講義では実装した部分の解説と実装を行いました。

講座前に行ったこと

3回分の事前課題

第1回課題はコメント+参考コード付き, 第2,3回課題はコメントのみ, 発展課題はノーヒントでした。 書く課題はYuka TakahashiさんのGitHubで公開されています。以下にリンクを置いておくので興味があれば参照してください。

発展課題: 演算子の追加実装

<=>=といった演算子等を追加で実装しました。

言語実装では, 演算子の優先度を規定する必要があります。 例えば, C++では以下のように演算子の優先度が規定されています。

ja.cppreference.com

MC言語では, std::map< char, int >で, keyを演算子, valueを優先度として定義していました。しかし, >=<=では2文字必要であるため, std::map< char, int >ではこれらの演算子の優先度を格納出来ませんでした。

そのため, これらの値をenum型で新たに定義することで, 2文字以上の演算子も定義することが出来ました。

制作過程はこちらのPullRequestを参照してください。

三項演算子の実装

三項演算子?を実装しました。

文法は, condition ? expression1 : expression2です。conditionがtrueならexpression1が評価され, falseならexpression2が評価されます。

一般的にコンパイラの読み取りは一方通行なので, 解析時にどのようにすればASTを構築できるかを考えるのに苦労しました。

講座で得られたこと

得られた知見はツイッターで適宜呟いていたので, 抜粋してコメントしていきます。

Google Summer of Code

Google Summer of Codeとは, 公式サイトによると, より多くの学生がOSS開発に取り込むことに焦点を当てたグローバルプログラムで, OSS組織と協力して3ヶ月間続けるプロジェクトです。Yuka Takahashiさんは積極性と英語力があれば行けるでしょうと仰っていました。

UNIX初心者におすすめの本

チューターの方が「UNIXに初めて触れるならこの本がおすすめ」と仰っていました。

puts vs printf

putsはprintfよりも速いようです。誤差なので気にするようなことではないと思いますが, 何度も出力する際はputsを使用した方が良いと思います。

C++における正規表現

参加者の中でパターンマッチを利用している方がいらっしゃいました*2C++でも出来ないことはないだろうと考えていましたが, 実際にあることを確認していなかったためいい機会になりました。

専門講座: OSの力を借りずに起動するアプリを作ろう

講座概要

UEFIアプリケーションを作成して, QEMU*3上で動かす講座でした。 Qiitaの記事によると, UEFIは以下のように説明されています。

UEFIとは、一言で言うと「最近のPCやサーバーに入っている、新しくて高機能なファームウェア(及びそのインターフェースの仕様)」です。

したがって, 本講座のタイトルにもある「OSの力を借りずに」というのは, 「OSの力を借りずに, UEFIアプリケーションをUEFIの力を借りて 起動するアプリを作ろう」のことだと解釈しています。*4

実装は, EDK IIを用いて行いました。

os-devによると, EDKⅡは以下のように説明されています。

EDK II は元々、UEFI の開発に深くかかわっている Intel が作っていた SDK です。gnu-efi が「UEFI アプリケーション」専用なのに対し、EDK II は UEFI アプリはもちろん、周辺のライブラリや、UEFI ファームウェアそのものを開発するための SDK という役割も持っており、超高機能です。高機能ゆえに UEFI アプリを作るという目的のためには複雑すぎてとっつきにくい印象があります。が、フル装備の SDK ですから、慣れておけば後々困ることもないと思います。

講座前に行ったこと

いくつかの機能を実装しました。 具体的に実装した機能は以下の通りです。

EDK IIを用いたハローワールドアプリの作成(事前課題)

EDK IIを用いてUEFIアプリケーションを作成しました。 EDK II で UEFI アプリケーションを作るを参考に作成しました。

アプリケーションのメモリマップをファイルに保存する(事前課題)

ここでやるべきことは2つです。 1つ目はアプリケーションのメモリマップを取得すること, 2つ目はファイルにその情報を保存することです。

まず, アプリケーションのメモリマップを取得するためには, EFI_BOOT_SERVICE.GetMemoryMap()を用います。このメソッドは, アプリケーションのメモリをマッピングしたものを読み取ることが出来ます。このメソッドの詳細は, UEFI Specificationの7.2 Memory Allocation Servicesを参照してください。

次に, ファイルにその情報を保存するためには, EFI_FILE_PROTOCOLおよびそれに関連するメソッドを利用します。これらのメソッドの詳細は, UEFI Specificationの13.5 File Protocolを参照してください。

MC言語で定義した関数が出力した値をPrint関数を用いて画面に出力(発展課題)

シェルもどきを作る(趣味)

OS_Girls 2を参考にI/Oを実装しました。

講座で得られたこと

最も大きかったのは, ポインタとアドレスの理解が深まったことだと考えています。元々, ポインタとアドレス自体はある程度理解していたのですが, 今回のミニキャンプを経て更に理解が深まりました。特に, Cのコードをアセンブリに変換して考える部分が最もしっくりきた部分でした。

おわりに

以上が参加記録になります。

今回のミニキャンプを振り返ると, 参加者が主体となって構成されているイベントだと強く感じました。一般的なイベントでは, 公演の拝聴やハンズオンはあれど, 基本的に主体はイベントを開催している側でした。しかし, ミニキャンプでは参加者が何かをしたいと言えば, それを講師やチューターの方が一緒に解決してくださるという内容だったと記憶しています。

その点で, ミニキャンプは参加者が中心となって何かができるイベントと言えるのではないでしょうか?

このミニキャンプは他の場所でも開催されています。興味のある方は, ぜひ参加してみてはいかがでしょうか?

*1:事前課題が本講義のような気がしました

*2:実名は控えさせていただきます

*3:これQ Emulatorの略だったんですね

*4:解釈違いの部分があればご指摘お願いします

BIT VALLEY 2019で印象に残った3つのセッションとその感想

はじめに

BIT VALLEY 2019に参加しました。この記事では, 私が印象に残った3つのセッションを紹介します。私は後半の1日しか参加していないため, 2日目のセッションについてのみ書きます。

また, この記事は私なりに咀嚼した概要です。そのため, 誤った捉え方をしている部分があれば訂正をお願いします。

もくじ

BIT VALLEYとは

2019年09月13日(金)〜09月14日(土)にかけて開催されたカンファレンスイベントです。ホームページには以下のように書かれています。

「BIT VALLEY 2019」は、技術だけでは成しえない、人の感性に訴え、共感を呼ぶサービスを創造するために必要な、気づきを得られるカンファレンスイベントです。

要するに, 「なに」で創造するかではなく 「どのように」創造するかに焦点をあてたカンファレンスイベント です。

「よい」だけでは足りない! –世界に飛び出していくために必要なマインドセット

スピーカーは澤 円(@madoka510)さんでした。

マインドセット更新の必要性

世界に存在する全データのうち, 90%が直近2年で生まれたデータ です。これほど頻繁に変わるデータに対応するために, 私たちもマインドセットを更新する必要があります。

「よい」は変化する

「よい」という言葉があります。一昔前は, 品質の高いモノが「よい」モノとされていました。実際に, 日本はそのおかげで高いマーケットシェアを誇っていました。しかし, 今は違います。高品質でも価格が高いモノは今のマーケットニーズに反しているためです。したがって, 過去の「よい」考え方だけでは, イノベーションは生まれません

「知識・経験」×「スピード」のマトリクスによる人の分類

では, どのような人になるべきなのでしょうか?それを理解するために, 人を「知識・経験」と「スピード」の2軸で分類します。すると, 以下のようになります。

f:id:task4233:20190915124137p:plain

左上から反時計回りに見ていきます。

「賢いが遅い」人は, 組織の成長を阻害します。いわゆる「口だけの人」です。日本に多いタイプのようです。
「愚かで遅い」人は, 組織を停滞させます。いわゆる「どうしようもないノロマ」です。

「愚かで速い」人は, 変化への対応に弱いです。いわゆる「タスクワーカー」です。単純作業がメインなので, 技術革新によって消えていく可能性が高いです。また, 他の場所に移動しづらいのも特徴です。

したがって, 「賢くて速い」人が狙い目です。

「賢くて速い」人になるためには

「賢くて速い」人になるためには, あなたが「どうありたいか(being)」を考えてください。 人は, 「どうありたいか(being)」よりも「何をすべきか(doing)」を考えがちです。

「どうありたいか(being)」を考える過程で重要なことが3つあります。

1つ目は, 押し付けられている価値観を取り払うこと です。最も簡単なやり方は, 「新しく何をやるか」ではなく 「新しく何をやめるか」 を考えることです。

2つ目は, どんどんアウトプットすること です。アウトプットによって得られるフィードバックは高品質なインプットに繋がります。アウトプットのやり方に困ったら, 質問をしてください

質問は, 自分向けにカスタマイズされた情報を得られる立派なアウトプットです。

3つ目は, もっと心を自由にすること です。人生は1回きりです。1日は等しく24時間です。 嫌ならやめましょう。

感想

最も印象に残っているのは,

人は「どうありたいか(being)」よりも「何をすべきか(doing)」を考えがち

という部分です。私は 「〜をする」という小目標を立てていた時期があったので刺さりました。その時は日を跨ぐにつれ停滞していったことをよく覚えています。これは, 「どうありたいか(being)」よりも「何をすべきか(doing)」を考えすぎた結果だなと感じました。

クラウド時代のエンジニア生存戦略

スピーカーは高橋 慎一さんでした。

www.slideshare.net

エンジニア編(習慣づくり)とプレイングマネージャ編(現場づくり)の2部構成です。

エンジニア編(習慣づくり)

エンジニアの習慣づくりに重要なことは4つあります。

1. キャリアパスを見据えること

言い換えれば, 市場が求める人材を理解することです。

では,今クラウド業界で必要とされている人材はどのような人材でしょうか?その答えは, 複数の分野がある程度出来て, かつ尖った部分を2・3個持っている人材 です。

例えば, AWSでは100を優に超える膨大なサービスが提供されています。そのため, その一部しか使いこなせないΠ型の人*1は市場が求める人材とは言えません。したがって, クラウド業界では, より一層複数の分野に知見を養う必要があります。

2. インプットを大事にすること

アウトプットをするためには, インプットが必要不可欠です。ただし, 継続することが重要なので, インプットは無理のないボリュームで行ってください。例えば, はてブ*2タイトルの流し読みや本屋に足を運ぶことが手軽で良いでしょう。

3. 目標設定を心がけること

2〜3年単位の長期目標から逆算して, 1年単位の中期目標や2〜3ヶ月単位の短期目標を設定してください。ただし, 各目標で見据えるものは異なります。

具体的に, 長期目標は 自分が望むキャリア変化を見据えて設定してください。 中期目標は, そのキャリア変化をもたらすための環境変化を見据えて設定してください。 短期目標はその環境変化をもたらすためのスキル変化を見据えて設定してください。そうすることで, ブレない技術習得サイクルを築くことが出来ます。

ここで, 長期目標と関連のないことを短期目標に設定しないでください。例えば, カレーの作り方を考えている時に, ポン酢を作れる必要はないですよね。

4. 小さな成功体験を作ること

無作為にあなたを含めた100人を抽出したとき, あなたが一番だと誇れるものはありますか? そこで誇れるような成功体験を作ってください

小さなことでも他分野のことでも問題ありません。重要なのは, 1つでも成功体験があることです。なぜなら, 1つでも成功体験がある人は次に繋がりやすいためです。その結果, セルフイメージが高く, 成功癖がついた人になっていきます。

プレイングマネージャ編(現場づくり)

プレイングマネージャとは, この記事に以下のように書かれています。

プレイングマネージャーとは、現場の最前線で売上や利益に貢献する実務を担当する一方、部下の育成や指導を行う管理職を兼任する人物を指します。

いわゆる, 中間管理職です。このプレイングマネージャの現場づくりに重要なことは3つあります。

1. 「できない理由」を探さないこと

「できる理由」を考えてください 。人はやる前から, 無意識のうちに前提条件を作りがちです。そのために, あなた自身を含む従業員で「どうやったらできるか」の思考訓練*3を積んでください。

2. 挑戦できる環境を作ること

メンバーが業務中にスキルアップ可能な「挑戦できる環境」を作ってくださいクラウド業界は早い段階で小さな失敗を繰り返せる挑戦にはもってこいの環境です。そのため, 常に挑戦できる環境づくりをしてください。例えば, プロジェクトごとで別の言語を使用したり, マネージャ自ら挑戦する姿勢を見せたりといった働きかけができます。

3. 視座を下げて考えること

相手(部下)の立場に立った時に, 自分がどう見えるかを適切に振り返る機会を作ってください。考える際に相手の興味・関心を意識するとよいです。

クラウド時代を生き抜くために

以上7つがクラウド時代に重要なことです。

これらを総括して, クラウド時代を生き抜くために 挑戦できる環境に飛び込んでください

感想

BIT VALLEYの趣旨である「どのように」創造するかを体現したようなセッションでした。このセッションは, エンジニア編では4つ, プレイングマネージャ編では3つのポイントを言語化していました。言語化した情報は意識に留めやすく, 人にも伝えやすいのでありがたかったです。

世界中の開発者と共にモノづくりをするために必要な6つのこと

スピーカーは田中 洋一郎(@yoichiro)さんでした。

speakerdeck.com

前座は抜きにします。タイトルにもある「世界中の開発者と共にモノづくりをするために必要な6つのこと」は以下の通りです。

  • 素振りを欠かさないこと
  • 居場所を探し続けること
  • 外部とのつながりを持つこと
  • 何かを作って公開すること
  • カッとなったときにやること
  • 英語に屈しないこと

1つずつ深掘りします。

1. 素振りを欠かさないこと

基本をこなしながら, 試行錯誤を繰り返して引き出しの数を増やしてください

素振りとは「基本をこなす」という意味合いです。人は何も土台のないところから閃くことはありません。そのため, 基本→応用→閃きの順に構成していくことが必要です。言い換えれば, 土台→工夫→未知となります。その過程で, 素振りを欠かさないでおけば, 自分の引き出しが増えていきます。それにより, 突然降ってきたタスクに対応しやすくなります。

引き出しの数を増やすためには, 様々なことに少しずつチャレンジしてください。オススメはチュートリアルをやることです。チュートリアルが余裕ならベータ版に触ってみるのも良いです。

2. 居場所を探し続けること

どこにいれば自分の信じる次のステージに行けるかを考えてください

ハードウェアやサービスは日々刻々と変化しています。それに応じて属する場所を変えていくと良いでしょう。

3. 外部とのつながりを持つこと

広い視野を持つために, 身近なことから始めてください。 始めるのは簡単なことからで良いです。

最初は, 手軽に始められる勉強会に参加しましょう。そこで手を動かしてアウトプットします。時には身内に対して情報を共有するのも良いでしょう。それを繰り返して, 徐々に影響範囲を広めていきます。その過程で, よりアクティブで, より詳しく, より尊敬できる多くの人々と出会います。そして, 迷ったら即相談できるような仲間ができていきます。

気がつくと, 自分の周りに日本人がいなくなります。なぜなら, 自分より詳しい日本人がいなくなるためです。その時, あなたは「多様性」の中に自分がいるでしょう。

4. 何かを作って公開すること

何かを自分で作ってください。 そして, 作ったものを公開しましょう。公開すれば, その制作物が独り歩きして, 人や情報を集めてくれます。

5. カッとなったときにやること

カッとなったとき*4に, 積極的に行動してください

積極的に取り組むと事故の発生率は上がります。ただし, 優秀な人ほど事故も経験しています。すなわち, 優秀さとはどれだけ失敗しそれをリカバリーしたかということです。日頃から積極的に行動し, 事故を経験すればするほど, そのあとの伸び率は高いでしょう。

6. 英語に屈しないこと

得意なことに英語を取り入れてください

具体的には, 様々なチュートリアルを英語で学んだり, GitHubリポジトリを英語のみで書いてみたり, 作ってみたモノを英語で宣伝してみたり, stackoverflowで回答してみたりと, 様々です。

世界には第二外国語が英語の人が多いので, 拙い英語なのはお互い様です。お互い興味のあることなら何度でも聞き直して問題ありません。

この繰り返しで成功体験を積み上げることで, あなたの自信につながります。

感想

このセッションは私の考えと似た部分があったので, 共感できる部分が多かったです。それに加えて, 私が出来ていないことが言語化されていて, モヤモヤしていた部分が少し晴れました。残りのモヤモヤは, 実践して自信をつけて解消していくつもりです。

全体を通して

個々のセッションの方向性は違えど, よく耳にした内容が3つあります。

1つ目は, 「アウトプットすること」 です。これが最も多かったように感じました。アウトプットは成果を公開するだけでなく, 情報が集まるきっかけになったり, 情報を整理するきっかけになったりします。そのため, 小さなことでもアウトプットしていくことは重要だと感じました。

2つ目は, 「気になったらやってみること」 です。「カッとなったときにやる」や「違和感をきっかけにモノを作る」といったように表現は違えど, 根は同じであると考えています。私は興味のあることにひたすら取り組んでいるので, この姿勢を続けていこうと考えています。

3つ目は, 「成功体験を作ること」 です。成功体験はあなたに自信をもたらします。そのため, 「どのように創造するか」において重要な要因の1つなのではないでしょうか?私は小さな成功体験はあるものの, 1番秀でていると誇れるほどの成功体験は未だにないので, 徐々に積み上げていくつもりです。

おわりに

以上が参加記録になります。

全体的に刺さったセッションが多く, 気づけたことの多いカンファレンスでした。 そのため是非来年も参加したいと思います。

学生は無料だったので, 興味のある方は来年のBit Valleyに参加してはいかがでしょうか?

*1:少数深掘りしているものの, 他の知識は平均以下の人のこと

*2:はてなブックマーク

*3:常にそのことを考えるような意識を持つこと

*4:何かトラブルが起きた時など

セキュリティ・キャンプ全国大会2019参加記

はじめに

先日セキュリティ・キャンプ全国大会2019に参加してきたので, その参加記録を書きました。

f:id:task4233:20190824131652j:plain

この記事の目的は, 今後セキュリティ・キャンプに参加する方々に対して, セキュリティ・キャンプの概要や得られるモノなど, 私の印象に残ったことを共有するために書きます。全体の流れは以下のもくじを参照してください。主観的な意見も複数含まれるため, 参考程度に読んでいただければ幸いです。

また, 今回のキャンプで行われたことは, 詳細に記述すると色々と問題が生じる内容を含んでいます。そのため, 内容があいまいになっている部分が多々あるので, その点を理解した上で読んでいただくよう, よろしくお願いします。

もくじ

応募したきっかけとAトラックを選択した理由

応募したきっかけ

昨年, 私が大学内のPC実習室でアルバイトをしていた際にポスターを見つけたのがきっかけでした。しかし, 気づいた頃には応募締め切りを過ぎていたため, 今年こそは申し込もうと考えていました。

A 脆弱性マルウェア解析トラックを選択した理由

脆弱性マルウェア解析トラックに応募した理由は, 選べるトラックの中で個人の力で学ぶことが最も難しそうな内容だと感じたためです。マルウェアはその危険性から専門的な知識を持った人間のみが解析をしています。そのため, このトラックの集中講義を受けることで非常にレアな経験ができると考えました。

キャンプ全体の大まかな流れ

キャンプは5日間で構成されており, そのうち専門講義を受講できるのは2・3・4日目の3日間です。残りの期間は, 全体講義やグループワークで構成されていました。 したがって, トラックごとの特色が現れてくるのは3日間ということになります。参考までに私の専門講義のある2・3・4日目のスケジュールは以下の通りでした。

  • 6:00~ 起床
  • 6:45~ 朝食
  • 7:15~ 前日の内容と事前学習の復習
  • 8:30~ 専門講義
  • 12:00~ 昼食
  • 13:30~ 専門講義
  • 17:30~ 夕食
  • 19:00~ イベントや専門講義
  • 21:00~ HR
  • 22:00~ 本日の復習と翌日分の事前学習の復習
  • 23:00~ 就寝

6時起床なんて無理だろうと思っていましたが, 割と起きられました。とはいえ, 7時起床している方や8時起床をしている方もいたので, 6時起床しなければならないという訳ではありませんでした。

会場でのフリートークについて

今回のセキュリティキャンプでは, 可能な限り積極的に人と話すように心がけていました。結果的に, 5日を通して60人ほどの方々とお話できました。そこで重要になってきたのが名刺の存在です。参加する方は必ず名刺を刷っていきましょう。とはいえ, 名刺に載せる情報に困ると思うので, 私が名刺に書いておいた方が良いと感じた項目をいくつか書いておきます。

  • 氏名(漢字の場合はふりがなを振っておくと良い)
  • ハンドルネーム(あれば)
  • 所属(学校名/学科/専攻)
  • メールアドレス
  • SNSアカウント(Twitter/Facebook等)
  • WebページのURL(Portofolio/GitHub/Blog等)
  • 趣味・普段やっていること

そして, 今後参加する方は, 講師・チューター陣に対してはパケット欠損率0%が保証されているので, 積極的に質問パケットを飛ばすことをオススメします*1。話すことがなくなったら「興味のあることはなんですか?」や「何の人ですか?」という質問をすると, DDOS攻撃さながらの応答パケットが帰ってくるのでオススメです。

また, 食事の時は講師やスポンサーの方々が固まって食事をしていることが多いので, 図々しく突撃して話をすることもオススメします。突撃してお話をすると以下のようなメリットがあります。

  • 名刺交換の機運が高まります
  • フォロワーが増えます
  • 思いもよらぬ情報が得られます
  • 相手のツテで他の方を紹介してくれることもあります
    • リクルートのスポンサーに話が飛び, 会社紹介の資料を共有していただきました
    • マルウェアつよつよな方に話が飛び, マルウェア解析に関する情報を共有していただきました

専門講義の概要等

私が参加した専門講義の内容を書きます。全体講義に関しては, 私より文章力のある他の方のブログ等を参考にしてください。その代わり, 専門講義は可能な限り具体的に書くつもりです。

A1-3 インシデントレスポンスで攻撃者を追いかけろ

概要

事前学習で学ぶ知識のうちの約8割の内容を学習するので, 事前学習は本当に重要です(事前学習ができていないと本番で何もすることが無くなります)。

そして, 本番ではproxyサーバのログやPCごとのイメージファイルが配布されます。それらを解析することで, マルウェアはどこにあるのか, 何をpersistenceとして動いているのか, いつ感染したと考えられるのか等を調査し, どのような流れで攻撃者が攻撃を行ったのかをCTF形式で解明していきました。私のCTFの結果では3位でした。

また, CTF形式の調査終了後, グループを作って今回のインシデントの問題点とその解決策を発表しました。

事前課題

事前学習の時期とテスト期間およびサンフランシスコでの講義が重なり, 時間のやりくりが大変でした。そのため, セキュリティ・キャンプ前の数日間にフリーな時間を作ることをオススメします

講師の梨和さんは, 事前課題に対して「知識や技術のばらつきがあると思いますので一概には言えませんが, 問題自体は1〜2時間程度あれば回答できるような内容です」と仰っていましたが, 私は1つの課題につき最低でも5〜6時間はかかりました。その原因は, 問われていない部分を調査して言語化して回答していたためだと考えています。具体的には, 以下のPDFのようなログを検索する際のコマンドの使い方が挙げられます(これは単純にパースするだけのコマンドなので公開しても問題ないはずですが, 削除要請があれば消します)。

drive.google.com

これをやっておいたおかげで, 本番でproxyサーバのログを解析する際に, コマンドを思い通りに使用することができました。私は計画と時間の使い方が下手だったので, 全ての課題についてまとめることは出来ませんでしたが, 来年度以降に参加する方は理解を深めるためにぜひ知識のまとめをすると良いかもしれません。

講義を終えて

講義が終わって抱いていたことは「もっと解析したかった」ということです。私は最初から足踏みをしてしまい, 結果的に事前課題の半分も活用できませんでした。とはいえ, 足踏みしていた際に講師の梨和さんや小林さんが質問に応じてくださったため, なんとか足踏みを解消して問題解決に取り組むことができました。質問に対して真摯に対応してくださった講師のお二方には感謝しかありません。

また, 最後に扱ったインシデントのタイムラインを公開してくださったおかげで, 扱ったインシデントの全体像を捉えることができました。それに応じて, 私がCTF中に解明できた部分と合致している部分と勘違いしている部分が明確になったため, 非常に参考になりました。

A4 Reverse Engineering Malware - Know Your Enemies

概要

本講義では前半で座学があり, 後半ではにIDAを用いて実際のアセンブリコードを解析することで, コードがどのような挙動をするのかを調査する形式がとられました。

座学では次で触れる事前課題のレビューや直近3年間の攻撃手法, 静的解析のための知識等を扱いました。そして, アセンブリコードの解析では, 与えられたi64ファイルを解析して, Moduleごとの役割を調査しました。

事前課題

事前課題として, idbファイル*2のModuleにコメントをつけたり変数名を変更したりして各Moduleの機能を明確にする課題が課されました。この課題に際して, 以下の3つのポイントを段階的に解明していくと良さそうでした。

  1. WinAPIを調査する
  2. WinAPIに与えられるArgumentsを調査する
  3. 状態に応じた分岐を調査する

これを極めることで, 中津留さんのような高速な静的解析ができるのではないでしょうか(ホンマか?)

講義を終えて

私は応募課題のアセンブリを読む問題が解けなかったため, アセンブリを解析することに不安がありました。しかし, 本講義を受けたことでアセンブリをすべて読む必要はなく, 必要な部分のみを読むことで解析ができることを学べました。中津留さんのように高速かつ的確に読むことはできませんが, 講義を通して明らかにアセンブリを効率よく読めるようになったので, 受講して良かったと考えています。

B5 体系的に学ぶモダンWebセキュリティ

概要

本講義では座学と実習を組み合わせながら学ぶ形式が取られました。以下が講義で使用されたスライドです。

speakerdeck.com

丸投げになりますが, スライドを見れば内容はわかると思います(素晴らしい出来なので, 私が書かなくても情報は伝わってくると思います)。

事前課題

事前課題は3つありました。

1つ目の課題は講師のつばめさんが執筆中のPDFの確認でした。基礎的なOriginの説明から入り, サイドチャネル攻撃についても具体的に触れられていました。

2つ目の課題は, SOP/CORSの挙動確認でした。具体的には, つばめさんが公開しているWebページで実際にそれが挙動していることを確認するというものでした。

3つ目の課題は, XSS-ChallengeでのWeb問の確認でした。XSS-Challengeとは, つばめさんが岡山のミニキャンプで利用したXSS用のWebページで, それを各自解くというものでした。

これらの事前課題は実際に手を動かす必要があり, 事前課題から体系的に学ぶことができる内容となっていました。XSS-Challengeを全て解くことは大変でしたが, 解答も同時に教えてくださったためサクサクと進められました。

講義を終えて

本講義では, CTF風の形態で演習が行われたので, 実践的に学ぶことができました。その上で, 受講生の進度に合わせて講義を進めてくださったため, 進度もちょうど良かったです。具体的には, CSS-injectionのexploitを書くのに時間がかかったため, 後半のXS-LeaksやXS-Searchの話題を省き, Recon Challengeに入ったことが挙げられます。

また, 講義が終了してからも1週間ほどサーバーを稼働し続けてくださったため, キャンプ終了後も手を動かして復習することができました(ありがとうございました)。

A6 マルウェアの暗号処理を解析しよう

概要

本講義では座学と実習を組み合わせながら学ぶ形式が取られました。

まず, 座学にてRC4(ARC4), ChaCha, Blowfishの3つの暗号化を学びました(講義資料にはAESも含まれていました)。次に, C言語で各暗号化を実装したファイルとそれをコンパイルしたアセンブリを確認し, Cで記述された処理がアセンブリではどのように記述されているのかを確認できました。最後に, 各暗号化の特徴を確認し, それを検知するPythonスクリプトを書きました。

事前課題

ありませんでした。

講義を終えて

RC4(ARC4)という名前を知っていたものの, その中身の実装は理解していなかったので, 講義の序盤から知見が得られました。

そして, ChaCha, blowfishのアルゴリズムを確認していく中で, RC4(ARC4)はループとxor, ChaChaおよびblowfishは平文がパラメータとして与えられることなどを理解でき, 難解だと考えていた暗号化技術に対する印象がガラリと変わりました

この講義で良かった部分は, C言語のコードとアセンブリコードの両方があり, これらを比較することで処理の対応づけが出来たことです。IDAで見ると, 各暗号化の特徴がしっかりと確認できたので, 納得のいく講義でした。

E7 実践トラフィック解析

講義の概要

最初に座学が行われ, 次に実際にトラフィックをキャプチャして解析し, 最後にトラフィックに対するレポートをまとめて発表するという形式が取られました。

キャプチャするトラフィックセキュリティキャンプ会場の生のトラフィックであったため, 他講義のトラフィックを確認したりShinoBOTを確認したりする班がありました。

事前課題

事前課題は3つありました。

1つ目の課題はWiresharkInstallBattleでした*3

2つ目の課題は自端末のNICをキャプチャして得られたパケットの内容確認でした。私は, キャプチャしてからネットサーフィンをしていたので, HTTP関連のパケットが非常に多かったです。

3つ目の課題は, 配布されたpcapファイルの解析でした。私は10個あるファイルのうち3,4個しか解析しませんでした。

講義を終えて

生のトラフィックを解析した経験が無かったので, 生のトラフィックを見ることができたことが印象に残っています。それに加えて, 人間はネットサーフィンをしがちなので, HTTPパケットが多くなるだろうと私は想定していましたが, 実際はTCPパケットが多かったのも印象的でした。

また, キャンプ内のネットワークでCTF問題のパケットらしきものがありました。そのページにはネクストキャンプ講師の伊東さんの画像が貼られていたので, ネクストキャンプでCTF問題でも解いていたのでしょうか......?

キャンプ終了後に行っている活動について

既に行っている活動は3つです。

健康的な生活習慣の継続

割とこれは冗談じみていますが, 重要なことだと考えています。

セキュリティ・キャンプでは, 6~7時起床, 23~24時就寝という健康的な生活習慣をしており, その後もこの習慣を続けています。私は, つい2~3時ごろまでPCを触って夜更かしをして最終的に昼夜逆転することも珍しくないので, この習慣を続けていこうと思います。

CTF学習グループの形成

初級者から中級者に上がるためのCTFグループでの学習およびCTFの参加です。私はCTFの初心者にあたるので, そこから中級者になるために, 同様の状態にある方々とグループを作り, CTFに関する話題の共有等を行っています。

実際に昨日開催されていたHackCon'19では705Pointsで113位でした。私は0ACでしたが, 情報共有で役に立てたのではないかと考えています。

マルウェア解析の情報共有

今回, 私は脆弱性マルウェア解析トラックに応募して, マルウェアを解析したいという同士がいました。その同士と共にマルウェアの解析について情報共有を行っています。具体的に何かを始めた訳ではありませんが, グループで1つのマルウェア解析コンペのようなものが出来たら楽しそうだなと考えています。

さいごに

ここまでお読みいただきありがとうございました。

セキュリティ・キャンプ全国大会で印象に残った部分を可能な限り述べ, その素晴らしさを押し出したつもりです。私は大学で教職課程を履修しているため, 大学のある時期にはイベントに参加しづらいですが, セキュリティ・キャンプのように夏季休暇中に行われるイベントには参加することが出来ます。故に, このようなイベントは非常にありがたく, 内容としても非常に濃いものを受容することが出来ました。今回受け取ったモノを還元したいという意味でも, さらに新しいモノを吸収したいという意味でも, 来年度もチューターとして参加したいと考えています

そのために, 今回の事前課題等を改めて復習したり趣味でマルウェアの解析を行なったりして, チューターとして申し分ないような知識と技術を身につけようと考えています。

キャンプ前に運営にご迷惑をおかけしたり, キャンプ中には夜遅くまでお話していただいたり, キャンプ後には講義の内容を教えていただいたりと最初から最後まで色々とご迷惑をおかけしましたが, 全てしっかりと対応していただき悔いのないキャンプにすることができ, 本当に感謝しています。セキュリティキャンプに従事された講師, チューター, スポンサーの方々および私と話をして情報共有してくださった受講生の皆さま, 本当にありがとうございました!

以上がセキュリティ・キャンプの参加記となります。セキュリティ系の専門分野について集中的に学べるだけでなく, スタッフや他の参加者と話して知識を広げるチャンスなので, ぜひ今後のセキュリティ・キャンプやミニキャンプに参加してみてはいかがでしょうか?

終了

*1:5日は本当に速く過ぎ去るので積極的に質問しましょう

*2:古いversionのIDAで解析をする際に用いるファイル

*3:ArchLinuxInstallBattleを真似しました