Pwnableの本をRe:VIEWで作って技術書典7で頒布した

Malleus CTF Pwn

sanya.sweetduet.info

techbookfest.org

自分のためにも色々とメモを残しておこう思っていたけど、1か月以上経ってしまった。 とらのあなにはまだ物理本の在庫が残っているし、電子版はBOOK☆WALKERにあるのでよろしくお願いします。

Pwnableというテーマについて

CTFに参加したことのない人には「なんだそりゃ?」だと思う。 CTFのジャンルの一つ。 C言語C++で書かれたプログラムが問題として与えられて、そのプログラムは出題者のサーバーでも動いている。 プログラムを解析してバッファオーバーフローなどの脆弱性を探し、その脆弱性を攻撃するスクリプトを書いて、出題者のサーバーからフラグの書かれたテキストファイルを奪取するというのが典型的な流れ。 セキュリティのコンテストと聞いてまず想像する形式だと思う。 花形ジャンルなのでたいていは問題数が多いし、解けるとカッコイイ。

しかし、私はpwnableが苦手。 1問も解けなかったり、解けてもチュートリアル的な簡単な問題だけということが多い。

Pwnableは他のジャンルに比べて狭くて深い。 例えば、webの問題で ' を入力したときにエラーになったらその場でSQL Injectionについて調べて解けるかもしれないけれど、pwnableで長い文字列を入力して落ちたからといってそこから何も知らない人が解ききるのはまず無理だと思う。 よっぽど簡単な問題でもない限り、スタックやライブラリのアドレスはランダム化されているし、書き込み可能な領域は実行不可能なので、ROPでlibcのアドレスをリークしてOne-gadget RCEか何かでシェルを取る必要がある。 最近だと system 関数を呼び出すときにスタックが16バイト境界に揃っていないといけないという問題にハマる。 そもそも、問題文にファイルへのリンクとサーバーのアドレス・ポートしか書かれていないことが多いので、このファイルがサーバーで動いているということも分からなそう。 一方、他のジャンルに比べて必要とされる知識は多くない。 一度覚えたテクニックは使い回せるし、何か新しい脆弱性があってそれを知らないと解けないということもない。

ということで、一回ちゃんと勉強すればその後のコンテストで得点源にできるし、ついでにそれを本にしようと考えた。 「お前の勉強ノートを売りつけるのか?」と言われそうだけど、この後のpicoCTFではpwnableの問題は全部解けたし、SECCONの予選で2桁チームしか解いていない問題を解ける程度の実力は付いた。

表紙

サークルカットには頒布する表紙を使い回すのが定番。 申込時に必要なのでまずは表紙用の画像を作らないといけない。 とはいえ、サークルカット無しで受かっているサークルもあるし、抽選にもサークル配置にも使われないなら、実はサークルリストが一般公開されるタイミングに間に合えば良いのか?

と、写真イラストは過去に実績を解除したので、次はCGにしたかった。 ジェネラティブアートに挑戦したかったけれど、難しそうで断念。 写真を元にプログラムで生成した。 遠目で見ると画質が悪いようにしか見えないけれど、近くで見ると良い感じで気に入っている。

紫陽花の写真を撮ります。

f:id:kusano_k:20191115044424j:plain:w400

最近のフォトショップなら人工知能が何とかしてくれるらしいけど、そんなものは無いので、手作業で切り抜きます。

f:id:kusano_k:20191115044709p:plain:w400

ボカしたり色調を調整したりして良い感じにした別の写真を用意します(A)。

f:id:kusano_k:20191115044832j:plain:w400

重ねます(B)。

f:id:kusano_k:20191115044950j:plain:w400

Aに文字を置いていって、Bに近づけます。 ただし、良い感じにランダムさがほしい(背景にもちょっとは文字を置いてほしい)ので、こんな感じのプログラム。

image = A
for c in 文字列:
  font_size = 徐々に小さくする
  # 各サイズで合計面積が同じになるように、小さい文字ほど個数を多くする
  for i in range(64):
    color = ランダム
    x = ランダム
    y = ランダム
    (x, y)に色colorで文字cを試しに置いたときのBとの差分を計算
  最も差分が小さくなるcolor, x, yでimageに実際に文字を置く

実際には、文字の座標や色を出力しておいて、影を付けたりちょっと透明にしたりして生成し直した。

f:id:kusano_k:20191115045859j:plain:w400

ノイズを加えたり、グラデーションを掛けたり、タイトルを書いたりします。

f:id:kusano_k:20191115050118j:plain:w400

