Пример #1
0
 def __str__(self):
     """Print the direct members values. Never tries to recurse."""
     import ctypes
     if hasattr(self, '_orig_address_'):
         s = "# <%s at @%x>\n" % (
             self.__class__.__name__, self._orig_address_)
     else:
         s = "# <%s at @???>\n" % (self.__class__.__name__)
     # we need to ensure _mappings_ is defined in all children.
     for field, attrtype in self.getFields():
         attr = getattr(self, field)
         if ctypes.is_basic_type(attrtype):
             # basic type, ctypes or python
             s += '%s : %s, \n' % (field, repr(attr))
         elif (ctypes.is_struct_type(attrtype) or
               ctypes.is_union_type(attrtype)):
             # you can print a inner struct content
             s += '%s (@0x%lx) : {\t%s}\n' % (field,
                                              ctypes.addressof(attr),
                                              attr)
         elif ctypes.is_function_type(attrtype):
             # only print address in target space
             s += '%s (@0x%lx) : 0x%lx (FIELD NOT LOADED: function type)\n' % (
                 field, ctypes.addressof(attr),
                 utils.get_pointee_address(attr))
         elif ctypes.is_array_of_basic_type(attrtype):
             try:
                 s += '%s (@0x%lx) : %s\n' % (field, ctypes.addressof(attr),
                                              repr(utils.array2bytes(attr)))
             except IndexError as e:
                 log.error('error while reading %s %s' % (repr(attr),
                                                          type(attr)))
                 # FIXME
         elif ctypes.is_array_type(attrtype):
             # array of something else than int
             s += '%s (@0x%lx)    :[' % (field, ctypes.addressof(attr))
             s += ','.join(["%s" % (val) for val in attr])
             s += '],\n'
         elif ctypes.is_cstring_type(attrtype):
             # only print address/null
             s += '%s (@0x%lx) : 0x%lx\n' % (field, ctypes.addressof(attr),
                                             utils.get_pointee_address(attr.ptr))
         elif ctypes.is_pointer_type(attrtype):  # and
             # not ctypes.is_pointer_to_void_type(attrtype)):
             # do not recurse.
             if attr is None:
                 attr = 0
                 s += '%s (@????) : 0x0\n' % (field)
             else:
                 s += '%s (@0x%lx) : 0x%lx\n' % (field, ctypes.addressof(attr),
                                             utils.get_pointee_address(attr))
         elif (isinstance(attr, long)) or (isinstance(attr, int)):
             s += '%s : %s\n' % (field, hex(attr))
         else:
             s += '%s : %s\n' % (field, repr(attr))
     return s
Пример #2
0
 def _attrToPyObject(self, attr, field, attrtype):
     import ctypes
     if ctypes.is_basic_type(attrtype):
         if ctypes.is_basic_ctype(type(attr)):
             obj = attr.value
         else:
             obj = attr
     elif ctypes.is_struct_type(attrtype) or ctypes.is_union_type(attrtype):
         attr._mappings_ = self.mappings
         obj = self.parse(attr)
     elif ctypes.is_array_of_basic_type(attrtype):
         # return a list of int, float, or a char[] to str
         obj = utils.ctypes_to_python_array(attr)
     elif ctypes.is_array_type(attrtype):
         # array of something else than int/byte
         obj = []
         eltyp = type(attr[0])
         for i in range(0, len(attr)):
             obj.append(self._attrToPyObject(attr[i], i, eltyp))
     elif ctypes.is_cstring_type(attrtype):
         obj = self.mappings.getRef(
             ctypes.CString,
             utils.get_pointee_address(
                 attr.ptr))
     elif ctypes.is_function_type(attrtype):
         obj = repr(attr)
     elif ctypes.is_pointer_type(attrtype):
         # get the cached Value of the LP.
         _subtype = get_subtype(attrtype)
         _address = utils.get_pointee_address(attr)
         if _address == 0:
             # Null pointer
             obj = None
         elif ctypes.is_pointer_to_void_type(attrtype):
             # TODO: make a prototype for c_void_p loading
             # void types a rereturned as None
             obj = None
         elif ctypes.is_array_of_basic_type(attrtype):
             log.error('basic Type array - %s' % (field))
             obj = 'BasicType array'
         else:
             # get the cached Value of the LP.
             _subtype = get_subtype(attrtype)
             cache = self.mappings.getRef(_subtype, _address)
             if cache is not None:  # struct, union...
                 obj = self._attrToPyObject(cache, field, _subtype)
             else:
                 # you got here because your pointer is not loaded:
                 #  did you ignore it in expectedValues ?
                 #  is it in the middle of a struct ?
                 #  is that a linked list ?
                 #  is it a invalid instance ?
                 log.debug('Pointer for field:%s %s/%s not in cache '
                           '0x%x' % (field, attrtype, get_subtype(attrtype),
                                     _address))
                 return (None, None)
     elif isinstance(attr, numbers.Number):
         # case for int, long. But needs to be after c_void_p pointers case
         obj = attr
     else:
         log.error('toPyObj default to return attr %s' % (type(attr)))
         obj = attr
     return obj
