Exemple #1
0
    def add_lib_handler(self, libimp, namespace):
        """Add search for handler based on a @libimp libimp instance

        Known functions will be looked by {name}_symb or {name}_{ord}_symb in the @namespace
        """
        namespace = dict(
            (force_bytes(name), func) for name, func in viewitems(namespace))

        # lambda cannot contain statement
        def default_func(dse):
            fname = libimp.fad2cname[dse.jitter.pc]
            if isinstance(fname, tuple):
                fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1])
            else:
                fname = b"%s_symb" % force_bytes(fname)
            raise RuntimeError("Symbolic stub '%s' not found" % fname)

        for addr, fname in viewitems(libimp.fad2cname):
            if isinstance(fname, tuple):
                fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1])
            else:
                fname = b"%s_symb" % force_bytes(fname)
            func = namespace.get(fname, None)
            if func is not None:
                self.add_handler(addr, func)
            else:
                self.add_handler(addr, default_func)
Exemple #2
0
 def default_func(dse):
     fname = libimp.fad2cname[dse.jitter.pc]
     if isinstance(fname, tuple):
         fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1])
     else:
         fname = b"%s_symb" % force_bytes(fname)
     raise RuntimeError("Symbolic stub '%s' not found" % fname)
Exemple #3
0
    def __init__(self, *args, **kwargs):
        Sandbox.__init__(self, *args, **kwargs)

        # Pre-stack some arguments
        if self.options.mimic_env:
            env_ptrs = []
            for env in self.envp:
                env = force_bytes(env)
                env += b"\x00"
                self.jitter.cpu.SP -= len(env)
                ptr = self.jitter.cpu.SP
                self.jitter.vm.set_mem(ptr, env)
                env_ptrs.append(ptr)
            argv_ptrs = []
            for arg in self.argv:
                arg = force_bytes(arg)
                arg += b"\x00"
                self.jitter.cpu.SP -= len(arg)
                ptr = self.jitter.cpu.SP
                self.jitter.vm.set_mem(ptr, arg)
                argv_ptrs.append(ptr)

            self.jitter.push_uint64_t(0)
            for ptr in reversed(env_ptrs):
                self.jitter.push_uint64_t(ptr)
            self.jitter.push_uint64_t(0)
            for ptr in reversed(argv_ptrs):
                self.jitter.push_uint64_t(ptr)
            self.jitter.push_uint64_t(len(self.argv))

        self.jitter.cpu.LR = self.CALL_FINISH_ADDR

        # Set the runtime guard
        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR,
                                   self.__class__.code_sentinelle)
Exemple #4
0
def canon_libname_libfunc(libname, libfunc):
    libname = force_bytes(libname)
    dn = libname.split(b'.')[0]
    if isinstance(libfunc, int_types):
        return str(dn), libfunc
    else:
        libfunc = force_bytes(libfunc)
        return b"%s_%s" % (dn, libfunc)
Exemple #5
0
def canon_libname_libfunc(libname, libfunc):
    libname = force_bytes(libname)
    dn = libname.split(b'.')[0]
    if isinstance(libfunc, int_types):
        return str(dn), libfunc
    else:
        libfunc = force_bytes(libfunc)
        return b"%s_%s" % (dn, libfunc)
