Ejemplo n.º 1
0
class ResourceReaderHeader(pstruct.type):
    class _Types(pstruct.type):
        _fields_ = [
            (pint.uint32_t, 'Count'),
            (lambda s: dyn.array(ResourceString, s['Count'].li.int()), 'Name'),
        ]

    def __Padding(self):
        cb = 0

        ri = self.getparent(ResourceInfo)
        cb += ri['Magic'].li.size()

        rfi = self.getparent(ResourceFileInfo)
        cb += rfi['Manager'].li.size()

        cb += sum(self[n].li.size() for n in ('Version', 'Count', 'Types'))

        top = ri.getoffset() + ri['Size'].li.size()
        bottom = top + cb
        res = (bottom - top) & 7
        return dyn.block((8 - res) if res > 0 else 0)

    _fields_ = [
        (pint.uint32_t, 'Version'),
        (pint.uint32_t, 'Count'),
        (_Types, 'Types'),
        (__Padding, 'Padding'),
        (lambda s: dyn.array(pint.uint32_t, s['Count'].li.int()), 'Hash'),
        (lambda s: dyn.array(pint.uint32_t, s['Count'].li.int()),
         'NameOffset'),
        (pint.uint32_t, 'DataOffset'),
    ]
Ejemplo n.º 2
0
class IMAGE_ENCLAVE_CONFIG64(pstruct.type):
    def blocksize(self):
        # If we're already loaded, then we can just read our size field. If we're not
        # loaded yet, then to get the size we need to cheat by duplicating the instance,
        # allocating with the original blocksize, and then taking its loaded size.
        Fblocksize = super(IMAGE_ENCLAVE_CONFIG64, self).blocksize
        return self['Size'].li.int() if self.value else self.copy(
            blocksize=Fblocksize).a.size()

    def __ImportList(self):
        count, size = (self[fld].li
                       for fld in ['NumberOfImports', 'ImportEntrySize'])

        # FIXME: set the size of IMAGE_ENCLAVE_IMPORT to the ImportEntrySize
        t = dyn.array(IMAGE_ENCLAVE_IMPORT, count.int())
        return virtualaddress(t, type=DWORD)

    _fields_ = [
        (DWORD, 'Size'),
        (DWORD, 'MinimumRequiredConfigSize'),
        (IMAGE_ENCLAVE_POLICY_, 'PolicyFlags'),
        (DWORD, 'NumberOfImports'),
        (__ImportList, 'ImportList'),
        (DWORD, 'ImportEntrySize'),
        (dyn.array(BYTE, IMAGE_ENCLAVE_SHORT_ID_LENGTH), 'FamilyID'),
        (dyn.array(BYTE, IMAGE_ENCLAVE_SHORT_ID_LENGTH), 'ImageID'),
        (DWORD, 'ImageVersion'),
        (DWORD, 'SecurityVersion'),
        (ULONGLONG, 'EnclaveSize'),
        (DWORD, 'NumberOfThreads'),
        (IMAGE_ENCLAVE_FLAG_, 'EnclaveFlags'),
    ]
Ejemplo n.º 3
0
class IMAGE_ENCLAVE_IMPORT(pstruct.type):
    _fields_ = [
        (IMAGE_ENCLAVE_IMPORT_MATCH_, 'MatchType'),
        (DWORD, 'MinimumSecurityVersion'),
        (dyn.array(BYTE, IMAGE_ENCLAVE_SHORT_ID_LENGTH), 'UniqueOrAuthorID'),
        (dyn.array(BYTE, IMAGE_ENCLAVE_SHORT_ID_LENGTH), 'FamilyID'),
        (dyn.array(BYTE, IMAGE_ENCLAVE_SHORT_ID_LENGTH), 'ImageID'),
        (virtualaddress(pstr.szstring, type=DWORD), 'ImportName'),
        (DWORD, 'Reserved'),
    ]
Ejemplo n.º 4
0
class IMAGE_LOADCONFIG_DIRECTORY64(pstruct.type):
    _fields_ = [
        (uint32, 'Size'),
        (TimeDateStamp, 'TimeDateStamp'),
        (uint16, 'MajorVersion'),
        (uint16, 'MinorVersion'),
        (uint32, 'GlobalFlagsClear'),
        (uint32, 'GlobalFlagsSet'),
        (uint32, 'CriticalSectionDefaultTimeout'),
        (uint64, 'DeCommitFreeBlockThreshold'),
        (uint64, 'DeCommitTotalFreeThreshold'),
        (realaddress(ptype.undefined, type=uint64), 'LockPrefixTable'),
        (uint64, 'MaximumAllocationSize'),
        (uint64, 'VirtualMemoryThreshold'),
        (uint64, 'ProcessAffinityMask'),
        (uint32, 'ProcessHeapFlags'),
        (uint16, 'CSDVersion'),
        (uint16, 'Reserved1'),
        (realaddress(ptype.undefined, type=uint64), 'EditList'),
        (realaddress(uint64, type=uint64), 'SecurityCookie'),
        (realaddress(
            lambda s: dyn.array(uint64, s.parent['SEHandlerCount'].li.int()),
            type=uint64), 'SEHandlerTable'),
        (uint64, 'SEHandlerCount'),
        (realaddress(uint64, type=uint64), 'GuardCFCheckFunctionPointer'),
        (realaddress(uint64, type=uint64), 'GuardCFDispatchFunctionPointer'),
        (realaddress(lambda s: dyn.array(
            uint64, s.parent['GuardCFFunctionCount'].li.int()),
                     type=uint64), 'GuardCFFunctionTable'),
        (uint64, 'GuardCFFunctionCount'),
        (pbinary.littleendian(IMAGE_GUARD_), 'GuardFlags'),
        (IMAGE_LOAD_CONFIG_CODE_INTEGRITY, 'CodeIntegrity'),
        (realaddress(lambda s: dyn.array(
            uint64, s.parent['GuardAddressTakenIatEntryCount'].li.int()),
                     type=uint64), 'GuardAddressTakenIatEntryTable'),
        (uint64, 'GuardAddressTakenIatEntryCount'),
        (realaddress(lambda s: dyn.array(
            uint64, s.parent['GuardLongJumpTargetCount'].li.int()),
                     type=uint64), 'GuardLongJumpTargetTable'),
        (uint64, 'GuardLongJumpTargetCount'),
        (realaddress(ptype.undefined, type=uint64), 'DynamicValueRelocTable'),
        (realaddress(ptype.undefined, type=uint64), 'CHPEMetadataPointer'),
        (realaddress(uint64, type=uint64), 'GuardRFFailureRoutine'),
        (realaddress(uint64,
                     type=uint64), 'GuardRFFailureRoutineFunctionPointer'),
        (uint32, 'DynamicValueRelocTableOffset'),
        (uint16, 'DynamicValueRelocTableSection'),
        (uint16, 'Reserved2'),
        (realaddress(uint64,
                     type=uint64), 'GuardRFVerifyStackPointerFunctionPointer'),
        (uint32, 'HotPatchTableOffset'),
        (uint32, 'Reserved3'),
        (realaddress(pstr.szwstring,
                     type=uint64), 'AddressOfSomeUnicodeString'),
    ]