原寸大だとこんな感じ。

f:id:kusano_k:20191115050321p:plain

ちなみに、描いている文字はglibcmalloc.cからコメントを取り除き、(文字が多すぎたので)1/8の確率でサンプリングしたもの。 プログラムコードのような雰囲気が出るかもしれない。 各文字の頻度情報しか残っていないはずなので、GPL適用は勘弁してほしい。

問題

単に説明を書いていくよりも、具体的な問題を解いていったほうが面白いし書きやすい。 ということで問題を作ることにした。

github.com

前半の問題はスタック、後半の問題はヒープ、間に書式文字列攻撃を挟んだ。

Pwnableの問題ではサーバーが必須。 しかし、サーバーの管理は面倒だし、後から本を買った人も遊べるようにしようと思うと、いつまでもサーバーを動かし続けないといけない。 Dockerで各自の手元で動かしてもらうことにした。 Dockerの中身を覗けばフラグが得られてしまうけれど、これで何かを競おうというわけでもないので、まあ良いだろう。 この問題と後述のRe:VIEWのビルドで、Dockerを初めてしっかり使ってみたけれど、とても便利。 流行るわけだ。

スコアサーバー(?)はNuxt.jsで静的ファイルを生成。 適当にハッシュ値でも取ってフラグをチェックすれば、クライアント側で処理しても、解析されてフラグが漏れることはない。 サーバーは要らない。

github.com

事前に問題を公開することで、解いた人がツイートとかしてくれて、宣伝になるのではという目論見があった……が、解いてくれる人があまりいなくて目論見は外れ。 Docker Hubのpull数は10くらいだった。 下心が見透かされたか、Dockerとはいえ手元で動かすのは面倒だからサーバーを立てておくべきだったか、そもそもpwnableはハードルが高いのか……。

今までの本は、Markdownで書いてPandocでPDFに変換していた。 今回はRe:VIEWを使うことにした。 技術書典だとRe:VIEWを使っている人が一番多いと思う。 長いものには巻かれろ。

Re:VIEW、荒削りだけれど、独自記法からPDFやepubの変換に特化している分、Pandocに比べて楽。

PandocだとMarkdownを書くだけでは解決できないことがあって、どうしてもLaTeXを書く必要が出てくる。 Re:VIEWならRe:VIEWだけで完結しないかなと期待していたけれど、そんなことはなかった。 LaTeXでちょこちょこ調節する必要があるし、何かにハマったときにRe:VIEWソースコードも読んだ。

Re:VIEWを一から書いたり、環境を構築するのは大変なので、TechBoosterのテンプレートとDockerを使った。

他の選択肢として、Re:VIEW Starterがある。 Re:VIEWに対する不満が解消されていて良さそうではあるけれど、Re:VIEW 3に対応していないのが残念。

技術系同人誌を書く人の味方「Re:VIEW Starter」の紹介 - Qiita

余談だが、この辺とかこの辺とかがだいぶ殺伐としていて良い。 競い合って良い感じになってほしい。

Re:VIEW Templateに書かれているコマンドでDockerでビルドすると、毎回npm installが走って遅いし、npmにも迷惑が掛かりそうなので、

docker run -it -v %CD%:/book --name review vvakame/review:3.2
cd /book
./setup.sh

を最初に実行して、ビルドするときには

docker start review
docker exec review /bin/bash -ci "cd /book && REVIEW_CONFIG_FILE=config.yml npm run pdf"
docker stop review

としていた。 Windowsでカレントディレクトリは%CD%。 Dockerはなぜディレクトリのマッピング相対パスで指定できないのか。

生成したPDFから一部の漢字をコピペすると部首になる問題と、GCCの出力の

fsa_test1.c: In function ‘main’:

このクォーテーションマークのせいで埋め込まれないフォントが使われる問題にハマった。 対応されているので、最新のDockerイメージを使えば大丈夫。 ありがたい。

電子版

今までは紙の本だけだったけれど、PDF版も作ることにした。

Re:VIEW Templateならば、config-ebook.ymlを使えば、トンボが無かったりリンクがクリックできたりするPDFが作れる。 後はPDFの編集ができる有料版のAcrobatで表紙と裏表紙を貼り合わせる。

f:id:kusano_k:20191117044522p:plain

そのままだと開いたときに本文の1ページ目にスクロールしてしまうので、表紙(PDFとしての1ページ目)を「開くページ」に設定。 ついでに、デフォルトのページレイアウトを見開きにした。

