セキュリティ・キャンプ全国大会2019に参加した
タイトルの通りなのですが、セキュリティ・キャンプ全国大会2019を修了したのでその参加記的なのを書いていきます。 前に応募用紙晒しをしたときにも書きましたが私はYトラックのOS開発ゼミのフルスクラッチOSを書こう!というテーマで参加しました。 集中開発コースなのでずっとOSを開発してたわけですが、OSの機能など細かい解説は復習も兼ねてじっくりとやっていきたいので追々scrapboxのほうにまとめていきます。この記事は開発日誌的なものだと思っていただければ良いと思います。
1日目
1日目は顔合わせの日なので開発はしませんでしたが、特別講演やLT大会、それとグループワークがありました。 余談ですが、実はこの日お昼くらいから偏頭痛をこじらせていて、ずっと痛い頭を抱えていたので何があったのかよく覚えていません。悲しい。こんなことにならないようにキャンプ前日はちゃんと休みましょう。
2日目
2日目は開発時間が一番長い日でした。
午前中はuchan先生つきっきりでOSのデバッグをしていました。
uchan先生つきっきりでデバッグしてもらってて心強い
— Δyuk! (@heppoko_yuki) August 14, 2019
バグ消えろーバグ消えろーって念じてる
— Δyuk! (@heppoko_yuki) August 14, 2019
バグの内容は割り込みハンドラの設定後、割り込みがあると再起動してしまうというものでした。再起動の直接的原因はトリプルフォルトというもので、x86の場合ダブルフォルトまでであればダブルフォルト例外を発行しますが、トリプルフォルトの場合は再起動します。おそらく目的の割り込みハンドラだけでなく、例外ハンドラも正しく設定できていないためトリプルフォルトとなっているのだろうと検討をつけ、まずはIDTを設定するコードにバグがないか静的解析を試みました。しかし問題がなさそうに見えたので、今度はsidt命令を使って登録したIDTRやディスクリプタが正しいか確認したところ、ディスクリプタに登録したハンドラ関数のアドレスが正しくないことが判明。実はこの事象、数日前に同じくOS開発ゼミに参加していた突撃隊さんも遭遇していたものを踏んでいたことがわかったのです。結論としてはコンパイルオプションに-fno-picをつければ解決するということだったのですが、もっと詳しく知りたいという方はこちらをご覧ください。
プロトタイプ宣言だけのundefinedな関数について,関数のアドレスを取ろうとしたとき,gccはなぜか知らないがそのアドレスが指すメモリ領域から8バイト読み出すような命令を吐いてしまうというのが問題の本質でした。
— 社会人でもOSを作りたい (@uchan_nos) July 30, 2019
バグが取れてうれしい私↓
バグとれた!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
— Δyuk! (@heppoko_yuki) August 14, 2019
やった!!!!!1
— Δyuk! (@heppoko_yuki) August 14, 2019
dsdhふぃsでぃふはsどいふyhさぢおlh
— Δyuk! (@heppoko_yuki) August 14, 2019
やったああああああああ
— Δyuk! (@heppoko_yuki) August 14, 2019
例外ハンドラが正しく登録出来たことでデバッグもしやすくなりました↓
零除算をするな💩💩 pic.twitter.com/IzMT4WPxbt
— Δyuk! (@heppoko_yuki) August 14, 2019
そして午後からはメモリ管理をしてみようと思い勉強や実装を始めました。メモリ管理をするためには、メモリマップを知らなければなりません。メモリマップはUEFIのBoot ServicesのgetMemoryMap()によって取得できます。
上記の通りメモリマップを取得するプログラムを書いていたのですが、ここで「配列の先頭アドレスのアドレス」を渡さなければいけない箇所を誤って「配列の先頭アドレス」を渡してしまっていたが為に、次の日の午前まで時間を溶かしてしまいました。
3日目
この日は寝坊して、IPAの方と看護師さんが起こしにきました。本当に申し訳ないです。
寝坊
— Δyuk! (@heppoko_yuki) August 14, 2019
起床技術者試験に落ちた後、朝食抜きで始まった開発ですが午前中は先程言ったバグのデバッグをチューターのPG_MANAさんとやっていました。C言語はもう少し人間に優しくなってほしいです。
C言語くそ
— Δyuk! (@heppoko_yuki) August 15, 2019
同じくOS開発ゼミに参加していて、Rustで組み込みOSを自作していたikubakuさんからこんなこんなお言葉を頂きました↓
Rust使いましょう
— ikubaku (@ikubaku10) August 15, 2019
取得できたメモリマップ↓
メモリアロケータ書くよ!! pic.twitter.com/KG0GXv77hP
— Δyuk! (@heppoko_yuki) August 15, 2019
午後は取得できたメモリマップをもとにメモリ管理を実装していくのですが、ページングを利用しているOSではまずページ単位でメモリの割当をするページフレームアロケーターを使い、その中でmalloc()などが細かくメモリの割当をするということがほとんどなそうなので私もそれにならうことにしました。
せっかくページフレームアロケーターを実装するのであればページテーブルの設定も出来たほうがいいと思い、PG_MANAさんに教えてもらいながらページテーブルの設定をしました。
この日の開発は夕食前までで、夕食後は企業紹介やグループワークがありました。
4日目
4日目はしっかり6:30に起床し朝食にありつくことができました。
起床学Ph.D pic.twitter.com/KuNKE3wJ1K
— Δyuk! (@heppoko_yuki) August 15, 2019
そして午前は3日目に設定したページテーブルに合わせて空き領域を4KiBにアラインメントしページフレームのブロックを作りました。
ページフレームはつくれたのであとは配るだけー pic.twitter.com/lIH3LrkWNA
— Δyuk! (@heppoko_yuki) August 16, 2019
また、簡単な実装ではありますがページフレームアロケーターも午前中にできました。
ページフレームアロケーターできた!!! pic.twitter.com/Gq8ee5ti2t
— Δyuk! (@heppoko_yuki) August 16, 2019
Yトラックでは昼食後に成果発表会を行うことになっていたので、午後はその準備をしました。 発表時間は一人2分ととても少なく、あまりいい発表が出来ずお見苦しいところをお見せしてしまいました。
発表会が終わってから夕食まではとりあえず今まで実装してきた機能がすべてちゃんと動作するか確かめてみようと思い、コメントアウトしていた関数をすべてもとに戻し動作確認してみたところ、シリアル通信がqemuでは動くものの実機では正しく動いていないことがわかりそのデバッグをしました。
しかし原因はよく分からずそのまま夕食、企業紹介、グループワークへ。
シリアル通信の設定が悪いのかなと思い、シリアル通信に詳しそうな坂井弘亮師匠に見てもらったところ、コンパイラの最適化でシリアル通信の送信が可能かどうか判断する関数の呼び出しが、1回しか行われていない(ソースコード上ではbusy loopで呼び出してる)のではないかというアドバイスを頂きました。
そこでコンパイルオプションに-O0を追加し動かしてみたのですがこれでもまだ動かず。 講師のuchan先生にも見てもらい、最終的に原因はアセンブリで定義していたinb()関数が間違っていたことであることがわかりました。悲しい。
5日目
5日目は最終日です。他のトラックも含めた成果発表を聞きました。 井上root取っ太郎が面白かったです。
これがね、最終日の偉い人がたくさんいる成果報告会で「ドーン😎」って感じでね!w https://t.co/KfP6MCd9rF pic.twitter.com/717y258GQ0
— 黒林檎 (@r00tapple) August 19, 2019
全体を通しての感想
色んな人が自分のOSのデバッグを手伝ってくれるのが本当に心強いなと思いました。こんな機会なかなかないです。
今までは30日OS自作本やブログ記事、同人誌を見て写してただ動作を確認してみるということが多かったのですが、キャンプではオリジナルなコードもたくさん生やせてやっと自分でOSを作るということがわかった気がします。
5日間お疲れ様でした。
「セキュリティ・キャンプ 全国大会 2019」「セキュリティ・ネクストキャンプ 2019」の全ての日程が無事に終了しました。また来年もよろしくお願いいたします! #seccamp pic.twitter.com/q4ymhy8D6Y
— セキュリティ・キャンプ (@security_camp) 2019年8月17日
6日目?
— Δyuk! (@heppoko_yuki) August 18, 2019
7日目??
これは雲海を眺め飲む焙じ茶 pic.twitter.com/EkWtBfkTnx
— Δyuk! (@heppoko_yuki) August 19, 2019
セキュリティ・キャンプ全国大会2019へ参加することになった(応募用紙晒し)
中間試験が一段落したので少し出遅れた感はあるけれど、この記事を書いています。
題名のとおりセキュリティ・キャンプ全国大会2019のシステムプログラミングトラックOS開発ゼミに参加することになったので、恒例の応募用紙晒しをしてみようと思います。 ちなみにセキュキャンに応募するのは今回が2回目です。実はリバースエンジニアリングゼミにも興味があってそちらの応募用紙も完成させてはいたのですが、最終的にOS開発ゼミのほうで提出することにしました。
あらためて自分の応募用紙を見直してみると結構はずかしいです。そういえば書いている最中も自分の文章にあまり自信がもてなくて何回も消したり書いたりしてたなあなんて思いだしました。
以下で掲載している応募用課題はこちらで公開されています https://www.ipa.go.jp/files/000073173.txt
セキュリティ・キャンプ全国大会2019のホームページはこちら https://www.ipa.go.jp/jinzai/camp/2019/zenkoku2019_index.html
応募用紙
- 共通問題A
我々講師は、普段いくつかのOSを使っていますが、使い込むうちに色々な発見をします。 皆さんもきっとそういう体験があると思います。 あなたが普段使っているOSで、好きな機能と改善してほしい部分について、思いのたけを聞かせてください。 この問では、皆さんが普段どの程度興味を持って既存OSを観察しているかを評価します。
私が使っているOSで好きな部分は、OSのソースコードが大変に簡潔に記述されていること、そして余計な機能を一切入れないこと、またそれらによってOSに存在する脆弱性を限りなく少なくすることを目的にしていることです。 このOSのソースコードは本当にびっくりするくらいにきれいです。私はOSというものにそこまで深く触れたことがなく、C言語やC++でのプログラミングを少ししたことがある程度なのですが、それでも他のOSのソースコードを読もうとしたときより「これは楽に読めるぞ」と感じたのでトリッキーなコードが少なく素直なのだと思います。また、余計な機能を一切入れないこともコードの単純化に寄与しています。普段ほとんどの人が使わないような機能のためにOSの開発がより困難なものになってしまうのは私は良くないと思います。このようにOSの構造を簡潔に、わかりやすくすることで見通しを良くすることに私はとても共感しています。 しかし、これらは決していいことづくしというわけではありません。このOSはソースコードの単純さや余計な機能を一切入れないことによってパフォーマンスを犠牲にしています。ハードウェアの性能向上を待てばパフォーマンスは良くなると思いますが、ハードウェアの性能向上にそこまで期待していいのかという問題もありますから、なかなか難しい問題だなと思います。
- 共通問題B
皆さんが仮にOSを作るとしたら、「どんなOS(やOSの機能)を作ってみたい」でしょうか? (既にOSを作った事がある人は、その特徴を書いてくれても構いません。) そして、なぜそれを作ってみたいと思ったのでしょうか? 皆さんが心の中で夢描いているであろう、ワクワクするようなOS像を教えてください。 ※「Linux開発者を目指そう!」テーマを受講したいと思っている方は「どんなLinuxカーネルの機能を作ってみたいか」を答えてください。 ※「Raspberry Pi向け組み込みOSを作ろう!」テーマを受講したいと思っている方は「どんな組み込みシステムを作ってみたいか」を答えてください。
Linuxでは現在Linux向けにコンパイルされたプログラムしか実行することができなかったと思いますが、他のOS向けにコンパイルされたプログラムを動かすことができるバイナリエミュレーションの機能をつくってみたいです。 動機としては、この機能が特別ほしいなと思ったというわけではなく、単に実装してみたいなと思ったからです。私は数多くあるOSの機能のうちユーザーアプリケーションを実行する機能が好きです。もともと私がOSに興味をもったきっかけが、自分の書いたプログラムがどのように動いているのか知りたかったことにあるのが影響しているのかもしれません。ユーザープログラムを実行するに際してはいろんなOSでいろんな工夫がされているなと思います。例えば、LinuxにはVDSOというものがありますが、これはシステムコールはkernel側で処理されるものだという常識を覆すおもしろい発明だなと思います。
- 共通問題C
C言語で双方向リンクリストとそれを操作する関数を作り、ソースコードを提出してください。 リンクリストを生成する関数、要素を任意の場所に挿入する関数、全ての要素を順に標準出力に印字する関数、の3つがあれば十分です。 やる気があればもっとたくさんの機能を実装しても構いません!
#include <stdio.h> #include <stdlib.h> int init(void); void end(void); struct node * search_tail(void); int insert_tail(int value); void delete_tail(void); int insert_index(int value, unsigned int index); void print_list(void); struct node { int value; struct node *next; struct node *prev; }; struct node *head; int init(void) { head = malloc(sizeof(struct node)); if(head == NULL) return -1; head->value = 0; head->next = NULL; head->prev = NULL; return 0; } void end(void) { struct node *tail = search_tail(); while(tail != head) { delete_tail(); tail = search_tail(); } free(head); return; } struct node * search_tail(void) { struct node *search = head; while(1) { if(search->next == NULL) return search; search = search->next; } } int insert_tail(int value) { struct node *ins; struct node *tail = search_tail(); ins = malloc(sizeof(struct node)); if(ins == NULL) return -1; ins->value = value; ins->next = NULL; ins->prev = tail; tail->next = ins; return 0; } void delete_tail(void) { struct node *tail = search_tail(); if(tail == head) return; tail->prev->next = NULL; free(tail); return; } int insert_index(int value, unsigned int index) { unsigned int counter = 0; struct node *current = head; struct node *ins; ins = malloc(sizeof(struct node)); if(ins == NULL) return -1; if(index < 0) return -1; while(counter < index) { if(current == NULL) return -1; current = head->next; counter++; } if(current == NULL) return -1; ins->value = value; ins->prev = current; ins->next = current->next; current->next = ins; return 0; } void print_list(void) { struct node *current = head->next; while(current != NULL) { printf("%d\n", current->value); current = current->next; } return; } int main(int argc, char *argv[]) { if(init() < 0) return -1; if(insert_index(5, 0) < 0) puts("error"); if(insert_tail(6) < 0) puts("error"); if(insert_index(3, 1) < 0) puts("error"); print_list(); end(); return 0; }
設計・実装で工夫した点を述べてください。
整数型の符号の有無や関数の引数などを最小限に抑え、簡潔な実装を心がけました。また、メモリリークなどのバグがないようエラーチェックをしっかりと行ったつもりです。
- 選択問題S3
Linuxカーネルについて知りたいこと、それについてこれまで調べたこと、 つまづいたことを教えてください。最終的に解決しなかったとしてもOKです。 技術力が優れているかではなく、どれだけ試行錯誤したかという観点で採点をします。 「この機能のこのコードの意味がわからなかった」という高度なものでもいいですし、 「そもそも何から手を付けていいのかもわからなかった」というものでも構いません。
共通課題でも述べたのですが、私はプログラムを実行する仕組みに興味があるのでそれに関連するコードを少しだけ読んだことがあります。そこで不思議に思ったことなのですが、linuxのローダーの実装はfsというディレクトリの下に配置されています。fsというのはおそらくfilesystemのことをさしているのだと思いますが、自分にはこの理由がよくわかりませんでしたし、調べてもこれについて述べているものは探した限りなかったです。また、実際にLinuxにコントリビュートするとして、どういう機能を実装するかというアイデアをどうやって思いつくのか知りたいです。Linuxは多くの優秀な人がコントリビュートしていると思いますが、そのなかで必要とされる実装をどうやって生み出すのか私には全然分かりません。
- 共通問題D
その他、書ききれなかったことを好きなだけ書いてください。
いままで自分一人では解決できなかった疑問をこの機会にぜひ解消していきたいです。そして、自分もLinuxや他のOSも含め貢献出来るような人になれるように努めていきたいです。
Emacsの設定@Gentoo&X11
春休みで時間があるので環境づくりに勤しんでおります。 今回は、前から気になっていたEmacsをインストールしたのでその設定方法を備忘録として残しておきます。
一番苦労したのはGUIのフォントの設定でした。ですから、まずはフォントの設定について述べておこうと思います。
フォントの設定@GUI
まず、Emacsのインストールですが「xft」のコンパイルオプションをpackage.useで有効にしておきます。
app-editors/emacs xft
次に~/.Xresourcesを以下のように編集します。
Xft.antialias: true
最後に、~/.emacs.d/init.elに以下の文字列を追加します。
(cond ((display-graphic-p) (set-default-font "{FontName}") (set-fontset-font (frame-parameter nil 'font) 'japanese-jisx0208 '("{FontName}" . "unicode-bmp")) ) (t 0))
これで、GUIのEmacsのフォントがいい感じになって幸せです。
package.elの設定
~/.emacs.d/init.elに以下を追加。
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/")) (add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages/")) (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/"))
Mozcインストール
M-x package-list-packages mozc i x
~/.emacs.d/init.elに以下を追加。
(require 'mozc) (set-language-environment "Japanese") (setq default-input-mothod "japanese-mozc") (prefer-coding-system 'utf-8) (global-set-key (kbd "C-j") 'toggle-input-method)
mewインストール
SMTP: STARTTLS, IMAP: STARTTLSで設定。
stunnelをコンパイルしておきます。
~/.emacs.d/init.elに以下を追加。
(autoload 'mew "mew" nil t) (autoload 'mew-send "mew" nil t) (setq read-mail-command 'mew) ;; Optional setup (e.g. C-xm for sending a message): (autoload 'mew-user-agent-compose "mew" nil t) (if (boundp 'mail-user-agent) (setq mail-user-agent 'mew-user-agent)) (if (fboundp 'define-mail-user-agent) (define-mail-user-agent 'mew-user-agent 'mew-user-agent-compose 'mew-draft-send-message 'mew-draft-kill 'mew-send-hook)) (setq mew-prog-ssl "/usr/bin/stunnel") (setq mew-name "{Name}") (setq mew-user "{Name}") (setq mew-mail-domain "{Domain}") (setq mew-smtp-user "{Name}") (setq mew-smtp-server "{Domain}") (setq mew-smtp-auth t) (setq mew-smtp-ssl t) (setq mew-smtp-port {Port}) (setq mew-smtp-ssl-port mew-smtp-port) (setq mew-proto "%") (setq mew-imap-user "{Name}") (setq mew-imap-server "{Domain}") (setq mew-imap-auth t) (setq mew-imap-ssl t) (setq mew-imap-port {Port}) (setq mew-imap-ssl-port mew-imap-port) (setq mew-use-cached-passwd t) (setq mew-ssl-verify-level 0)
以上。
Gentoo Linuxを使い始めた
TL;DR
前々からsystemdから抜け出したいなーという気持ちがあったので、initシステムを含め随所で選択の自由が与えられているLinuxディストリビューション、Gentoo Linuxを使い始めました。 この記事は、Firefoxのコンパイル中に暇だから書こうと思い立ち、とりあえずインストール手順をまとめてみたポエムです。
さてインストールですが、基本はwikiに忠実にやっていけば大丈夫です。とても親切にわかりやすくまとめられているなと感動しました。
以下、自分で選択する必要があったところについて簡単に書いていきます。
インストール環境
- PC: Thihkpad yoga 260
- CPU: Intel core i7-6500U
- Memory: 8GB DDR4
- Storage: 256GiB SSD
- NIC(WiFi): Intel 8260
手順
Live Mediaを用意し、起動する
自分はminimalのやつをUSB Memoryに書き込みました。起動するとおなじみのgrubが出てくるので適当に選んで進みます。
インストールの準備をする
- ネットワーク
自分のPCにはRJ45がささらない(かつUSBtoRJ45を持ってなかった)のでWiFiでインストールしました。 Live環境にはもとからwpa_supplicantが入っているのでこれでよしなに繋いでdhcpcdでip addressを貰えばいい感じです。
% ifconfig {interface} up % wpa_supplicant -B -i {interface} -c <(wpa_passphrase {SSID} {PASSWORD}) % dhcpcd
- ストレージ
自分のPCのSSDにはすでにOpenBSDとArchLinuxとUbuntuが入っていて一杯だったのでUbuntuの入っているパーティションをmkfs.ext4して使うことにしました。
- 日時
ntpがちゃんと降ってくる恵まれた環境だったのでntpdで時間を合わせました。
- stage tarballのダウンロード&展開
current-stage3-amd64を選択しました。tar.xzの展開方法が分からなかったので調べました。
- make.conf
CFLAGSに-march=nativeを足して、MAKEOPTSに-j3を指定しました。
- mirror serverの選択
北陸先端科学技術大学院大学にお世話になります。
- DNS情報のコピー
これ最初忘れてて、あれ?インターネットにつながらないぞ!!を20分くらいやってました。
あとは適当にマウントしてchrootすればベース環境に入れます。
ベース環境の整備
よくわからないのでwikiに従って適当にやりました。eselectでprofileを選ぶところ、変にgnomeとかついているやつを選んでしまったので@worldの更新に3時間くらい取られました。まいった。
カーネルビルド
Gentooの象徴とも言えるカーネルビルドのお時間です。 まともに使えるLinuxカーネルのビルドはいままでに一度もやったことがなかったので結構苦戦しました。 とりあえず大事なのは、使うファイルシステムのドライバとUSBドライバをちゃんと選択しておくことです。これだけクリアしてればあとから何度でもやり直しできます。
自分がいじった設定としては、MMCとSCSI周りとUSBのNetworking Frameworkの有効化、それとNICのドライバをカーネルに含めてしまう設定くらいのものです。
今後いじってみて足りない機能は追加してみます。
設定が終わったらmakeしてカーネルモジュールとbzimageのインストールをして終わりです。このとき、/bootをマウントするのをお忘れなく。
fstab
必要に応じて書きます。最低限、/と/bootがあれば良さそう。
Hostname
かっこいい名前をつけましょう。モテるための秘訣です。
あとはwiki通りにやってumountして、grubのコンフィグをいじるとブートできます。 ブートしたあとはx11とwmを入れてstartxすると幸せになれます。
InterKosenCTF Writeup [初のイベント型CTFに参戦]
学校の先輩に誘われて、初めてリアルタイムで開催されているCTFに参加してみました(といっても、ksnctfのVillager Aくらいしか解いたことがないので実質CTF処女です)。 3日間の開催でしたが、1日目は早々にして寝落ちしたため、3日目はアマチュア無線の試験を受けに行っていたため取り組めたのは1日だけでした。その1日は先輩と一緒に新宿のルノアールで一日中CTFをやっていました(ルノアールさん長居してごめんなさい)。
webとかcryptoとかはそもそも全く見たこともなかったので解法の検討が全くつきませんでした。なので先輩に任せっきりでした(ごめんなさい)。私が唯一行けそうだなーと思ったのはreversingとpwnだけだったので基本的にその2つだけに集中して取り組みました。 それで、結局解けたのはreversingの100pt問題、「flag generator」だけでした。他の人の参考に、というよりかは解いただけで放置してしまうのはもったいない気がするのでこうして記録しておこうと思った次第です。
問題で渡されたのはx86_64 Linux向けのELFバイナリでした。 実行しても何も表示されず... とりあえず逆アセンブルして読んで見る。
0000000000401152 <r>: 401152: 55 push rbp 401153: 48 89 e5 mov rbp,rsp 401156: 8b 05 f0 2e 00 00 mov eax,DWORD PTR [rip+0x2ef0] # 40404c <s> 40115c: 69 c0 6d 4e c6 41 imul eax,eax,0x41c64e6d 401162: 05 39 30 00 00 add eax,0x3039 401167: 25 ff ff ff 7f and eax,0x7fffffff 40116c: 89 05 da 2e 00 00 mov DWORD PTR [rip+0x2eda],eax # 40404c <s> 401172: 8b 05 d4 2e 00 00 mov eax,DWORD PTR [rip+0x2ed4] # 40404c <s> 401178: 5d pop rbp 401179: c3 ret 000000000040117a <main>: 40117a: 55 push rbp 40117b: 48 89 e5 mov rbp,rsp 40117e: 48 83 ec 50 sub rsp,0x50 401182: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28 401189: 00 00 40118b: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax 40118f: 31 c0 xor eax,eax 401191: c7 45 d0 35 59 8f 60 mov DWORD PTR [rbp-0x30],0x608f5935 401198: c7 45 d4 91 64 50 57 mov DWORD PTR [rbp-0x2c],0x57506491 40119f: c7 45 d8 57 55 36 27 mov DWORD PTR [rbp-0x28],0x27365557 4011a6: c7 45 dc a1 de e3 54 mov DWORD PTR [rbp-0x24],0x54e3dea1 4011ad: c7 45 e0 d5 4e 5a 75 mov DWORD PTR [rbp-0x20],0x755a4ed5 4011b4: c7 45 e4 b7 2e f4 17 mov DWORD PTR [rbp-0x1c],0x17f42eb7 4011bb: c7 45 e8 59 90 4f 4a mov DWORD PTR [rbp-0x18],0x4a4f9059 4011c2: c7 45 ec 27 e8 08 1a mov DWORD PTR [rbp-0x14],0x1a08e827 4011c9: c7 45 f0 1f 39 9d 0d mov DWORD PTR [rbp-0x10],0xd9d391f 4011d0: c7 45 f4 aa 33 e5 59 mov DWORD PTR [rbp-0xc],0x59e533aa 4011d7: c7 45 c8 7e 16 dc 25 mov DWORD PTR [rbp-0x38],0x25dc167e 4011de: c7 45 cc 0a 00 00 00 mov DWORD PTR [rbp-0x34],0xa 4011e5: c7 45 c0 00 00 00 00 mov DWORD PTR [rbp-0x40],0x0 4011ec: c7 45 c4 00 00 00 00 mov DWORD PTR [rbp-0x3c],0x0 4011f3: c7 45 bc 00 00 00 00 mov DWORD PTR [rbp-0x44],0x0 4011fa: 83 7d c4 00 cmp DWORD PTR [rbp-0x3c],0x0 4011fe: 75 10 jne 401210 <main+0x96> 401200: bf 00 00 00 00 mov edi,0x0 401205: e8 46 fe ff ff call 401050 <time@plt> 40120a: 89 05 3c 2e 00 00 mov DWORD PTR [rip+0x2e3c],eax # 40404c <s> 401210: b8 00 00 00 00 mov eax,0x0 401215: e8 38 ff ff ff call 401152 <r> 40121a: 89 45 bc mov DWORD PTR [rbp-0x44],eax 40121d: 8b 45 bc mov eax,DWORD PTR [rbp-0x44] 401220: 39 45 c8 cmp DWORD PTR [rbp-0x38],eax 401223: 75 07 jne 40122c <main+0xb2> 401225: c7 45 c4 01 00 00 00 mov DWORD PTR [rbp-0x3c],0x1 40122c: 83 7d c4 00 cmp DWORD PTR [rbp-0x3c],0x0 401230: 74 35 je 401267 <main+0xed> 401232: 8b 45 c0 mov eax,DWORD PTR [rbp-0x40] 401235: 48 98 cdqe 401237: 8b 54 85 d0 mov edx,DWORD PTR [rbp+rax*4-0x30] 40123b: 8b 45 bc mov eax,DWORD PTR [rbp-0x44] 40123e: 31 d0 xor eax,edx 401240: 89 45 bc mov DWORD PTR [rbp-0x44],eax 401243: 48 8d 45 bc lea rax,[rbp-0x44] 401247: 48 89 c6 mov rsi,rax 40124a: 48 8d 3d b3 0d 00 00 lea rdi,[rip+0xdb3] # 402004 <_IO_stdin_used+0x4> 401251: b8 00 00 00 00 mov eax,0x0 401256: e8 e5 fd ff ff call 401040 <printf@plt> 40125b: 83 45 c0 01 add DWORD PTR [rbp-0x40],0x1 40125f: 8b 45 c0 mov eax,DWORD PTR [rbp-0x40] 401262: 3b 45 cc cmp eax,DWORD PTR [rbp-0x34] 401265: 74 0c je 401273 <main+0xf9> 401267: bf 01 00 00 00 mov edi,0x1 40126c: e8 ef fd ff ff call 401060 <sleep@plt> 401271: eb 87 jmp 4011fa <main+0x80> 401273: 90 nop 401274: b8 00 00 00 00 mov eax,0x0 401279: 48 8b 4d f8 mov rcx,QWORD PTR [rbp-0x8] 40127d: 64 48 33 0c 25 28 00 xor rcx,QWORD PTR fs:0x28 401284: 00 00 401286: 74 05 je 40128d <main+0x113> 401288: e8 a3 fd ff ff call 401030 <__stack_chk_fail@plt> 40128d: c9 leave 40128e: c3 ret 40128f: 90 nop
適当にジャンプ命令をnopで埋めてみたりしていたら、何やらよくわからない文字が出力されました。 この文字は一体どこからきているのだろうとアセンブラを見てみると 40121aでr()の返り値がDWORD PTR [rbp-0x44]に代入されてそれを元に演算した結果が出力されていると分かりました。 なのでDWORD PTR [rbp-0x44]が正しい文字になるようにしてあげればよいのです。
じゃあ正しい文字になるような値ってなんだよとまたアセンブラを見直してみると最初にnopで埋めていたジャンプ命令の前にcmp DWORD PTR [rbp-0x38],eaxというのがあったのでここからDWORD PTR [rbp-0x38]がその値であると分かりました。
それでこの値をDWORD PTR [rbp-0x44]に入れてstep実行してみると「KOSE」という文字が出力されたのでよっしゃと思い続く処理もステップ実行してみたのですが、その後の文字はうまくASCIIにはなっていませんでした。
それでなにがいけないのかともう一度見直して、そもそもこのr()の返り値は40404cを元に計算されていることを発見し、またこの40404cはループ毎に変化する値であることが分かりました。それで、じゃあ最初のr()を実行し終わった後だけ手動で40404cとDWORD PTR [rbp-0x44]にDWORD PTR [rbp-0x38]の値をいれてステップ実行してみると次のような出力を得られました。
0x45534f4b 0x14654434e 0x25f53497b 0x353494854 0x44145525f 0x55f594c4c 0x645525f41 0x753524556 0x83f474e49 0x90000007d
最後の7dは「}」なので、これはFLAGだ!と思いどうにかこねくり回してFLAGにするのだと思い眺めてみると、MSBが0から9の値で変化していることに気づきました。これがあるせいでうまく文字に出来なかったのですが、これを除いて文字にしてみると見事FLAGが取得できました。
KOSENCTF{IS_THIS_REALLY_A_REVERSING?}
結局1問しか解けませんでしたが、初めて自力で解けたので結構感動しました。CTF面白いね!運営の皆さんありがとうございました。
Majestouch Convertible 2を買った
この記事はプロコンゼミ(SPC同好会) その1 Advent Calendar 2018の18日目の記事です。 夢の中で宇宙旅行を楽しんでいたら、地球のタイムゾーンをすっかり失念していました。ごめんなさい!!! というか、このアドベントカレンダー担当者はほぼ埋まっていたのに全然投稿されていないですねーなんででしょうか。
本来なら、この記事は高速ナベアツの続きを書く予定だったのですが、忙しくて続きがあまり出来ていないのと他のネタが出来たので、ネタ替えをすることにしました。重ねてごめんなさい!! 高速ナベアツの続きは年度内に書ければなーと思います。
さて、弊部のアドベントカレンダーには他にもキーボードの記事が投稿されていました。
これです。彼いわく、このキーボードはHHKBより良いらしいです。
さて、まあキーボードと言えどもピンキリですよね。高いものは学生には手が出せないくらいの値段しますし、秋葉原で投げ売られているものを買えば100円とか、ひょっとしたらもっと安く手に入るかもしれません。 筆者はしがない三流ソフトウェアエンジニアではあるものの、やはり良いキーボードというものに憧憬を抱くわけです。そこで、今回タイトルの通りMajestouch Convertible 2というキーボードを買ったという次第です。
それで、まずこのMajestouch Convertible 2(以下、MC2と呼ぶ)を買うにあたって重要になるのは軸の色です。 MC2はメカニカルキーボードと呼ばれるキーボードの一つで、キーのひとつひとつが独立したスイッチになっています。 MC2ではこのスイッチにCherry MXというブランドのスイッチを使っています。詳しくは、次のページを見てみてください。
このページを見ると分かるように、キースイッチには幾つか種類がありその種類が軸の色によって決まっています。 筆者は、茶軸を買おうと決めました。
そして、アマゾンで注文して届きました。
— Δyuk!@hepp0k0 (@heppoko_yuki) December 28, 2018
それで、よく見ると赤軸を注文してしまっていました。間違えてしまった。まあ、違いはクリック感だけらしいのでそんなに気にしてません。
この日はちょうど友人とNTTの技術史料館に行く用事があったのでこのキーボードを持ち歩いてみることにしました。もともとキーボードは色々なところに持ち歩いて使おうと思っていたので良い機会です。
— Δyuk!@hepp0k0 (@heppoko_yuki) December 28, 2018
重量は電池を入れると1kgくらいあるので結構重かったです。リュックサックじゃなかったら持っていくのは迷いますね。
それで、打鍵感についてですが、赤軸でもけっこう良かったです。打っていて楽しいです。さっそくAtCoderの問題も解いてみました↓
Enterキーが今まで使っていたキーボードより長くてこのあたりの慣れが必要です。あ、キーボードの写真が未掲載でした。載せます。
こちらが今回買ったMC2のキーボード。
こちらが普段使っているThinkPad Yoga 260の内蔵キーボード。
初めて手にしたノートパソコンのキー配列がUS配列だったので、それからずっとUS配列を使ってます。プログラミングをするときは記号のキーがいいかんじの所にあるので打ちやすいです。
見ての通り、配列自体はほぼ一緒(MC2のCapital LockとControlは入れ替えた)ですが、キートップの表面積が結構違うので前述の通り慣れが必要です。
HHKBは矢印キーが独立して存在していないですが、MC2にはあるので全体長は少し長めです。まあギリギリ持ち運べるサイズです。
あ、あとBluetooth機能もついています。ペアリングも簡単でした。
# systemctl start bluetooth # bluetoothctl [bluetooth]# power on [bluetooth]# agent KeyboardOnly [bluetooth]# default-agent [bluetooth]# pairable on [bluetooth]# scan on [bluetooth]# pair [MAC address] [bluetooth]# trust [MAC address] [bluetooth]# connect [MAC address]
こんな感じだと思います。信頼したデバイスに登録しておくと、次回以降接続時にconnectを実行するだけなので楽です。
他のブログ記事を見ていると、キーの遅延があるだとかそういうレビューもあったのですが今の所僕の環境では起きていないです。bluetoothも好調に使えます。
という感じで、雑多なレビューをしてみました。 もしMC2の購入、あるいはキーボードの購入を検討している人がいたら参考にしていただけると幸いです。
お気に入りのキーボードを買って進捗を爆上げしていきましょう!!!