Ejemplo n.º 5
0
    def _object_(self):
        res = self.getparent(HTables)
        index, lengths = len(self.value), res['Rows'].li
        count = lengths[index].int()

        if count:
            cls = self.__class__
            logging.debug(
                "{:s} : {:s} : Loading {:s}({:d}) table with {:d} rows. : {:d} of {:d}"
                .format('.'.join((res.typename(), cls.__name__)),
                        self.instance(), TableType.byvalue(index, 'undefined'),
                        index, count, 1 + len(self.value), self.length))

        rowtype = Table.withdefault(index, type=index)
        rowsize = rowtype.PreCalculateSize(res) if Table.has(index) else 0

        tr, tn = TableRow.__name__, TableType.byvalue(index, None)
        t = dyn.clone(
            TableRow,
            _object_=rowtype,
            _value_=dyn.block(rowsize),
            typename=classmethod(lambda cls: "{:s}({:s})".format(tr, tn)
                                 if tn else tr))

        def Get(self, index):
            if index > 0:
                return self[index - 1]
            raise IndexError(index)

        return dyn.array(t,
                         count,
                         Get=Get,
                         blocksize=(lambda s, cb=rowsize * count: cb))
Ejemplo n.º 6
0
    def __ImportList(self):
        count, size = (self[fld].li
                       for fld in ['NumberOfImports', 'ImportEntrySize'])

        # FIXME: set the size of IMAGE_ENCLAVE_IMPORT to the ImportEntrySize
        t = dyn.array(IMAGE_ENCLAVE_IMPORT, count.int())
        return virtualaddress(t, type=DWORD)
Ejemplo n.º 7
0
class ESTypeList(pstruct.type):
    _fields_ = [
        (int32, 'nCount'),
        (lambda self: virtualaddress(
            dyn.array(HandlerType, self['nCount'].li.int()), type=dword),
         'pHandlerArray'),
    ]
Ejemplo n.º 8
0
class UNWIND_INFO(pstruct.type):
    class Header(pbinary.struct):
        class UNW_FLAG_(pbinary.enum):
            width = 5
            _values_ = [
                ('NHANDLER', 0),
                ('EHANDLER', 1),
                ('UHANDLER', 2),
                ('FHANDLER', 3),
                ('CHAININFO', 4),
            ]

        _fields_ = [
            (UNW_FLAG_, 'Flags'),
            (3, 'Version'),
        ]

    class Frame(pbinary.struct):
        _fields_ = [
            (4, 'Register'),
            (4, 'Offset'),
        ]

    class ExceptionHandler(pstruct.type):
        _fields_ = [(virtualaddress(ptype.undefined, type=dword), 'Address'),
                    (ptype.undefined, 'Data')]

    def __ExceptionHandler(self):
        h = self['Header'].l
        n = h.__field__('Flags')
        if (n.int() & (n.byname('EHANDLER') | n.byname('UHANDLER')) >
                0) and (n.int() & n.byname('CHAININFO') == 0):
            return self.ExceptionHandler
        return ptype.undefined

    def __ChainedUnwindInfo(self):
        h = self['Header'].l
        n = h.__field__('Flags')
        if n.int() == n.byname('CHAININFO') > 0:
            return RUNTIME_FUNCTION
        return ptype.undefined

    _fields_ = [
        (Header, 'Header'),
        (byte, 'SizeOfProlog'),
        (byte, 'CountOfCodes'),
        (Frame, 'Frame'),
        (lambda s: dyn.array(UNWIND_CODE, s['CountOfCodes'].li.int()),
         'UnwindCode'),
        (dyn.align(4),
         'align(ExceptionHandler)'),  # FIXME: this was copied from IDA
        (__ExceptionHandler, 'ExceptionHandler'),
        (__ChainedUnwindInfo, 'ChainedUnwindInfo'),
    ]
Ejemplo n.º 9
0
class PermissionSet(pstruct.type):
    class Attribute(pstruct.type):
        _fields_ = [
            (SerString, 'String'),
            (SerBlock, 'Properties'),
        ]

    _fields_ = [
        (pint.uint8_t, 'period'),
        (CInt, 'count'),
        (lambda s: dyn.array(s.Attribute, s['count'].li.Get()), 'attributes'),
    ]
Ejemplo n.º 10
0
    def __Entry(self):
        self = self.getparent(VtableFixup)
        cls = self.__class__

        res = self['Type'].li
        if res['32BIT'] and res['64BIT']:
            logging.warn("{:s} : {:s} : Both 32-bit and 64-bit flag is set. Assuming 0-bit. : {!r}".format('.'.join((__name__,cls.__name__)), self.instance(), res.summary()))
            t = pint.uint_t
        elif not res['32BIT'] and not res['64BIT']:
            logging.warn("{:s} : {:s} : Neither 32-bit and 64-bit flag is set. Assuming 0-bit. : {!r}".format('.'.join((__name__,cls.__name__)), self.instance(), res.summary()))
            t = pint.uint_t
        else:
            t = pint.uint32_t if res['32BIT'] else pint.uint64_t if res['64BIT'] else pint.uint_t
        count = self['Size'].li.int()
        return dyn.array(t, count)            
