はじめに
アプリケーションを起動させるEXEファイルを、普段何気なく実行していることと思います。皆さんは、このEXEファイルの中身について考えてみたことはありますか? 本連載は、そのEXEファイルの内部構造がどのようになっているのかを解説していくものです。
EXEファイルには具体的に、どのような情報が格納されているのでしょうか。通常、Visual C++やVisual Basic、Delphiなどのコンパイラが自動的に生成してくれるので、考えることはありませんが、今回はこの疑問に真っ向から勝負を挑んでいきます。
EXEは魔法の箱?
筆者は「ActiveBasic」というネイティブコンパイラ搭載型の統合開発環境を開発しています。コンパイラ開発イコール、EXEファイルの仕様をかなり細かい部分まで理解しなければならないという状況に置かれることを意味します。
Javaや.NETが騒がれる昨今、あえてEXEファイルというディープな内容に迫っていこうということで本稿へ筆を入れ始めたわけですが、やはり、この手の話題はプログラマ魂がうずきます。このように感じる技術者の方は多いはず。しかしその反面、世の中にはアセンブラを書けないプログラマが数多く存在すると聞きます。EXEファイルの構造をきちんと理解している人がどれくらいいるのだろうと思うと、それこそ稀な人種になってくるのかもしれません。
参考書を読めば大抵のソースコードは書けてしまいますし、コンパイルを行えば、即座にプログラムは実行可能な状態になります。しかしよく考えてみてみてください。皆さん、EXEを魔法の箱だと思っていませんか? 実はEXEには万人が読むことのできないネイティブコード、それを実行するための下準備データがフンダンに取り込まれている摩訶不思議な存在なんです。
ちなみに、筆者の個人的な印象では、EXEファイル内に存在するデータの構造はかなり雑然としています。そのほとんどがデータサイズやファイル・メモリを指し示すオフセット値で構成されているので、いざ解析しようと思ってみても、中途半端な気持ちでは挫折することが多いことでしょう。実際、筆者もコンパイラ開発の際に、EXEファイルの読解にたくさんの時間を費やした経験があります。
特にEXEファイルに関する日本語の資料が少ないのが現状です。そのため、解析に手を出してみたいと思っても挫折してしまった方が少なくないのではないでしょうか。本連載は、筆者自身の経験を踏まえ、実際にEXEファイルの解析ができるようになるための資料として解説していきます。この解説が皆さんの理解への一助になれば幸いです。
EXEファイルに隠されている情報は?
皆さんご存知の通り、EXEファイルはプログラムの実行ファイルです。その実体は、人間が読むことのできるソースコードではないので、メモ帳などでファイルを開いても、意味不明な文字の羅列が表示されます。EXEファイルの内容はコンピュータが理解できる機械語で保存されているのですが、実はその中にはさまざまな情報が隠されています。
まずは、興味深いポイントを抜粋して説明していくこととします。
MZシグネチャ
EXEファイルをメモ帳で開いてみると、必ず先頭部分に「MZ」という文字列があります。これは、EXEファイルであることを裏付けるためのデータであり、シグネチャと呼ばれるものです。特に深い意味はなく、署名のようなものだと思えば良いでしょう。
マシンタイプ
EXEファイルがどのようなマシン上での動作を想定しているのか、次のようなマシンを識別するためのフラグが格納されています。
- Intel 386以降およびその互換プロセッサ
- MIPS(r)リトルエンディアン
- Alpha AXP(tm)
- Motorola 68000シリーズ
- Power PC、リトルエンディアン
- 日立SH3
- 日立SH4
普段皆さんがWindows上で利用するものであれば、「Intel 386以降およびその互換プロセッサ」というフラグを格納したEXEファイルを扱っていることになります。Windows CEやAlphaマシンなど、異なるバイナリのEXEファイルなどが識別されていることが分かります。
ネイティブコード
ネイティブコードとは機械語データのことを指します。プログラムの実行手順が書かれており、このネイティブコード部分がソフトウェアの中核になります。一般的にはx86に対応する機械語命令が並んでいます。
あくまで機械語なので、アセンブラではありません。メモ帳やバイナリエディタで開いても意味不明な文字の羅列しか表示されませんので、アセンブリソースを閲覧されたい方は、逆アセンブルを行う必要があります。
リソース
アプリケーションにはそれぞれ独自のアイコンが用意されていますが、それらのアイコンは、EXEファイルの中のリソース部に格納されています。ここには画像や音楽、その他、さまざまなデータを格納することができます。
デバッグ情報
Visual C++などで開発している方にとって、デバッギング作業は日常の出来事だと思います。実はこの作業は、EXEファイルにデバッグ情報という内部データを持たせることで実現しています。
そもそも、EXEファイルにはネイティブコードしか格納されていないので、EXEファイルの元になったソースコードとの関連性が分からなくなっています。しかし、デバッガはネイティブコードの位置とソースコードの位置を探りながらデバッギング作業を実行しなければなりません。このようなケースを想定し、ネイティブコードの位置と行番号の位置を格納しているのが、このデバッグ情報です。