PEフォーマットを覗いてみた。あとついでにPythonを忘れかけてたので復習。 #more|| show_nt_header.py: #code|python|> 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の定義については [[660]] 参照。 ということで、 [[660]] で使ったcui01.exeを使って試してみる。 #pre||> > 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アプリケーションではありません」メッセージボックスが表示されたりして面白い。