15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# -*- coding: Latin-1 -*-
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""pefile, Portable Executable reader module
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)All the PE file basic structures are available with their default names
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)as attributes of the instance returned.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Processed elements such as the import table are made available with lowercase
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)names, to differentiate them from the upper case basic structure names.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pefile has been tested against the limits of valid PE headers, that is, malware.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Lots of packed malware attempt to abuse the format way beyond its standard use.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)To the best of my knowledge most of the abuses are handled gracefully.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Copyright (c) 2005, 2006, 2007, 2008 Ero Carrera <ero@dkbza.org>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)All rights reserved.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)For detailed copyright information see the file COPYING in
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the root of the distribution archive.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__author__ = 'Ero Carrera'
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__version__ = '1.2.9.1'
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)__contact__ = 'ero@dkbza.org'
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import struct
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import math
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import exceptions
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import string
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import array
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sha1, sha256, sha512, md5 = None, None, None, None
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)try:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    import hashlib
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sha1 = hashlib.sha1
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sha256 = hashlib.sha256
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sha512 = hashlib.sha512
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    md5 = hashlib.md5
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)except ImportError:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import sha
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sha1 = sha.new
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except ImportError:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pass
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import md5
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        md5 = md5.new
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except ImportError:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pass
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fast_load = False
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_DOS_SIGNATURE             = 0x5A4D
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_OS2_SIGNATURE             = 0x454E
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_OS2_SIGNATURE_LE          = 0x454C
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_VXD_SIGNATURE             = 0x454C
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_NT_SIGNATURE              = 0x00004550
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_NUMBEROF_DIRECTORY_ENTRIES= 16
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_ORDINAL_FLAG              = 0x80000000L
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_ORDINAL_FLAG64            = 0x8000000000000000L
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OPTIONAL_HEADER_MAGIC_PE        = 0x10b
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OPTIONAL_HEADER_MAGIC_PE_PLUS   = 0x20b
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)directory_entry_types = [
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_EXPORT',        0),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_IMPORT',        1),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_RESOURCE',      2),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_EXCEPTION',     3),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_SECURITY',      4),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_BASERELOC',     5),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_DEBUG',         6),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_COPYRIGHT',     7),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_GLOBALPTR',     8),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_TLS',           9),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG',   10),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT',  11),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_IAT',           12),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT',  13),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR',14),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DIRECTORY_ENTRY_RESERVED',      15) ]
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DIRECTORY_ENTRY = dict([(e[1], e[0]) for e in directory_entry_types]+directory_entry_types)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)image_characteristics = [
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_RELOCS_STRIPPED',          0x0001),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_EXECUTABLE_IMAGE',         0x0002),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_LINE_NUMS_STRIPPED',       0x0004),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_LOCAL_SYMS_STRIPPED',      0x0008),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_AGGRESIVE_WS_TRIM',        0x0010),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_LARGE_ADDRESS_AWARE',      0x0020),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_16BIT_MACHINE',            0x0040),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_BYTES_REVERSED_LO',        0x0080),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_32BIT_MACHINE',            0x0100),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_DEBUG_STRIPPED',           0x0200),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP',  0x0400),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_NET_RUN_FROM_SWAP',        0x0800),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_SYSTEM',                   0x1000),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_DLL',                      0x2000),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_UP_SYSTEM_ONLY',           0x4000),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_BYTES_REVERSED_HI',        0x8000) ]
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IMAGE_CHARACTERISTICS = dict([(e[1], e[0]) for e in
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_characteristics]+image_characteristics)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)section_characteristics = [
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_CNT_CODE',                  0x00000020),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_CNT_INITIALIZED_DATA',      0x00000040),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_CNT_UNINITIALIZED_DATA',    0x00000080),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_LNK_OTHER',                 0x00000100),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_LNK_INFO',                  0x00000200),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_LNK_REMOVE',                0x00000800),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_LNK_COMDAT',                0x00001000),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_FARDATA',               0x00008000),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_PURGEABLE',             0x00020000),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_16BIT',                 0x00020000),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_LOCKED',                0x00040000),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_PRELOAD',               0x00080000),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_1BYTES',              0x00100000),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_2BYTES',              0x00200000),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_4BYTES',              0x00300000),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_8BYTES',              0x00400000),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_16BYTES',             0x00500000),
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_32BYTES',             0x00600000),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_64BYTES',             0x00700000),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_128BYTES',            0x00800000),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_256BYTES',            0x00900000),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_512BYTES',            0x00A00000),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_1024BYTES',           0x00B00000),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_2048BYTES',           0x00C00000),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_4096BYTES',           0x00D00000),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_8192BYTES',           0x00E00000),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_ALIGN_MASK',                0x00F00000),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_LNK_NRELOC_OVFL',           0x01000000),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_DISCARDABLE',           0x02000000),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_NOT_CACHED',            0x04000000),
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_NOT_PAGED',             0x08000000),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_SHARED',                0x10000000),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_EXECUTE',               0x20000000),
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_READ',                  0x40000000),
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SCN_MEM_WRITE',                 0x80000000L) ]
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECTION_CHARACTERISTICS = dict([(e[1], e[0]) for e in
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    section_characteristics]+section_characteristics)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)debug_types = [
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_UNKNOWN',        0),
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_COFF',           1),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_CODEVIEW',       2),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_FPO',            3),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_MISC',           4),
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_EXCEPTION',      5),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_FIXUP',          6),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_OMAP_TO_SRC',    7),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_OMAP_FROM_SRC',  8),
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_BORLAND',        9),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DEBUG_TYPE_RESERVED10',     10) ]
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEBUG_TYPE = dict([(e[1], e[0]) for e in debug_types]+debug_types)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)subsystem_types = [
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_UNKNOWN',     0),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_NATIVE',      1),
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_WINDOWS_GUI', 2),
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_WINDOWS_CUI', 3),
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_OS2_CUI',     5),
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_POSIX_CUI',   7),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI',  9),
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_EFI_APPLICATION', 10),
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', 11),
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER',      12),
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_EFI_ROM',     13),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_SUBSYSTEM_XBOX',        14)]
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SUBSYSTEM_TYPE = dict([(e[1], e[0]) for e in subsystem_types]+subsystem_types)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)machine_types = [
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_UNKNOWN',  0),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_AM33',     0x1d3),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_AMD64',    0x8664),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_ARM',      0x1c0),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_EBC',      0xebc),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_I386',     0x14c),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_IA64',     0x200),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_MR32',     0x9041),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_MIPS16',   0x266),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_MIPSFPU',  0x366),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_MIPSFPU16',0x466),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_POWERPC',  0x1f0),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_POWERPCFP',0x1f1),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_R4000',    0x166),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_SH3',      0x1a2),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_SH3DSP',   0x1a3),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_SH4',      0x1a6),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_SH5',      0x1a8),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_THUMB',    0x1c2),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_FILE_MACHINE_WCEMIPSV2',0x169),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MACHINE_TYPE = dict([(e[1], e[0]) for e in machine_types]+machine_types)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)relocation_types = [
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_ABSOLUTE',        0),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_HIGH',            1),
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_LOW',             2),
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_HIGHLOW',         3),
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_HIGHADJ',         4),
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_MIPS_JMPADDR',    5),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_SECTION',         6),
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_REL',             7),
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_MIPS_JMPADDR16',  9),
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_IA64_IMM64',      9),
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_DIR64',           10),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_REL_BASED_HIGH3ADJ',        11) ]
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RELOCATION_TYPE = dict([(e[1], e[0]) for e in relocation_types]+relocation_types)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dll_characteristics = [
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0001', 0x0001),
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0002', 0x0002),
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0004', 0x0004),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0008', 0x0008),
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE',      0x0040),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY',   0x0080),
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT',         0x0100),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION',      0x0200),
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_NO_SEH',    0x0400),
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_NO_BIND',   0x0800),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x1000', 0x1000),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER',    0x2000),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE', 0x8000) ]
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DLL_CHARACTERISTICS = dict([(e[1], e[0]) for e in dll_characteristics]+dll_characteristics)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Resource types
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)resource_type = [
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_CURSOR',          1),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_BITMAP',          2),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_ICON',            3),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_MENU',            4),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_DIALOG',          5),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_STRING',          6),
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_FONTDIR',         7),
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_FONT',            8),
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_ACCELERATOR',     9),
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_RCDATA',          10),
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_MESSAGETABLE',    11),
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_GROUP_CURSOR',    12),
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_GROUP_ICON',      14),
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_VERSION',         16),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_DLGINCLUDE',      17),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_PLUGPLAY',        19),
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_VXD',             20),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_ANICURSOR',       21),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_ANIICON',         22),
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_HTML',            23),
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('RT_MANIFEST',        24) ]
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RESOURCE_TYPE = dict([(e[1], e[0]) for e in resource_type]+resource_type)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Language definitions
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)lang = [
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_NEUTRAL',       0x00),
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_INVARIANT',     0x7f),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_AFRIKAANS',     0x36),
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ALBANIAN',      0x1c),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ARABIC',        0x01),
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ARMENIAN',      0x2b),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ASSAMESE',      0x4d),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_AZERI',         0x2c),
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_BASQUE',        0x2d),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_BELARUSIAN',    0x23),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_BENGALI',       0x45),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_BULGARIAN',     0x02),
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_CATALAN',       0x03),
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_CHINESE',       0x04),
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_CROATIAN',      0x1a),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_CZECH',         0x05),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_DANISH',        0x06),
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_DIVEHI',        0x65),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_DUTCH',         0x13),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ENGLISH',       0x09),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ESTONIAN',      0x25),
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_FAEROESE',      0x38),
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_FARSI',         0x29),
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_FINNISH',       0x0b),
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_FRENCH',        0x0c),
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GALICIAN',      0x56),
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GEORGIAN',      0x37),
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GERMAN',        0x07),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GREEK',         0x08),
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GUJARATI',      0x47),
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_HEBREW',        0x0d),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_HINDI',         0x39),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_HUNGARIAN',     0x0e),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ICELANDIC',     0x0f),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_INDONESIAN',    0x21),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ITALIAN',       0x10),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_JAPANESE',      0x11),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KANNADA',       0x4b),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KASHMIRI',      0x60),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KAZAK',         0x3f),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KONKANI',       0x57),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KOREAN',        0x12),
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_KYRGYZ',        0x40),
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_LATVIAN',       0x26),
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_LITHUANIAN',    0x27),
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MACEDONIAN',    0x2f),
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MALAY',         0x3e),
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MALAYALAM',     0x4c),
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MANIPURI',      0x58),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MARATHI',       0x4e),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MONGOLIAN',     0x50),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_NEPALI',        0x61),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_NORWEGIAN',     0x14),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ORIYA',         0x48),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_POLISH',        0x15),
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_PORTUGUESE',    0x16),
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_PUNJABI',       0x46),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ROMANIAN',      0x18),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_RUSSIAN',       0x19),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SANSKRIT',      0x4f),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SERBIAN',       0x1a),
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SINDHI',        0x59),
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SLOVAK',        0x1b),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SLOVENIAN',     0x24),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SPANISH',       0x0a),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SWAHILI',       0x41),
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SWEDISH',       0x1d),
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SYRIAC',        0x5a),
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TAMIL',         0x49),
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TATAR',         0x44),
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TELUGU',        0x4a),
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_THAI',          0x1e),
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TURKISH',       0x1f),
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_UKRAINIAN',     0x22),
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_URDU',          0x20),
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_UZBEK',         0x43),
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_VIETNAMESE',    0x2a),
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_GAELIC',        0x3c),
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MALTESE',       0x3a),
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_MAORI',         0x28),
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_RHAETO_ROMANCE',0x17),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SAAMI',         0x3b),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SORBIAN',       0x2e),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_SUTU',          0x30),
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TSONGA',        0x31),
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_TSWANA',        0x32),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_VENDA',         0x33),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_XHOSA',         0x34),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ZULU',          0x35),
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_ESPERANTO',     0x8f),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_WALON',         0x90),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_CORNISH',       0x91),
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_WELSH',         0x92),
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('LANG_BRETON',        0x93) ]
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LANG = dict(lang+[(e[1], e[0]) for e in lang])
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Sublanguage definitions
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sublang =  [
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_NEUTRAL',                        0x00),
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_DEFAULT',                        0x01),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SYS_DEFAULT',                    0x02),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_SAUDI_ARABIA',            0x01),
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_IRAQ',                    0x02),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_EGYPT',                   0x03),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_LIBYA',                   0x04),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_ALGERIA',                 0x05),
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_MOROCCO',                 0x06),
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_TUNISIA',                 0x07),
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_OMAN',                    0x08),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_YEMEN',                   0x09),
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_SYRIA',                   0x0a),
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_JORDAN',                  0x0b),
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_LEBANON',                 0x0c),
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_KUWAIT',                  0x0d),
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_UAE',                     0x0e),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_BAHRAIN',                 0x0f),
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ARABIC_QATAR',                   0x10),
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_AZERI_LATIN',                    0x01),
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_AZERI_CYRILLIC',                 0x02),
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CHINESE_TRADITIONAL',            0x01),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CHINESE_SIMPLIFIED',             0x02),
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CHINESE_HONGKONG',               0x03),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CHINESE_SINGAPORE',              0x04),
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CHINESE_MACAU',                  0x05),
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_DUTCH',                          0x01),
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_DUTCH_BELGIAN',                  0x02),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_US',                     0x01),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_UK',                     0x02),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_AUS',                    0x03),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_CAN',                    0x04),
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_NZ',                     0x05),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_EIRE',                   0x06),
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_SOUTH_AFRICA',           0x07),
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_JAMAICA',                0x08),
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_CARIBBEAN',              0x09),
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_BELIZE',                 0x0a),
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_TRINIDAD',               0x0b),
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_ZIMBABWE',               0x0c),
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ENGLISH_PHILIPPINES',            0x0d),
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH',                         0x01),
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH_BELGIAN',                 0x02),
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH_CANADIAN',                0x03),
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH_SWISS',                   0x04),
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH_LUXEMBOURG',              0x05),
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_FRENCH_MONACO',                  0x06),
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GERMAN',                         0x01),
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GERMAN_SWISS',                   0x02),
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GERMAN_AUSTRIAN',                0x03),
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GERMAN_LUXEMBOURG',              0x04),
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GERMAN_LIECHTENSTEIN',           0x05),
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ITALIAN',                        0x01),
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ITALIAN_SWISS',                  0x02),
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_KASHMIRI_SASIA',                 0x02),
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_KASHMIRI_INDIA',                 0x02),
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_KOREAN',                         0x01),
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_LITHUANIAN',                     0x01),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_MALAY_MALAYSIA',                 0x01),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_MALAY_BRUNEI_DARUSSALAM',        0x02),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_NEPALI_INDIA',                   0x02),
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_NORWEGIAN_BOKMAL',               0x01),
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_NORWEGIAN_NYNORSK',              0x02),
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_PORTUGUESE',                     0x02),
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_PORTUGUESE_BRAZILIAN',           0x01),
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SERBIAN_LATIN',                  0x02),
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SERBIAN_CYRILLIC',               0x03),
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH',                        0x01),
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_MEXICAN',                0x02),
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_MODERN',                 0x03),
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_GUATEMALA',              0x04),
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_COSTA_RICA',             0x05),
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_PANAMA',                 0x06),
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_DOMINICAN_REPUBLIC',     0x07),
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_VENEZUELA',              0x08),
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_COLOMBIA',               0x09),
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_PERU',                   0x0a),
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_ARGENTINA',              0x0b),
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_ECUADOR',                0x0c),
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_CHILE',                  0x0d),
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_URUGUAY',                0x0e),
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_PARAGUAY',               0x0f),
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_BOLIVIA',                0x10),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_EL_SALVADOR',            0x11),
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_HONDURAS',               0x12),
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_NICARAGUA',              0x13),
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SPANISH_PUERTO_RICO',            0x14),
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SWEDISH',                        0x01),
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_SWEDISH_FINLAND',                0x02),
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_URDU_PAKISTAN',                  0x01),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_URDU_INDIA',                     0x02),
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_UZBEK_LATIN',                    0x01),
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_UZBEK_CYRILLIC',                 0x02),
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_DUTCH_SURINAM',                  0x03),
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ROMANIAN',                       0x01),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_ROMANIAN_MOLDAVIA',              0x02),
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_RUSSIAN',                        0x01),
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_RUSSIAN_MOLDAVIA',               0x02),
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_CROATIAN',                       0x01),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_LITHUANIAN_CLASSIC',             0x02),
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GAELIC',                         0x01),
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GAELIC_SCOTTISH',                0x02),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('SUBLANG_GAELIC_MANX',                    0x03) ]
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SUBLANG = dict(sublang+[(e[1], e[0]) for e in sublang])
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnicodeStringWrapperPostProcessor:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """This class attemps to help the process of identifying strings
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    that might be plain Unicode or Pascal. A list of strings will be
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapped on it with the hope the overlappings will help make the
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decission about their type."""
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, pe, rva_ptr):
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.pe = pe
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.rva_ptr = rva_ptr
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.string = None
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_rva(self):
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the RVA of the string."""
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.rva_ptr
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __str__(self):
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the escaped ASCII representation of the string."""
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        def convert_char(char):
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if char in string.printable:
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return char
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return r'\x%02x' % ord(char)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.string:
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ''.join([convert_char(c) for c in self.string])
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ''
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def invalidate(self):
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Make this instance None, to express it's no known string type."""
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self = None
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def render_pascal_16(self):
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.string = self.pe.get_string_u_at_rva(
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.rva_ptr+2,
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            max_length=self.__get_pascal_16_length())
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ask_pascal_16(self, next_rva_ptr):
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """The next RVA is taken to be the one immediately following this one.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Such RVA could indicate the natural end of the string and will be checked
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        with the possible length contained in the first word.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        length = self.__get_pascal_16_length()
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if length == (next_rva_ptr - (self.rva_ptr+2)) / 2:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.length = length
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return True
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return False
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __get_pascal_16_length(self):
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.__get_word_value_at_rva(self.rva_ptr)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __get_word_value_at_rva(self, rva):
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data = self.pe.get_data(self.rva_ptr, 2)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, e:
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return False
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(data)<2:
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return False
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.unpack('<H', data)[0]
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #def render_pascal_8(self):
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #    """"""
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ask_unicode_16(self, next_rva_ptr):
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """The next RVA is taken to be the one immediately following this one.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Such RVA could indicate the natural end of the string and will be checked
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to see if there's a Unicode NULL character there.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.__get_word_value_at_rva(next_rva_ptr-2) == 0:
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.length = next_rva_ptr - self.rva_ptr
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return True
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return False
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def render_unicode_16(self):
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.string = self.pe.get_string_u_at_rva(self.rva_ptr)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PEFormatError(Exception):
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generic PE format error exception."""
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, value):
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.value = value
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __str__(self):
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return repr(self.value)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Dump:
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Convenience class for dumping the PE information."""
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self):
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.text = ''
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add_lines(self, txt, indent=0):
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Adds a list of lines.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The list can be indented with the optional argument 'indent'.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for line in txt:
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.add_line(line, indent)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add_line(self, txt, indent=0):
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Adds a line.
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The line can be indented with the optional argument 'indent'.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.add(txt+'\n', indent)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add(self, txt, indent=0):
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Adds some text, no newline will be appended.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The text can be indented with the optional argument 'indent'.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if isinstance(txt, unicode):
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s = []
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for c in txt:
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                try:
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    s.append(str(c))
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                except UnicodeEncodeError, e:
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    s.append(repr(c))
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            txt = ''.join(s)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.text += ' '*indent+txt
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add_header(self, txt):
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Adds a header element."""
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.add_line('-'*10+txt+'-'*10+'\n')
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add_newline(self):
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Adds a newline."""
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.text += '\n'
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_text(self):
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the text in its current state."""
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.text
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Structure:
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Prepare structure object to extract members from data.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Format is a list containing definitions for the elements
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    of the structure.
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, format, name=None, file_offset=None):
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Format is forced little endian, for big endian non Intel platforms
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__format__ = '<'
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__keys__ = []
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        self.values = {}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__format_length__ = 0
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__set_format__(format[1])
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._all_zeroes = False
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__unpacked_data_elms__ = None
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__file_offset__ = file_offset
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if name:
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.name = name
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.name = format[0]
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __get_format__(self):
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.__format__
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_file_offset(self):
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.__file_offset__
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_file_offset(self, offset):
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__file_offset__ = offset
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def all_zeroes(self):
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Returns true is the unpacked data is all zeroes."""
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self._all_zeroes
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __set_format__(self, format):
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for elm in format:
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ',' in elm:
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elm_type, elm_name = elm.split(',', 1)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__format__ += elm_type
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elm_names = elm_name.split(',')
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                names = []
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for elm_name in elm_names:
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if elm_name in self.__keys__:
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        search_list = [x[:len(elm_name)] for x in self.__keys__]
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        occ_count = search_list.count(elm_name)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        elm_name = elm_name+'_'+str(occ_count)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    names.append(elm_name)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Some PE header structures have unions on them, so a certain
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # value might have different names, so each key has a list of
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # all the possible members referring to the data.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__keys__.append(names)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__format_length__ = struct.calcsize(self.__format__)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def sizeof(self):
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return size of the structure."""
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.__format_length__
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __unpack__(self, data):
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(data)>self.__format_length__:
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data = data[:self.__format_length__]
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Some malware have incorrect header lengths.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Fail gracefully if this occurs
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Buggy malware: a29b0118af8b7408444df81701ad5a7f
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif len(data)<self.__format_length__:
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('Data length less than expected header length.')
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if data.count(chr(0)) == len(data):
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self._all_zeroes = True
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__unpacked_data_elms__ = struct.unpack(self.__format__, data)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in xrange(len(self.__unpacked_data_elms__)):
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for key in self.__keys__[i]:
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#                self.values[key] = self.__unpacked_data_elms__[i]
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                setattr(self, key, self.__unpacked_data_elms__[i])
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __pack__(self):
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_values = []
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in xrange(len(self.__unpacked_data_elms__)):
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for key in self.__keys__[i]:
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                new_val = getattr(self, key)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                old_val = self.__unpacked_data_elms__[i]
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # In the case of Unions, when the first changed value
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # is picked the loop is exited
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if new_val != old_val:
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new_values.append(new_val)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.pack(self.__format__, *new_values)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __str__(self):
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return '\n'.join( self.dump() )
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __repr__(self):
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return '<Structure: %s>' % (' '.join( [' '.join(s.split()) for s in self.dump()] ))
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def dump(self, indentation=0):
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Returns a string representation of the structure."""
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump = []
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.append('[%s]' % self.name)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Refer to the __set_format__ method for an explanation
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # of the following construct.
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for keys in self.__keys__:
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for key in keys:
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                val = getattr(self, key)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if isinstance(val, int) or isinstance(val, long):
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    val_str = '0x%-8X' % (val)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if key == 'TimeDateStamp' or key == 'dwTimeStamp':
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        try:
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            val_str += ' [%s UTC]' % time.asctime(time.gmtime(val))
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        except exceptions.ValueError, e:
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            val_str += ' [INVALID TIME]'
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    val_str = ''.join(filter(lambda c:c != '\0', str(val)))
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.append('%-30s %s' % (key+':', val_str))
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return dump
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SectionStructure(Structure):
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Convenience section handling class."""
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_data(self, start, length=None):
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get data chunk from a section.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Allows to query data from the section by passing the
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        addresses where the PE file would be loaded by default.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        It is then possible to retrieve code and data by its real
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        addresses as it would be if loaded.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset = start - self.VirtualAddress
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if length:
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            end = offset+length
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            end = len(self.data)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.data[offset:end]
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_rva_from_offset(self, offset):
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return offset - self.PointerToRawData + self.VirtualAddress
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_offset_from_rva(self, rva):
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (rva - self.VirtualAddress) + self.PointerToRawData
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def contains_offset(self, offset):
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Check whether the section contains the file offset provided."""
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not self.PointerToRawData:
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           # bss and other sections containing only uninitialized data must have 0
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           # and do not take space in the file
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           return False
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.PointerToRawData <= offset < self.VirtualAddress + self.SizeOfRawData
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def contains_rva(self, rva):
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Check whether the section contains the address provided."""
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # PECOFF documentation v8 says:
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # The total size of the section when loaded into memory.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # If this value is greater than SizeOfRawData, the section is zero-padded.
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # This field is valid only for executable images and should be set to zero
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # for object files.
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(self.data) < self.SizeOfRawData:
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size = self.Misc_VirtualSize
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size = max(self.SizeOfRawData, self.Misc_VirtualSize)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.VirtualAddress <= rva < self.VirtualAddress + size
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def contains(self, rva):
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #print "DEPRECATION WARNING: you should use contains_rva() instead of contains()"
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.contains_rva(rva)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_data(self, data):
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the data belonging to the section."""
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.data = data
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_entropy(self):
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Calculate and return the entropy for the section."""
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.entropy_H( self.data )
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_hash_sha1(self):
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the SHA-1 hex-digest of the section's data."""
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if sha1 is not None:
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return sha1( self.data ).hexdigest()
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_hash_sha256(self):
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the SHA-256 hex-digest of the section's data."""
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if sha256 is not None:
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return sha256( self.data ).hexdigest()
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_hash_sha512(self):
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the SHA-512 hex-digest of the section's data."""
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if sha512 is not None:
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return sha512( self.data ).hexdigest()
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_hash_md5(self):
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the MD5 hex-digest of the section's data."""
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if md5 is not None:
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return md5( self.data ).hexdigest()
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def entropy_H(self, data):
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Calculate the entropy of a chunk of data."""
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(data) == 0:
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 0.0
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        occurences = array.array('L', [0]*256)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for x in data:
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            occurences[ord(x)] += 1
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entropy = 0
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for x in occurences:
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if x:
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                p_x = float(x) / len(data)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entropy -= p_x*math.log(p_x, 2)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return entropy
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DataContainer:
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generic data container."""
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, **args):
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for key, value in args.items():
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            setattr(self, key, value)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImportDescData(DataContainer):
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds import descriptor information.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dll:        name of the imported DLL
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    imports:    list of imported symbols (ImportData instances)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_IMPORT_DESCRIPTOR sctruture
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImportData(DataContainer):
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds imported symbol's information.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ordinal:    Ordinal of the symbol
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name:       Name of the symbol
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bound:      If the symbol is bound, this contains
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                the address.
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExportDirData(DataContainer):
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds export directory information.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_EXPORT_DIRECTORY structure
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    symbols:    list of exported symbols (ExportData instances)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExportData(DataContainer):
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds exported symbols' information.
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ordinal:    ordinal of the symbol
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    address:    address of the symbol
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name:       name of the symbol (None if the symbol is
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                exported by ordinal only)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    forwarder:  if the symbol is forwarded it will
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                contain the name of the target symbol,
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                None otherwise.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceDirData(DataContainer):
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds resource directory information.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_RESOURCE_DIRECTORY structure
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries:    list of entries (ResourceDirEntryData instances)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceDirEntryData(DataContainer):
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds resource directory entry data.
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_RESOURCE_DIRECTORY_ENTRY structure
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name:       If the resource is identified by name this
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                attribute will contain the name string. None
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                otherwise. If identified by id, the id is
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                availabe at 'struct.Id'
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    id:         the id, also in struct.Id
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    directory:  If this entry has a lower level directory
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this attribute will point to the
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ResourceDirData instance representing it.
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data:       If this entry has no futher lower directories
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                and points to the actual resource data, this
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                attribute will reference the corresponding
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ResourceDataEntryData instance.
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (Either of the 'directory' or 'data' attribute will exist,
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    but not both.)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceDataEntryData(DataContainer):
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds resource data entry information.
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_RESOURCE_DATA_ENTRY structure
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lang:       Primary language ID
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sublang:    Sublanguage ID
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DebugData(DataContainer):
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds debug information.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_DEBUG_DIRECTORY structure
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseRelocationData(DataContainer):
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds base relocation information.
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_BASE_RELOCATION structure
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries:    list of relocation data (RelocationData instances)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RelocationData(DataContainer):
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds relocation information.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type:       Type of relocation
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                The type string is can be obtained by
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                RELOCATION_TYPE[type]
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rva:        RVA of the relocation
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TlsData(DataContainer):
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds TLS information.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_TLS_DIRECTORY structure
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BoundImportDescData(DataContainer):
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds bound import descriptor data.
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This directory entry will provide with information on the
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLLs this PE files has been bound to (if bound at all).
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The structure will contain the name and timestamp of the
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLL at the time of binding so that the loader can know
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    whether it differs from the one currently present in the
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system and must, therefore, re-bind the PE's imports.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_BOUND_IMPORT_DESCRIPTOR structure
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name:       DLL name
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries:    list of entries (BoundImportRefData instances)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                the entries will exist if this DLL has forwarded
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                symbols. If so, the destination DLL will have an
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entry in this list.
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BoundImportRefData(DataContainer):
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Holds bound import forwader reference data.
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Contains the same information as the bound descriptor but
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for forwarded DLLs, if any.
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct:     IMAGE_BOUND_FORWARDER_REF structure
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name:       dll name
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PE:
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """A Portable Executable representation.
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This class provides access to most of the information in a PE file.
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    It expects to be supplied the name of the file to load or PE data
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to process and an optional argument 'fast_load' (False by default)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    which controls whether to load all the directories information,
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    which can be quite time consuming.
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pe = pefile.PE('module.dll')
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pe = pefile.PE(name='module.dll')
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    would load 'module.dll' and process it. If the data would be already
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    available in a buffer the same could be achieved with:
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pe = pefile.PE(data=module_dll_data)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The "fast_load" can be set to a default by setting its value in the
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module itself by means,for instance, of a "pefile.fast_load = True".
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    That will make all the subsequent instances not to load the
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    whole PE structure. The "full_load" method can be used to parse
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    the missing data at a later stage.
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Basic headers information will be available in the attributes:
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DOS_HEADER
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NT_HEADERS
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_HEADER
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTIONAL_HEADER
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    All of them will contain among their attrbitues the members of the
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    corresponding structures as defined in WINNT.H
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The raw data corresponding to the header (from the beginning of the
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file up to the start of the first section) will be avaiable in the
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance's attribute 'header' as a string.
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The sections will be available as a list in the 'sections' attribute.
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Each entry will contain as attributes all the structure's members.
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Directory entries will be available as attributes (if they exist):
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (no other entries are processed at this point)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_IMPORT (list of ImportDescData instances)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_EXPORT (ExportDirData instance)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_RESOURCE (ResourceDirData instance)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_DEBUG (list of DebugData instances)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_BASERELOC (list of BaseRelocationData instances)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_TLS
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY_BOUND_IMPORT (list of BoundImportData instances)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The following dictionary attributes provide ways of mapping different
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    constants. They will accept the numeric value and return the string
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    representation and the opposite, feed in the string and get the
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    numeric constant:
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIRECTORY_ENTRY
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IMAGE_CHARACTERISTICS
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECTION_CHARACTERISTICS
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_TYPE
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SUBSYSTEM_TYPE
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MACHINE_TYPE
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RELOCATION_TYPE
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RESOURCE_TYPE
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LANG
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SUBLANG
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Format specifications for PE structures.
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_DOS_HEADER_format__ = ('IMAGE_DOS_HEADER',
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,e_magic', 'H,e_cblp', 'H,e_cp',
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,e_crlc', 'H,e_cparhdr', 'H,e_minalloc',
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,e_maxalloc', 'H,e_ss', 'H,e_sp', 'H,e_csum',
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,e_ip', 'H,e_cs', 'H,e_lfarlc', 'H,e_ovno', '8s,e_res',
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,e_oemid', 'H,e_oeminfo', '20s,e_res2',
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,e_lfanew'))
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_FILE_HEADER_format__ = ('IMAGE_FILE_HEADER',
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Machine', 'H,NumberOfSections',
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,TimeDateStamp', 'L,PointerToSymbolTable',
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,NumberOfSymbols', 'H,SizeOfOptionalHeader',
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,Characteristics'))
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_DATA_DIRECTORY_format__ = ('IMAGE_DATA_DIRECTORY',
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,VirtualAddress', 'L,Size'))
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_OPTIONAL_HEADER_format__ = ('IMAGE_OPTIONAL_HEADER',
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Magic', 'B,MajorLinkerVersion',
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'B,MinorLinkerVersion', 'L,SizeOfCode',
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfInitializedData', 'L,SizeOfUninitializedData',
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,AddressOfEntryPoint', 'L,BaseOfCode', 'L,BaseOfData',
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,ImageBase', 'L,SectionAlignment', 'L,FileAlignment',
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorOperatingSystemVersion', 'H,MinorOperatingSystemVersion',
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorImageVersion', 'H,MinorImageVersion',
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorSubsystemVersion', 'H,MinorSubsystemVersion',
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,Reserved1', 'L,SizeOfImage', 'L,SizeOfHeaders',
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,CheckSum', 'H,Subsystem', 'H,DllCharacteristics',
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfStackReserve', 'L,SizeOfStackCommit',
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfHeapReserve', 'L,SizeOfHeapCommit',
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,LoaderFlags', 'L,NumberOfRvaAndSizes' ))
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_OPTIONAL_HEADER64_format__ = ('IMAGE_OPTIONAL_HEADER64',
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Magic', 'B,MajorLinkerVersion',
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'B,MinorLinkerVersion', 'L,SizeOfCode',
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfInitializedData', 'L,SizeOfUninitializedData',
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,AddressOfEntryPoint', 'L,BaseOfCode',
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Q,ImageBase', 'L,SectionAlignment', 'L,FileAlignment',
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorOperatingSystemVersion', 'H,MinorOperatingSystemVersion',
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorImageVersion', 'H,MinorImageVersion',
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MajorSubsystemVersion', 'H,MinorSubsystemVersion',
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,Reserved1', 'L,SizeOfImage', 'L,SizeOfHeaders',
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,CheckSum', 'H,Subsystem', 'H,DllCharacteristics',
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Q,SizeOfStackReserve', 'Q,SizeOfStackCommit',
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Q,SizeOfHeapReserve', 'Q,SizeOfHeapCommit',
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,LoaderFlags', 'L,NumberOfRvaAndSizes' ))
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_NT_HEADERS_format__ = ('IMAGE_NT_HEADERS', ('L,Signature',))
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_SECTION_HEADER_format__ = ('IMAGE_SECTION_HEADER',
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('8s,Name', 'L,Misc,Misc_PhysicalAddress,Misc_VirtualSize',
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,VirtualAddress', 'L,SizeOfRawData', 'L,PointerToRawData',
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,PointerToRelocations', 'L,PointerToLinenumbers',
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,NumberOfRelocations', 'H,NumberOfLinenumbers',
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,Characteristics'))
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_DELAY_IMPORT_DESCRIPTOR_format__ = ('IMAGE_DELAY_IMPORT_DESCRIPTOR',
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,grAttrs', 'L,szName', 'L,phmod', 'L,pIAT', 'L,pINT',
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,pBoundIAT', 'L,pUnloadIAT', 'L,dwTimeStamp'))
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_IMPORT_DESCRIPTOR_format__ =  ('IMAGE_IMPORT_DESCRIPTOR',
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,OriginalFirstThunk,Characteristics',
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,TimeDateStamp', 'L,ForwarderChain', 'L,Name', 'L,FirstThunk'))
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_EXPORT_DIRECTORY_format__ =  ('IMAGE_EXPORT_DIRECTORY',
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,Characteristics',
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,TimeDateStamp', 'H,MajorVersion', 'H,MinorVersion', 'L,Name',
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,Base', 'L,NumberOfFunctions', 'L,NumberOfNames',
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,AddressOfFunctions', 'L,AddressOfNames', 'L,AddressOfNameOrdinals'))
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_RESOURCE_DIRECTORY_format__ = ('IMAGE_RESOURCE_DIRECTORY',
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,Characteristics',
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,TimeDateStamp', 'H,MajorVersion', 'H,MinorVersion',
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,NumberOfNamedEntries', 'H,NumberOfIdEntries'))
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_RESOURCE_DIRECTORY_ENTRY_format__ = ('IMAGE_RESOURCE_DIRECTORY_ENTRY',
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,Name',
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,OffsetToData'))
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_RESOURCE_DATA_ENTRY_format__ = ('IMAGE_RESOURCE_DATA_ENTRY',
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,OffsetToData', 'L,Size', 'L,CodePage', 'L,Reserved'))
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __VS_VERSIONINFO_format__ = ( 'VS_VERSIONINFO',
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Length', 'H,ValueLength', 'H,Type' ))
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __VS_FIXEDFILEINFO_format__ = ( 'VS_FIXEDFILEINFO',
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,Signature', 'L,StrucVersion', 'L,FileVersionMS', 'L,FileVersionLS',
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'L,ProductVersionMS', 'L,ProductVersionLS', 'L,FileFlagsMask', 'L,FileFlags',
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'L,FileOS', 'L,FileType', 'L,FileSubtype', 'L,FileDateMS', 'L,FileDateLS'))
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __StringFileInfo_format__ = ( 'StringFileInfo',
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Length', 'H,ValueLength', 'H,Type' ))
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __StringTable_format__ = ( 'StringTable',
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Length', 'H,ValueLength', 'H,Type' ))
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __String_format__ = ( 'String',
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('H,Length', 'H,ValueLength', 'H,Type' ))
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __Var_format__ = ( 'Var', ('H,Length', 'H,ValueLength', 'H,Type' ))
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_THUNK_DATA_format__ = ('IMAGE_THUNK_DATA',
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,ForwarderString,Function,Ordinal,AddressOfData',))
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_THUNK_DATA64_format__ = ('IMAGE_THUNK_DATA',
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('Q,ForwarderString,Function,Ordinal,AddressOfData',))
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_DEBUG_DIRECTORY_format__ = ('IMAGE_DEBUG_DIRECTORY',
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,Characteristics', 'L,TimeDateStamp', 'H,MajorVersion',
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'H,MinorVersion', 'L,Type', 'L,SizeOfData', 'L,AddressOfRawData',
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,PointerToRawData'))
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_BASE_RELOCATION_format__ = ('IMAGE_BASE_RELOCATION',
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,VirtualAddress', 'L,SizeOfBlock') )
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_TLS_DIRECTORY_format__ = ('IMAGE_TLS_DIRECTORY',
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,StartAddressOfRawData', 'L,EndAddressOfRawData',
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,AddressOfIndex', 'L,AddressOfCallBacks',
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfZeroFill', 'L,Characteristics' ) )
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_TLS_DIRECTORY64_format__ = ('IMAGE_TLS_DIRECTORY',
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('Q,StartAddressOfRawData', 'Q,EndAddressOfRawData',
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'Q,AddressOfIndex', 'Q,AddressOfCallBacks',
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'L,SizeOfZeroFill', 'L,Characteristics' ) )
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ = ('IMAGE_BOUND_IMPORT_DESCRIPTOR',
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,TimeDateStamp', 'H,OffsetModuleName', 'H,NumberOfModuleForwarderRefs'))
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __IMAGE_BOUND_FORWARDER_REF_format__ = ('IMAGE_BOUND_FORWARDER_REF',
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ('L,TimeDateStamp', 'H,OffsetModuleName', 'H,Reserved') )
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, name=None, data=None, fast_load=None):
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.sections = []
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__warnings = []
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.PE_TYPE = None
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if  not name and not data:
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # This list will keep track of all the structures created.
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # That will allow for an easy iteration through the list
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # in order to save the modifications made
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__structures__ = []
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not fast_load:
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fast_load = globals()['fast_load']
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__parse__(name, data, fast_load)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __unpack_data__(self, format, data, file_offset):
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Apply structure format to raw data.
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns and unpacked structure object if successful, None otherwise.
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        structure = Structure(format, file_offset=file_offset)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #if len(data) < structure.sizeof():
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #    return None
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            structure.__unpack__(data)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, err:
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Corrupt header "%s" at file offset %d. Exception: %s' % (
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    format[0], file_offset, str(err))  )
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.__structures__.append(structure)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return structure
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __parse__(self, fname, data, fast_load):
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse a Portable Executable file.
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Loads a PE file, parsing all its structures and making them available
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        through the instance's attributes.
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if fname:
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fd = file(fname, 'rb')
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__ = fd.read()
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fd.close()
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif data:
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__ = data
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.DOS_HEADER = self.__unpack_data__(
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_DOS_HEADER_format__,
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__, file_offset=0)
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not self.DOS_HEADER or self.DOS_HEADER.e_magic != IMAGE_DOS_SIGNATURE:
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('DOS Header magic not found.')
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Check for sane value in e_lfanew
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.DOS_HEADER.e_lfanew > len(self.__data__):
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('Invalid e_lfanew value, probably not a PE file')
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nt_headers_offset = self.DOS_HEADER.e_lfanew
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.NT_HEADERS = self.__unpack_data__(
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_NT_HEADERS_format__,
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__[nt_headers_offset:],
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = nt_headers_offset)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # We better check the signature right here, before the file screws
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # around with sections:
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Some malware will cause the Signature value to not exist at all
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not self.NT_HEADERS or not self.NT_HEADERS.Signature:
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('NT Headers not found.')
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.NT_HEADERS.Signature != IMAGE_NT_SIGNATURE:
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('Invalid NT Headers signature.')
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.FILE_HEADER = self.__unpack_data__(
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_FILE_HEADER_format__,
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__[nt_headers_offset+4:],
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = nt_headers_offset+4)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        image_flags = self.retrieve_flags(IMAGE_CHARACTERISTICS, 'IMAGE_FILE_')
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not self.FILE_HEADER:
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('File Header missing')
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Set the image's flags according the the Characteristics member
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.set_flags(self.FILE_HEADER, self.FILE_HEADER.Characteristics, image_flags)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        optional_header_offset =    \
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            nt_headers_offset+4+self.FILE_HEADER.sizeof()
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Note: location of sections can be controlled from PE header:
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sections_offset = optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.OPTIONAL_HEADER = self.__unpack_data__(
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_OPTIONAL_HEADER_format__,
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__[optional_header_offset:],
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = optional_header_offset)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # According to solardesigner's findings for his
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Tiny PE project, the optional header does not
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # need fields beyond "Subsystem" in order to be
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # loadable by the Windows loader (given that zeroes
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # are acceptable values and the header is loaded
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # in a zeroed memory page)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # If trying to parse a full Optional Header fails
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # we try to parse it again with some 0 padding
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ( self.OPTIONAL_HEADER is None and
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            len(self.__data__[optional_header_offset:])
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE ):
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Add enough zeroes to make up for the unused fields
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            padding_length = 128
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Create padding
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            padded_data = self.__data__[optional_header_offset:] + (
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                '\0' * padding_length)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.OPTIONAL_HEADER = self.__unpack_data__(
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_OPTIONAL_HEADER_format__,
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                padded_data,
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                file_offset = optional_header_offset)
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Check the Magic in the OPTIONAL_HEADER and set the PE file
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # type accordingly
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.OPTIONAL_HEADER is not None:
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE:
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            elif self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE_PLUS:
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE_PLUS
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.OPTIONAL_HEADER = self.__unpack_data__(
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__IMAGE_OPTIONAL_HEADER64_format__,
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__data__[optional_header_offset:],
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    file_offset = optional_header_offset)
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Again, as explained above, we try to parse
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # a reduced form of the Optional Header which
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # is still valid despite not including all
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # structure members
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69+4
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if ( self.OPTIONAL_HEADER is None and
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    len(self.__data__[optional_header_offset:])
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE ):
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    padding_length = 128
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    padded_data = self.__data__[optional_header_offset:] + (
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        '\0' * padding_length)
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.OPTIONAL_HEADER = self.__unpack_data__(
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.__IMAGE_OPTIONAL_HEADER64_format__,
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        padded_data,
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        file_offset = optional_header_offset)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not self.FILE_HEADER:
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError('File Header missing')
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Die gracefully if there is no OPTIONAL_HEADER field
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # 975440f5ad5e2e4a92c4d9a5f22f75c1
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.PE_TYPE is None or self.OPTIONAL_HEADER is None:
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError("No Optional Header found, invalid PE32 or PE32+ file")
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dll_characteristics_flags = self.retrieve_flags(DLL_CHARACTERISTICS, 'IMAGE_DLL_CHARACTERISTICS_')
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Set the Dll Characteristics flags according the the DllCharacteristics member
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.set_flags(
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.OPTIONAL_HEADER,
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.OPTIONAL_HEADER.DllCharacteristics,
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dll_characteristics_flags)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.OPTIONAL_HEADER.DATA_DIRECTORY = []
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #offset = (optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset = (optional_header_offset + self.OPTIONAL_HEADER.sizeof())
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.NT_HEADERS.FILE_HEADER = self.FILE_HEADER
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.NT_HEADERS.OPTIONAL_HEADER = self.OPTIONAL_HEADER
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # The NumberOfRvaAndSizes is sanitized to stay within
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # reasonable limits so can be casted to an int
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.OPTIONAL_HEADER.NumberOfRvaAndSizes > 0x10:
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Suspicious NumberOfRvaAndSizes in the Optional Header. ' +
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Normal values are never larger than 0x10, the value is: 0x%x' %
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.OPTIONAL_HEADER.NumberOfRvaAndSizes )
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in xrange(int(0x7fffffffL & self.OPTIONAL_HEADER.NumberOfRvaAndSizes)):
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if len(self.__data__[offset:]) == 0:
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if len(self.__data__[offset:]) < 8:
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.__data__[offset:]+'\0'*8
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.__data__[offset:]
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dir_entry = self.__unpack_data__(
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_DATA_DIRECTORY_format__,
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data,
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                file_offset = offset)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if dir_entry is None:
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Would fail if missing an entry
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # 1d4937b2fa4d84ad1bce0309857e70ca offending sample
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dir_entry.name = DIRECTORY_ENTRY[i]
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except (KeyError, AttributeError):
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            offset += dir_entry.sizeof()
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.OPTIONAL_HEADER.DATA_DIRECTORY.append(dir_entry)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the offset goes outside the optional header,
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # the loop is broken, regardless of how many directories
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # NumberOfRvaAndSizes says there are
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # We assume a normally sized optional header, hence that we do
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # a sizeof() instead of reading SizeOfOptionalHeader.
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Then we add a default number of drectories times their size,
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # if we go beyond that, we assume the number of directories
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # is wrong and stop processing
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if offset >= (optional_header_offset +
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.OPTIONAL_HEADER.sizeof() + 8*16) :
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset = self.parse_sections(sections_offset)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # There could be a problem if there are no raw data sections
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # greater than 0
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # fc91013eb72529da005110a3403541b6 example
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Should this throw an exception in the minimum header offset
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # can't be found?
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rawDataPointers = [
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s.PointerToRawData for s in self.sections if s.PointerToRawData>0]
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(rawDataPointers) > 0:
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            lowest_section_offset = min(rawDataPointers)
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            lowest_section_offset = None
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not lowest_section_offset or lowest_section_offset<offset:
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.header = self.__data__[:offset]
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.header = self.__data__[:lowest_section_offset]
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Check whether the entry point lies within a section
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.get_section_by_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint) is not None:
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Check whether the entry point lies within the file
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ep_offset = self.get_offset_from_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ep_offset > len(self.__data__):
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Possibly corrupt file. AddressOfEntryPoint lies outside the file. ' +
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'AddressOfEntryPoint: 0x%x' %
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.OPTIONAL_HEADER.AddressOfEntryPoint )
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'AddressOfEntryPoint lies outside the sections\' boundaries. ' +
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'AddressOfEntryPoint: 0x%x' %
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.OPTIONAL_HEADER.AddressOfEntryPoint )
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not fast_load:
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.parse_data_directories()
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_warnings(self):
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the list of warnings.
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Non-critical problems found when parsing the PE file are
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        appended to a list of warnings. This method returns the
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        full list.
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.__warnings
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def show_warnings(self):
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Print the list of warnings.
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Non-critical problems found when parsing the PE file are
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        appended to a list of warnings. This method prints the
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        full list to standard output.
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for warning in self.__warnings:
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            print '>', warning
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def full_load(self):
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Process the data directories.
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This mathod will load the data directories which might not have
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        been loaded if the "fast_load" option was used.
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.parse_data_directories()
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def write(self, filename=None):
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Write the PE file.
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This function will process all headers and components
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        of the PE file and include all changes made (by just
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assigning to attributes in the PE objects) and write
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        the changes back to a file whose name is provided as
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        an argument. The filename is optional.
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The data to be written to the file will be returned
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        as a 'str' object.
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_data = list(self.__data__)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for struct in self.__structures__:
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            struct_data = list(struct.__pack__())
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            offset = struct.get_file_offset()
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_data[offset:offset+len(struct_data)] = struct_data
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'VS_VERSIONINFO'):
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if hasattr(self, 'FileInfo'):
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for entry in self.FileInfo:
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if hasattr(entry, 'StringTable'):
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for st_entry in entry.StringTable:
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            for key, entry in st_entry.entries.items():
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                offsets = st_entry.entries_offsets[key]
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                lengths = st_entry.entries_lengths[key]
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if len( entry ) > lengths[1]:
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    uc = zip(
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            list(entry[:lengths[1]]), ['\0'] * lengths[1] )
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    l = list()
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    map(l.extend, uc)
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    file_data[
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        offsets[1] : offsets[1] + lengths[1]*2 ] = l
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                else:
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    uc = zip(
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            list(entry), ['\0'] * len(entry) )
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    l = list()
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    map(l.extend, uc)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    file_data[
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        offsets[1] : offsets[1] + len(entry)*2 ] = l
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    remainder = lengths[1] - len(entry)
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    file_data[
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        offsets[1] + len(entry)*2 :
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        offsets[1] + lengths[1]*2 ] = [
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            u'\0' ] * remainder*2
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_file_data = ''.join( [ chr(ord(c)) for c in file_data ] )
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if filename:
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            f = file(filename, 'wb+')
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            f.write(new_file_data)
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            f.close()
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return new_file_data
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_sections(self, offset):
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Fetch the PE file sections.
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The sections will be readily available in the "sections" attribute.
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Its attributes will contain all the section information plus "data"
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        a buffer containing the section's data.
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The "Characteristics" member will be processed and attributes
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        representing the section characteristics (with the 'IMAGE_SCN_'
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string trimmed from the constant's names) will be added to the
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        section instance.
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Refer to the SectionStructure class for additional info.
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.sections = []
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in xrange(self.FILE_HEADER.NumberOfSections):
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__)
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not section:
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_offset = offset + section.sizeof() * i
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section.set_file_offset(section_offset)
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section.__unpack__(self.__data__[section_offset:])
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__structures__.append(section)
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.SizeOfRawData > len(self.__data__):
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Error parsing section %d. ' % i) +
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'SizeOfRawData is larger than file.')
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.PointerToRawData > len(self.__data__):
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Error parsing section %d. ' % i) +
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'PointerToRawData points beyond the end of the file.')
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.Misc_VirtualSize > 0x10000000:
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Suspicious value found parsing section %d. ' % i) +
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'VirtualSize is extremely large > 256MiB.')
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.VirtualAddress > 0x10000000:
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Suspicious value found parsing section %d. ' % i) +
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'VirtualAddress is beyond 0x10000000.')
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Some packer used a non-aligned PointerToRawData in the sections,
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # which causes several common tools not to load the section data
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # properly as they blindly read from the indicated offset.
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # It seems that Windows will round the offset down to the largest
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # offset multiple of FileAlignment which is smaller than
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # PointerToRawData. The following code will do the same.
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #alignment = self.OPTIONAL_HEADER.FileAlignment
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_data_start = section.PointerToRawData
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ( self.OPTIONAL_HEADER.FileAlignment != 0 and
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (section.PointerToRawData % self.OPTIONAL_HEADER.FileAlignment) != 0):
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Error parsing section %d. ' % i) +
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Suspicious value for FileAlignment in the Optional Header. ' +
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Normally the PointerToRawData entry of the sections\' structures ' +
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'is a multiple of FileAlignment, this might imply the file ' +
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'is trying to confuse tools which parse this incorrectly')
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_data_end = section_data_start+section.SizeOfRawData
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section.set_data(self.__data__[section_data_start:section_data_end])
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_flags = self.retrieve_flags(SECTION_CHARACTERISTICS, 'IMAGE_SCN_')
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Set the section's flags according the the Characteristics member
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.set_flags(section, section.Characteristics, section_flags)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ( section.__dict__.get('IMAGE_SCN_MEM_WRITE', False)  and
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                section.__dict__.get('IMAGE_SCN_MEM_EXECUTE', False) ):
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ('Suspicious flags set for section %d. ' % i) +
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set.' +
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'This might indicate a packed executable.')
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.sections.append(section)
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.FILE_HEADER.NumberOfSections > 0 and self.sections:
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return offset + self.sections[0].sizeof()*self.FILE_HEADER.NumberOfSections
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return offset
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def retrieve_flags(self, flag_dict, flag_filter):
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Read the flags from a dictionary and return them in a usable form.
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Will return a list of (flag, value) for all flags in "flag_dict"
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        matching the filter "flag_filter".
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return [(f[0], f[1]) for f in flag_dict.items() if
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                isinstance(f[0], str) and f[0].startswith(flag_filter)]
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_flags(self, obj, flag_field, flags):
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Will process the flags and set attributes in the object accordingly.
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The object "obj" will gain attritutes named after the flags provided in
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "flags" and valued True/False, matching the results of applyin each
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flag value from "flags" to flag_field.
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for flag in flags:
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if flag[1] & flag_field:
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                setattr(obj, flag[0], True)
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                setattr(obj, flag[0], False)
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_data_directories(self):
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse and process the PE file's data directories."""
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        directory_parsing = (
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_IMPORT', self.parse_import_directory),
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_EXPORT', self.parse_export_directory),
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_RESOURCE', self.parse_resources_directory),
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_DEBUG', self.parse_debug_directory),
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_BASERELOC', self.parse_relocations_directory),
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_TLS', self.parse_directory_tls),
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT', self.parse_delay_import_directory),
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ('IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT', self.parse_directory_bound_imports) )
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for entry in directory_parsing:
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # OC Patch:
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dir_entry = self.OPTIONAL_HEADER.DATA_DIRECTORY[
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    DIRECTORY_ENTRY[entry[0]]]
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except IndexError:
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if dir_entry.VirtualAddress:
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                value = entry[1](dir_entry.VirtualAddress, dir_entry.Size)
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if value:
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    setattr(self, entry[0][6:], value)
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_directory_bound_imports(self, rva, size):
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bnd_descr = Structure(self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__)
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bnd_descr_size = bnd_descr.sizeof()
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start = rva
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bound_imports = []
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while True:
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bnd_descr = self.__unpack_data__(
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__,
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   self.__data__[rva:rva+bnd_descr_size],
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   file_offset = rva)
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if bnd_descr is None:
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # If can't parse directory then silently return.
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # This directory does not necesarily have to be valid to
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # still have a valid PE file
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'The Bound Imports directory exists but can\'t be parsed.')
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if bnd_descr.all_zeroes():
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += bnd_descr.sizeof()
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            forwarder_refs = []
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for idx in xrange(bnd_descr.NumberOfModuleForwarderRefs):
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Both structures IMAGE_BOUND_IMPORT_DESCRIPTOR and
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # IMAGE_BOUND_FORWARDER_REF have the same size.
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                bnd_frwd_ref = self.__unpack_data__(
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__IMAGE_BOUND_FORWARDER_REF_format__,
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__data__[rva:rva+bnd_descr_size],
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    file_offset = rva)
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # OC Patch:
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if not bnd_frwd_ref:
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    raise PEFormatError(
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "IMAGE_BOUND_FORWARDER_REF cannot be read")
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                rva += bnd_frwd_ref.sizeof()
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                name_str =  self.get_string_from_data(
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    start+bnd_frwd_ref.OffsetModuleName, self.__data__)
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if not name_str:
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                forwarder_refs.append(BoundImportRefData(
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct = bnd_frwd_ref,
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    name = name_str))
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            name_str = self.get_string_from_data(
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                start+bnd_descr.OffsetModuleName, self.__data__)
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not name_str:
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bound_imports.append(
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                BoundImportDescData(
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct = bnd_descr,
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    name = name_str,
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entries = forwarder_refs))
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return bound_imports
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_directory_tls(self, rva, size):
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            format = self.__IMAGE_TLS_DIRECTORY_format__
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            format = self.__IMAGE_TLS_DIRECTORY64_format__
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tls_struct = self.__unpack_data__(
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            format,
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.get_data(rva),
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = self.get_offset_from_rva(rva))
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not tls_struct:
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TlsData( struct = tls_struct )
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_relocations_directory(self, rva, size):
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rlc = Structure(self.__IMAGE_BASE_RELOCATION_format__)
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rlc_size = rlc.sizeof()
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        end = rva+size
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        relocations = []
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while rva<end:
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # OC Patch:
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Malware that has bad rva entries will cause an error.
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Just continue on after an exception
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                rlc = self.__unpack_data__(
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__IMAGE_BASE_RELOCATION_format__,
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.get_data(rva, rlc_size),
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    file_offset = self.get_offset_from_rva(rva) )
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError:
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Invalid relocation information. Can\'t read ' +
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'data at RVA: 0x%x' % rva)
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                rlc = None
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not rlc:
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reloc_entries = self.parse_relocations(
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                rva+rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock-rlc_size)
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            relocations.append(
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                BaseRelocationData(
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct = rlc,
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entries = reloc_entries))
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not rlc.SizeOfBlock:
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += rlc.SizeOfBlock
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return relocations
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_relocations(self, data_rva, rva, size):
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data = self.get_data(data_rva, size)
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entries = []
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(len(data)/2):
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            word = struct.unpack('<H', data[idx*2:(idx+1)*2])[0]
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reloc_type = (word>>12)
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reloc_offset = (word&0x0fff)
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entries.append(
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                RelocationData(
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    type = reloc_type,
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rva = reloc_offset+rva))
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return entries
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_debug_directory(self, rva, size):
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """"""
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbg = Structure(self.__IMAGE_DEBUG_DIRECTORY_format__)
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbg_size = dbg.sizeof()
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        debug = []
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(size/dbg_size):
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.get_data(rva+dbg_size*idx, dbg_size)
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, e:
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Invalid debug information. Can\'t read ' +
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'data at RVA: 0x%x' % rva)
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return None
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dbg = self.__unpack_data__(
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_DEBUG_DIRECTORY_format__,
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data, file_offset = self.get_offset_from_rva(rva+dbg_size*idx))
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not dbg:
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return None
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            debug.append(
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                DebugData(
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct = dbg))
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return debug
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_resources_directory(self, rva, size=0, base_rva = None, level = 0):
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse the resources directory.
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Given the rva of the resources directory, it will process all
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        its entries.
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The root will have the corresponding member of its structure,
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IMAGE_RESOURCE_DIRECTORY plus 'entries', a list of all the
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entries in the directory.
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Those entries will have, correspondingly, all the structure's
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        members (IMAGE_RESOURCE_DIRECTORY_ENTRY) and an additional one,
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "directory", pointing to the IMAGE_RESOURCE_DIRECTORY structure
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        representing upper layers of the tree. This one will also have
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        an 'entries' attribute, pointing to the 3rd, and last, level.
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Another directory with more entries. Those last entries will
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        have a new atribute (both 'leaf' or 'data_entry' can be used to
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        access it). This structure finally points to the resource data.
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        All the members of this structure, IMAGE_RESOURCE_DATA_ENTRY,
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        are available as its attributes.
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_rva = rva
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if base_rva is None:
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base_rva = rva
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resources_section = self.get_section_by_rva(rva)
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the RVA is invalid all would blow up. Some EXEs seem to be
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # specially nasty and have an invalid RVA.
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data = self.get_data(rva)
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, e:
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Invalid resources directory. Can\'t read ' +
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'directory data at RVA: 0x%x' % rva)
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Get the resource directory structure, that is, the header
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # of the table preceding the actual entries
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource_dir = self.__unpack_data__(
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_RESOURCE_DIRECTORY_format__, data,
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = self.get_offset_from_rva(rva) )
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if resource_dir is None:
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If can't parse resources directory then silently return.
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # This directory does not necesarily have to be valid to
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # still have a valid PE file
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Invalid resources directory. Can\'t parse ' +
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'directory data at RVA: 0x%x' % rva)
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dir_entries = []
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Advance the rva to the positon immediately following the directory
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # table header and pointing to the first entry in the table
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rva += resource_dir.sizeof()
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        number_of_entries = (
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            resource_dir.NumberOfNamedEntries +
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            resource_dir.NumberOfIdEntries )
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        strings_to_postprocess = list()
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(number_of_entries):
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            res = self.parse_resource_entry(rva)
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if res is None:
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the resources directory, ' +
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Entry %d is invalid, RVA = 0x%x. ' %
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    (idx, rva) )
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry_name = None
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry_id = None
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If all named entries have been processed, only Id ones
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # remain
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if idx >= resource_dir.NumberOfNamedEntries:
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entry_id = res.Name
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ustr_offset = base_rva+res.NameOffset
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                try:
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #entry_name = self.get_string_u_at_rva(ustr_offset, max_length=16)
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entry_name = UnicodeStringWrapperPostProcessor(self, ustr_offset)
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    strings_to_postprocess.append(entry_name)
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                except PEFormatError, excp:
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.__warnings.append(
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'Error parsing the resources directory, ' +
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'attempting to read entry name. ' +
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'Can\'t read unicode string at offset 0x%x' %
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        (ustr_offset) )
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if res.DataIsDirectory:
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # OC Patch:
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # One trick malware can do is to recursively reference
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # the next directory. This causes hilarity to ensue when
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # trying to parse everything correctly.
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # If the original RVA given to this function is equal to
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # the next one to parse, we assume that it's a trick.
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Instead of raising a PEFormatError this would skip some
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # reasonable data so we just break.
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # 9ee4d0a0caf095314fd7041a3e4404dc is the offending sample
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if original_rva == (base_rva + res.OffsetToDirectory):
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entry_directory = self.parse_resources_directory(
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base_rva+res.OffsetToDirectory,
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base_rva=base_rva, level = level+1)
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if not entry_directory:
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dir_entries.append(
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ResourceDirEntryData(
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        struct = res,
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        name = entry_name,
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        id = entry_id,
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        directory = entry_directory))
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                struct = self.parse_resource_data_entry(
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base_rva + res.OffsetToDirectory)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if struct:
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entry_data = ResourceDataEntryData(
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        struct = struct,
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        lang = res.Name & 0xff,
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sublang = (res.Name>>8) & 0xff)
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dir_entries.append(
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ResourceDirEntryData(
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            struct = res,
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            name = entry_name,
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            id = entry_id,
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            data = entry_data))
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Check if this entry contains version information
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if level == 0 and res.Id == RESOURCE_TYPE['RT_VERSION']:
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if len(dir_entries)>0:
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    last_entry = dir_entries[-1]
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                rt_version_struct = None
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                try:
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rt_version_struct = last_entry.directory.entries[0].directory.entries[0].data.struct
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                except:
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Maybe a malformed directory structure...?
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Lets ignore it
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    pass
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if rt_version_struct is not None:
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.parse_version_information(rt_version_struct)
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += res.sizeof()
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string_rvas = [s.get_rva() for s in strings_to_postprocess]
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string_rvas.sort()
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx, s in enumerate(strings_to_postprocess):
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s.render_pascal_16()
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource_directory_data = ResourceDirData(
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            struct = resource_dir,
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entries = dir_entries)
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return resource_directory_data
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_resource_data_entry(self, rva):
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse a data entry from the resources directory."""
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the RVA is invalid all would blow up. Some EXEs seem to be
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # specially nasty and have an invalid RVA.
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data = self.get_data(rva)
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, excp:
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Error parsing a resource directory data entry, ' +
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'the RVA is invalid: 0x%x' % ( rva ) )
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_entry = self.__unpack_data__(
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_RESOURCE_DATA_ENTRY_format__, data,
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = self.get_offset_from_rva(rva) )
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return data_entry
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_resource_entry(self, rva):
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse a directory entry from the resources directory."""
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource = self.__unpack_data__(
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__, self.get_data(rva),
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = self.get_offset_from_rva(rva) )
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if resource is None:
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #resource.NameIsString = (resource.Name & 0x80000000L) >> 31
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource.NameOffset = resource.Name & 0x7FFFFFFFL
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource.__pad = resource.Name & 0xFFFF0000L
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource.Id = resource.Name & 0x0000FFFFL
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource.DataIsDirectory = (resource.OffsetToData & 0x80000000L) >> 31
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFFL
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return resource
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_version_information(self, version_struct):
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse version information structure.
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The date will be made available in three attributes of the PE object.
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VS_VERSIONINFO     will contain the first three fields of the main structure:
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'Length', 'ValueLength', and 'Type'
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VS_FIXEDFILEINFO    will hold the rest of the fields, accessible as sub-attributes:
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'Signature', 'StrucVersion', 'FileVersionMS', 'FileVersionLS',
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'ProductVersionMS', 'ProductVersionLS', 'FileFlagsMask', 'FileFlags',
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'FileOS', 'FileType', 'FileSubtype', 'FileDateMS', 'FileDateLS'
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileInfo    is a list of all StringFileInfo and VarFileInfo structures.
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StringFileInfo structures will have a list as an attribute named 'StringTable'
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        containing all the StringTable structures. Each of those structures contains a
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dictionary 'entries' with all the key/value version information string pairs.
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VarFileInfo structures will have a list as an attribute named 'Var' containing
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all Var structures. Each Var structure will have a dictionary as an attribute
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        named 'entry' which will contain the name and value of the Var.
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Retrieve the data for the version info resource
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start_offset = self.get_offset_from_rva( version_struct.OffsetToData )
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raw_data = self.__data__[ start_offset : start_offset+version_struct.Size ]
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Map the main structure and the subsequent string
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        versioninfo_struct = self.__unpack_data__(
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__VS_VERSIONINFO_format__, raw_data,
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = start_offset )
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if versioninfo_struct is None:
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ustr_offset = version_struct.OffsetToData + versioninfo_struct.sizeof()
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            versioninfo_string = self.get_string_u_at_rva( ustr_offset )
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, excp:
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Error parsing the version information, ' +
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'attempting to read VS_VERSION_INFO string. Can\'t ' +
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'read unicode string at offset 0x%x' % (
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ustr_offset ) )
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            versioninfo_string = None
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # If the structure does not contain the expected name, it's assumed to be invalid
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if versioninfo_string != u'VS_VERSION_INFO':
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append('Invalid VS_VERSION_INFO block')
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Set the PE object's VS_VERSIONINFO to this one
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.VS_VERSIONINFO = versioninfo_struct
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # The the Key attribute to point to the unicode string identifying the structure
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.VS_VERSIONINFO.Key = versioninfo_string
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Process the fixed version information, get the offset and structure
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fixedfileinfo_offset = self.dword_align(
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            versioninfo_struct.sizeof() + 2 * (len(versioninfo_string) + 1),
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            version_struct.OffsetToData)
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fixedfileinfo_struct = self.__unpack_data__(
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__VS_FIXEDFILEINFO_format__,
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raw_data[fixedfileinfo_offset:],
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_offset = start_offset+fixedfileinfo_offset )
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not fixedfileinfo_struct:
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Set the PE object's VS_FIXEDFILEINFO to this one
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.VS_FIXEDFILEINFO = fixedfileinfo_struct
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Start parsing all the StringFileInfo and VarFileInfo structures
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Get the first one
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stringfileinfo_offset = self.dword_align(
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fixedfileinfo_offset + fixedfileinfo_struct.sizeof(),
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            version_struct.OffsetToData)
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_stringfileinfo_offset = stringfileinfo_offset
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Set the PE object's attribute that will contain them all.
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.FileInfo = list()
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while True:
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Process the StringFileInfo/VarFileInfo struct
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            stringfileinfo_struct = self.__unpack_data__(
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__StringFileInfo_format__,
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                raw_data[stringfileinfo_offset:],
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                file_offset = start_offset+stringfileinfo_offset )
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if stringfileinfo_struct is None:
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing StringFileInfo/VarFileInfo struct' )
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return None
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Get the subsequent string defining the structure.
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ustr_offset = ( version_struct.OffsetToData +
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                stringfileinfo_offset + versioninfo_struct.sizeof() )
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                stringfileinfo_string = self.get_string_u_at_rva( ustr_offset )
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, excp:
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the version information, ' +
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'attempting to read StringFileInfo string. Can\'t ' +
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'read unicode string at offset 0x%x' %  ( ustr_offset ) )
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Set such string as the Key attribute
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            stringfileinfo_struct.Key = stringfileinfo_string
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Append the structure to the PE object's list
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.FileInfo.append(stringfileinfo_struct)
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Parse a StringFileInfo entry
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if stringfileinfo_string == u'StringFileInfo':
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if stringfileinfo_struct.Type == 1 and stringfileinfo_struct.ValueLength == 0:
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    stringtable_offset = self.dword_align(
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringfileinfo_offset + stringfileinfo_struct.sizeof() +
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            2*(len(stringfileinfo_string)+1),
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        version_struct.OffsetToData)
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    stringfileinfo_struct.StringTable = list()
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Process the String Table entries
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    while True:
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_struct = self.__unpack_data__(
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.__StringTable_format__,
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            raw_data[stringtable_offset:],
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            file_offset = start_offset+stringtable_offset )
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if not stringtable_struct:
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ustr_offset = ( version_struct.OffsetToData + stringtable_offset +
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_struct.sizeof() )
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        try:
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_string = self.get_string_u_at_rva( ustr_offset )
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        except PEFormatError, excp:
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.__warnings.append(
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'Error parsing the version information, ' +
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'attempting to read StringTable string. Can\'t ' +
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'read unicode string at offset 0x%x' % ( ustr_offset ) )
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_struct.LangID = stringtable_string
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_struct.entries = dict()
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_struct.entries_offsets = dict()
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_struct.entries_lengths = dict()
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringfileinfo_struct.StringTable.append(stringtable_struct)
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        entry_offset = self.dword_align(
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_offset + stringtable_struct.sizeof() +
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                2*(len(stringtable_string)+1),
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            version_struct.OffsetToData)
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        # Process all entries in the string table
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        #
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        while entry_offset < stringtable_offset + stringtable_struct.Length:
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            string_struct = self.__unpack_data__(
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                self.__String_format__, raw_data[entry_offset:],
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                file_offset = start_offset+entry_offset )
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if not string_struct:
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                break
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ustr_offset = ( version_struct.OffsetToData + entry_offset +
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                string_struct.sizeof() )
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            try:
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                key = self.get_string_u_at_rva( ustr_offset )
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                key_offset = self.get_offset_from_rva( ustr_offset )
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            except PEFormatError, excp:
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                self.__warnings.append(
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'Error parsing the version information, ' +
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'attempting to read StringTable Key string. Can\'t ' +
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'read unicode string at offset 0x%x' % ( ustr_offset ) )
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                break
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            value_offset = self.dword_align(
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                2*(len(key)+1) + entry_offset + string_struct.sizeof(),
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                version_struct.OffsetToData)
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ustr_offset = version_struct.OffsetToData + value_offset
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            try:
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                value = self.get_string_u_at_rva( ustr_offset,
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    max_length = string_struct.ValueLength )
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                value_offset = self.get_offset_from_rva( ustr_offset )
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            except PEFormatError, excp:
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                self.__warnings.append(
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'Error parsing the version information, ' +
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'attempting to read StringTable Value string. ' +
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    'Can\'t read unicode string at offset 0x%x' % (
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ustr_offset ) )
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                break
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if string_struct.Length == 0:
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                entry_offset = stringtable_offset + stringtable_struct.Length
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            else:
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                entry_offset = self.dword_align(
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    string_struct.Length+entry_offset, version_struct.OffsetToData)
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            key_as_char = []
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            for c in key:
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if ord(c)>128:
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    key_as_char.append('\\x%02x' %ord(c))
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                else:
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    key_as_char.append(c)
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            key_as_char = ''.join(key_as_char)
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            setattr(stringtable_struct, key_as_char, value)
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_struct.entries[key] = value
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_struct.entries_offsets[key] = (key_offset, value_offset)
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_struct.entries_lengths[key] = (len(key), len(value))
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringtable_offset = self.dword_align(
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stringtable_struct.Length + stringtable_offset,
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            version_struct.OffsetToData)
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if stringtable_offset >= stringfileinfo_struct.Length:
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Parse a VarFileInfo entry
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            elif stringfileinfo_string == u'VarFileInfo':
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                varfileinfo_struct = stringfileinfo_struct
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                varfileinfo_struct.name = 'VarFileInfo'
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if varfileinfo_struct.Type == 1 and varfileinfo_struct.ValueLength == 0:
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    var_offset = self.dword_align(
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        stringfileinfo_offset + varfileinfo_struct.sizeof() +
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            2*(len(stringfileinfo_string)+1),
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        version_struct.OffsetToData)
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    varfileinfo_struct.Var = list()
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Process all entries
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    while True:
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        var_struct = self.__unpack_data__(
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.__Var_format__,
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            raw_data[var_offset:],
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            file_offset = start_offset+var_offset )
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if not var_struct:
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ustr_offset = ( version_struct.OffsetToData + var_offset +
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            var_struct.sizeof() )
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        try:
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            var_string = self.get_string_u_at_rva( ustr_offset )
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        except PEFormatError, excp:
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.__warnings.append(
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'Error parsing the version information, ' +
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'attempting to read VarFileInfo Var string. ' +
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                'Can\'t read unicode string at offset 0x%x' % (ustr_offset))
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        varfileinfo_struct.Var.append(var_struct)
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        varword_offset = self.dword_align(
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            2*(len(var_string)+1) + var_offset + var_struct.sizeof(),
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            version_struct.OffsetToData)
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        orig_varword_offset = varword_offset
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        while varword_offset < orig_varword_offset + var_struct.ValueLength:
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            word1 = self.get_word_from_data(
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                raw_data[varword_offset:varword_offset+2], 0)
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            word2 = self.get_word_from_data(
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                raw_data[varword_offset+2:varword_offset+4], 0)
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            varword_offset += 4
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            var_struct.entry = {var_string: '0x%04x 0x%04x' % (word1, word2)}
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        var_offset = self.dword_align(
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            var_offset+var_struct.Length, version_struct.OffsetToData)
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if var_offset <= var_offset+var_struct.Length:
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            break
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Increment and align the offset
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            stringfileinfo_offset = self.dword_align(
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                stringfileinfo_struct.Length+stringfileinfo_offset,
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                version_struct.OffsetToData)
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Check if all the StringFileInfo and VarFileInfo items have been processed
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if stringfileinfo_struct.Length == 0 or stringfileinfo_offset >= versioninfo_struct.Length:
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_export_directory(self, rva, size):
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse the export directory.
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Given the rva of the export directory, it will process all
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        its entries.
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The exports will be made available through a list "exports"
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        containing a tuple with the following elements:
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ordinal, symbol_address, symbol_name)
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        And also through a dicionary "exports_by_ordinal" whose keys
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        will be the ordinals and the values tuples of the from:
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (symbol_address, symbol_name)
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The symbol addresses are relative, not absolute.
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            export_dir =  self.__unpack_data__(
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_EXPORT_DIRECTORY_format__, self.get_data(rva),
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                file_offset = self.get_offset_from_rva(rva) )
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError:
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Error parsing export directory at RVA: 0x%x' % ( rva ) )
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not export_dir:
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            address_of_names = self.get_data(
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                export_dir.AddressOfNames, export_dir.NumberOfNames*4)
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            address_of_name_ordinals = self.get_data(
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                export_dir.AddressOfNameOrdinals, export_dir.NumberOfNames*4)
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            address_of_functions = self.get_data(
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                export_dir.AddressOfFunctions, export_dir.NumberOfFunctions*4)
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError:
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__warnings.append(
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Error parsing export directory at RVA: 0x%x' % ( rva ) )
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exports = []
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in xrange(export_dir.NumberOfNames):
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            symbol_name = self.get_string_at_rva(
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.get_dword_from_data(address_of_names, i))
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            symbol_ordinal = self.get_word_from_data(
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                address_of_name_ordinals, i)
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if symbol_ordinal*4<len(address_of_functions):
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                symbol_address = self.get_dword_from_data(
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    address_of_functions, symbol_ordinal)
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Corrupt? a bad pointer... we assume it's all
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # useless, no exports
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return None
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the funcion's rva points within the export directory
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # it will point to a string with the forwarded symbol's string
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # instead of pointing the the function start address.
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if symbol_address>=rva and symbol_address<rva+size:
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                forwarder_str = self.get_string_at_rva(symbol_address)
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                forwarder_str = None
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            exports.append(
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ExportData(
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ordinal = export_dir.Base+symbol_ordinal,
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    address = symbol_address,
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    name = symbol_name,
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    forwarder = forwarder_str))
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ordinals = [exp.ordinal for exp in exports]
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(export_dir.NumberOfFunctions):
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not idx+export_dir.Base in ordinals:
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                symbol_address = self.get_dword_from_data(
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    address_of_functions,
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    idx)
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # Checking for forwarder again.
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if symbol_address>=rva and symbol_address<rva+size:
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    forwarder_str = self.get_string_at_rva(symbol_address)
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    forwarder_str = None
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                exports.append(
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExportData(
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ordinal = export_dir.Base+idx,
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        address = symbol_address,
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        name = None,
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        forwarder = forwarder_str))
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ExportDirData(
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                struct = export_dir,
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                symbols = exports)
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def dword_align(self, offset, base):
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset += base
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (offset+3) - ((offset+3)%4) - base
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_delay_import_directory(self, rva, size):
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Walk and parse the delay import directory."""
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import_descs =  []
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while True:
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # If the RVA is invalid all would blow up. Some PEs seem to be
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # specially nasty and have an invalid RVA.
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.get_data(rva)
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, e:
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the Delay import directory at RVA: 0x%x' % ( rva ) )
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            import_desc =  self.__unpack_data__(
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__,
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data, file_offset = self.get_offset_from_rva(rva) )
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the structure is all zeores, we reached the end of the list
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not import_desc or import_desc.all_zeroes():
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += import_desc.sizeof()
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                import_data =  self.parse_imports(
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_desc.pINT,
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_desc.pIAT,
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    None)
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, e:
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the Delay import directory. ' +
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Invalid import data at RVA: 0x%x' % ( rva ) )
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not import_data:
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dll = self.get_string_at_rva(import_desc.szName)
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if dll:
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                import_descs.append(
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ImportDescData(
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        struct = import_desc,
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        imports = import_data,
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dll = dll))
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return import_descs
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_import_directory(self, rva, size):
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Walk and parse the import directory."""
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        import_descs =  []
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while True:
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # If the RVA is invalid all would blow up. Some EXEs seem to be
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # specially nasty and have an invalid RVA.
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.get_data(rva)
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, e:
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the Import directory at RVA: 0x%x' % ( rva ) )
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            import_desc =  self.__unpack_data__(
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__IMAGE_IMPORT_DESCRIPTOR_format__,
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data, file_offset = self.get_offset_from_rva(rva) )
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the structure is all zeores, we reached the end of the list
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not import_desc or import_desc.all_zeroes():
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += import_desc.sizeof()
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                import_data =  self.parse_imports(
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_desc.OriginalFirstThunk,
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_desc.FirstThunk,
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_desc.ForwarderChain)
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, excp:
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the Import directory. ' +
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Invalid Import data at RVA: 0x%x' % ( rva ) )
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #raise excp
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not import_data:
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dll = self.get_string_at_rva(import_desc.Name)
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if dll:
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                import_descs.append(
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ImportDescData(
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        struct = import_desc,
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        imports = import_data,
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dll = dll))
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return import_descs
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def parse_imports(self, original_first_thunk, first_thunk, forwarder_chain):
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Parse the imported symbols.
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        It will fill a list, which will be avalable as the dictionary
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attribute "imports". Its keys will be the DLL names and the values
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all the symbols imported from that object.
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        imported_symbols = []
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        imports_section = self.get_section_by_rva(first_thunk)
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not imports_section:
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError, 'Invalid/corrupt imports.'
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Import Lookup Table. Contains ordinals or pointers to strings.
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ilt = self.get_import_table(original_first_thunk)
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Import Address Table. May have identical content to ILT if
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # PE file is not bounded, Will contain the address of the
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # imported symbols once the binary is loaded or if it is already
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # bound.
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iat = self.get_import_table(first_thunk)
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch:
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Would crash if iat or ilt had None type
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not iat and not ilt:
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError(
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Invalid Import Table information. ' +
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                'Both ILT and IAT appear to be broken.')
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not iat and ilt:
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            table = ilt
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif iat and not ilt:
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            table = iat
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif ilt and ((len(ilt) and len(iat)==0) or (len(ilt) == len(iat))):
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            table = ilt
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif (ilt and len(ilt))==0 and (iat and len(iat)):
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            table = iat
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(len(table)):
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            imp_ord = None
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            imp_hint = None
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            imp_name = None
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hint_name_table_rva = None
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if table[idx].AddressOfData:
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ordinal_flag = IMAGE_ORDINAL_FLAG
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ordinal_flag = IMAGE_ORDINAL_FLAG64
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # If imported by ordinal, we will append the ordinal number
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                #
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if table[idx].AddressOfData & ordinal_flag:
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_by_ordinal = True
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    imp_ord = table[idx].AddressOfData & 0xffff
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    imp_name = None
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import_by_ordinal = False
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    try:
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        hint_name_table_rva = table[idx].AddressOfData & 0x7fffffff
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        data = self.get_data(hint_name_table_rva, 2)
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        # Get the Hint
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        imp_hint = self.get_word_from_data(data, 0)
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        imp_name = self.get_string_at_rva(table[idx].AddressOfData+2)
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    except PEFormatError, e:
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        pass
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            imp_address = first_thunk+self.OPTIONAL_HEADER.ImageBase+idx*4
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if iat and ilt and ilt[idx].AddressOfData != iat[idx].AddressOfData:
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                imp_bound = iat[idx].AddressOfData
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                imp_bound = None
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if imp_name != '' and (imp_ord or imp_name):
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                imported_symbols.append(
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ImportData(
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        import_by_ordinal = import_by_ordinal,
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ordinal = imp_ord,
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        hint = imp_hint,
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        name = imp_name,
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        bound = imp_bound,
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        address = imp_address,
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        hint_name_table_rva = hint_name_table_rva))
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return imported_symbols
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_import_table(self, rva):
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        table = []
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while True and rva:
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = self.get_data(rva)
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except PEFormatError, e:
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__warnings.append(
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Error parsing the import table. ' +
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'Invalid data at RVA: 0x%x' % ( rva ) )
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return None
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                format = self.__IMAGE_THUNK_DATA_format__
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                format = self.__IMAGE_THUNK_DATA64_format__
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            thunk_data = self.__unpack_data__(
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                format, data, file_offset=self.get_offset_from_rva(rva) )
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not thunk_data or thunk_data.all_zeroes():
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rva += thunk_data.sizeof()
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            table.append(thunk_data)
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return table
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_memory_mapped_image(self, max_virtual_address=0x10000000, ImageBase=None):
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Returns the data corresponding to the memory layout of the PE file.
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The data includes the PE header and the sections loaded at offsets
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        corresponding to their relative virtual addresses. (the VirtualAddress
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        section header member).
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Any offset in this data corresponds to the absolute memory address
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ImageBase+offset.
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The optional argument 'max_virtual_address' provides with means of limiting
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        which section are processed.
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Any section with their VirtualAddress beyond this value will be skipped.
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Normally, sections with values beyond this range are just there to confuse
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tools. It's a common trick to see in packed executables.
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        If the 'ImageBase' optional argument is supplied, the file's relocations
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        will be applied to the image by calling the 'relocate_image()' method.
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Collect all sections in one code block
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data = self.header
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for section in self.sections:
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Miscellanous integrity tests.
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Some packer will set these to bogus values to
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # make tools go nuts.
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.Misc_VirtualSize == 0 or section.SizeOfRawData == 0:
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.SizeOfRawData > len(self.__data__):
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.PointerToRawData > len(self.__data__):
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if section.VirtualAddress >= max_virtual_address:
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            padding_length = section.VirtualAddress - len(data)
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if padding_length>0:
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data += '\0'*padding_length
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            elif padding_length<0:
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data = data[:padding_length]
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data += section.data
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return data
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_data(self, rva, length=None):
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get data regardless of the section where it lies on.
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Given a rva and the size of the chunk to retrieve, this method
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        will find the section where the data lies and return the data.
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = self.get_section_by_rva(rva)
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not s:
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if rva<len(self.header):
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if length:
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    end = rva+length
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    end = None
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return self.header[rva:end]
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?'
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s.get_data(rva, length)
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_rva_from_offset(self, offset):
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the rva corresponding to this file offset. """
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = self.get_section_by_offset(offset)
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not s:
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError("specified offset (0x%x) doesn't belong to any section." % offset)
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s.get_rva_from_offset(offset)
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_offset_from_rva(self, rva):
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the file offset corresponding to this rva.
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Given a rva , this method will find the section where the
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data lies and return the offset within the file.
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = self.get_section_by_rva(rva)
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not s:
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?'
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s.get_offset_from_rva(rva)
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_string_at_rva(self, rva):
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get an ASCII string located at the given address."""
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = self.get_section_by_rva(rva)
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not s:
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if rva<len(self.header):
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return self.get_string_from_data(rva, self.header)
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.get_string_from_data(rva-s.VirtualAddress, s.data)
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_string_from_data(self, offset, data):
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get an ASCII string from within the data."""
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # OC Patch
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        b = None
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            b = data[offset]
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except IndexError:
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ''
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = ''
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while ord(b):
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s += b
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            offset += 1
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                b = data[offset]
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except IndexError:
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_string_u_at_rva(self, rva, max_length = 2**16):
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get an Unicode string located at the given address."""
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # If the RVA is invalid all would blow up. Some EXEs seem to be
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # specially nasty and have an invalid RVA.
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data = self.get_data(rva, 2)
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError, e:
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #length = struct.unpack('<H', data)[0]
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = u''
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for idx in xrange(max_length):
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            try:
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                uchr = struct.unpack('<H', self.get_data(rva+2*idx, 2))[0]
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            except struct.error:
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if unichr(uchr) == u'\0':
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s += unichr(uchr)
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_section_by_offset(self, offset):
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the section containing the given file offset."""
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sections = [s for s in self.sections if s.contains_offset(offset)]
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if sections:
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return sections[0]
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return None
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_section_by_rva(self, rva):
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Get the section containing the given address."""
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sections = [s for s in self.sections if s.contains_rva(rva)]
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if sections:
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return sections[0]
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return None
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __str__(self):
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.dump_info()
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def print_info(self):
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Print all the PE header information in a human readable from."""
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print self.dump_info()
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def dump_info(self, dump=None):
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Dump all the PE header information into human readable string."""
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if dump is None:
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump = Dump()
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        warnings = self.get_warnings()
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if warnings:
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Parsing Warnings')
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for warning in warnings:
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line(warning)
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_header('DOS_HEADER')
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_lines(self.DOS_HEADER.dump())
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_newline()
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_header('NT_HEADERS')
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_lines(self.NT_HEADERS.dump())
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_newline()
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_header('FILE_HEADER')
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_lines(self.FILE_HEADER.dump())
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        image_flags = self.retrieve_flags(IMAGE_CHARACTERISTICS, 'IMAGE_FILE_')
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add('Flags: ')
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flags = []
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for flag in image_flags:
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if getattr(self.FILE_HEADER, flag[0]):
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                flags.append(flag[0])
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_line(', '.join(flags))
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_newline()
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'OPTIONAL_HEADER') and self.OPTIONAL_HEADER is not None:
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('OPTIONAL_HEADER')
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(self.OPTIONAL_HEADER.dump())
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dll_characteristics_flags = self.retrieve_flags(DLL_CHARACTERISTICS, 'IMAGE_DLL_CHARACTERISTICS_')
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add('DllCharacteristics: ')
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flags = []
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for flag in dll_characteristics_flags:
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if getattr(self.OPTIONAL_HEADER, flag[0]):
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                flags.append(flag[0])
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_line(', '.join(flags))
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_newline()
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dump.add_header('PE Sections')
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        section_flags = self.retrieve_flags(SECTION_CHARACTERISTICS, 'IMAGE_SCN_')
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for section in self.sections:
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(section.dump())
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add('Flags: ')
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            flags = []
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for flag in section_flags:
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if getattr(section, flag[0]):
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    flags.append(flag[0])
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_line(', '.join(flags))
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_line('Entropy: %f (Min=0.0, Max=8.0)' % section.get_entropy() )
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if md5 is not None:
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line('MD5     hash: %s' % section.get_hash_md5() )
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if sha1 is not None:
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line('SHA-1   hash: %s' % section.get_hash_sha1() )
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if sha256 is not None:
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line('SHA-256 hash: %s' % section.get_hash_sha256() )
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if sha512 is not None:
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line('SHA-512 hash: %s' % section.get_hash_sha512() )
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (hasattr(self, 'OPTIONAL_HEADER') and
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hasattr(self.OPTIONAL_HEADER, 'DATA_DIRECTORY') ):
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Directories')
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for idx in xrange(len(self.OPTIONAL_HEADER.DATA_DIRECTORY)):
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[idx]
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(directory.dump())
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'VS_VERSIONINFO'):
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Version Information')
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(self.VS_VERSIONINFO.dump())
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if hasattr(self, 'VS_FIXEDFILEINFO'):
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(self.VS_FIXEDFILEINFO.dump())
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if hasattr(self, 'FileInfo'):
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for entry in self.FileInfo:
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_lines(entry.dump())
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_newline()
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if hasattr(entry, 'StringTable'):
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for st_entry in entry.StringTable:
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            [dump.add_line('  '+line) for line in st_entry.dump()]
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dump.add_line('  LangID: '+st_entry.LangID)
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dump.add_newline()
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            for str_entry in st_entry.entries.items():
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                dump.add_line('    '+str_entry[0]+': '+str_entry[1])
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_newline()
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    elif hasattr(entry, 'Var'):
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for var_entry in entry.Var:
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if hasattr(var_entry, 'entry'):
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                [dump.add_line('  '+line) for line in var_entry.dump()]
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                dump.add_line(
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    '    ' + var_entry.entry.keys()[0] +
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ': ' + var_entry.entry.values()[0])
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_newline()
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_EXPORT'):
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Exported symbols')
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(self.DIRECTORY_ENTRY_EXPORT.struct.dump())
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_line('%-10s   %-10s  %s' % ('Ordinal', 'RVA', 'Name'))
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for export in self.DIRECTORY_ENTRY_EXPORT.symbols:
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add('%-10d 0x%08Xh    %s' % (
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    export.ordinal, export.address, export.name))
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if export.forwarder:
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line(' forwarder: %s' % export.forwarder)
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_newline()
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_IMPORT'):
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Imported symbols')
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for module in self.DIRECTORY_ENTRY_IMPORT:
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(module.struct.dump())
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for symbol in module.imports:
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if symbol.import_by_ordinal is True:
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add('%s Ordinal[%s] (Imported by Ordinal)' % (
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            module.dll, str(symbol.ordinal)))
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    else:
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add('%s.%s Hint[%s]' % (
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            module.dll, symbol.name, str(symbol.hint)))
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if symbol.bound:
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_line(' Bound: 0x%08X' % (symbol.bound))
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    else:
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_newline()
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_BOUND_IMPORT'):
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Bound imports')
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT:
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(bound_imp_desc.struct.dump())
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_line('DLL: %s' % bound_imp_desc.name)
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for bound_imp_ref in bound_imp_desc.entries:
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_lines(bound_imp_ref.struct.dump(), 4)
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line('DLL: %s' % bound_imp_ref.name, 4)
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_newline()
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_DELAY_IMPORT'):
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Delay Imported symbols')
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for module in self.DIRECTORY_ENTRY_DELAY_IMPORT:
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(module.struct.dump())
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for symbol in module.imports:
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if symbol.import_by_ordinal is True:
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add('%s Ordinal[%s] (Imported by Ordinal)' % (
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            module.dll, str(symbol.ordinal)))
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    else:
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add('%s.%s Hint[%s]' % (
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            module.dll, symbol.name, str(symbol.hint)))
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if symbol.bound:
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_line(' Bound: 0x%08X' % (symbol.bound))
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    else:
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_newline()
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_RESOURCE'):
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Resource directory')
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(self.DIRECTORY_ENTRY_RESOURCE.struct.dump())
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for resource_type in self.DIRECTORY_ENTRY_RESOURCE.entries:
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if resource_type.name is not None:
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line('Name: [%s]' % resource_type.name, 2)
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line('Id: [0x%X] (%s)' % (
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        resource_type.struct.Id, RESOURCE_TYPE.get(
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            resource_type.struct.Id, '-')),
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        2)
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(resource_type.struct.dump(), 2)
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if hasattr(resource_type, 'directory'):
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_lines(resource_type.directory.struct.dump(), 4)
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    for resource_id in resource_type.directory.entries:
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if resource_id.name is not None:
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dump.add_line('Name: [%s]' % resource_id.name, 6)
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else:
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dump.add_line('Id: [0x%X]' % resource_id.struct.Id, 6)
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_lines(resource_id.struct.dump(), 6)
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if hasattr(resource_id, 'directory'):
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dump.add_lines(resource_id.directory.struct.dump(), 8)
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            for resource_lang in resource_id.directory.entries:
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            #    dump.add_line('\\--- LANG [%d,%d][%s]' % (
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            #        resource_lang.data.lang,
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            #        resource_lang.data.sublang,
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            #        LANG[resource_lang.data.lang]), 8)
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                dump.add_lines(resource_lang.struct.dump(), 10)
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                dump.add_lines(resource_lang.data.struct.dump(), 12)
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ( hasattr(self, 'DIRECTORY_ENTRY_TLS') and
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             self.DIRECTORY_ENTRY_TLS and
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             self.DIRECTORY_ENTRY_TLS.struct ):
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('TLS')
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_lines(self.DIRECTORY_ENTRY_TLS.struct.dump())
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_newline()
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_DEBUG'):
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Debug information')
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for dbg in self.DIRECTORY_ENTRY_DEBUG:
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(dbg.struct.dump())
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                try:
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line('Type: '+DEBUG_TYPE[dbg.struct.Type])
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                except KeyError:
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    dump.add_line('Type: 0x%x(Unknown)' % dbg.struct.Type)
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if hasattr(self, 'DIRECTORY_ENTRY_BASERELOC'):
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dump.add_header('Base relocations')
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for base_reloc in self.DIRECTORY_ENTRY_BASERELOC:
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_lines(base_reloc.struct.dump())
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for reloc in base_reloc.entries:
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    try:
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_line('%08Xh %s' % (
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            reloc.rva, RELOCATION_TYPE[reloc.type][16:]), 4)
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    except KeyError:
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dump.add_line('0x%08X 0x%x(Unknown)' % (
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            reloc.rva, reloc.type), 4)
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dump.add_newline()
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return dump.get_text()
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # OC Patch
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_physical_by_rva(self, rva):
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Gets the physical address in the PE file from an RVA value."""
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return self.get_offset_from_rva(rva)
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except Exception:
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Double-Word get/set
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_data_from_dword(self, dword):
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return a four byte string representing the double word value. (little endian)."""
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.pack('<L', dword)
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_dword_from_data(self, data, offset):
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Convert four bytes of data to a double word (little endian)
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'offset' is assumed to index into a dword array. So setting it to
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        N will return a dword out of the data sarting at offset N*4.
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the data can't be turned into a double word.
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (offset+1)*4 > len(data):
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.unpack('<L', data[offset*4:(offset+1)*4])[0]
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_dword_at_rva(self, rva):
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the double word value at the given RVA.
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the value can't be read, i.e. the RVA can't be mapped
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to a file offset.
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return self.get_dword_from_data(self.get_data(rva)[:4], 0)
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError:
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_dword_from_offset(self, offset):
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the double word value at the given file offset. (little endian)"""
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if offset+4 > len(self.__data__):
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.get_dword_from_data(self.__data__[offset:offset+4], 0)
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_dword_at_rva(self, rva, dword):
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the double word value at the file offset corresponding to the given RVA."""
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword))
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_dword_at_offset(self, offset, dword):
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the double word value at the given file offset."""
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword))
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Word get/set
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_data_from_word(self, word):
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return a two byte string representing the word value. (little endian)."""
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.pack('<H', word)
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_word_from_data(self, data, offset):
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Convert two bytes of data to a word (little endian)
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'offset' is assumed to index into a word array. So setting it to
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        N will return a dword out of the data sarting at offset N*2.
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the data can't be turned into a word.
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (offset+1)*2 > len(data):
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.unpack('<H', data[offset*2:(offset+1)*2])[0]
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_word_at_rva(self, rva):
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the word value at the given RVA.
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the value can't be read, i.e. the RVA can't be mapped
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to a file offset.
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return self.get_word_from_data(self.get_data(rva)[:2], 0)
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError:
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_word_from_offset(self, offset):
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the word value at the given file offset. (little endian)"""
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if offset+2 > len(self.__data__):
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.get_word_from_data(self.__data__[offset:offset+2], 0)
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_word_at_rva(self, rva, word):
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the word value at the file offset corresponding to the given RVA."""
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_rva(rva, self.get_data_from_word(word))
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_word_at_offset(self, offset, word):
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the word value at the given file offset."""
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_offset(offset, self.get_data_from_word(word))
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Quad-Word get/set
35045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_data_from_qword(self, word):
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return a eight byte string representing the quad-word value. (little endian)."""
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.pack('<Q', word)
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_qword_from_data(self, data, offset):
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Convert eight bytes of data to a word (little endian)
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'offset' is assumed to index into a word array. So setting it to
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        N will return a dword out of the data sarting at offset N*8.
35165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the data can't be turned into a quad word.
35185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
35195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (offset+1)*8 > len(data):
35215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return struct.unpack('<Q', data[offset*8:(offset+1)*8])[0]
35245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_qword_at_rva(self, rva):
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the quad-word value at the given RVA.
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Returns None if the value can't be read, i.e. the RVA can't be mapped
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to a file offset.
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return self.get_qword_from_data(self.get_data(rva)[:8], 0)
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except PEFormatError:
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get_qword_from_offset(self, offset):
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the quad-word value at the given file offset. (little endian)"""
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if offset+8 > len(self.__data__):
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return None
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.get_qword_from_data(self.__data__[offset:offset+8], 0)
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_qword_at_rva(self, rva, qword):
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the quad-word value at the file offset corresponding to the given RVA."""
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_rva(rva, self.get_data_from_qword(qword))
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_qword_at_offset(self, offset, qword):
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Set the quad-word value at the given file offset."""
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_offset(offset, self.get_data_from_qword(qword))
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set bytes
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ##
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_bytes_at_rva(self, rva, data):
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Overwrite, with the given string, the bytes at the file offset corresponding to the given RVA.
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Return True if successful, False otherwise. It can fail if the
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset is outside the file's boundaries.
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset = self.get_physical_by_rva(rva)
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not offset:
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise False
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.set_bytes_at_offset(offset, data)
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def set_bytes_at_offset(self, offset, data):
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Overwrite the bytes at the given file offset with the given string.
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Return True if successful, False otherwise. It can fail if the
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset is outside the file's boundaries.
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not isinstance(data, str):
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise TypeError('data should be of type: str')
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if offset >= 0 and offset < len(self.__data__):
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.__data__ = ( self.__data__[:offset] +
35905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data +
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.__data__[offset+len(data):] )
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return False
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Refresh the section's data with the modified information
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for section in self.sections:
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_data_start = section.PointerToRawData
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section_data_end = section_data_start+section.SizeOfRawData
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            section.data = self.__data__[section_data_start:section_data_end]
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return True
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def relocate_image(self, new_ImageBase):
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Apply the relocation information to the image using the provided new image base.
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This method will apply the relocation information to the image. Given the new base,
36105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all the relocations will be processed and both the raw data and the section's data
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        will be fixed accordingly.
36125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        The resulting image can be retrieved as well through the method:
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            get_memory_mapped_image()
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        In order to get something that would more closely match what could be found in memory
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        once the Windows loader finished its work.
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        relocation_difference = new_ImageBase - self.OPTIONAL_HEADER.ImageBase
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for reloc in self.DIRECTORY_ENTRY_BASERELOC:
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            virtual_address = reloc.struct.VirtualAddress
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size_of_block = reloc.struct.SizeOfBlock
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # We iterate with an index because if the relocation is of type
36295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # IMAGE_REL_BASED_HIGHADJ we need to also process the next entry
36305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # at once and skip it for the next interation
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry_idx = 0
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while entry_idx<len(reloc.entries):
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entry = reloc.entries[entry_idx]
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entry_idx += 1
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_ABSOLUTE']:
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Nothing to do for this type of relocation
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    pass
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGH']:
36435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Fix the high 16bits of a relocation
36445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Add high 16bits of relocation_difference to the
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # 16bit value at RVA=entry.rva
36475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.set_word_at_rva(
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        entry.rva,
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ( self.get_word_at_rva(entry.rva) + relocation_difference>>16)&0xffff )
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_LOW']:
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Fix the low 16bits of a relocation
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Add low 16 bits of relocation_difference to the 16bit value
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # at RVA=entry.rva
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.set_word_at_rva(
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        entry.rva,
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ( self.get_word_at_rva(entry.rva) + relocation_difference)&0xffff)
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGHLOW']:
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Handle all high and low parts of a 32bit relocation
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Add relocation_difference to the value at RVA=entry.rva
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.set_dword_at_rva(
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        entry.rva,
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.get_dword_at_rva(entry.rva)+relocation_difference)
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGHADJ']:
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Fix the high 16bits of a relocation and adjust
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Add high 16bits of relocation_difference to the 32bit value
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # composed from the (16bit value at RVA=entry.rva)<<16 plus
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # the 16bit value at the next relocation entry.
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # If the next entry is beyond the array's limits,
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # abort... the table is corrupt
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    #
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if entry_idx == len(reloc.entries):
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    next_entry = reloc.entries[entry_idx]
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    entry_idx += 1
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.set_word_at_rva( entry.rva,
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ((self.get_word_at_rva(entry.rva)<<16) + next_entry.rva +
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        relocation_difference & 0xffff0000) >> 16 )
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_DIR64']:
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # Apply the difference to the 64bit value at the offset
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    # RVA=entry.rva
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.set_qword_at_rva(
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        entry.rva,
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.get_qword_at_rva(entry.rva) + relocation_difference)
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def verify_checksum(self):
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.OPTIONAL_HEADER.CheckSum == self.generate_checksum()
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def generate_checksum(self):
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Get the offset to the CheckSum field in the OptionalHeader
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #
37095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checksum_offset = self.OPTIONAL_HEADER.__file_offset__ + 0x40 # 64
37105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checksum = 0
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for i in range( len(self.__data__) / 4 ):
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            # Skip the checksum field
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            #
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if i == checksum_offset / 4:
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dword = struct.unpack('L', self.__data__[ i*4 : i*4+4 ])[0]
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            checksum = (checksum & 0xffffffff) + dword + (checksum>>32)
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if checksum > 2**32:
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                checksum = (checksum & 0xffffffff) + (checksum >> 32)
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checksum = (checksum & 0xffff) + (checksum >> 16)
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checksum = (checksum) + (checksum >> 16)
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checksum = checksum & 0xffff
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return checksum + len(self.__data__)
3730