Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

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

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

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/07/07 00:00

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

目次

はじめに

 これまで解説してきた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空間用のデータを定義して先頭部分のコーディングは完了です。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

修正履歴

  • 2006/07/04 01:46 「使用するソフトウェア」に「Microsoft Platform SDKをインストールしておきましょう」の文を追加。

著者プロフィール

バックナンバー

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

もっと読む

All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5