Exemple #6
0
    def __init__(self, loc_db, *args, **kwargs):
        super(Sandbox_Linux_ppc32b, self).__init__(loc_db, *args, **kwargs)

        # Init stack
        self.jitter.stack_size = self.STACK_SIZE
        self.jitter.stack_base = self.STACK_BASE
        self.jitter.init_stack()
        self.jitter.cpu.R1 -= 8

        # Pre-stack some arguments
        if self.options.mimic_env:
            env_ptrs = []
            for env in self.envp:
                env = force_bytes(env)
                env += b"\x00"
                self.jitter.cpu.R1 -= len(env)
                ptr = self.jitter.cpu.R1
                self.jitter.vm.set_mem(ptr, env)
                env_ptrs.append(ptr)
            argv_ptrs = []
            for arg in self.argv:
                arg = force_bytes(arg)
                arg += b"\x00"
                self.jitter.cpu.R1 -= len(arg)
                ptr = self.jitter.cpu.R1
                self.jitter.vm.set_mem(ptr, arg)
                argv_ptrs.append(ptr)

            self.jitter.push_uint32_t(0)
            for ptr in reversed(env_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.cpu.R5 = self.jitter.cpu.R1	# envp
            self.jitter.push_uint32_t(0)
            for ptr in reversed(argv_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.cpu.R4 = self.jitter.cpu.R1	# argv
            self.jitter.cpu.R3 = len(self.argv)		# argc
            self.jitter.push_uint32_t(self.jitter.cpu.R3)

            self.jitter.cpu.R6 = 0			# auxp
            self.jitter.cpu.R7 = 0			# termination function

            # From the glibc, we should push a 0 here to distinguish a
            # dynamically linked executable from a statically linked one.
            # We actually do not do it and attempt to be somehow compatible
            # with both types of executables.
            #self.jitter.push_uint32_t(0)

        self.jitter.cpu.LR = self.CALL_FINISH_ADDR

        # Set the runtime guard
        self.jitter.add_breakpoint(
            self.CALL_FINISH_ADDR,
            self.__class__.code_sentinelle
        )
Exemple #7
0
    def __init__(self, *args, **kwargs):
        super(Sandbox_Linux_ppc32b, self).__init__(*args, **kwargs)

        # Init stack
        self.jitter.stack_size = self.STACK_SIZE
        self.jitter.stack_base = self.STACK_BASE
        self.jitter.init_stack()
        self.jitter.cpu.R1 -= 8

        # Pre-stack some arguments
        if self.options.mimic_env:
            env_ptrs = []
            for env in self.envp:
                env = force_bytes(env)
                env += b"\x00"
                self.jitter.cpu.R1 -= len(env)
                ptr = self.jitter.cpu.R1
                self.jitter.vm.set_mem(ptr, env)
                env_ptrs.append(ptr)
            argv_ptrs = []
            for arg in self.argv:
                arg = force_bytes(arg)
                arg += b"\x00"
                self.jitter.cpu.R1 -= len(arg)
                ptr = self.jitter.cpu.R1
                self.jitter.vm.set_mem(ptr, arg)
                argv_ptrs.append(ptr)

            self.jitter.push_uint32_t(0)
            for ptr in reversed(env_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.cpu.R5 = self.jitter.cpu.R1	# envp
            self.jitter.push_uint32_t(0)
            for ptr in reversed(argv_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.cpu.R4 = self.jitter.cpu.R1	# argv
            self.jitter.cpu.R3 = len(self.argv)		# argc
            self.jitter.push_uint32_t(self.jitter.cpu.R3)

            self.jitter.cpu.R6 = 0			# auxp
            self.jitter.cpu.R7 = 0			# termination function

            # From the glibc, we should push a 0 here to distinguish a
            # dynamically linked executable from a statically linked one.
            # We actually do not do it and attempt to be somehow compatible
            # with both types of executables.
            #self.jitter.push_uint32_t(0)

        self.jitter.cpu.LR = self.CALL_FINISH_ADDR

        # Set the runtime guard
        self.jitter.add_breakpoint(
            self.CALL_FINISH_ADDR,
            self.__class__.code_sentinelle
        )
Exemple #8
0
 def get_name_location(self, name):
     """
     Return the LocKey of @name if any, None otherwise.
     @name: target name
     """
     name = force_bytes(name)
     return self._name_to_loc_key.get(name)
Exemple #9
0
 def get_name_location(self, name):
     """
     Return the LocKey of @name if any, None otherwise.
     @name: target name
     """
     name = force_bytes(name)
     return self._name_to_loc_key.get(name)
Exemple #10
0
 def add_name(self, name):
     name = force_bytes(name)
     name = name + b"\x00"
     if name in self.content:
         return self.content.find(name)
     n = len(self.content)
     self.content = bytes(self.content) + name
     return n
Exemple #11
0
 def getsectionbyname(self, name):
     name = force_bytes(name)
     for s in self.sh:
         try:
             if s.sh.name.strip(b'\x00') == name:
                 return s
         except UnicodeDecodeError:
             pass
     return None
Exemple #12
0
 def get_or_create_name_location(self, name):
     """
     Return the LocKey of @name if any, create one otherwise.
     @name: target name
     """
     name = force_bytes(name)
     loc_key = self._name_to_loc_key.get(name)
     if loc_key is not None:
         return loc_key
     return self.add_location(name=name)
Exemple #13
0
 def get_name_offset(self, name):
     """
     Return the offset of @name if any, None otherwise.
     @name: target name
     """
     name = force_bytes(name)
     loc_key = self.get_name_location(name)
     if loc_key is None:
         return None
     return self.get_location_offset(loc_key)
Exemple #14
0
 def get_name_offset(self, name):
     """
     Return the offset of @name if any, None otherwise.
     @name: target name
     """
     name = force_bytes(name)
     loc_key = self.get_name_location(name)
     if loc_key is None:
         return None
     return self.get_location_offset(loc_key)
Exemple #15
0
 def get_or_create_name_location(self, name):
     """
     Return the LocKey of @name if any, create one otherwise.
     @name: target name
     """
     name = force_bytes(name)
     loc_key = self._name_to_loc_key.get(name)
     if loc_key is not None:
         return loc_key
     return self.add_location(name=name)
Exemple #16
0
    def __init__(self, *args, **kwargs):
        Sandbox.__init__(self, *args, **kwargs)

        # Pre-stack some arguments
        if self.options.mimic_env:
            env_ptrs = []
            for env in self.envp:
                env = force_bytes(env)
                env += b"\x00"
                self.jitter.cpu.SP -= len(env)
                ptr = self.jitter.cpu.SP
                self.jitter.vm.set_mem(ptr, env)
                env_ptrs.append(ptr)
            argv_ptrs = []
            for arg in self.argv:
                arg = force_bytes(arg)
                arg += b"\x00"
                self.jitter.cpu.SP -= len(arg)
                ptr = self.jitter.cpu.SP
                self.jitter.vm.set_mem(ptr, arg)
                argv_ptrs.append(ptr)

            # Round SP to 4
            self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3

            self.jitter.push_uint32_t(0)
            for ptr in reversed(env_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.push_uint32_t(0)
            for ptr in reversed(argv_ptrs):
                self.jitter.push_uint32_t(ptr)
            self.jitter.push_uint32_t(len(self.argv))

        self.jitter.cpu.LR = self.CALL_FINISH_ADDR

        # Set the runtime guard
        self.jitter.add_breakpoint(
            self.CALL_FINISH_ADDR,
            self.__class__.code_sentinelle
        )
Exemple #17
0
 def add_location_name(self, loc_key, name):
     """Associate a name @name to a given @loc_key
     @name: str instance
     @loc_key: LocKey instance
     """
     name = force_bytes(name)
     assert loc_key in self._loc_keys
     already_existing_loc = self._name_to_loc_key.get(name)
     if already_existing_loc is not None and already_existing_loc != loc_key:
         raise KeyError("%r is already associated to a different loc_key "
                        "(%r)" % (name, already_existing_loc))
     self._loc_key_to_names.setdefault(loc_key, set()).add(name)
     self._name_to_loc_key[name] = loc_key
Exemple #18
0
    def add_lib_handler(self, libimp, namespace):
        """Add search for handler based on a @libimp libimp instance

        Known functions will be looked by {name}_symb in the @namespace
        """
        namespace = dict(
            (force_bytes(name), func) for name, func in viewitems(namespace)
        )

        # lambda cannot contain statement
        def default_func(dse):
            fname = b"%s_symb" % libimp.fad2cname[dse.jitter.pc]
            raise RuntimeError("Symbolic stub '%s' not found" % fname)

        for addr, fname in viewitems(libimp.fad2cname):
            fname = force_bytes(fname)
            fname = b"%s_symb" % fname
            func = namespace.get(fname, None)
            if func is not None:
                self.add_handler(addr, func)
            else:
                self.add_handler(addr, default_func)
Exemple #19
0
 def add_location_name(self, loc_key, name):
     """Associate a name @name to a given @loc_key
     @name: str instance
     @loc_key: LocKey instance
     """
     name = force_bytes(name)
     assert loc_key in self._loc_keys
     already_existing_loc = self._name_to_loc_key.get(name)
     if already_existing_loc is not None and already_existing_loc != loc_key:
         raise KeyError("%r is already associated to a different loc_key "
                        "(%r)" % (name, already_existing_loc))
     self._loc_key_to_names.setdefault(loc_key, set()).add(name)
     self._name_to_loc_key[name] = loc_key
Exemple #20
0
    def pack(self):
        out = b''
        for field in self._fields:
            cpt = None
            if len(field) == 2:
                fname, ffmt = field
            elif len(field) == 3:
                fname, ffmt, cpt = field

            value = getattr(self, fname + self.__class__.field_suffix)
            if ffmt in type2realtype or (isinstance(ffmt, str)
                                         and re.match(r'\d+s', ffmt)):
                # basic types
                fmt = real_fmt(ffmt, self._wsize)
                if cpt == None:
                    if value == None:
                        o = struct.calcsize(fmt) * b"\x00"
                    elif ffmt.endswith('s'):
                        new_value = force_bytes(value)
                        o = struct.pack(self.sex + fmt, new_value)
                    else:
                        o = struct.pack(self.sex + fmt, value)
                else:
                    o = b""
                    for v in value:
                        if value == None:
                            o += struct.calcsize(fmt) * b"\x00"
                        else:
                            o += struct.pack(self.sex + fmt, v)

            elif ffmt == "sz":  # null terminated special case
                o = value + b'\x00'
            elif ffmt in all_cstructs:
                # sub structures
                if cpt == None:
                    o = bytes(value)
                else:
                    o = b""
                    for v in value:
                        o += bytes(v)
            elif isinstance(ffmt, tuple):
                f_get, f_set = ffmt
                o = f_set(self, value)

            else:
                raise ValueError('unknown class', ffmt)
            out += o

        return out
Exemple #21
0
    def find_free_name(self, name):
        """
        If @name is not known in DB, return it
        Else append an index to it corresponding to the next unknown name

        @name: string
        """
        name = force_bytes(name)
        if self.get_name_location(name) is None:
            return name
        i = 0
        while True:
            new_name = "%s_%d" % (name, i)
            if self.get_name_location(new_name) is None:
                return new_name
            i += 1
Exemple #22
0
 def remove_location_name(self, loc_key, name):
     """Disassociate a name @name from a given @loc_key
     Fail if @name is not already associated to @loc_key
     @name: str instance
     @loc_key: LocKey instance
     """
     assert loc_key in self._loc_keys
     name = force_bytes(name)
     already_existing_loc = self._name_to_loc_key.get(name)
     if already_existing_loc is None:
         raise KeyError("%r is not already associated" % name)
     if already_existing_loc != loc_key:
         raise KeyError("%r is already associated to a different loc_key "
                        "(%r)" % (name, already_existing_loc))
     del self._name_to_loc_key[name]
     self._loc_key_to_names[loc_key].remove(name)
Exemple #23
0
    def find_free_name(self, name):
        """
        If @name is not known in DB, return it
        Else append an index to it corresponding to the next unknown name

        @name: string
        """
        name = force_bytes(name)
        if self.get_name_location(name) is None:
            return name
        i = 0
        while True:
            new_name = "%s_%d" % (name, i)
            if self.get_name_location(new_name) is None:
                return new_name
            i += 1
Exemple #24
0
 def remove_location_name(self, loc_key, name):
     """Disassociate a name @name from a given @loc_key
     Fail if @name is not already associated to @loc_key
     @name: str instance
     @loc_key: LocKey instance
     """
     assert loc_key in self._loc_keys
     name = force_bytes(name)
     already_existing_loc = self._name_to_loc_key.get(name)
     if already_existing_loc is None:
         raise KeyError("%r is not already associated" % name)
     if already_existing_loc != loc_key:
         raise KeyError("%r is already associated to a different loc_key "
                        "(%r)" % (name, already_existing_loc))
     del self._name_to_loc_key[name]
     self._loc_key_to_names[loc_key].remove(name)
Exemple #25
0
    def lib_get_add_base(self, name):
        name = force_bytes(name)
        name = name.lower().strip(b' ')
        if not b"." in name:
            log.debug('warning adding .dll to modulename')
            name += b'.dll'
            log.debug(name)

        if name in self.name2off:
            ad = self.name2off[name]
        else:
            ad = self.libbase_ad
            log.warning("Create dummy entry for %r", name)
            self.fake_libs.add(name)
            self.name2off[name] = ad
            self.libbase2lastad[ad] = ad + 0x4
            self.lib_imp2ad[ad] = {}
            self.lib_imp2dstad[ad] = {}
            self.libbase_ad += 0x1000
        return ad
Exemple #26
0
    def lib_get_add_base(self, name):
        name = force_bytes(name)
        name = name.lower().strip(b' ')
        if not b"." in name:
            log.debug('warning adding .dll to modulename')
            name += b'.dll'
            log.debug(name)

        if name in self.name2off:
            ad = self.name2off[name]
        else:
            ad = self.libbase_ad
            log.warning("Create dummy entry for %r", name)
            self.fake_libs.add(name)
            self.name2off[name] = ad
            self.libbase2lastad[ad] = ad + 0x4
            self.lib_imp2ad[ad] = {}
            self.lib_imp2dstad[ad] = {}
            self.libbase_ad += 0x1000
        return ad
Exemple #27
0
 def default_func(dse):
     fname = b"%s_symb" % force_bytes(libimp.fad2cname[dse.jitter.pc])
     raise RuntimeError("Symbolic stub '%s' not found" % fname)
Exemple #28
0
    def add_location(self, name=None, offset=None, strict=True):
        """Add a new location in the locationDB. Returns the corresponding LocKey.
        If @name is set, also associate a name to this new location.
        If @offset is set, also associate an offset to this new location.

        Strict mode (set by @strict, default):
          If a location with @offset or @name already exists, an error will be
        raised.
        Otherwise:
          If a location with @offset or @name already exists, the corresponding
        LocKey may be updated and will be returned.
        """

        name = force_bytes(name)
        # Deprecation handling
        if is_int(name):
            assert offset is None or offset == name
            warnings.warn(
                "Deprecated API: use 'add_location(offset=)' instead."
                " An additional 'name=' can be provided to also "
                "associate a name (there is no more default name)")
            offset = name
            name = None

        # Argument cleaning
        offset_loc_key = None
        if offset is not None:
            offset = int(offset)
            offset_loc_key = self.get_offset_location(offset)

        # Test for collisions
        name_loc_key = None
        if name is not None:
            name_loc_key = self.get_name_location(name)

        if strict:
            if name_loc_key is not None:
                raise ValueError("An entry for %r already exists (%r), and "
                                 "strict mode is enabled" %
                                 (name, name_loc_key))
            if offset_loc_key is not None:
                raise ValueError("An entry for 0x%x already exists (%r), and "
                                 "strict mode is enabled" %
                                 (offset, offset_loc_key))
        else:
            # Non-strict mode
            if name_loc_key is not None:
                known_offset = self.get_offset_location(name_loc_key)
                if known_offset is None:
                    if offset is not None:
                        self.set_location_offset(name_loc_key, offset)
                elif known_offset != offset:
                    raise ValueError(
                        "Location with name '%s' already have an offset: 0x%x "
                        "(!= 0x%x)" % (name, offset, known_offset))
                # Name already known, same offset -> nothing to do
                return name_loc_key

            elif offset_loc_key is not None:
                if name is not None:
                    # Check for already known name are checked above
                    return self.add_location_name(offset_loc_key, name)
                # Offset already known, no name specified
                return offset_loc_key

        # No collision, this is a brand new location
        loc_key = LocKey(self._loc_key_num)
        self._loc_key_num += 1
        self._loc_keys.add(loc_key)

        if offset is not None:
            assert offset not in self._offset_to_loc_key
            self._offset_to_loc_key[offset] = loc_key
            self._loc_key_to_offset[loc_key] = offset

        if name is not None:
            self._name_to_loc_key[name] = loc_key
            self._loc_key_to_names[loc_key] = set([name])

        return loc_key
Exemple #29
0
    def add_location(self, name=None, offset=None, strict=True):
        """Add a new location in the locationDB. Returns the corresponding LocKey.
        If @name is set, also associate a name to this new location.
        If @offset is set, also associate an offset to this new location.

        Strict mode (set by @strict, default):
          If a location with @offset or @name already exists, an error will be
        raised.
        Otherwise:
          If a location with @offset or @name already exists, the corresponding
        LocKey may be updated and will be returned.
        """

        name = force_bytes(name)
        # Deprecation handling
        if is_int(name):
            assert offset is None or offset == name
            warnings.warn("Deprecated API: use 'add_location(offset=)' instead."
                          " An additional 'name=' can be provided to also "
                          "associate a name (there is no more default name)")
            offset = name
            name = None

        # Argument cleaning
        offset_loc_key = None
        if offset is not None:
            offset = int(offset)
            offset_loc_key = self.get_offset_location(offset)

        # Test for collisions
        name_loc_key = None
        if name is not None:
            name_loc_key = self.get_name_location(name)

        if strict:
            if name_loc_key is not None:
                raise ValueError("An entry for %r already exists (%r), and "
                                 "strict mode is enabled" % (
                                     name, name_loc_key
                                 ))
            if offset_loc_key is not None:
                raise ValueError("An entry for 0x%x already exists (%r), and "
                                 "strict mode is enabled" % (
                                     offset, offset_loc_key
                                 ))
        else:
            # Non-strict mode
            if name_loc_key is not None:
                known_offset = self.get_offset_location(name_loc_key)
                if known_offset is None:
                    if offset is not None:
                        self.set_location_offset(name_loc_key, offset)
                elif known_offset != offset:
                    raise ValueError(
                        "Location with name '%s' already have an offset: 0x%x "
                        "(!= 0x%x)" % (name, offset, known_offset)
                        )
                # Name already known, same offset -> nothing to do
                return name_loc_key

            elif offset_loc_key is not None:
                if name is not None:
                    # Check for already known name are checked above
                    return self.add_location_name(offset_loc_key, name)
                # Offset already known, no name specified
                return offset_loc_key

        # No collision, this is a brand new location
        loc_key = LocKey(self._loc_key_num)
        self._loc_key_num += 1
        self._loc_keys.add(loc_key)

        if offset is not None:
            assert offset not in self._offset_to_loc_key
            self._offset_to_loc_key[offset] = loc_key
            self._loc_key_to_offset[loc_key] = offset

        if name is not None:
            self._name_to_loc_key[name] = loc_key
            self._loc_key_to_names[loc_key] = set([name])

        return loc_key
Exemple #30
0
def set_str_ansi(value):
    value = force_bytes(value)
    return value + b"\x00"