Пример #3
0
    def _loadMember(self, attr, attrname, attrtype, mappings, maxDepth):
        ctypes = self._mappings_.config.ctypes
        # skip static void_p data members
        if not self._isLoadableMember(attr, attrname, attrtype):
            log.debug("%s %s not loadable bool(attr) = %s" % (attrname, attrtype,
                                                              bool(attr)))
            return True
        # load it, fields are valid
        elif ctypes.is_struct_type(attrtype) or ctypes.is_union_type(attrtype):
            # its an embedded record. Bytes are already loaded.
            offset = utils.offsetof(type(self), attrname)
            log.debug('st: %s %s is STRUCT at @%x' % (attrname, attrtype,
                                                      self._orig_address_ + offset))
            # TODO pydoc for impl.
            attr._orig_address_ = self._orig_address_ + offset
            attr._mappings = mappings
            if not attr.loadMembers(mappings, maxDepth - 1):
                log.debug(
                    "st: %s %s not valid, error while loading inner struct" %
                    (attrname, attrtype))
                return False
            log.debug("st: %s %s inner struct LOADED " % (attrname, attrtype))
            return True
        elif ctypes.is_array_of_basic_type(attrtype):
            return True
        elif ctypes.is_array_type(attrtype):
            log.debug('a: %s is arraytype %s recurse load' % (attrname,
                                                              repr(attr)))
            attrLen = len(attr)
            if attrLen == 0:
                return True
            elType = type(attr[0])
            for i in range(0, attrLen):
                # FIXME BUG DOES NOT WORK
                # offsetof("%s[%d]") is called, and %s exists, not %s[%d]
                # if not self._loadMember(attr[i], "%s[%d]"%(attrname,i),
                # elType, mappings, maxDepth):
                if not self._loadMember(
                        attr[i], attrname, elType, mappings, maxDepth):
                    return False
            return True
        # we have PointerType here . Basic or complex
        # exception cases
        elif ctypes.is_function_type(attrtype):
            pass
            # FIXME
        elif ctypes.is_cstring_type(attrtype):
            # can't use basic c_char_p because we can't load in foreign memory
            # FIXME, you need to keep a ref to this ctring if
            # your want _mappings_ to exists
            # or just mandate mappings in toString
            attr_obj_address = utils.get_pointee_address(attr.ptr)
            if not bool(attr_obj_address):
                log.debug('%s %s is a CString, the pointer is null (validation '
                          'must have occurred earlier)' % (attrname, attr))
                return True
            memoryMap = mappings.is_valid_address_value(attr_obj_address)
            if not memoryMap:
                log.warning('Error on addr while fetching a CString.'
                            'should not happen')
                return False
            ref = mappings.getRef(ctypes.CString, attr_obj_address)
            if ref:
                log.debug("%s %s loading from references cache %s/0x%lx" % (attrname,
                                                                            attr, ctypes.CString, attr_obj_address))
                return True
            max_size = min(
                self.MAX_CSTRING_SIZE,
                memoryMap.end -
                attr_obj_address)
            log.debug('%s %s is defined as a CString, loading %d bytes from 0x%lx '
                      'is_valid_address %s' % (attrname, attr, max_size, attr_obj_address,
                                               mappings.is_valid_address_value(attr_obj_address)))
            txt, truncated = memoryMap.readCString(attr_obj_address, max_size)
            if truncated:
                log.warning(
                    'buffer size was too small for this CString: %d' %
                    (max_size))

            # that will SEGFAULT attr.string = txt - instead keepRef to String
            mappings.keepRef(txt, ctypes.CString, attr_obj_address)
            log.debug(
                'kept CString ref for "%s" at @%x' %
                (txt, attr_obj_address))
            return True
        # not functionType, it's not loadable
        elif ctypes.is_pointer_type(attrtype):
            _attrType = get_subtype(attrtype)
            attr_obj_address = utils.get_pointee_address(attr)
            ####
            # memcpy and save objet ref + pointer in attr
            # we know the field is considered valid, so if it's not in
            # memory_space, we can ignore it
            memoryMap = mappings.is_valid_address(attr, _attrType)
            if(not memoryMap):
                # big BUG Badaboum, why did pointer changed validity/value ?
                log.warning(
                    "%s %s not loadable 0x%lx but VALID " %
                    (attrname, attr, attr_obj_address))
                return True

            ref = mappings.getRef(_attrType, attr_obj_address)
            if ref:
                log.debug(
                    "%s %s loading from references cache %s/0x%lx" %
                    (attrname, attr, _attrType, attr_obj_address))
                # DO NOT CHANGE STUFF SOUPID attr.contents = ref. attr.contents
                # will SEGFAULT
                return True
            log.debug(
                "%s %s loading from 0x%lx (is_valid_address: %s)" %
                (attrname, attr, attr_obj_address, memoryMap))
            # Read the struct in memory and make a copy to play with.
            # DO NOT COPY THE STRUCT, we have a working readStruct for that...
            # ERRROR
            # attr.contents=_attrType.from_buffer_copy(memoryMap.readStruct(attr_obj_address,
            # _attrType ))
            contents = memoryMap.readStruct(attr_obj_address, _attrType)

            # save that validated and loaded ref and original addr so we dont
            # need to recopy it later
            mappings.keepRef(contents, _attrType, attr_obj_address)
            log.debug(
                "keepRef %s.%s @%x" %
                (_attrType, attrname, attr_obj_address))
            log.debug(
                "%s %s loaded memcopy from 0x%lx to 0x%lx" %
                (attrname,
                 attr,
                 attr_obj_address,
                 (utils.get_pointee_address(attr))))
            # recursive validation checks on new struct
            if not bool(attr):
                log.warning(
                    'Member %s is null after copy: %s' %
                    (attrname, attr))
                return True
            # go and load the pointed struct members recursively
            subtype = utils.get_subtype(attrtype)
            if (ctypes.is_basic_type(subtype) or
                    ctypes.is_array_of_basic_type(subtype)):
                # do nothing
                return True
            elif (ctypes.is_array_type(subtype) or
                  ctypes.is_pointer_type(subtype)):
                return self._loadMember(
                    contents, 'pointee', subtype, mappings, maxDepth - 1)

            if not contents.loadMembers(mappings, maxDepth - 1):
                log.debug('member %s was not loaded' % (attrname))
                # invalidate the cache ref.
                mappings.delRef(_attrType, attr_obj_address)
                return False
            return True
        # TATAFN
        return True
