「Binary Hacks」を語る

本記事では、バイナリアン向け著作「Binary Hacks ─ ハッカー秘伝のテクニック100選」について、業務でアプリを担当しているに加えて、低レイヤー担当のが語ります。

この本は元々さんの推薦だったんだよね。

新入社員向けにプログラム本を勧めることになって、私の方でKR本ラクダ本GOF、 Effective C++ といった大家を挙げた後、「他にもオススメ本はないですか?」という感じで3人の人に聞いて回ったんですよ。


ありましたね、そんなこと。

1人目の人は、既に挙げてあったGOFを、「これは前提知識として知っておく必要がありますね」と念押ししてくれた。
2人目の人は、リーダブルコードを勧めてくれた。

あぁ、あの青い本。

リーダブルコードはサイズも内容もお手頃だし、一般性も高いので、新入社員向けという点でピッタリだったね。
で、3人目のさんが推薦してくれたのが、それとは真逆の、上級者向けでディープな「Binary Hacks」だったというわけ。私もこの時に初めて知った。

私も新入社員じゃないけど話を聞いて、本を買いましたね。

ディープ過ぎるから、新入社員は誰も反応しなかったけどね(笑)。

とは言っても、ディープな割りには読み易いとも思ったね。


確かに、項目ごとにテーマがハッキリしているので、読み易いですね。

はじめから順番に読んでいく本ではなく、困った時、手詰まった時に何か解決策がないかと参照する感じですね。





読み物として面白いと思ったのは、Hello World を小さくしようという話(「25. glibcを使わないでHello Worldを書く」)。
普通に printf で書いたら 5KB あった Hello World が、glibc を使わないようにし、さらにダイエットすることで 500B まで小さくできるというのは、スゴ技って感じがしたね。

そこで挙げらている技は、我々のチームは実際に使ってるんですよ。

え!?

カーネルが立ち上がった直後っていうのは glibc がまだ無いんで、システムコールは直に呼ぶしかないんです。システムコールを呼ぶためのマクロをいっぱい定義していますよ。

そ、そうだったのか、、、。
Hello World をいかに小さくするか大会、をやってるだけかと思ってたよ。

glibc 依存を無くすというのは、そんなに重要な技だったんですね。

それしか手がないんで、やるしかないですね。




直近で使ったのは strace(「82. straceでシステムコールをトレースする」)。システムコールを頻繁に呼ぶと思わぬ副作用があったのでシステムコールの呼び出しを減らしたんだけど、その対策の確認に strace が使えたね。

兄弟分の ltrace もあるんで(83. ltraceで共有ライブラリの関数呼び出しをトレースする)、セットで使いこなすべきでしょうね。




これは! と思ったのが Valgrind(「54. Valgrindでメモリリークを検出する」「55. Valgrindでメモリの不正アクセスを検出する」)。これは動的テストツールとしてスゴイと思ったね。

スゴイですよね。
どうも VM みたいなものを動かしてるみたいなんですよ。なのでメモリの動きを把握できるんでしょうね。

ただ、大きなプログラムに対して使ったら、プログラム終了時に大量の出力が出て、使い物にならなかったですね。


メモリリークは実際にどうやって検出してるんでしょうね。

malloc されてから、参照元を監視してるんだと思いますよ。

ちなみに、C++ で STL を使ってると、malloc の呼び出し回数が半端じゃないですよ。大きなプログラムに対して malloc 呼び出し回数をカウントする仕組みを入れたら、一晩で 32bit がオーバーフローしてましたからね。


別の有力な動的テストツールとして sanitizer がある。sanitizer の紹介ページを見ると、たいてい Valgrind との比較が載ってるんだよね。
sanitizer の方が高速らしいので、Valgrind では遅すぎるという案件では sanitizer の方が良さそうだね。




他によく使った技はありますか?

LD_PRELOAD はよく使いましたね。

「60. LD_PRELOADで共有ライブラリを差し替える」と「61. LD_PRELOADで既存の関数をラップする」ですね。これはどういう使い道があるのですか?

さっき言った malloc 呼び出し回数を数えるとかも、LD_PRELOAD で malloc を差し替えて実現しましたね。

なるほど、確かにそんなレベルで差し替えができるなら、かなり意のままに操れるようになりそうですね。



-fthreadsafe-statics なんかもこの本の「36. C++でsynchronized methodを書く」で知りましたね。
それまでは本の中にある“よくない方法(1)”の実装でしたからね。

今我々のアプリでは main() の最初の方でわざわざシングルトンを呼び出してるけど、あれはこの辺りの話を聞いて、付け足したんだよね。超原始的なやり方だけど。
ちなみに、C++11 では static変数は1つというのが保証されるようになってる。この本の初版は2006年なので、今では古い話題も一部にあるみたいだね。



「13. stringsでバイナリファイルから文字列を抽出する」で strings というのが紹介されているけど、使い方が想像つかないですね。

これも実際に使ってますよ。

え? それはどういう使い方ですか?

プログラム内で使われているパスワードだけ置き換えたい時に、strings でパスワードデータの位置を特定しましたね。

そういう事案もあったんですね。もちろんパスワードが平文で書かれているという前提があるのでしょうけど。

総じて1章と2章に書かれている内容は使うことが多いですね。

あと、この本のホームページにはバイナリアン度チェックというクイズページもあるので、やってみたらいいと思います。

0 件のコメント:

コメントを投稿