PDF版の配布方法。 ダウンロードカードごとにちゃんとパスワードを変えている人もいるけれど、まあ共通パスワードで良いだろう。 パスワードを変えるとダウンロードカードの用意が大変。 PHPか何かでサーバー側のスクリプトを書くなり、HTTPサーバーの設定なりでパスワードを入力してPDFをダウンロードするようにするのは簡単だけど、この先サーバーを移したりすることを考えると、静的ファイルにしておきたい。 PDFは暗号化したZIPに入れて、JavaScriptで復号するようにした。

Malleus CTF Pwn 電子版ダウンロード

問題はスマホで、パスワードを入力してPDFを表示することはできても、保存することができない。 blob://のURLをブラウザから他のアプリに飛ばしても、他のアプリから読めない。 ダウンロードカードにはたいていQRコードが付いていることを考えると、スマホでダウンロードする人も多いのだろうか。 まあ、技術書典に来てこの本を買う人でPCを持っていない人はいないだろう……。

ダウンロードカード。 名刺サイズを良く見るけれど、私がダウンロードカードを買ったときに無くしそうで怖かったので、ポストカードサイズにした。 kinko'sで200枚印刷して1万円掛からないくらい。 郵便番号欄とかが無いものでもいけるのかちょっと心配だったけれど、特に問題は無かった。 本と違ってポストカードなら大量に余っても場所を取らないので、200枚刷ったけど、電子版を買う人はあまりいなかったので、200枚も要らなかったな。 電子版を買う人は技術書典かんたん後払いシステムを使っていることが多いので、システムのダウンロード機能だけで充分だったかもしれない。

ポストカード印刷・DMハガキ印刷・プリント | サービス・料金(価格) | オンデマンド印刷のキンコーズ・ジャパン

Illustratorでデータを作って持っていったら「これ、アウトライン化されてないですね……。まあこちらで何とかしておきましたけど」と言われた。 ごめんなさい。

肝心のパスワードを間違えるという重大ミスをやらかした。 Ctrl+vで貼り付けるときに、Ctrlが抜けたっぽい。 ごめんなさい。

電子書籍

せっかく電子版を作るのだから、技術書典後にオンラインでも売りたい。

定番はBOOTHでPDFを販売。 しかしBOOTHは販売者がBOOTHではなく自分なのがちょっと気になる。 電子書籍も作ってみたい。 AmazonKindle Direct Publishingは料率が低い。 ということで、BOOK☆WALKERにした。 同人に力を入れている感じがあるのも良い。

EPUBという形式で作るらしい。 Re:VIEWは対応している。 PDFのようにどのデバイスでも同じように表示するのが目的の形式だと思っていたけれど、そんなことはなくHTMLをZIPで固めたものだった。 ウェブサイトでブラウザごとに見た目を調整するのと同じ対応が必要。 つらい。 コード領域のスタイルを font-family: monospace, serif; にするとか。

silight.hatenablog.jp

何かのチェッカーに掛けたら、「画像ファイルが無いけど大丈夫?」みたいなことを言われたので、この部分を消した。 Re:VIEW Templateはあくまで「TechBoosterで利用しているRe:VIEWのテンプレート」か。

github.com

BOOK☆WALKERのブラウザビューアはコード領域が等幅フォントにならなかったりしてつらい。 頑張ろうにも事前に手元で見た目を確認する手段が無い。 電子版でも別途PDFをダウンロードできるので、そちらを見てほしい。

お釣り

冊子版は1,000円で、電子版はちょっと安く900円にしたので、お釣りが必要。 みずほ銀行をメインで使っているので、両替機で両替。 両替機に来月から10枚が上限になるというお知らせがあった。 使い物にならない。 今回両替した100円玉は大事にとっておこう。

技術書典当日

今回は2フロア開催。 私は3階。 ちゃんと早めに行ったのに、サークル入場に時間が掛かって、開場までギリギリ。 たしかに、2階より人が少ないというのも感じた。

note.mu

「3階であまり売れなかった」と怒っていた人もいたけれど、まあ、今までの技術書典の売れ行きが良すぎたのかもしれない。 買う側の自分としても「あれ? 技術書典で買った本を次の技術書典までに何冊読んだっけ?」と気が付きつつある。 委託販売をしてくれているサークルも多いので、買い逃しても何とかなるし。

ということで売れ残った分をとらのあなの受付に預けて終わり。 ダイレクト入庫サービスが楽で良かった。 事前に申込みしておけば、当日受付に本を持っていくだけ。