Пример #4
0
 def _isValidAttr(self, attr, attrname, attrtype, mappings):
     """ Validation of a single member """
     import ctypes
     # a)
     log.debug('valid: %s, %s' % (attrname, attrtype))
     if ctypes.is_basic_type(attrtype):
         if attrname in self.expectedValues:
             if attr not in self.expectedValues[attrname]:
                 log.debug(
                     'basicType: %s %s %s bad value not in self.expectedValues[attrname]:' %
                     (attrname, attrtype, repr(attr)))
                 return False
         log.debug(
             'basicType: %s %s %s ok' %
             (attrname, attrtype, repr(attr)))
         return True
     # b)
     elif ctypes.is_struct_type(attrtype) or ctypes.is_union_type(attrtype):
         # do i need to load it first ? becaus it should be memcopied with
         # the super()..
         if not attr.isValid(mappings):
             log.debug(
                 'structType: %s %s %s isValid FALSE' %
                 (attrname, attrtype, repr(attr)))
             return False
         log.debug(
             'structType: %s %s %s isValid TRUE' %
             (attrname, attrtype, repr(attr)))
         return True
     # c)
     elif ctypes.is_array_of_basic_type(attrtype):
         if attrname in self.expectedValues:
             if attr not in self.expectedValues[attrname]:
                 log.debug(
                     'basicArray: %s %s %s - bad value not in self.expectedValues[attrname]:' %
                     (attrname, attrtype, type(attr)))
                 return False
         log.debug(
             'basicArray: %s is arraytype %s we decided it was valid',
             attrname,
             type(attr))
         return True
     # d)
     elif ctypes.is_array_type(attrtype):
         log.debug('array: %s is arraytype %s recurse validate' % (attrname,
                                                                   repr(attr)))
         attrLen = len(attr)
         if attrLen == 0:
             return True
         elType = type(attr[0])
         for i in range(0, attrLen):
             # FIXME BUG DOES NOT WORK - offsetof("%s[%d]") is called,
             # and %s exists, not %s[%d]
             if not self._isValidAttr(attr[i], "%s[%d]" % (attrname, i), elType,
                                      mappings):
                 return False
         return True
     # e)
     elif ctypes.is_cstring_type(attrtype):
         myaddress = utils.get_pointee_address(attr.ptr)
         if attrname in self.expectedValues:
             # test if NULL is an option
             if not bool(myaddress):
                 if not ((None in self.expectedValues[attrname]) or
                         (0 in self.expectedValues[attrname])):
                     log.debug('str: %s %s %s isNULL - NOT EXPECTED' % (
                         attrname, attrtype, repr(attr)))
                     return False
                 log.debug('str: %s %s %s isNULL - OK' % (attrname, attrtype,
                                                          repr(attr)))
                 # e.1)
                 return True
         if (myaddress != 0 and
                 not mappings.is_valid_address_value(myaddress)):
             log.debug('str: %s %s %s 0x%lx INVALID' % (attrname, attrtype,
                                                        repr(attr), myaddress))
             # e.2)
             return False
         log.debug('str: %s %s %s is at 0x%lx OK' % (attrname, attrtype,
                                                     repr(attr), myaddress))
         # e.3)
         return True
     # f)
     elif ctypes.is_pointer_type(attrtype):
         myaddress = utils.get_pointee_address(attr)
         if attrname in self.expectedValues:
             # test if NULL is an option
             log.debug('ctypes.is_pointer_type: bool(attr):%s attr:%s' % (
                 bool(attr), attr))
             if not bool(myaddress):
                 if not ((None in self.expectedValues[attrname]) or
                         (0 in self.expectedValues[attrname])):
                     log.debug('ptr: %s %s %s isNULL - NOT EXPECTED' % (
                         attrname, attrtype, repr(attr)))
                     # f.1) expectedValues specifies NULL to be invalid
                     return False
                 log.debug('ptr: %s %s %s isNULL - OK' % (attrname, attrtype,
                                                          repr(attr)))
                 # f.2) expectedValues specifies NULL to be valid
                 return True
         _attrType = None
         if (ctypes.is_pointer_to_void_type(attrtype) or
                 ctypes.is_function_type(attrtype)):
             log.debug(
                 'Its a simple type. Checking mappings only. attr=%s' %
                 (attr))
             if (myaddress != 0 and
                     not mappings.is_valid_address_value(myaddress)):
                 log.debug('voidptr: %s %s %s 0x%lx INVALID simple pointer' % (
                     attrname, attrtype, repr(attr), myaddress))
                 # f.3) address must be valid, no type requirement
                 return False
         else:
             # test valid address mapping
             _attrType = get_subtype(attrtype)
         if (myaddress != 0 and
                 not mappings.is_valid_address(attr, _attrType)):
             log.debug('ptr: %s %s %s 0x%lx INVALID' % (attrname, attrtype,
                                                        repr(attr), utils.get_pointee_address(attr)))
             # f.4) its a pointer, but not valid in our mappings for this
             # pointee type.
             return False
         log.debug('ptr: name:%s repr:%s address:0x%lx OK' % (attrname,
                                                              repr(attr), utils.get_pointee_address(attr)))
         # f.5) null is accepted by default
         return True
     # g)
     log.error('What type are You ?: %s/%s' % (attrname, attrtype))
     return True