情報処理安全確保支援士試験を受験した(合格)
概要
タイトル通りです。
受験記
受験3~5ヶ月前
応用情報に受かった次の日にAmazonで教本を注文しました。
早く勉強を始めると途中でモチベが必ず無になります。
買ったはいいもののモチベや時間の関係で、結局半分くらいまでしか読みませんでした。
受験1~2ヶ月前
この辺りで少しづつ焦り始めたのを覚えています。
インターン、高専プロコンが重なっていたので教本を使った勉強はほとんど出来ず、空いた時間でタブレット端末を使って情報セキリュティ白書を読んでいました。
また、情報処理安全確保支援士ドットコムで午前2過去問をずっとやっていました。
最終的には9割近く正答できるようになり、午前については特に不安要素もなく受験することができました。
受験2週間前
この辺りで午後に手をつけました。
買った教本には午後解説pdfがついてきたので(嬉しい)、解いて答え合わせ…を繰り返しました。
高度試験からは午後試験が2種類になりボリュームが増すので、1日に午後1or午後2のどちらかをやるので精一杯でした。
DNSとメール分野の正答率が極端に低かったので、教本と解説pdfを復習しながら「当日出ないでくれ〜〜」と祈っていました。
受験当日
午前1
免除です。
午前2
8割過去問だったような気がします。
特にこれといったミスや分からない問題もなく、92点を取ることができました。
午後1
苦手分野は出てもどっちかだけだろうと思っていたので問題冊子を開いて焦りました。
プログラミング問題が出なかったのが予想外で、調子を少し崩されました。(なんで消えたの…?)
パッと見た感じメールが厳しそうだったのでDNS問を解くことにしました。
一部DNSを用いた通信についての問が分からなかったのですが、問題を読みつつ教本の内容と自分の経験に頼ることでなんとか答えました。
マルウェア問は過去問通りの出題で、ゆったり解くことができました。
午後1が一番の不安要素でしたが上手く答えられていたようです。78点でした。
午後2
出題はコンテナ、ネットワークでした。
コンテナについてはまだ勉強中で自信がなかったので、ネットワークを選択しました。
午後2よりも、午後1の方が難しく感じました。
しかし記述量は午後2が圧倒的に多く、思うように記述回答ができずに受験教室で頭を抱えたの覚えています。
選択肢に弄ばれたり(エア乱れ打ち)しましたが、結果は81点。予想以上の出来でした。
結果
合格しました!
午後2については80点超えが300人だけということで、少し自信をもてました。
記述についても、好意的に採点されたようで満足です。
情報処理安全確保支援士、合格!!! pic.twitter.com/B0qZWN9VbT
— ゆん (@yn0014) 2019年12月20日
最後に
普段サーバを弄ったりしていれば、過去問や教本で2ヶ月しっかり勉強することで合格ラインに乗ると思います。
5ヶ月も前から勉強を始めてしまうと途中でモチベが無くなるので気をつけてください…。
合格はしましたが、まだまだ勉強不足な部分が多いので引き続きセキリュティ分野は勉強していきます。
2020春試験はエンベデッド目指して頑張ります。
最後まで読んでいただきありがとうございました。
Cコンパイラ(yncc)進捗 20191128
概要
9月頃からちょっとずつ作っていたCコンパイラ(yncc)がひと段落したので、その進捗とこれからやりたいことを書きます
Cコンパイラ、完成には程遠いけどひと段落まで行けたってことでブログ書きたいな
— ゆん (@yn0014) 2019年11月8日
進捗
- プリミティブ型 (int, char)
- 変数 (ローカル/グローバル)
- ポインタ
- 配列
- 関数
- if
- for
- while
以上が実装済みの機能、構文です。
↓のようなプログラムをコンパイルすることができます。
int main() { int memo[10]; memo[0] = 1; memo[1] = 1; int idx; for(idx = 2; idx < 10; idx = idx + 1){ memo[idx] = memo[idx-1] + memo[idx-2]; } return memo[9]; }
自分がプログラムを始めたてのときに書いた数当てゲームがあるのですが、一部を変更するだけでコンパイル出来ました
これからや りたい ること
最終的な目標はセルフホスト…ですが、あまりに大きすぎる目標を置いても自爆するだけなので
書いたままのプログラムをコンパイル出来るようにする
を当面の目標にします。
現段階のynccでプログラムをコンパイルしようとした場合、変数宣言の場所やスコープなど…コンパイラの実装状況に合わせたプログラムに変更してあげる必要があります。
…なので、「そんなつまらない事なんて考えずに書いたプログラムを手直しせずすぐコンパイルできるようにしたい!」ということです。
(例えば、for文の初期化式で変数定義が出来ないので1回外で定義する必要がある…など面倒くさい仕様になっている)
まとめ
やるぞ!
並行して進めていること
ついでにこの記事を書いた時点で並行して進めていることを書いておきます。(後から見直したときに役に立つかも)
マルチタスクで、進めるぞ!
入門 マルチタスクな人間
— ゆん (@yn0014) 2019年11月6日
GoでBrainf**kコンパイラを作ってみた
かかった時間
5.5時間
完成したもの
Brainf**kコンパイラ
Brainf**kコンパイラ完成! pic.twitter.com/weWCTqCdhs
— ゆん (@yn0014) August 31, 2019
言語・環境
- 使用言語 : Golang
- OS : MacOS Mojave 10.14.5
- GCC : gcc (Homebrew GCC 8.2.0) 8.2.0
- Golang : go1.12.4 darwin/amd64
工程
1. ベースを作る
とりあえずベースを作ってどんどん拡張していくことに決める。
吐き出すアセンブリのヘッダー/フッター部分を出力する関数を作った。
2. 便利系関数を作る
続する文字の数を数える、エラーを出力するなどの関数を作った。
3. >, < 記号実装
ポインタ位置をインクリメント/デクリメントする記号「<」「>」を実装した。
(途中まで「+」「-」と勘違いしていたのでコミットメッセージが若干おかしい…)
この時点でParse関数とAsmBody関数のベースも完成していたのでこの後の実装作業が格段に楽になった。
4. +, - 記号実装
ポインタの指す値をインクリメント/デクリメントする記号「+」「-」を実装した。
同時にメモリ確保関連の処理も実装した。
5. [, ] 記号実装
ループを表す記号「[」「]」を実装した。
対応する記号にIDを降って、対応したラベルを出力するような感じにした。
cmp byte ptr [レジスタ], 0 je __loop_end_0 __loop_start_0: . . cmp byte ptr [レジスタ], 0 jne __loop_start_0 __loop_end_0:
6. バグ修正
ここで色々バグが見つかり出したので修正作業をした。
アドレス計算のミスが目立ったのでもっと精進したい…。
7. . 記号実装
ポインタの示す値をASCIIコードとして呼んで出力する記号「.」を実装した。manページのwriteを読みつつ実装した。
8. , 記号実装
1バイト標準入力からデータを受け取ってポインタが指す場所に保存する記号「,」を実装した。この記号もmanページのreadを読みつつ実装した。
9. テストプログラム
HelloWorldを出力する定番プログラムと、入力された内容をそのまま出力するプログラムを書いた。
どちらのプログラムも正常に動作することを確認した👍
// hello world >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.>
// 3byte input ,>,>,<<.>.>.>++++++++++.>
10. 完成
やったーーーーーーー〜!!!!
動作具合
このBrainf**kコードをコンパイルすると…
+++++[>+++++++++++++<-]>.+.+.>++[>+++++<-]>.>
以下のようなアセンブリを吐き出す。
.intel_syntax noprefix .global _main _main: header: push rbp mov rbp, rsp mov rdi, 0 __init_stack: push 0 add rdi, 1 cmp rdi, 5 jb __init_stack mov rdi, 0 body: mov rdx, rbp sub rdx, 8 add byte ptr [rdx], 5 mov rdx, rbp sub rdx, 8 cmp byte ptr [rdx], 0 je __loop_end_0 __loop_start_0: mov rdx, rbp sub rdx, 16 add byte ptr [rdx], 13 mov rdx, rbp sub rdx, 8 add byte ptr [rdx], -1 mov rdx, rbp sub rdx, 8 cmp byte ptr [rdx], 0 jne __loop_start_0 __loop_end_0: mov rax, 0x2000004 mov rdi, 1 mov rsi, rbp sub rsi, 16 mov rdx, 1 syscall mov rdx, rbp sub rdx, 16 add byte ptr [rdx], 1 mov rax, 0x2000004 mov rdi, 1 mov rsi, rbp sub rsi, 16 mov rdx, 1 syscall mov rdx, rbp sub rdx, 16 add byte ptr [rdx], 1 mov rax, 0x2000004 mov rdi, 1 mov rsi, rbp sub rsi, 16 mov rdx, 1 syscall mov rdx, rbp sub rdx, 24 add byte ptr [rdx], 2 mov rdx, rbp sub rdx, 24 cmp byte ptr [rdx], 0 je __loop_end_1 __loop_start_1: mov rdx, rbp sub rdx, 32 add byte ptr [rdx], 5 mov rdx, rbp sub rdx, 24 add byte ptr [rdx], -1 mov rdx, rbp sub rdx, 24 cmp byte ptr [rdx], 0 jne __loop_start_1 __loop_end_1: mov rax, 0x2000004 mov rdi, 1 mov rsi, rbp sub rsi, 32 mov rdx, 1 syscall mov rdx, rbp sub rdx, 40 movzx rax, byte ptr [rdx] footer: mov rsp, rbp pop rbp ret
冗長な部分が多いので時間が空いた時に直していきたい…!
ちなみに上のコードの出力は…
ABC
こんな感じ。
本家と違うところ
- >\<+_[]., 以外の入力は全てエラーになる
- 最終的なポインタの指す値がそのまま返り値になる
今後やっていくこと
まとめ
Cコンパイラ入門で少しずつ学んでいることが1つ実った形になってとても嬉しい!!!
簡単な命令の復習、システムコールの確認も出来たのでとても良かった!!終わり!!!
ソースコード
Githubにあります。
本名・学校バレがあるのでこの記事には貼りませんれません。Publicにはなっているので探してください…。
サーバ設定コマンド集 (メモ用)
新しく設定し直したのでその備忘録みたいな感じで…
言語設定
> localectl set-locale LANG=eu_US.utf8 > source /etc/locale.conf
Python3
> sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm > sudo yum install -y python36u python36u-libs python36u-devel python36u-pip > sudo ln -s /usr/bin/python3.6 /usr/bin/python3 > sudo ln -s /usr/bin/pip3.6 /usr/bin/pip3 > sudo pip3 install --upgrade pip > sudo pip3 install falcon gunicorn flask flask_socketio flask_bootstrap requests python-dateutil pycrypto six pdfminer.six numpy bcrypt markdown2 docker gevent pymysql twitter
Golang
> sudo yum install -y epel-release > sudo yum install -y golang
Nginx
> sudo yum install -y nginx > sudo systemctl enable nginx > sudo systemctl start nginx
Docker
> sudo yum install -y yum-utils device-mapper-persistent-data lvm2 > sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo > sudo yum install -y docker-ce docker-ce-cli containerd.io > sudo systemctl enable docker > sudo sysmtectl start docker
zsh
> sudo yum install -y zsh > sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zplugin/master/doc/install.sh)"
MySQL
> sudo yum remove mariadb-libs > sudo rm -rf /var/lib/mysql > sudo yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm > sudo yum -y install mysql-community-server > sudo sytemctl enable mysqld.service > sudo systemctl start mysqld.service > sudo cat /var/log/mysqld.log > mysql_secure_installation
sslh
> sudo yum install -y sslh > sudo vim /etc/sslh.cfg > sudo systemctl enable sslh > sudo systemctl start sslh > sudo vim /etc/ssh/sshd_config > sudo systemctl restart sshd
gcc
以下サイトを参考にさせていただきました。
ポート解放
> sudo firewall-cmd --add-port=80/tcp --zone=public --permanent > sudo firewall-cmd --add-port=443/tcp --zone=public --permanent > sudo firewall-cmd --reload
Let's Encrypt
> sudo yum install -y certbot
ptrace, fork, pipeの備忘録
概要
「ハロー HelloWorld」P.81で ptrace
を用いた独自トレーサを作成した際に色々詰まったところがあったので備忘録として書き留めておく
独自トレーサ
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/user.h> int main(int argc, char *argv[], char *envp[]){ int pid, status, size, fildes[2]; fd_set fds; struct timeval t; char buf[64]; struct user_regs_struct regs; // パイプを生成する // fildes[0] : 読み出し, fildes[1] : 書き込み pipe(fildes); // プロセス生成 pid = fork(); // pid == 0 -> 子プロセス if(pid == 0){ close(1); // 標準出力にパイプを割り当てる dup2(fildes[1], 1); // パイプを閉じる close(fildes[0]); close(fildes[1]); // TRACEMEリクエスト ptrace(PTRACE_TRACEME, 0, NULL, NULL); // 引数のコマンドを実行 execve(argv[1], argv + 1, envp); } // 親プロセス while(1){ // 子プロセスのBreak待ち waitpid(pid, &status, 0); // 子プロセスが正常終了したら if(WIFEXITED(status)){ break; } // ファイルディスクリプタ(FD)集合の初期化 -> fildes[0] を監視対象に FD_ZERO(&fds); FD_SET(fildes[0], &fds); // タイムアウト設定(0 = すぐに復帰) t.tv_sec = t.tv_usec = 0; // FD監視 select(fildes[0] + 1, &fds, NULL, NULL, &t); // 利用可能(読み込みが出来る)なFDが存在する if(FD_ISSET(fildes[0], &fds)){ // 子プロセスの出力読み込み size = read(fildes[0], buf, sizeof(buf)); buf[size] = '\0'; // レジスタ取得 -> 出力 -> トレース終了 ptrace(PTRACE_GETREGS, pid, NULL, ®s); fprintf(stderr, "WROTE : EIP = %08x %s\n", (int)regs.eip, buf); ptrace(PTRACE_CONT, pid, NULL, SIGABRT); ptrace(PTRACE_DETACH, pid, NULL, NULL); break; } // 子プロセスを1ステップ実行 ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL); } return 0; }
しつこいくらいにコメントを書いた。動作イメージは多分こんな感じ…だと思う。
詰まったところ
fork
プロセスを新しく生成することは分かるが、どんな動きをするのか捉える事ができなかった。
結果
- forkした時点での親プロセスのコピーが新しく動き始める感じ。
- 子プロセスで
execve
などを使って新しくコマンドを実行することができる。
fd_set
単純に知らなかった…。
結果
- いくつかのファイルディスクリプタ(FD)を監視してくれる。
- selectでFDに何かしらの動きがあるまで待機する事ができる。タイムアウト する時間を設定可能。0を指定する事ですぐに戻ってきてくれる。
- FD_ISSETを使って読み込み可能 or 書き込み可能なFDがあるか調べる事ができる。
まとめ
勉強します…。