home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

日記/2010/05/25/IMAGE_NT_HEADERSとIMAGE_FILE_HEADERを覗いてみる。

日記/2010/05/25/IMAGE_NT_HEADERSとIMAGE_FILE_HEADERを覗いてみる。

日記 / 2010 / 05 / 25 / IMAGE_NT_HEADERSとIMAGE_FILE_HEADERを覗いてみる。
id: 661 所有者: msakamoto-sf    作成日: 2010-05-25 19:37:40
カテゴリ: Python Windows 

PEフォーマットを覗いてみた。あとついでにPythonを忘れかけてたので復習。

show_nt_header.py:

import sys, logging, struct, ctypes
 
WORD = ctypes.c_ushort
LONG = ctypes.c_long
DWORD = ctypes.c_ulong
 
class IMAGE_DOS_HEADER(ctypes.Structure):
  # 省略
 
class IMAGE_FILE_HEADER(ctypes.Structure):
  _fields_ = [
      ('Machine', WORD),
      ('NumberOfSections', WORD),
      ('TimeDateStamp', DWORD),
      ('PointerToSymbolTable', DWORD),
      ('NumberOfSymbols', DWORD),
      ('SizeOfOptionalHeader', WORD),
      ('Characteristics', WORD),
      ]
 
class IMAGE_NT_HEADERS(ctypes.Structure):
  _fields_ = [
      ('Signature', DWORD),
      ('FileHeader', IMAGE_FILE_HEADER),
#      ('OptionalHeader', IMAGE_OPTIONAL_HEADER32),
# IMAGE_OPTIONAL_HEADERSは後日。
      ]
 
if 2 != len(sys.argv):
  print 'usage: python %s filename' % sys.argv[0]
  quit()
 
file_name = sys.argv[1]
 
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(name)s %(levelname)s %(message)s',
    )
log = logging.getLogger('main')
 
try:
  f = open(file_name, 'rb')
except IOError, e:
  log.error("open(%s) faileed." % file_name)
  log.error(e)
  raise e
 
f.seek(0, 0)
sz = ctypes.sizeof(IMAGE_DOS_HEADER)
data = f.read(sz)
dos_header = IMAGE_DOS_HEADER()
fit = min(len(data), sz)
ctypes.memmove(ctypes.addressof(dos_header), data, fit)
 
f.seek(dos_header.e_lfanew, 0)
sz = ctypes.sizeof(IMAGE_NT_HEADERS)
data = f.read(sz)
pe_header = IMAGE_NT_HEADERS()
fit = min(len(data), sz)
ctypes.memmove(ctypes.addressof(pe_header), data, fit)
 
print "IMAGE_NT_HEADER:"
print "\tSignature: %08X" % pe_header.Signature
print "\tFileHeader: (continued)"
print "-------------------------------"
print "IMAGE_FILE_HEADER:"
print "\tMachine: %04X" % pe_header.FileHeader.Machine
print "\tNumberOfSections: %04X" % pe_header.FileHeader.NumberOfSections
print "\tTimeDateStamp: %08X" % pe_header.FileHeader.TimeDateStamp
print "\tPointerToSymbolTable: %08X" % pe_header.FileHeader.PointerToSymbolTable
print "\tNumberOfSymbols: %08X" % pe_header.FileHeader.NumberOfSymbols
print "\tSizeOfOptionalHeader: %08X" % pe_header.FileHeader.SizeOfOptionalHeader
print "\tCharacteristics: %04X" % pe_header.FileHeader.Characteristics

IMAGE_DOS_HEADERの定義については 日記/2010/05/25/PEフォーマットのIMAGE_DOS_HEADERを眺めてみる 参照。
ということで、 日記/2010/05/25/PEフォーマットのIMAGE_DOS_HEADERを眺めてみる で使ったcui01.exeを使って試してみる。

> show_nt_header.py cui01.exe
IMAGE_NT_HEADER:
        Signature: 00004550
        FileHeader: (continued)
-------------------------------
IMAGE_FILE_HEADER:
        Machine: 014C
        NumberOfSections: 0003
        TimeDateStamp: 4BFB5901
        PointerToSymbolTable: 00000000
        NumberOfSymbols: 00000000
        SizeOfOptionalHeader: 000000E0
        Characteristics: 0103

Signatureは"PE\0\0"がエンディアンの影響でひっくり返った値になってる。Machineについては、WinNT.hを確認してみると i386 が 014Ch とのこと。なので、i386用のバイナリ。
NumberOfSectionsについては、dumpbinで確認すると".data", ".rdata", ".text"の3セクションなので03hでOK。
SizeOfOptionalHeaderについては後日。
Characterisiticsについては次の3つのビットのOR値になってた。

IMAGE_FILE_RELOCS_STRIPPED(0x0001) : 再配置情報はstripされてる
IMAGE_FILE_EXECUTABLE_IMAGE(0x0002) : 実行可能ファイルです
IMAGE_FILE_32BIT_MACHINE(0x0100) : 1ワード32bitのCPU用です

バイナリエディタで、NumberOfSectionsやCharacteristicsを弄ると「有効なWin32アプリケーションではありません」メッセージボックスが表示されたりして面白い。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2010-05-25 19:47:44
md5:a0e16ed93b359d1018ba523c2ac99d5b
sha1:8439078afcb396b544744bacd88ca03bf80c6bd9
コメント
コメントを投稿するにはログインして下さい。