プログラムの解析というものにとても興味があったもので、Kindleで「解析魔法少女 美咲ちゃん マジカルオープン」という巷では有名な本を結構前に買ってはいたのですが、全く読まずに放置していたのでブログを始めたという勢いと共に、進めてみたいと思います。
ちなみに、プログラミング、メモリ、アセンブラの知識ともに赤ちゃんレベルです。全く知らないというわけではないですが、社会では通用しない()レベルだとお考えください。ので、わけのわからないことを書いたりしているかもしれません。
ということで、いきなりollydbgというデバッカを使ってプログラムの中身を見ていくわけですが、レジスタについて知識が要求されます。本がとてもわかり易く書いてあるおかげで、ほぼゼロ知識で読み始めてもスラスラと読み進めることができました。
以降、知ったように書いてますが、初学者です。
レジスタ
レジスタはC言語で言う変数みたいなものであるという説明があり、上記の画像の通り10個あります。汎用レジスタ、ベースポインタ、インストラクションポインタと格納するものが決まっています。
インストラクションポインタ(EIP)は実行している場所が格納されているだけで、実際にollydgbでみてみると、エントリポイントを指しています。
スタックポインタ(ESP)は、関数内に入った後に元のプログラムの流れに戻るための場所を格納しておくもので、言葉だけだと分かりづらいですが、実際に簡単なプログラムを書いたことあると想像しやすいと思いました。main関数内からhoge関数を実行して、hoge関数が終わるとmain関数に戻ってくるわけですが、この戻ってくる際にESPを見ているということでしょう。
そして、スタックはメモリの領域をマイナス方向に積んでいく(マイナス方向という表現は間違っていると思うけどメージとしてはマイナス方向のほうがわかりすい…正しくは「上位方向に伸びる」)ので、実際に関数から返ってくる(returnした)ときは、ESPのアドレスを見て飛び、飛んだ後に積んだアドレスを捨てるためにEIPに+4バイト足すそうだ。なるほど納得。
フラグレジスタは必要なときに確認すればいいと思ったので特に詳しく見ていないです。8つのアルファベット覚えられません。Zero Flagくらいは覚えましたが…
命令
いよいよコードを読んでいきます。
マシンコードはリトルエンディアンで表されているので、逆アセンブルされたコードと乖離して混乱します。逆アセンブルされたコードは人間が楽に理解できるようにした文章になっているだけで、その元のコードの実際の意味がわかると、ちょっと面白いものがあります。
見た目では、「00401818をCALLします」だけども、実際は「現在の実行アドレス(EIP)に0x0000037Fを足したアドレスをCALLします」です。なるほどー!
続けてジャンプ命令。CMPと組み合わせてジャンプ命令を出します。JZは演算結果がゼロの時にジャンプする命令です。内部的にはa-b==0での判定をしていますが、結局の所、同値であればジャンプする、つまり a==bが条件なのです。もうこんがらがる。JZ=Jump Zeroと覚えていても、「同値ならジャンプ」という連想は…されないですね。逆にゼロならジャンプって何だ…ってなりそうです。a==bだとZFのフラグが1となり、晴れてジャンプが成立です。
ジャンプ命令は、命令は違うのに動作が同じものがいくつか存在するということで、覚えておかないと、逆アセンブルを読むのに時間がかかってしまいそうです。諦めて覚えてみます。
次にTEST命令。TEST EAX,EAX って意味不明過ぎますね…
TEST命令ではAND演算をするようですが、同じ値をANDしたらその値が出てくるのは当たり前です。ここでやりたいことは、EAXがゼロなのかどうかを判断したいだけ。CMP EAX,0と一緒。TEST命令の結果はZero Flagに反映されます。そしてジャンプ命令JNZ(Jump Not Zero)はZFがゼロではなかったらジャンプという意味なので、EAXがゼロ出ない場合にジャンプすると読めます。
一旦ここで一区切り。