Ejemplo n.º 11
0
class IMAGE_DYNAMIC_RELOCATION64_V2(pstruct.type):
    class _Symbol(pint.enum, ULONGLONG):
        _values_ = [
            ('PROLOGUE', 1),
            ('EPILOGUE', 2),
        ]

    _fields_ = [
        (DWORD, 'HeaderSize'),
        (DWORD, 'FixupInfoSize'),
        (_Symbol, 'Symbol'),
        (DWORD, 'SymbolGroup'),
        (DWORD, 'Flags'),
        (lambda self: dyn.array(BYTE, self['FixupInfoSize'].li.int()),
         'FixupInfo'),
    ]
Ejemplo n.º 12
0
 def __Entry(self):
     self = self.getparent(VtableFixup)
     res = self['Type'].li
     if res['32BIT'] and res['64BIT']:
         logging.warn(
             "{:s} : {:s} : Both 32-bit and 64-bit flag is set. Assuming 0-bit. : {!r}"
             .format('.'.join((__name__, self.__class__.__name__)),
                     self.instance(), res.summary()))
         t = pint.uint_t
     elif not res['32BIT'] and not res['64BIT']:
         logging.warn(
             "{:s} : {:s} : Neither 32-bit and 64-bit flag is set. Assuming 0-bit. : {!r}"
             .format('.'.join((__name__, self.__class__.__name__)),
                     self.instance(), res.summary()))
         t = pint.uint_t
     else:
         t = pint.uint32_t if res[
             '32BIT'] else pint.uint64_t if res['64BIT'] else pint.uint_t
     count = self['Size'].li.int()
     return dyn.array(t, count)
Ejemplo n.º 13
0
    def _object_(self):
        res = self.getparent(HTables)
        index, lengths = len(self.value), res['Rows'].li
        count = lengths[index].int()

        if count:
            cls = self.__class__
            logging.debug("{:s} : {:s} : Loading {:s}({:d}) table with {:d} rows. : {:d} of {:d}".format('.'.join((res.typename(),cls.__name__)), self.instance(), TableType.byvalue(index, 'undefined'), index, count, 1+len(self.value), self.length))

        rowtype = Table.withdefault(index, type=index)
        rowsize = rowtype.PreCalculateSize(res) if Table.has(index) else 0

        tr, tn = TableRow.__name__, TableType.byvalue(index, None)
        t = dyn.clone(TableRow, _object_=rowtype, _value_=dyn.block(rowsize), typename=classmethod(lambda cls: "{:s}({:s})".format(tr, tn) if tn else tr))

        def Get(self, index):
            if index > 0:
                return self[index - 1]
            raise IndexError(index)
        return dyn.array(t, count, Get=Get, blocksize=(lambda s, cb=rowsize*count: cb))
Ejemplo n.º 14
0
class IMAGE_SECTION_HEADER(pstruct.type):
    """PE Executable Section Table Entry"""
    class IMAGE_SCN(pbinary.flags):
        _fields_ = [
            (1, 'MEM_WRITE'),               # 0x80000000
            (1, 'MEM_READ'),                # 0x40000000
            (1, 'MEM_EXECUTE'),             # 0x20000000
            (1, 'MEM_SHARED'),              # 0x10000000
            (1, 'MEM_NOT_PAGED'),           # 0x08000000
            (1, 'MEM_NOT_CACHED'),          # 0x04000000
            (1, 'MEM_DISCARDABLE'),         # 0x02000000
            (1, 'LNK_NRELOC_OVFL'),         # 0x01000000

        #   (1, 'ALIGN_8192BYTES'), # 0x00e00000
        #   (1, 'ALIGN_4096BYTES'), # 0x00d00000
        #   (1, 'ALIGN_2048BYTES'), # 0x00c00000
        #   (1, 'ALIGN_1024BYTES'), # 0x00b00000
        #   (1, 'ALIGN_512BYTES'), # 0x00a00000
        #   (1, 'ALIGN_256BYTES'), # 0x00900000
        #   (1, 'ALIGN_128BYTES'), # 0x00800000
        #   (1, 'ALIGN_64BYTES'), # 0x00700000
        #   (1, 'ALIGN_32BYTES'), # 0x00600000
        #   (1, 'ALIGN_16BYTES'), # 0x00500000
        #   (1, 'ALIGN_8BYTES'), # 0x00400000
        #   (1, 'ALIGN_4BYTES'), # 0x00300000
        #   (1, 'ALIGN_2BYTES'), # 0x00200000
        #   (1, 'ALIGN_1BYTES'), # 0x00100000

            (4, 'ALIGN'),                   # 0x00?00000
            (1, 'MEM_PRELOAD'),             # 0x00080000
            (1, 'MEM_LOCKED'),              # 0x00040000
        #   (1, 'MEM_16BIT'),              # 0x00020000 # ARM
            (1, 'MEM_PURGEABLE'),           # 0x00020000
            (1, 'reserved_16'),

            (1, 'GPREL'),                   # 0x00008000
            (2, 'reserved_14'),
            (1, 'LNK_COMDAT'),              # 0x00001000
            (1, 'LNK_REMOVE'),              # 0x00000800
            (1, 'reserved_11'),
            (1, 'LNK_INFO'),                # 0x00000200
            (1, 'LNK_OTHER'),               # 0x00000100

            (1, 'CNT_UNINITIALIZED_DATA'),  # 0x00000080
            (1, 'CNT_INITIALIZED_DATA'),    # 0x00000040
            (1, 'CNT_CODE'),                # 0x00000020
            (1, 'reserved_4'),
            (1, 'TYPE_NO_PAD'),             # 0x00000008
            (3, 'reserved_0'),
        ]

    # FIXME: we can store a longer than 8 byte Name if we want to implement code that navigates to the string table
    #      apparently executables don't care though...
    _fields_ = [
        (dyn.clone(pstr.string, length=8), 'Name'),
        (uint32, 'VirtualSize'),
        (virtualaddress(lambda s:dyn.block(s.parent.getloadedsize()), type=uint32), 'VirtualAddress'),
        (uint32, 'SizeOfRawData'),
        (fileoffset(lambda s:dyn.block(s.parent.getreadsize()), type=uint32), 'PointerToRawData'),
        (fileoffset(lambda s:dyn.array(relocations.MachineRelocation.lookup(s.getparent(Header).Machine().int()), s.parent['NumberOfRelocations'].li.int()), type=uint32), 'PointerToRelocations'),
        (fileoffset(lambda s:dyn.array(linenumbers.LineNumber, s.parent['NumberOfLinenumbers'].li.int()), type=uint32), 'PointerToLinenumbers'),
        (uint16, 'NumberOfRelocations'),
        (uint16, 'NumberOfLinenumbers'),
        (pbinary.littleendian(IMAGE_SCN), 'Characteristics'),
    ]

    def getreadsize(self):
        portable = self.getparent(SectionTableArray)

        # if it's a portable executable, then apply the alignment
        try:
            nt = portable.p
            alignment = nt['OptionalHeader']['FileAlignment'].int()
            mask = alignment - 1

        # otherwise, there's no alignment necessary
        except KeyError:
            mask = 0

        res = (self['SizeOfRawData'].int() + mask) & ~mask
        return min((self.source.size() - self['PointerToRawData'].int(), res)) if hasattr(self.source, 'size') else res

    def getloadedsize(self):
        # XXX: even though the loadedsize is aligned to SectionAlignment,
        #      the loader doesn't actually map data there and thus the
        #      actual mapped size is rounded to pagesize

        # nt = self.getparent(Header)
        # alignment = nt['OptionalHeader']['SectionAlignment'].int()
        alignment = 0x1000  # pagesize
        mask = alignment - 1
        return (self['VirtualSize'].int() + mask) & ~mask

    def containsaddress(self, address):
        start = self['VirtualAddress'].int()
        return True if (address >= start) and (address < start + self.getloadedsize()) else False

    def containsoffset(self, offset):
        start = self['PointerToRawData'].int()
        return True if (offset >= start) and (offset < start + self.getreadsize()) else False

    def data(self):
        return self['PointerToRawData'].d

    getrelocations = lambda self: self['PointerToRelocations'].d
    getlinenumbers = lambda self: self['NumberOfLinenumbers'].d

    ## offset means file offset
    def getoffsetbyaddress(self, address):
        return address - self['VirtualAddress'].int() + self['PointerToRawData'].int()

    def getaddressbyoffset(self, offset):
        return offset - self['PointerToRawData'].int() + self['VirtualAddress'].int()
Ejemplo n.º 15
0
class Fields(pstruct.type):
    _fields_ = [
        (clr.CInt, 'Count'),
        (lambda s: dyn.array(CustomField, s['Count'].li.Get()), 'Fields'),
    ]
Ejemplo n.º 16
0
class IMAGE_EXPORT_DIRECTORY(pstruct.type):
    _p_AddressOfFunctions =    lambda self: virtualaddress(dyn.array(FuncPointer, self['NumberOfFunctions'].li.int()), type=dword)
    _p_AddressOfNames =        lambda self: virtualaddress(dyn.array(NamePointer, self['NumberOfNames'].li.int()), type=dword)
    _p_AddressOfNameOrdinals = lambda self: virtualaddress(dyn.array(Ordinal,     self['NumberOfNames'].li.int()), type=dword)

    def __ExportData(self):
        res = sum(self[n].li.size() for _,n in self._fields_[:-1])
        return dyn.block(self.blocksize() - res)

    _fields_ = [
        ( dword, 'Flags' ),
        ( TimeDateStamp, 'TimeDateStamp' ),
        ( word, 'MajorVersion' ),
        ( word, 'MinorVersion' ),
        ( virtualaddress(pstr.szstring, type=dword), 'Name' ),
        ( dword, 'Base' ),
        ( dword, 'NumberOfFunctions' ),
        ( dword, 'NumberOfNames' ),
        ( _p_AddressOfFunctions, 'AddressOfFunctions' ),
        ( _p_AddressOfNames, 'AddressOfNames' ),
        ( _p_AddressOfNameOrdinals, 'AddressOfNameOrdinals' ),
        ( __ExportData, 'ExportData'),
    ]

    def GetNames(self):
        """Returns a list of all the export names"""
        Header = headers.locateHeader(self)
        cache, sections = {}, Header['Sections']

        res = []
        for va in self['AddressOfNames'].d.l:
            section = sections.getsectionbyaddress(va.int())
            sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
            nameofs = va.int() - sectionva
            res.append(utils.strdup(data[nameofs:].tostring()))
        return res

    def GetNameOrdinals(self):
        """Returns a list of all the Ordinals for each export"""
        Header = headers.locateHeader(self)
        address = self['AddressOfNameOrdinals'].int()
        section = Header['Sections'].getsectionbyaddress(address)

        sectionva = section['VirtualAddress'].int()
        base, offset = self['Base'].int(), address - sectionva

        data = section.data().load().serialize()

        block = data[offset: offset + 2*self['NumberOfNames'].int()]
        return [base+ordinal for ordinal in array.array('H', block)]

    def GetExportAddressTable(self):
        """Returns (export address table offset,[virtualaddress of each export]) from the export address table"""
        Header = headers.locateHeader(self)
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)

        address = self['AddressOfFunctions'].int()
        section = Header['Sections'].getsectionbyaddress(address)

        sectionva = section['VirtualAddress'].int()
        offset = address - sectionva
        data = section.data().l.serialize()

        block = data[offset: offset + 4*self['NumberOfFunctions'].int()]
        return address, array.array('L', block)

    def Hint(self, index):
        '''Returns the hint/ordinal of the specified export.'''
        aono = self['AddressOfNameOrdinals']
        if aono.int() == 0:
            raise ValueError("{:s} : No ordinals found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aono.summary()))

        # validate the index against the ordinals table
        ordinals = aono.d.li
        if not (0 <= index < len(ordinals)):
            raise IndexError("{:s} : Specified index {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), index, 0, len(ordinals)))

        # got it
        res = ordinals[index]
        return res.int()

    def Offset(self, index):
        '''Returns the va for the address of the export.'''
        aof = self['AddressOfFunctions']
        if aof.int() == 0:
            raise ValueError("{:s} : No functions found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))

        # validate the ordinal
        hint = self.Hint(index)
        if not (0 <= hint < len(aof.d)):
            raise IndexError("{:s} : Specified ordinal {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), hint, 0, len(aof.d)))

        # now we can figure the index into the function table
        res = headers.calculateRelativeOffset(self, aof.int())
        return res + hint * 4

    def Name(self, index):
        '''Returns the name of the specified export.'''
        aon = self['AddressOfNames']
        if aon.int() == 0:
            raise ValueError("{:s} : No names found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aon.summary()))

        # validate the index
        names = aon.d.li
        if not (0 <= index < len(names)):
            raise IndexError("{:s} : Specified index {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), index, 0, len(names)))

        # got it
        res = names[index]
        return res.d.li.str()

    def Ordinal(self, index):
        hint = self.Hint(index)
        return hint + self['Base'].int()

    def OrdinalName(self, index):
        '''Returns the ordinal name for the specified export.'''
        return "Ordinal{:d}".format(self.Ordinal(index))

    def ForwardQ(self, index):
        '''Returns True if the specified index is a forwarded export.'''
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)

        aof = self['AddressOfFunctions']
        if aof.int() == 0:
            raise ValueError("{:s} : No functions found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))

        # validate the ordinal
        hint = self.Hint(index)
        if not (0 <= hint < len(aof.d)):
            raise IndexError("{:s} : Specified ordinal {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), hint, 0, len(aof.d)))

        # now check if it's a forwarded function or not
        va = aof.d.li[hint]
        return ExportDirectory.containsaddress(va.int())

    def Entrypoint(self, index):
        '''Returns the va of the entrypoint for the specified export.'''
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)

        aof = self['AddressOfFunctions']
        if aof.int() == 0:
            raise ValueError("{:s} : No functions found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))

        # validate the ordinal
        hint = self.Hint(index)
        if not (0 <= hint < len(aof.d)):
            raise IndexError("{:s} : Specified ordinal {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), hint, 0, len(aof.d)))

        # grab the address out of the function table
        va = aof.d.li[hint]
        return None if ExportDirectory.containsaddress(va.int()) else va.int()

    def ForwardTarget(self, index):
        '''Returns the string that the specified export is forwarded to.'''
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)

        aof = self['AddressOfFunctions']
        if aof.int() == 0:
            raise ValueError("{:s} : No functions found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))

        # validate the ordinal
        hint = self.Hint(index)
        if not (0 <= hint < len(aof.d)):
            raise IndexError("{:s} : Specified ordinal {:d} is out of bounds for IMAGE_EXPORT_DIRECTORY. ({:d}{:+d})".format('.'.join((cls.__module__, cls.__name__)), hint, 0, len(aof.d)))

        # grab the address out of the function table
        va = aof.d.li[hint]
        return va.d.li.str() if ExportDirectory.containsaddress(va.int()) else None

    def iterate(self):
        """For each export, yields (rva offset, hint, name, ordinalname, entrypoint, forwardedrva)"""
        cls = self.__class__
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)
        Header, Base = headers.locateHeader(self), self['Base'].int()

        # our section data cache
        cache, sections = {}, Header['Sections']

        # grab everything that's important
        aof, aon, aono = self['AddressOfFunctions'], self['AddressOfNames'], self['AddressOfNameOrdinals']

        ## export address table
        if aof.int() > 0:
            # cache the section the eat is contained in since we need it anyways
            section = sections.getsectionbyaddress(aof.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aof into an array that's wikiwiki
            data = aof.d.l.cast(dyn.array(dword, len(aof.d)))
            eat = array.array('L', data.l.serialize())

            # check that the aof is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aof.int(), aof.int() + 4*self['NumberOfFunctions'].int())):
                logging.warn("{:s} : Export Address Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aof.int(), aof.int() + 4*self['NumberOfFunctions'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No export addresses found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))
            eat = array.array('L', [])

        ## name ordinal table
        if aono.int() > 0:
            # cache the section the aono is contained in since we need it anyways
            section = sections.getsectionbyaddress(aono.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aono into an array that's also quick
            data = aono.d.l.cast(dyn.array(word, len(aono.d)))
            no = array.array('H', data.l.serialize())

            # check that the aono is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aono.int(), aono.int() + 2*self['NumberOfNames'].int())):
                logging.warn("{:s} : Export Name Ordinal Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aono.int(), aono.int() + 2*self['NumberOfNames'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No Export Name Ordinal Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aono.summary()))
            no = array.array('H', [])

        # check the name table
        if aon.int() == 0:
            logging.warn("{:s} : No Export Name Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aon.summary()))
            nt = []
        else:
            nt = aon.d.l

        # now we can start returning things to the user
        va = headers.calculateRelativeOffset(self, aof.int())
        for nameva, ordinal in map(None, nt, no):

            # grab the name if we can
            if nameva is None:
                name = None
            else:
                section = sections.getsectionbyaddress(nameva.int())
                sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                nameofs = nameva.int() - sectionva
                name = utils.strdup(data[nameofs:].tostring())

            # grab the ordinal if we can
            if ordinal is None:
                forwarded, value = None, None

            elif 0 <= ordinal <= len(eat):
                # this is inside the export directory, so it's a forwardedrva
                if ExportDirectory.containsaddress(eat[ordinal]):
                    section = sections.getsectionbyaddress(eat[ordinal])
                    sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                    forwarded, value = utils.strdup(data[eat[ordinal] - sectionva:].tostring()), None

                # otherwise, it's a valid address
                else:
                    forwarded, value = None, eat[ordinal]

            # this ordinal is outside the export address table, although
            # we can read from the file to deal with these sort of fuxed
            # things... this is currently unsupported by pecoff
            else:
                logging.warning("{:s} : Error resolving export address for {:s} : !({:d} <= {:d} < {:d})".format('.'.join((cls.__module__, cls.__name__)), name, 0, ordinal, len(eat)))
                forwarded, value = None, None

            ordinalstring = None if ordinal is None else "Ordinal{:d}".format(ordinal + Base)
            yield va, ordinal, name, ordinalstring, value, forwarded
            va += 4
        return

    def search(self, key):
        '''Search the export list for an export that matches key.

        Return its index/hint.
        '''
        for offset, ordinal, name, ordinalstring, value, forwardedrva in self.iterate():
            if key == ordinal or key == name or key == ordinalstring or key == forwardedrva:
                return ordinal
            continue
        raise KeyError(key)
Ejemplo n.º 17
0
    def iterate(self):
        """For each export, yields (rva offset, hint, name, ordinalname, entrypoint, forwardedrva)"""
        cls = self.__class__
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)
        Header, Base = headers.locateHeader(self), self['Base'].int()

        # our section data cache
        cache, sections = {}, Header['Sections']

        # grab everything that's important
        aof, aon, aono = self['AddressOfFunctions'], self['AddressOfNames'], self['AddressOfNameOrdinals']

        ## export address table
        if aof.int() > 0:
            # cache the section the eat is contained in since we need it anyways
            section = sections.getsectionbyaddress(aof.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aof into an array that's wikiwiki
            data = aof.d.l.cast(dyn.array(dword, len(aof.d)))
            eat = array.array('L', data.l.serialize())

            # check that the aof is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aof.int(), aof.int() + 4*self['NumberOfFunctions'].int())):
                logging.warn("{:s} : Export Address Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aof.int(), aof.int() + 4*self['NumberOfFunctions'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No export addresses found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))
            eat = array.array('L', [])

        ## name ordinal table
        if aono.int() > 0:
            # cache the section the aono is contained in since we need it anyways
            section = sections.getsectionbyaddress(aono.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aono into an array that's also quick
            data = aono.d.l.cast(dyn.array(word, len(aono.d)))
            no = array.array('H', data.l.serialize())

            # check that the aono is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aono.int(), aono.int() + 2*self['NumberOfNames'].int())):
                logging.warn("{:s} : Export Name Ordinal Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aono.int(), aono.int() + 2*self['NumberOfNames'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No Export Name Ordinal Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aono.summary()))
            no = array.array('H', [])

        # check the name table
        if aon.int() == 0:
            logging.warn("{:s} : No Export Name Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aon.summary()))
            nt = []
        else:
            nt = aon.d.l

        # now we can start returning things to the user
        va = headers.calculateRelativeOffset(self, aof.int())
        for nameva, ordinal in map(None, nt, no):

            # grab the name if we can
            if nameva is None:
                name = None
            else:
                section = sections.getsectionbyaddress(nameva.int())
                sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                nameofs = nameva.int() - sectionva
                name = utils.strdup(data[nameofs:].tostring())

            # grab the ordinal if we can
            if ordinal is None:
                forwarded, value = None, None

            elif 0 <= ordinal <= len(eat):
                # this is inside the export directory, so it's a forwardedrva
                if ExportDirectory.containsaddress(eat[ordinal]):
                    section = sections.getsectionbyaddress(eat[ordinal])
                    sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                    forwarded, value = utils.strdup(data[eat[ordinal] - sectionva:].tostring()), None

                # otherwise, it's a valid address
                else:
                    forwarded, value = None, eat[ordinal]

            # this ordinal is outside the export address table, although
            # we can read from the file to deal with these sort of fuxed
            # things... this is currently unsupported by pecoff
            else:
                logging.warning("{:s} : Error resolving export address for {:s} : !({:d} <= {:d} < {:d})".format('.'.join((cls.__module__, cls.__name__)), name, 0, ordinal, len(eat)))
                forwarded, value = None, None

            ordinalstring = None if ordinal is None else "Ordinal{:d}".format(ordinal + Base)
            yield va, ordinal, name, ordinalstring, value, forwarded
            va += 4
        return
Ejemplo n.º 18
0
 def __ModuleForwarderRefs(self):
     res = self['NumberOfModuleForwarderRefs'].li
     return dyn.array(IMAGE_BOUND_FORWARDER_REF, res.int())
Ejemplo n.º 19
0
class IMAGE_LOADCONFIG_DIRECTORY(pstruct.type):
    # FIXME: The size field in the DataDirectory is used to determine which
    #        IMAGE_LOADCONFIG_DIRECTORY to use. Instead we're cheating and
    #        using the size specified in the data-directory entry and a
    #        feature of pstruct.type when defining a custom .blocksize(). A
    #        proper implementation should check the 'Size' field and then
    #        use this to determine which IMAGE_LOADCONFIG_DIRECTORY
    #        should be used. Once that's done, then we can define a
    #        sub-object that chooses the correct IMAGE_LOADCONFIG_DIRECTORY
    #        to use.

    _fields_ = [
        (uint32, 'Size'),
        (TimeDateStamp, 'TimeDateStamp'),
        (uint16, 'MajorVersion'),
        (uint16, 'MinorVersion'),
        (uint32, 'GlobalFlagsClear'),  # FIXME
        (uint32, 'GlobalFlagsSet'),  # FIXME
        (uint32, 'CriticalSectionDefaultTimeout'),
        (uint32, 'DeCommitFreeBlockThreshold'),
        (uint32, 'DeCommitTotalFreeThreshold'),
        (realaddress(ptype.undefined, type=uint32),
         'LockPrefixTable'),  # XXX: NULL-terminated list of VAs
        (uint32, 'MaximumAllocationSize'),
        (uint32, 'VirtualMemoryThreshold'),
        (uint32, 'ProcessAffinityMask'),
        (uint32, 'ProcessHeapFlags'),  # FIXME: where are these flags at?
        (uint16, 'CSDVersion'),
        (uint16, 'Reserved'),
        (realaddress(ptype.undefined, type=uint32),
         'EditList'),  # XXX: also probably a NULL-terminated list of VAs
        (realaddress(uint32, type=uint32), 'SecurityCookie'),
        (realaddress(
            lambda s: dyn.array(uint32, s.parent['SEHandlerCount'].li.int()),
            type=uint32), 'SEHandlerTable'),
        (uint32, 'SEHandlerCount'),
        (realaddress(uint32, type=uint32), 'GuardCFCheckFunctionPointer'),
        (realaddress(uint32, type=uint32), 'GuardCFDispatchFunctionPointer'),
        (realaddress(lambda s: dyn.array(
            uint32, s.parent['GuardCFFunctionCount'].li.int()),
                     type=uint32), 'GuardCFFunctionTable'),
        (uint32, 'GuardCFFunctionCount'),
        (pbinary.littleendian(IMAGE_GUARD_), 'GuardFlags'),
        (IMAGE_LOAD_CONFIG_CODE_INTEGRITY, 'CodeIntegrity'),
        (realaddress(lambda s: dyn.array(
            uint32, s.parent['GuardAddressTakenIatEntryCount'].li.int()),
                     type=uint32), 'GuardAddressTakenIatEntryTable'),
        (uint32, 'GuardAddressTakenIatEntryCount'),
        (realaddress(lambda s: dyn.array(
            uint32, s.parent['GuardLongJumpTargetCount'].li.int()),
                     type=uint32), 'GuardLongJumpTargetTable'),
        (uint32, 'GuardLongJumpTargetCount'),
        (realaddress(ptype.undefined, type=uint32), 'DynamicValueRelocTable'
         ),  # XXX: Probably another NULL-terminated list of VAs
        (realaddress(ptype.undefined,
                     type=uint32), 'CHPEMetadataPointer'),  # FIXME
        (realaddress(uint32, type=uint32), 'GuardRFFailureRoutine'),
        (realaddress(uint32,
                     type=uint32), 'GuardRFFailureRoutineFunctionPointer'),
        (uint32, 'DynamicValueRelocTableOffset'
         ),  # XXX: depends on DynamicValueRelocTableSection
        (uint16, 'DynamicValueRelocTableSection'),
        (uint16, 'Reserved2'),
        (realaddress(uint32,
                     type=uint32), 'GuardRFVerifyStackPointerFunctionPointer'),
        (uint32, 'HotPatchTableOffset'),
        (realaddress(pstr.wstring, type=uint32), 'AddressOfSomeUnicodeString'),
        (uint32, 'Reserved3'),
    ]
Ejemplo n.º 20
0
class IMAGE_LOAD_CONFIG_DIRECTORY64(IMAGE_LOAD_CONFIG_DIRECTORY):
    _fields_ = [
        (DWORD, 'Size'),
        (TimeDateStamp, 'TimeDateStamp'),
        (WORD, 'MajorVersion'),
        (WORD, 'MinorVersion'),
        (DWORD, 'GlobalFlagsClear'),
        (DWORD, 'GlobalFlagsSet'),
        (DWORD, 'CriticalSectionDefaultTimeout'),
        (ULONGLONG, 'DeCommitFreeBlockThreshold'),
        (ULONGLONG, 'DeCommitTotalFreeThreshold'),
        (realaddress(VOID, type=ULONGLONG), 'LockPrefixTable'),
        (ULONGLONG, 'MaximumAllocationSize'),
        (ULONGLONG, 'VirtualMemoryThreshold'),
        (ULONGLONG, 'ProcessAffinityMask'),
        (DWORD, 'ProcessHeapFlags'),
        (WORD, 'CSDVersion'),
        (LOAD_LIBRARY_SEARCH_, 'DependentLoadFlags'),
        (realaddress(VOID, type=ULONGLONG), 'EditList'),
        (realaddress(ULONGLONG, type=ULONGLONG), 'SecurityCookie'),
        (realaddress(lambda self: dyn.array(
            ULONGLONG, self.parent['SEHandlerCount'].li.int()),
                     type=ULONGLONG), 'SEHandlerTable'),
        (ULONGLONG, 'SEHandlerCount'),
        (realaddress(realaddress(VOID, type=ULONGLONG),
                     type=ULONGLONG), 'GuardCFCheckFunctionPointer'),
        (realaddress(realaddress(VOID, type=ULONGLONG),
                     type=ULONGLONG), 'GuardCFDispatchFunctionPointer'),
        (realaddress(lambda self: dyn.array(
            virtualaddress(VOID, type=DWORD), self.parent[
                'GuardCFFunctionCount'].li.int()),
                     type=ULONGLONG), 'GuardCFFunctionTable'),
        (ULONGLONG, 'GuardCFFunctionCount'),
        (pbinary.littleendian(IMAGE_GUARD_), 'GuardFlags'),
        (IMAGE_LOAD_CONFIG_CODE_INTEGRITY, 'CodeIntegrity'),
        (realaddress(lambda self: dyn.array(
            ULONGLONG, self.parent['GuardAddressTakenIatEntryCount'].li.int()),
                     type=ULONGLONG), 'GuardAddressTakenIatEntryTable'),
        (ULONGLONG, 'GuardAddressTakenIatEntryCount'),
        (realaddress(lambda self: dyn.array(
            ULONGLONG, self.parent['GuardLongJumpTargetCount'].li.int()),
                     type=ULONGLONG), 'GuardLongJumpTargetTable'),
        (ULONGLONG, 'GuardLongJumpTargetCount'),
        (realaddress(IMAGE_DYNAMIC_RELOCATION_TABLE,
                     type=ULONGLONG), 'DynamicValueRelocTable'),
        (realaddress(VOID, type=ULONGLONG), 'CHPEMetadataPointer'),
        (realaddress(VOID, type=ULONGLONG), 'GuardRFFailureRoutine'),
        (realaddress(VOID,
                     type=ULONGLONG), 'GuardRFFailureRoutineFunctionPointer'),
        (DWORD, 'DynamicValueRelocTableOffset'),
        (WORD, 'DynamicValueRelocTableSection'),
        (WORD, 'Reserved2'),
        (realaddress(ULONGLONG, type=ULONGLONG),
         'GuardRFVerifyStackPointerFunctionPointer'),
        (DWORD, 'HotPatchTableOffset'),
        (DWORD, 'Reserved3'),
        (realaddress(IMAGE_ENCLAVE_CONFIG64,
                     type=ULONGLONG), 'EnclaveConfigurationPointer'),
        (realaddress(VOID, type=ULONGLONG), 'VolatileMetadataPointer'),
        (realaddress(lambda self: dyn.array(
            ULONGLONG, self.parent['GuardEHContinuationCount'].li.int()),
                     type=ULONGLONG), 'GuardEHContinuationTable'),
        (ULONGLONG, 'GuardEHContinuationCount'),
        (realaddress(VOID, type=ULONGLONG), 'GuardXFGCheckFunctionPointer'),
        (realaddress(VOID, type=ULONGLONG), 'GuardXFGDispatchFunctionPointer'),
        (realaddress(VOID,
                     type=ULONGLONG), 'GuardXFGTableDispatchFunctionPointer'),
        (ULONGLONG, 'CastGuardOsDeterminedFailureMode'),
    ]
Ejemplo n.º 21
0
    def iterate(self):
        """For each export, yields (rva offset, hint, name, ordinalname, entrypoint, forwardedrva)"""
        cls = self.__class__
        ExportDirectory = self.getparent(headers.IMAGE_DATA_DIRECTORY)
        Header, Base = LocateHeader(self), self['Base'].int()

        # our section data cache
        cache, sections = {}, Header['Sections']

        # grab everything that's important
        aof, aon, aono = self['AddressOfFunctions'], self['AddressOfNames'], self['AddressOfNameOrdinals']

        ## export address table
        if aof.int() > 0:
            # cache the section the eat is contained in since we need it anyways
            section = sections.getsectionbyaddress(aof.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aof into an array that's wikiwiki
            data = aof.d.l.cast(dyn.array(dword, len(aof.d)))
            eat = array.array('I', data.serialize())

            # check that the aof is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aof.int(), aof.int() + 4*self['NumberOfFunctions'].int())):
                logging.warn("{:s} : Export Address Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aof.int(), aof.int() + 4*self['NumberOfFunctions'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No export addresses found in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aof.summary()))
            eat = array.array('I', [])

        ## name ordinal table
        if aono.int() > 0:
            # cache the section the aono is contained in since we need it anyways
            section = sections.getsectionbyaddress(aono.int())
            cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))

            # convert the aono into an array that's also quick
            data = aono.d.l.cast(dyn.array(word, len(aono.d)))
            no = array.array('H', data.l.serialize())

            # check that the aono is within the bounds of the section, warn the user despite supporting it anyways
            if any(not section.containsaddress(ea) for ea in (aono.int(), aono.int() + 2*self['NumberOfNames'].int())):
                logging.warn("{:s} : Export Name Ordinal Table goes outside bounds of designated section. ({:#x} <= {:#x}{:+#x} < {:#x})".format('.'.join((cls.__module__, cls.__name__)), section['VirtualAddress'].int(), aono.int(), aono.int() + 2*self['NumberOfNames'].int(), section['VirtualAddress'].int() + section['VirtualSize'].int()))
        else:
            logging.warn("{:s} : No Export Name Ordinal Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aono.summary()))
            no = array.array('H', [])

        # check the name table
        if aon.int() == 0:
            logging.warn("{:s} : No Export Name Table in IMAGE_EXPORT_DIRECTORY. ({:s})".format('.'.join((cls.__module__, cls.__name__)), aon.summary()))
            nt = []
        else:
            nt = aon.d.l

        # now we can start returning things to the user
        va = CalculateRelativeOffset(self, aof.int())
        for nameva, ordinal in map(None, nt, no):

            # grab the name if we can
            if nameva is None:
                name = None
            else:
                section = sections.getsectionbyaddress(nameva.int())
                sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                nameofs = nameva.int() - sectionva
                name = utils.strdup(data[nameofs:].tostring())

            # grab the ordinal if we can
            if ordinal is None:
                forwarded, value = None, None

            elif 0 <= ordinal <= len(eat):
                # this is inside the export directory, so it's a forwardedrva
                if ExportDirectory.containsaddress(eat[ordinal]):
                    section = sections.getsectionbyaddress(eat[ordinal])
                    sectionva, data = cache[section.getoffset()] if section.getoffset() in cache else cache.setdefault(section.getoffset(), (section['VirtualAddress'].int(), array.array('B', section.data().l.serialize())))
                    forwarded, value = utils.strdup(data[eat[ordinal] - sectionva:].tostring()), None

                # otherwise, it's a valid address
                else:
                    forwarded, value = None, eat[ordinal]

            # this ordinal is outside the export address table, although
            # we can read from the file to deal with these sort of fuxed
            # things... this is currently unsupported by pecoff
            else:
                logging.warning("{:s} : Error resolving export address for {:s} : !({:d} <= {:d} < {:d})".format('.'.join((cls.__module__, cls.__name__)), name, 0, ordinal, len(eat)))
                forwarded, value = None, None

            ordinalstring = None if ordinal is None else "Ordinal{:d}".format(ordinal + Base)
            yield va, ordinal, name, ordinalstring, value, forwarded
            va += 4
        return
Ejemplo n.º 22
0
class IMAGE_PROLOGUE_DYNAMIC_RELOCATION_HEADER(pstruct.type):
    _fields_ = [
        (BYTE, 'PrologueByteCount'),
        (lambda self: dyn.array(BYTE, self['PrologueByteCount'].li.int()),
         'PrologueBytes'),
    ]
Ejemplo n.º 23
0
 def result(self, type=type):
     res = self.getparent(ResourceFileInfo)
     header = res['Reader'].li
     return dyn.array(type, header['Count'].int())
Ejemplo n.º 24
0
 class _Types(pstruct.type):
     _fields_ = [
         (pint.uint32_t, 'Count'),
         (lambda s: dyn.array(ResourceString, s['Count'].li.int()), 'Name'),
     ]
Ejemplo n.º 25
0
 def result(self, type=type):
     res = self.getparent(ResourceFileInfo)
     header = res['Reader'].li
     return dyn.array(type, header['Count'].int())