私は以前、任意のプログラムを他プロセスへ注入する「DLLインジェクション」のテクニックを紹介しました。このテクニックについての詳細は「常駐プログラム隠蔽テクニック」を参照してください。
さて、この「DLLインジェクション」は、任意のプログラムを現在実行中の他プロセスへ注入し、他プロセスの一部としてこちら側が用意したプログラムを実行させるテクニックでした。これはとても面白く、任意のプロセスの情報を取得するための手法としてはSetWindowsHookExと同じくらい強力であり、かつ、実行したいプロセスの隠蔽という目的においても利用できるものでした。しかし、これはあくまでも実行中のプロセスへ注入したわけであり、EXEファイル自体を書き換えたわけではありません。よって、例えば、そのプロセスが何かしらの理由で強制終了し、再度起動された場合、もう一度、任意のプログラムの注入処理をほどこさなければ、我々の望む動作は得られません。もちろん、このテクニックも利用価値は多々ありますが、今回はこの「任意のプログラムを他のプログラムへ注入する」という行為を、「EXEファイルの変更」という角度から見ていくことにします。
今回、私が使用する環境はWindowsXPです。なお、このテキストを読むにあたって、PEフォーマットとアセンブラについての知識が必須となります。
PEフォーマットとは、Win32のバイナリフォーマットであり「Portable Executable」の略です。WindowsのEXEファイルは、このファイル形式で作られています。このファイル形式の詳細は、「マシン語大研究」のページを参考にしてください。このテキストでは、PEフォーマットについて簡単に解説します。まずは以下のEXEファイルmsg.exeをダウンロードしてください。
msg.exeをバイナリエディタで開くと、以下のようになっています。私はバイナリエディタに「Stirling」を使用しています。
----- msg.exe(抜粋) 00000000 4D 5A 6C 00 01 00 00 00 02 00 00 00 FF FF 00 00 MZl............. 00000010 00 00 00 00 11 00 00 00 40 00 00 00 00 00 00 00 ........@....... 00000020 57 69 6E 33 32 20 50 72 6F 67 72 61 6D 21 0D 0A Win32 Program!.. 00000030 24 B4 09 BA 00 01 CD 21 B4 4C CD 21 60 00 00 00 $............... 00000040 47 6F 4C 69 6E 6B 20 77 77 77 2E 47 6F 44 65 76 GoLink www.GoDev 00000050 54 6F 6F 6C 2E 63 6F 6D 00 00 00 00 00 00 00 00 Tool.com........ -----
アドレス「00000020」以降は「Win32 Program!\r\n$」という17バイトの文字列があるのが分かります。そして、アドレス「00000031」以降の「B4 09 BA 00 01 CD 21 B4 4C CD 21」は16ビット環境でのマシン語となっています。このマシン語をアセンブリ言語に変換すると以下のようになります。
----- 355C:0011 B409 MOV AH, 09 355C:0013 BA0001 MOV DX, 0100 355C:0016 CD21 INT 21 355C:0018 B44C MOV AH, 4C 355C:001A CD21 INT 21 -----
「AH = 09」は文字列出力のシステムコールです。そして、出力すべき文字列のアドレスはDXレジスタに格納するので、「355C:0100」にある文字列を出力することになります。さらに「AH = 4C」はプログラム終了のシステムコールなので、ここで16ビットプログラムは終了となります。
そして、「0000003C」から続く4バイトがPEフォーマットの先頭アドレスとなります。つまり、「60 00 00 00」がPEフォーマットの先頭アドレスとなります。
----- msg.exe(抜粋) 00000060 50 45 00 00 4C 01 01 00 E9 65 E4 42 00 00 00 00 PE..L........... 00000070 00 00 00 00 E0 00 0F 01 0B 01 00 25 00 04 00 00 ...........%.... -----
ご覧の通り、アドレス「00000060」以降は「50 45」(文字列にすると「PE」)となっています。
さて、重要なのは、この「0000003C」から続く4バイトなので、例えば「0000003C」から続く4バイトを「40 00 00 00」に変更し、PEフォーマット部分も32バイト(20h)ずらし「00000040」から始めれば、msg.exeの「00000040から0000005Fまで」のデータは削除することが可能です。それは、この領域のデータ(文字列)をみても、リンカが意図的に付加したものだと分かります。
では、次に「00000000から0000001Fまで」のフォーマットをみていくことにします。
----- msg.exe(抜粋) 00000000 4D 5A 6C 00 01 00 00 00 02 00 00 00 FF FF 00 00 MZl............. 00000010 00 00 00 00 11 00 00 00 40 00 00 00 00 00 00 00 ........@....... -----
-----
0000h 2byte 4D 5A 「MZ」(固定)
0002h 2byte 6C 00 Number of bytes in last 512-byte page of executable
0004h 2byte 01 00 Total number of 512-byte pages
in executable (including the last page)
0006h 2byte 00 00 Number of relocation entries
再配置エントリ数
0008h 2byte 02 00 Header size in paragraphs
ヘッダのサイズ(16バイト単位)
000Ah 2byte 00 00 Minimum paragraphs of memory allocated
in addition to the code size
割り当てるメモリの最小値
000Ch 2byte FF FF Maximum number of paragraphs allocated
in addition to the code size
割り当てるメモリの最大値
000Eh 2byte 00 00 Initial SS relative to start of executable
スタックセグメントの初期値
0010h 2byte 00 00 Initial SP
スタックポインタの初期値
0012h 2byte 00 00 Checksum (or 0) of executable
チェックサム
0014h 4byte 11 00 00 00 CS:IP relative to start of executable (entry point)
プログラムのエントリーポイント
0018h 2byte 40 00 Offset of relocation table;
40h for new-(NE,LE,LX,W3,PE etc.) executable
プログラムの開始アドレス
001Ah 2byte 00 00 Overlay number (0h = main program)
001Ch 4byte 00 00 00 00 reserved?
多分予約語です(^^;。
-----
さて、ここまでのバイナリデータは、DOS用に用意されたプログラムです。つまりWindowsプログラムが実行できない環境でmsg.exeが実行された場合、標準出力に「Win32 Program!」と表示して、プログラムを終了するわけです。DOS用のデータであるため、Windows環境で実行する場合は、意味がありません。よってPEフォーマットの解説でも、よくこの部分の説明は省かれることが多いです。なぜなら、この部分はPEフォーマットというよりむしろMZフォーマットなので(笑)。というわけで、ここからがPEフォーマットの本番ということになります。ちなみにPE以前のデータ(00000000から0000005Fまで)をtest.comというようなCOMファイルとして作成し、コマンドプロンプトに「test.com」と入力すれば、ちゃんと実行されます。よかったら一度試してみてください。
----- test.com 00000000 4D 5A 6C 00 01 00 00 00 02 00 00 00 FF FF 00 00 MZl............. 00000010 00 00 00 00 11 00 00 00 40 00 00 00 00 00 00 00 ........@....... 00000020 57 69 6E 33 32 20 50 72 6F 67 72 61 6D 21 0D 0A Win32 Program!.. 00000030 24 B4 09 BA 00 01 CD 21 B4 4C CD 21 60 00 00 00 $............... 00000040 47 6F 4C 69 6E 6B 20 77 77 77 2E 47 6F 44 65 76 GoLink www.GoDev 00000050 54 6F 6F 6C 2E 63 6F 6D 00 00 00 00 00 00 00 00 Tool.com........ -----
----- コマンドプロンプト C:\nasm>test.com Win32 Program! C:\nasm> -----

では、ここから本当のPEフォーマットを見ていくことにします。
----- msg.exe(抜粋) 00000060 50 45 00 00 4C 01 01 00 E9 65 E4 42 00 00 00 00 PE..L........... 00000070 00 00 00 00 E0 00 0F 01 ........ -----
----- PEヘッダ 0060h 4byte 50 45 00 00 「PE\0\0」(固定) 0064h 2byte 4C 01 CPUタイプ(「4C 01」はIntel386以降) 0066h 2byte 01 00 セクション数 0068h 4byte E9 65 E4 42 タイムスタンプ 006Ch 4byte 00 00 00 00 シンボルテーブルの位置(存在しなければ0) 0070h 4byte 00 00 00 00 シンボルテーブル内のエントリ数(存在しなければ0) 0074h 2byte E0 00 オプションヘッダのサイズ 0076h 2byte 0F 01 ファイルの特性 -----
----- msg.exe(抜粋) 00000070 0B 01 00 25 00 04 00 00 ...........%.... 00000080 00 00 00 00 00 00 00 00 00 10 00 00 00 10 00 00 ................ 00000090 00 00 00 00 .... -----
----- オプションヘッダ(標準フィールド) 0078h 2byte 0B 01 識別子(実行ファイル「0B 01」、ROMイメージ「07 01」) 007Ah 1byte 00 リンカのメジャーバージョン 007Bh 1byte 25 リンカのマイナーバージョン 007Ch 4byte 00 04 00 00 コードセクションのサイズ 0080h 4byte 00 00 00 00 初期化されたデータセクションのサイズ(.data) 0084h 4byte 00 00 00 00 初期化されていないデータセクションのサイズ(.bss) 0088h 4byte 00 10 00 00 メモリ上のベースアドレス相対のプログラム開始アドレス 008Ch 4byte 00 10 00 00 メモリ上のベースアドレス相対のコードセクションの先頭アドレス 0090h 4byte 00 00 00 00 メモリ上のベースアドレス相対のデータセクションの先頭アドレス -----
----- msg.exe(抜粋) 00000090 00 00 40 00 00 10 00 00 00 02 00 00 ..@......... 000000A0 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 000000B0 00 20 00 00 00 02 00 00 B9 FC 00 00 02 00 00 00 . .............. 000000C0 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 ................ 000000D0 00 00 00 00 10 00 00 00 -----
----- オプションヘッダ(Windowsフィールド) 0094h 4byte 00 00 40 00 メモリ上のベースアドレス 0098h 4byte 00 10 00 00 メモリ上に割り当てられるセクションのサイズ 009Ch 4byte 00 02 00 00 実行ファイルのセクションの単位 00A0h 2byte 04 00 OSのメジャーバージョン 00A2h 2byte 00 00 OSのマイナーバージョン 00A4h 2byte 00 00 実行ファイルのメジャーバージョン 00A6h 2byte 00 00 実行ファイルのマイナーバージョン 00A8h 2byte 04 00 サブシステムのメジャーバージョン 00AAh 2byte 00 00 サブシステムのマイナーバージョン 00ACh 4byte 00 00 00 00 予約語(常に0) 00B0h 4byte 00 20 00 00 プログラムが利用するメモリサイズ 00B4h 4byte 00 02 00 00 セクションデータの先頭アドレス 00B8h 4byte B9 FC 00 00 チェックサム 00BCh 2byte 02 00 サブシステム(「02 00」はGUIで実行されるファイル) 00BEh 2byte 00 00 DLLの特性 00C0h 4byte 00 00 10 00 スタックのために予約された仮想メモリのサイズ 00C4h 4byte 00 10 00 00 実際に使われるスタックのサイズ 00C8h 4byte 00 00 10 00 ヒープ領域として予約された仮想メモリのサイズ 00CCh 4byte 00 10 00 00 実際に使われるヒープ領域のサイズ 00D0h 4byte 00 00 00 00 デバッグ用のフラグ 00D4h 4byte 10 00 00 00 データディレクトリ配列の数(8バイト単位) -----
----- msg.exe(抜粋) 000000D0 00 00 00 00 00 00 00 00 ........ 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000150 00 00 00 00 00 00 00 00 ........ -----
----- データディレクトリ (最初の4バイトはアドレス、最後4バイトはサイズ) 00D8h 8byte 00 00 00 00 00 00 00 00 エクスポートテーブルのアドレスとサイズ 00E0h 8byte 00 00 00 00 00 00 00 00 インポートテーブルのアドレスとサイズ 00E8h 8byte 00 00 00 00 00 00 00 00 リソーステーブルのアドレスとサイズ 00F0h 8byte 00 00 00 00 00 00 00 00 例外テーブルのアドレスとサイズ 00F8h 8byte 00 00 00 00 00 00 00 00 属性認証テーブルのアドレスとサイズ 0100h 8byte 00 00 00 00 00 00 00 00 再配置テーブルのアドレスとサイズ 0108h 8byte 00 00 00 00 00 00 00 00 デバッグデータの開始アドレスとサイズ 0110h 8byte 00 00 00 00 00 00 00 00 アーキテクチャ固有データのアドレスとサイズ 0118h 8byte 00 00 00 00 00 00 00 00 グローバルポインタレジスタの相対仮想アドレスとサイズ 0120h 8byte 00 00 00 00 00 00 00 00 TLSテーブルのアドレスとサイズ 0128h 8byte 00 00 00 00 00 00 00 00 ロードコンフィグレーションテーブルのアドレスとサイズ 0130h 8byte 00 00 00 00 00 00 00 00 バウンドインポートテーブルのアドレスとサイズ 0138h 8byte 00 00 00 00 00 00 00 00 インポートアドレステーブルのアドレスとサイズ 0140h 8byte 00 00 00 00 00 00 00 00 遅延インポート記述子のアドレスとサイズ 0148h 8byte 00 00 00 00 00 00 00 00 予約語(常に0) 0150h 8byte 00 00 00 00 00 00 00 00 予約語(常に0) -----
----- msg.exe(抜粋) 00000150 2E 74 65 78 74 00 00 00 .text... 00000160 60 02 00 00 00 10 00 00 00 04 00 00 00 02 00 00 ................ 00000170 00 00 00 00 00 00 00 00 00 00 00 00 20 00 50 60 ............ .P. -----
----- セクションヘッダ
0158h 8byte 2E 74 65 78 セクション名(ASCII)
74 00 00 00
0160h 4byte 60 02 00 00 セクションサイズ
0164h 4byte 00 10 00 00 メモリ上のベースアドレスに相対なセクション先頭アドレス
0168h 4byte 00 04 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションサイズ
016Ch 4byte 00 02 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションの先頭アドレス
0170h 4byte 00 00 00 00 セクションの再配置エントリへのポインタ
0174h 4byte 00 00 00 00 セクションの行番号エントリへのポインタ
0176h 2byte 00 00 セクションの再配置エントリ数
0178h 2byte 00 00 セクションの行番号エントリ数
017Ch 4byte 20 00 50 60 セクションフラグ
-----
「00000180から00000200まで」のデータはセクション単位(アドレス009Ch以降の4バイトの値)にあわせるためにサイズを調整しているだけなので、すべて「00」となります。そして、実際に実行されるコードセクションのプログラムは、アドレス「00000200」から始まることになります。
----- msg.exe(抜粋) 00000200 55 89 E5 81 EC 00 01 00 00 B8 47 65 74 50 89 45 ................ (省略) -----
セクションデータ自体もサイズをセクション単位(アドレス009Ch以降の4バイトの値)の倍数にしなければならないので、実際のマシン語のサイズは260hバイトですが、「セクション単位(アドレス009Ch以降の4バイトの値)の倍数で表したセクションサイズ」は、400hバイトとなっています。つまり、「00000200から00000600」までがコードセクションとなります。ちなみにこのプログラムはコードセクションしかありませんが、通常のプログラムでは、データセクションやインポートセクションなど、他にも様々なものがあります。それらはまとめてセクションヘッダで定義され、コードセクションデータ以降に順番に追加されることになります。
PEフォーマットの解説に利用したプログラムmsg.exeは、ご覧の通りコードセクションのみで実現されています。「Wizard Bible vol.17」にて、まひんさんが「ウイルスプログラミングへの招待 〜インポートセクションを持たずにAPIを使う方法〜」という記事を書かれていますが、これを参考にして、コードセクションのみのプログラムを作成することができます。コンパイラはNASMとGOLINKを使います。
では、msg.exeのソースコードを見てください。
----- コマンドプロンプト C:\nasm>nasmw -fwin32 msg.asm C:\nasm>golink -entry main msg.obj GoLink.Exe Version 0.25.4 - Copyright Jeremy Gordon 2002/4 - JG@JGnet.co.uk Output file: msg.exe size: 1,536 bytes C:\nasm> -----

このプログラムは、実行するとMessageBoxを表示するだけの簡単なものです。ソースコードの解読にはPEフォーマットとアセンブリ言語の知識が必要です。では、このプログラムを任意のEXEファイルへ追加することにしましょう。ターゲットのEXEファイルは特に何でもよいのですが、今回は自前で用意しましょう。以下のプログラムをダウンロードしてください。
このターゲットプログラムhello.exeに、msg.exeのコードセクションのプログラムを追加します。msg.exeのコードセクションは以下です。
----- 追加するマシン語(msg.exeのコードセクション) 00000200 55 89 E5 81 EC 00 01 00 00 B8 47 65 74 50 89 45 00000210 CC B8 72 6F 63 41 89 45 D0 B8 64 64 72 65 89 45 00000220 D4 B8 73 73 41 00 89 45 D8 B8 4C 6F 61 64 89 45 00000230 BC B8 4C 69 62 72 89 45 C0 B8 61 72 79 41 89 45 00000240 C4 B8 00 00 00 00 89 45 C8 B8 45 78 69 74 89 45 00000250 AC B8 50 72 6F 63 89 45 B0 B8 65 73 73 00 89 45 00000260 B4 B8 00 00 00 00 89 45 B8 B8 75 73 65 72 89 45 00000270 9C B8 33 32 2E 64 89 45 A0 B8 6C 6C 00 00 89 45 00000280 A4 B8 00 00 00 00 89 45 A8 B8 4D 65 73 73 89 45 00000290 8C B8 61 67 65 42 89 45 90 B8 6F 78 41 00 89 45 000002A0 94 B8 00 00 00 00 89 45 98 B8 47 65 74 41 89 85 000002B0 7C FF FF FF B8 63 74 69 76 89 45 80 B8 65 57 69 000002C0 6E 89 45 84 B8 64 6F 77 00 89 45 88 B8 57 69 7A 000002D0 61 89 85 5C FF FF FF B8 72 64 20 42 89 85 60 FF 000002E0 FF FF B8 69 62 6C 65 89 85 64 FF FF FF B8 20 76 000002F0 6F 6C 89 85 68 FF FF FF B8 2E 31 39 00 89 85 6C 00000300 FF FF FF B8 48 65 6C 6C 89 85 3C FF FF FF B8 6F 00000310 21 20 54 89 85 40 FF FF FF B8 68 69 73 20 89 85 00000320 44 FF FF FF B8 69 73 20 49 89 85 48 FF FF FF B8 00000330 6E 6A 65 63 89 85 4C FF FF FF B8 74 20 43 6F 89 00000340 85 50 FF FF FF B8 64 65 2E 00 89 85 54 FF FF FF 00000350 8B 5D 04 81 E3 00 00 FF FF B9 05 00 00 00 66 81 00000360 3B 4D 5A 74 12 81 EB 00 00 01 00 49 31 C0 39 C1 00000370 75 EC E9 E4 00 00 00 8B 43 3C 01 D8 81 38 50 45 00000380 00 00 75 E1 89 5D FC FC 8B 70 78 03 75 FC 81 C6 00000390 18 00 00 00 AD 89 45 E8 AD 03 45 FC 89 45 E4 AD 000003A0 03 45 FC 89 45 E0 AD 03 45 FC 89 45 DC 31 D2 8B 000003B0 45 E0 8B 38 03 7D FC FC 31 C9 38 F2 75 08 8D 75 000003C0 CC E9 03 00 00 00 8D 75 BC A6 75 07 80 3F 00 74 000003D0 19 EB F6 41 3B 4D E8 7C 05 E9 7D 00 00 00 05 04 000003E0 00 00 00 8B 38 03 7D FC EB D0 D1 E1 8B 75 DC 01 000003F0 CE 31 C0 66 8B 06 C1 E0 02 8B 75 E4 01 C6 8B 3E 00000400 03 7D FC 38 F2 75 07 89 7D EC FE C2 EB A1 89 7D 00000410 F0 89 E8 2D 64 00 00 00 50 FF 55 F0 89 45 F8 89 00000420 E8 2D 74 00 00 00 50 FF 75 F8 FF 55 EC 89 45 F4 00000430 89 E8 2D 84 00 00 00 50 FF 75 F8 FF 55 EC FF D0 00000440 89 C2 68 00 00 00 00 89 E8 2D A4 00 00 00 50 89 00000450 E8 2D C4 00 00 00 50 52 FF 55 F4 89 EC 5D C3 00 00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ....(省略).... 000005F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -----
msg.exeのコードセクションは400h(1024)バイトあります。EXEファイル(hello.exe)に任意のプログラムを追加するためには、このマシン語をhello.exeのコードセクションの最初に追加し、しかもその後、もともとのhello.exeプログラムもちゃんと実行されるように配慮しなければなりません。そのためには、まず一番最後の「00」以降のデータをすべてNOP「90」に変換しましょう。これらはコードセクションをセクション単位(アドレス009Ch以降の4バイトの値)の倍数にするための追加データであるため、すべて「00」です。そして、さらに最後のマシン語命令である「C3」はret命令であり、KERNEL32.DLLへ処理を戻してしまうため、これもNOP「90」にします。
----- 変更前(00000450以降のデータ) 00000450 E8 2D C4 00 00 00 50 52 FF 55 F4 89 EC 5D C3 00 00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ....(省略).... 000005F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -----
----- 変更後(00000450以降のデータ) 00000450 E8 2D C4 00 00 00 50 52 FF 55 F4 89 EC 5D 90 90 00000460 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ....(省略).... 000005F0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 -----
では、このコードセクションのデータ400hバイトをhello.exeのコードセクションの先頭に追加します。追加することによって、EXEファイル(hello.exe)に以下のような変化が起きます。
よって、これらをPEフォーマットのデータに反映させなければなりません。では、ターゲットプログラムhello.exeのセクションヘッダをバイナリエディタで見てください。
----- hello.exeのセクションヘッダ
0158h 8byte 2E 74 65 78 セクション名(ASCII)「.text」(コードセクション)
74 00 00 00
0160h 4byte E0 01 00 00 セクションサイズ
0164h 4byte 00 10 00 00 メモリ上のベースアドレスに相対なセクション先頭アドレス
0168h 4byte 00 02 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションサイズ
016Ch 4byte 00 02 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションの先頭アドレス
0170h 4byte 00 00 00 00 セクションの再配置エントリへのポインタ
0174h 4byte 00 00 00 00 セクションの行番号エントリへのポインタ
0176h 2byte 00 00 セクションの再配置エントリ数
0178h 2byte 00 00 セクションの行番号エントリ数
017Ch 4byte 20 00 50 60 セクションフラグ
0180h 8byte 2E 74 65 78 セクション名(ASCII)「.data」(データセクション)
74 00 00 00
0188h 4byte 20 00 00 00 セクションサイズ
018Ch 4byte 00 20 00 00 メモリ上のベースアドレスに相対なセクション先頭アドレス
0190h 4byte 00 02 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションサイズ
0194h 4byte 00 04 00 00 セクション単位(アドレス009Ch以降の4バイトの値)の
倍数で表したセクションの先頭アドレス
0198h 4byte 00 00 00 00 セクションの再配置エントリへのポインタ
019Ch 4byte 00 00 00 00 セクションの行番号エントリへのポインタ
01A0h 2byte 00 00 セクションの再配置エントリ数
01A2h 2byte 00 00 セクションの行番号エントリ数
01A4h 4byte 40 00 30 C0 セクションフラグ
-----
0160h番目にセクションサイズがあります。また、0168h番目がセクション単位のサイズ、016Ch番目がセクション単位の先頭アドレスとなっています。よって、ターゲットのEXEファイルのこの部分を変更することで、OKだと考えられます。では、実際にhello.exeのバイナリを変更していきます。
まず、コードセクションのサイズを変更します。先頭に400h(1024)バイト追加したわけなので、hello.exeのアドレス「0169h」の「02」を「06」に変更します。さらにアドレス「0160h」のセクションサイズにも400hを加算しなければならないので、アドレス「0161h」の「01」を「05」に変更します。次にデータセクションのアドレスを変更します。アドレス「0194h」をみると、400h番目からデータセクションとなっているので、アドレス「0195h」の「04」を「08」に変更します。これで完了です。あとは、コードセクションの先頭(アドレス「0200h」)にさっき用意したマシン語を追加すれば、マシン語コードの追加は完了です。変更後のEXEファイルを保存し、実行すると、追加したマシン語コードが実行された後に、通常のプログラムが実行されます。


さて、今回は、hello.exeへの追加をバイナリエディタを使って手動で行いましたが、これを自動化したプログラムを作成すれば、すべてのEXEファイルに任意のプログラムを感染させることができます。これは一般的にいうコンピュータウイルスです。自分自身を他のEXEファイルへ感染させることによって、ウイルス自体の発見を難しくするわけです。EXEファイルに任意のプログラムを寄生させるテクニックなんて、ウイルスの作成にしか役に立たない気もしますが、このテクニック自体はとても興味深いものだと思います。ブラックか? ホワイトか? アンダーグラウンドか? オーバーグラウンド(?)か? といった括りに関係なく、こういった純粋な技術部分での話題はとても面白いものだと思いますので、興味を持たれた方は、ぜひいろいろと調べてみてください。
さて、いかがだったでしょうか。本当はこの作成したマシン語を任意のEXEファイルへ追加してくれるプログラムも作る予定だったのですが、最近なぜかやるべきことが多く、なぜか忙しいのでちょっとそこまで手がまわりませんでした。申し訳ないです。またいつか気が向いた時に作ってみることにしますので、そしたらまたWBに投稿するのでよろしくお願いします(^^;。さて、最後になりましたが、ここまで読んでくれて本当にありがとうございます。
では、また会う日まで...