ラベル c の投稿を表示しています。 すべての投稿を表示
ラベル c の投稿を表示しています。 すべての投稿を表示

2013年7月3日水曜日

EXEファイルの仕組み

EXEファイルの構造

MZヘッダー、PEヘッダー、セクションヘッダー からなる。

  1. MZヘッダー:DOSヘッダー
  2. MZヘッダー:MS-DOS用スタブ
  3. PEヘッダー:シグネチャ
  4. PEヘッダー:ファイルヘッダー
  5. PEヘッダー:オプションヘッダー
  6. セクションデータ:セクションヘッダー1
  7. セクションデータ:セクションヘッダー2
  8. セクションデータ:…
  9. セクションデータ:セクション1
  10. セクションデータ:セクション2
  11. セクションデータ:…

DOSヘッダー

先頭はMZ。


MS-DOS用スタブ

This program cannot be run in DOS mode. を表示するプログラム


PEヘッダー

PEという2文字と2byte分の0からなるシグネチャが先頭。


セクションデータ

Windowsプログラム本体。いくつかのコード(命令)やデータのまとまり(セクション)に分けられている。
各セクションヘッダーの並びの後に、セクション本体が並ぶ。



EXEファイルの内容をダンプする


ダンプツール:dumpbin.exe → MZヘッダーを読み飛ばす。

以下のダンプ出力コードで、exeを作成すれば、すべて閲覧できる。



%02Xは16進数を表す%xに02: 最低2文字出力し、足りなければ 0 で埋める。と X: 大文字で表記を追加した書き方。
%08Xであれば、最低8文字で足りなければ0で、大文字表記。


上記をコンパイル&リンクすれば、良い。

cl dump.c
上記で作成した dump.exe でMZ(4D 5A)ヘッダも確認できる。 50 45 00 00 はPEヘッダー。


このダンププログラムは exe だけに使えるわけではなく、txt ファイルなどにももちろん使える。

たとえばある文字列が exe のヘッダに含まれていることを確認したければ、txt ファイルに文字列を
記述して dump した文字列が、exe のdump結果に含まれているか見ればよい。


PEヘッダーとセクションデータの内容

dumpbin /[オプション] EXEファイル名

FILE HEADER VALUES の number of sections の個数分、section ヘッダー があることを確認できる。

プログラム中に分散したコードやデータは、コードのセクションとデータのセクションにまとめれていることも確認できる。


セクションの内容を見る

dumpbin /rawdata EXEファイル名
RAW DATAのナンバーが、セクションナンバーの数だけある。


逆アセンブル

コマンド: dissm

dumpbin /disasm EXEファイル名

push や mov、call などから、callが関数、pushがそれに渡す引数のように使われていることがわかる。


簡単なプログラムを書いて、コンパイラがどのようにコードを整理するのか確認してみると
おもしろい

次は メモリーロード。






2013年6月30日日曜日

CPPを本格的に始める

データ型を重視した言語。

基本データ型



  1. int 整数型 4byte
  2. float 単精度浮動小数点型 4byte
  3. double 倍精度浮動小数点型 8byte
  4. char 文字型 1byte

コンパイルツール:cl


ex)
cl /c HelloWorld.c

/cはコンパイルのみ行うオプション。自動リンクを行わない。

リンカー:link 


書式:link オブジェクトファイル1 2 … N /OUT:EXEファイル名

プログラムの実行に必要なオブジェクトファイルが指定されていないと、以下のようにエラーとなる。

ex)
HelloWorld.obj : error LNK2019: 未解決の外部シンボル _printf が関数 _main で参照
されました。
LINK : error LNK2001: 外部シンボル "_mainCRTStartup" は未解決です。
HelloWorld.exe : fatal error LNK1120: 2 件の未解決の外部参照


objのシンボルテーブルを確認すると、何が足りないのか発見できる。


オブジェクトファイルの内容確認:dumpbin


ex)
dumpbin HelloWorld.obj /SYMBOLS

COFF SYMBOL TABLE
000 00CEEB9B ABS    notype       Static       | @comp.id
001 80000191 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum
004 00000000 SECT2  notype       Static       | .debug$S
    Section length   68, #relocs    0, #linenums    0, checksum
006 00000000 SECT3  notype       Static       | .data
    Section length    D, #relocs    0, #linenums    0, checksum 9806FD4
008 00000000 SECT3  notype       Static       | $SG2940
009 00000000 SECT4  notype       Static       | .text
    Section length   14, #relocs    2, #linenums    0, checksum F829D91
00B 00000000 UNDEF  notype ()    External     | _printf
00C 00000000 SECT4  notype ()    External     | _main

上の_printfがUNDEFになっている。これが発見できなかったシンボル。


EXEファイルのスタートアップルーチン

スタートアップルーチン:_mainCRTStartup
EXEファイルの実行開始位置。main関数の呼び出し元。

以下で内容を確認できる。

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\crt\src\crt0.c

この中で、_mainCRTStartupが__mainCRTStartupを呼び出し、_tmainを呼び出していることがわかる。引数は、mainの引数と同じ、引数の個数、コマンドライン引数の配列、環境変数の配列


規定のライブラリリンク

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\libcmt.lib
安全のために、上記libを任意のディレクトリにコピーしたあと、下記を実行すると、temp.txtにデフォルトオブジェクトの一覧を記述できる。

lib libcmt.lib /LIST:temp.txt
この中に、printf.objなどの普段何気なく使用するシンボルが並んでいる。

このようにlinkし、エラーとなったオブジェクトをlinkに加えと繰り返すことでリンクを完了させることができる。


次はEXEファイルの構成。