SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Windows実行ファイル「EXE」の謎に迫る

プログラムからEXEファイルを生成してみよう

Windows実行ファイル「EXE」の謎に迫る 第4回


  • X ポスト
  • このエントリーをはてなブックマークに追加

本連載では、EXEファイルの内部構造について解説していきます。EXEファイルに関する日本語の資料は少ないため、筆者自身の経験を踏まえ、実際にEXEファイルの解析ができるようになるための資料として説明します。第4回では、今まで解説してきた情報を元に、オリジナルのEXE生成プログラムを作成してみます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 これまで解説してきたEXEファイルにまつわる情報をもとに、オリジナルのEXE生成プログラムを作ってみましょう。

 「EXEを生成するなんて、とてつもない量のコードが必要なんじゃっ!?」

 このように心配される方がいるかもしれませんが、ご安心ください。前回解説した構造体の各メンバに値を指定してファイルに流しこめば、知らず知らずのうちにEXEファイルが出来上がります。

 誤解を招くとマズいので初めに言っておきますが、コンパイラを作るワケではありません。コンパイラはソースコードをネイティブコード(機械語)に変換するためのツールであり、今回挑戦する内容とは異なります。今回は、あらかじめ用意する少量のネイティブコードを実行するためにEXEファイルを生成するのだということを念頭に置き、作業に取り掛かってみましょう。

本連載の既出記事

使用するソフトウェア

 Visual C++ 2005 Express Edition(以下、VC++)を使用してプログラミングを行います。VC++は、マイクロソフトのサイトからダウンロードできます。

 なお、ソースコード内でWin32 APIを利用するため、VC++のExpress Editionを使う場合は、別途Microsoft Platform SDKをインストールしておく必要があります。

プロジェクトの作成

 VC++を立ち上げたら、メニューの[ファイル]-[新規作成]-[プロジェクト]をクリックします。[新しいプロジェクト]ダイアログボックスが表示されたら、[Win32コンソール アプリケーション]を選択し、プロジェクト名を「ExeCreator」などとして[OK]ボタンをクリックします。続けてウィザードが表示されますが、[完了]ボタンをクリックしてください。

 これで空のプロジェクトが作成できます。

 次に、メニューの[プロジェクト]-[ExeCreatorのプロパティ]をクリックします。構成を[すべての構成]にし、[構成プロパティ]の[全般]にある[文字セット]を[マルチバイト文字セットを利用する]にセットして[OK]ボタンをクリックします。

 ここからコーディングに入るのですが、編集が必要なファイルは「ExeCreator.cpp」のみです。他のファイルは一切触らずに作業を進めます。

ヘッダ部分のコーディング

ExeCreator.cppの先頭部分
// ExeCreator.cpp : コンソール アプリケーションの
//                  エントリ ポイントを定義します。

#include "stdafx.h"

#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>

#define ALIGNMENT        0x1000 //ファイルおよびメモリにおけるアライメント
#define EXE_HEADER_SIZE  0x1000 //EXEヘッダの総合サイズ(アライメント考慮)

//ネイティブコード(コードセクションに保存されるバイナリ)
BYTE NativeBuffer[]={
    0x6A,0x00,                         //push 0
    0x68,  0x0D,0x30,0x40,0x00,        //push dword ptr["exetest"]
    0x68,  0x00,0x30,0x40,0x00,        //push dword ptr["Hello World!"]
    0x6A,0x00,                         //push 0
    0xFF,0x15,    0x4E,0x20,0x40,0x00, //call MessageBoxA
    0xC3                               //ret 0
};

//インポートセクションに保存されるデータ
#define USE_DLL 1
IMAGE_IMPORT_DESCRIPTOR ImportDesc[USE_DLL+1];
char szDllName[16]="user32.dll";
DWORD LookupTable[2];
char HintTable[]={
    0,0,
    'M','e','s','s','a','g','e','B','o','x','A',0
};

//初期済みデータ(データセクションに保存されるバイナリ)
BYTE InitBuffer[]="Hello World!\0exe test\0\0";

//NULL空間
char szNullSpace[ALIGNMENT];

 EXEファイルが保持する構造体はすべて「windows.h」で定義されています。特別なヘッダファイルのインクルードは必要ありません。

 ALIGNMENT定数ではアライメントを指定します。今回は、コードを簡略化するため、メモリ上・ファイル上のアライメントを同一にして計算を行います。

 NativeBufferにはネイティブコードを記述します。この配列データが生の機械語を保持します。

 この他、インポートセクション用のデータ、初期済みデータ、NULL空間用のデータを定義して先頭部分のコーディングは完了です。

次のページ
_tmain関数をコーディング(1/2)

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Windows実行ファイル「EXE」の謎に迫る連載記事一覧

もっと読む

この記事の著者

山本 大祐(ヤマモト ダイスケ)

普段はActiveBasicと周辺ツールの開発を行っています。最近は諸先輩方を見習いながら勉強中の身。AB開発日記

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/419 2006/07/12 15:02

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング