Пример #1
0
class RT_VERSION(pstruct.type):
    class _wType(pint.enum, word):
        _values_ = [
            ('Binary', 0),
            ('Text', 1),
        ]
    def __Value(self):
        length, attribute = self['wValueLength'].li.int(), getattr(self, 'ValueType') if hasattr(self, 'ValueType') else None
        if callable(attribute):
            return self.ValueType(length)

        cls, key = self.__class__, self['szKey'].li.str()
        if cls is not RT_VERSION:
            logging.debug("{:s} : No type callback implemented for Value in {!r}. Searching for one instead.".format('.'.join([cls.__module__, cls.__name__]), key))
        return RT_VERSION_ValueType.withdefault(key, type=key, length=length)

    def __Padding2(self):
        fields = ['wLength', 'wValueLength', 'wType', 'szKey', 'Padding1', 'Value']
        length, cb = self['wLength'].li.int(), sum(self[fld].li.size() for fld in fields)
        return dyn.align(4) if cb < length else dyn.align(0)

    def __Children(self):
        fields = ['wLength', 'wValueLength', 'wType', 'szKey', 'Padding1', 'Value', 'Padding2']
        length, cb = self['wLength'].li.int(), sum(self[fld].li.size() for fld in fields)
        if cb > length:
            raise AssertionError("Invalid block size returned by {!s} for child: {:d} > {:d}".format(self.instance(), cb, length))
        size = max(0, length - cb)

        # If our class implements a .Children() method, then use that to determine the type.
        attribute = getattr(self, 'Children') if hasattr(self, 'Children') else None
        if callable(attribute):
            return self.Children(size)

        # Otherwise, use the key to lookup the type in our definition.
        cls, key = self.__class__, self['szKey'].li.str()
        if cls is not RT_VERSION:
            logging.debug("{:s} : No type callback implemented for Children in {!r}. Searching for one instead.".format('.'.join([cls.__module__, cls.__name__]), key))

        # And then use that type to build the array of children.
        res = RT_VERSION_EntryType.lookup(key)
        return dyn.blockarray(res, size)

    def __Unknown(self):
        res, fields = self['wLength'].li.int(), ['wLength', 'wValueLength', 'wType', 'szKey', 'Padding1', 'Value', 'Padding2', 'Children']
        cb = sum(self[fld].li.size() for fld in fields)
        return dyn.block(max(0, res - cb))

    _fields_ = [
        (dyn.align(4), 'alignment'),
        (word, 'wLength'),
        (word, 'wValueLength'),
        (_wType, 'wType'),
        (pstr.szwstring, 'szKey'),
        (dyn.align(4), 'Padding1'),
        (__Value, 'Value'),
        (__Padding2, 'Padding2'),
        (__Children, 'Children'),
        (__Unknown, 'Unknown'),
    ]
Пример #2
0
class StreamHdr(pstruct.type):
    class _Offset(ptype.rpointer_t):
        _value_ = pint.uint32_t

        def _baseobject_(self):
            return self.getparent(MetaDataRoot)

        def _object_(self):
            res = self.getparent(StreamHdr)
            cb = res['Size'].int()
            t = Stream.withdefault(res['Name'].str(),
                                   blocksize=lambda s, cb=cb: cb)
            if issubclass(t, parray.block):
                return dyn.clone(t, blocksize=lambda s, cb=cb: cb)
            return t

    _fields_ = [
        (_Offset, 'Offset'),
        (pint.uint32_t, 'Size'),
        (pstr.szstring, 'Name'),
        (dyn.align(4), 'aligned(Name)'),
    ]

    def Name(self):
        return self['Name'].str()

    def Size(self):
        return self['Size'].int()
Пример #3
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'),
    ]
Пример #4
0
class RT_VERSION(pstruct.type):
    def __Type(self):
        if callable(getattr(self, 'Type', None)):
            return self.Type()

        cls, key = self.__class__, self['szKey'].li.str()
        if cls != RT_VERSION:
            logging.debug("{:s} : No type callback implemented for Value in {!r}. Searching for one instead.".format('.'.join((cls.__module__, cls.__name__)), key))

        sz = self['wValueLength'].li.int()
        return RT_VERSION_ValueType.withdefault(key, type=key, length=sz)

    def __ChildType(self):
        if callable(getattr(self, 'ChildType', None)):
            return self.ChildType()

        cls, key = self.__class__, self['szKey'].li.str()
        if self.__class__ != RT_VERSION:
            logging.debug("{:s} : No type callback implemented for Children in {!r}. Searching for one instead.".format('.'.join((cls.__module__, cls.__name__)), key))

        return RT_VERSION_EntryType.lookup(key)
        #bs = self['wLength'].li.int() - self.blocksize()
        #return RT_VERSION_EntryType.withdefault(szkey, type=szkey, length=bs)

    def __Children(self):
        fields = ['wLength', 'wValueLength', 'wType', 'szKey', 'Alignment', 'Value']
        length, cb = self['wLength'].li.int(), sum(self[fld].li.size() for fld in fields)

        if cb > length:
            raise AssertionError("Invalid block size returned for child: {:d}".format(bs))

        ct = self.__ChildType()
        class Member(pstruct.type):
            _fields_ = [
                (dyn.align(4), 'Alignment'),
                (ct, 'Child'),
            ]
        return dyn.clone(parray.block, _object_=Member, blocksize=lambda self, bs=length - cb: bs)

    def __Padding(self):
        cb = sum(self[fld].li.size() for _, fld in self._fields_[:-1])
        return dyn.block(self.blocksize() - cb)

    _fields_ = [
        (word, 'wLength'),
        (word, 'wValueLength'),
        (word, 'wType'),
        (pstr.szwstring, 'szKey'),
        (dyn.align(4), 'Alignment'),
        (__Type, 'Value'),
        (__Children, 'Children'),
        (__Padding, 'Padding'),
    ]
Пример #5
0
class IMAGE_IMPORT_HINT(pstruct.type):
    _fields_ = [(word, 'Hint'), (pstr.szstring, 'String'),
                (dyn.align(2), 'Padding')]

    def str(self):
        return self.String()

    def Hint(self):
        return self['Hint'].li.int()

    def String(self):
        return self['String'].li.str()
Пример #6
0
class MetaDataRoot(pstruct.type):
    class _Signature(pint.uint32_t):
        def properties(self):
            res = super(MetaDataRoot._Signature, self).properties()
            res['valid'] = self.valid()
            return res

        def valid(self):
            return self.int() == 0x424a5342

    class _StreamHeaders(parray.type):
        _object_ = StreamHdr

        def Get(self, name):
            res = next((stream for stream in self if stream.Name() == name),
                       None)
            if res is None:
                raise NameError(name)
            return res

    def __StreamHeaders(self):
        res = self['Streams'].li.int()
        return dyn.clone(self._StreamHeaders, length=res)

    def __StreamData(self):
        cb = self.getparent(IMAGE_DATA_DIRECTORY)['Size'].int()
        total = sum(self[n].li.size() for _, n in self._fields_[:-1])
        res = max((0, cb - total))
        return dyn.block(res)

    @pbinary.littleendian
    class StorageFlags(pbinary.flags):
        _fields_ = [
            (15, 'Reserved'),
            (1, 'ExtraData'),
        ]

    _fields_ = [
        (_Signature, 'Signature'),
        (pint.uint16_t, 'MajorVersion'),
        (pint.uint16_t, 'MinorVersion'),
        (pint.uint32_t, 'Reserved'),
        (pint.uint32_t, 'Length'),
        (lambda s: dyn.clone(pstr.string, length=s['Length'].li.int()),
         'Version'),
        (dyn.align(4), 'aligned(Version)'),
        (StorageFlags, 'Flags'),
        (pint.uint16_t, 'Streams'),
        (__StreamHeaders, 'StreamHeaders'),
        (__StreamData, 'StreamData'),
    ]
Пример #7
0
class UNWIND_INFO(pstruct.type):
    class _Header(pbinary.struct):
        _fields_ = [
            (UNW_FLAG_, 'Flags'),
            (3, 'Version'),
        ]

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

    class _HandlerInfo(pstruct.type):
        _fields_ = [(virtualaddress(ptype.undefined,
                                    type=dword), 'ExceptionHandler'),
                    (virtualaddress(FuncInfo, type=dword), 'ExceptionData')]

    def __HandlerInfo(self):
        res = self['Header'].li
        flags = res.item('Flags')
        return self._HandlerInfo if any(
            flags[item] for item in ['EHANDLER', 'UHANDLER', 'FHANDLER'
                                     ]) else ptype.undefined

    def __FunctionEntry(self):
        res = self['Header'].li
        flags = res.item('Flags')
        return RUNTIME_FUNCTION if flags['CHAININFO'] else ptype.undefined

    _fields_ = [
        (_Header, 'Header'),
        (byte, 'SizeOfProlog'),
        (byte, 'CountOfCodes'),
        (_Frame, 'Frame'),
        (lambda self: dyn.blockarray(UNWIND_CODE, 2 * self['CountOfCodes'].li.
                                     int()), 'UnwindCode'),
        (dyn.align(4),
         'align(ExceptionHandler)'),  # FIXME: this was copied from IDA
        (__HandlerInfo, 'HandlerInfo'),
        (__FunctionEntry, 'FunctionEntry'),
    ]
Пример #8
0
 class Member(pstruct.type):
     _fields_ = [
         (dyn.align(4), 'Padding'),
         (ct, 'Child'),
     ]
Пример #9
0
 class Member(pstruct.type):
     _fields_ = [
         (dyn.align(4), 'Alignment'),
         (ct, 'Child'),
     ]
Пример #10
0
 def __Padding2(self):
     fields = ['wLength', 'wValueLength', 'wType', 'szKey', 'Padding1', 'Value']
     length, cb = self['wLength'].li.int(), sum(self[fld].li.size() for fld in fields)
     return dyn.align(4) if cb < length else dyn.align(0)