Esempio n. 1
0
class DownloadProvider(with_metaclass(_DownloadProviderMetaclass, object)):
	name = None
	instance_class = None
	_registered_providers = []

	def __init__(self, handle = None):
		if handle is not None:
			self.handle = core.handle_of_type(handle, core.BNDownloadProvider)
			self.__dict__["name"] = core.BNGetDownloadProviderName(handle)

	def register(self):
		self._cb = core.BNDownloadProviderCallbacks()
		self._cb.context = 0
		self._cb.createInstance = self._cb.createInstance.__class__(self._create_instance)
		self.handle = core.BNRegisterDownloadProvider(self.__class__.name, self._cb)
		self.__class__._registered_providers.append(self)

	def _create_instance(self, ctxt):
		try:
			result = self.__class__.instance_class(self)
			if result is None:
				return None
			return ctypes.cast(core.BNNewDownloadInstanceReference(result.handle), ctypes.c_void_p).value
		except:
			log.log_error(traceback.format_exc())
			return None

	def create_instance(self):
		result = core.BNCreateDownloadProviderInstance(self.handle)
		if result is None:
			return None
		return DownloadInstance(self, handle = result)
Esempio n. 2
0
class BackgroundTask(with_metaclass(_BackgroundTaskMetaclass, object)):
    def __init__(self,
                 initial_progress_text="",
                 can_cancel=False,
                 handle=None):
        if handle is None:
            self.handle = core.BNBeginBackgroundTask(initial_progress_text,
                                                     can_cancel)
        else:
            self.handle = handle

    def __del__(self):
        core.BNFreeBackgroundTask(self.handle)

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    @property
    def progress(self):
        """Text description of the progress of the background task (displayed in status bar of the UI)"""
        return core.BNGetBackgroundTaskProgressText(self.handle)

    @progress.setter
    def progress(self, value):
        core.BNSetBackgroundTaskProgressText(self.handle, str(value))

    @property
    def can_cancel(self):
        """Whether the task can be cancelled (read-only)"""
        return core.BNCanCancelBackgroundTask(self.handle)

    @property
    def finished(self):
        """Whether the task has finished"""
        return core.BNIsBackgroundTaskFinished(self.handle)

    @finished.setter
    def finished(self, value):
        if value:
            self.finish()

    def finish(self):
        core.BNFinishBackgroundTask(self.handle)

    @property
    def cancelled(self):
        """Whether the task has been cancelled"""
        return core.BNIsBackgroundTaskCancelled(self.handle)

    @cancelled.setter
    def cancelled(self, value):
        if value:
            self.cancel()

    def cancel(self):
        core.BNCancelBackgroundTask(self.handle)
Esempio n. 3
0
class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)):
    _registered_providers = []

    def __init__(self, handle=None):
        if handle is not None:
            self.handle = core.handle_of_type(handle, core.BNScriptingProvider)
            self.__dict__["name"] = core.BNGetScriptingProviderName(handle)

    @property
    def name(self):
        return NotImplemented

    @property
    def instance_class(self):
        return NotImplemented

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    def register(self):
        self._cb = core.BNScriptingProviderCallbacks()
        self._cb.context = 0
        self._cb.createInstance = self._cb.createInstance.__class__(
            self._create_instance)
        self._cb.loadModule = self._cb.loadModule.__class__(self._load_module)
        self._cb.installModules = self._cb.installModules.__class__(
            self._install_modules)
        self.handle = core.BNRegisterScriptingProvider(self.__class__.name,
                                                       self.__class__.apiName,
                                                       self._cb)
        self.__class__._registered_providers.append(self)

    def _create_instance(self, ctxt):
        try:
            result = self.__class__.instance_class(self)
            if result is None:
                return None
            return ctypes.cast(
                core.BNNewScriptingInstanceReference(result.handle),
                ctypes.c_void_p).value
        except:
            log.log_error(traceback.format_exc())
            return None

    def create_instance(self):
        result = core.BNCreateScriptingProviderInstance(self.handle)
        if result is None:
            return None
        return ScriptingInstance(self, handle=result)

    def _load_plugin(self, ctx, repo_path, plugin_path, force):
        return False

    def _install_modules(self, ctx, modules):
        return False
Esempio n. 4
0
class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)):
    _registered_commands = []

    def __init__(self, cmd):
        self.command = core.BNPluginCommand()
        ctypes.memmove(ctypes.byref(self.command), ctypes.byref(cmd),
                       ctypes.sizeof(core.BNPluginCommand))
        self.name = str(cmd.name)
        self.description = str(cmd.description)
        self.type = PluginCommandType(cmd.type)

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    @classmethod
    def _default_action(cls, view, action):
        try:
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            action(view_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _address_action(cls, view, addr, action):
        try:
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            action(view_obj, addr)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _range_action(cls, view, addr, length, action):
        try:
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            action(view_obj, addr, length)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _function_action(cls, view, func, action):
        try:
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            func_obj = function.Function(view_obj,
                                         core.BNNewFunctionReference(func))
            action(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _low_level_il_function_action(cls, view, func, action):
        try:
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(view_obj,
                                      core.BNGetLowLevelILOwnerFunction(func))
            func_obj = binaryninja.lowlevelil.LowLevelILFunction(
                owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
            action(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _low_level_il_instruction_action(cls, view, func, instr, action):
        try:
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(view_obj,
                                      core.BNGetLowLevelILOwnerFunction(func))
            func_obj = binaryninja.lowlevelil.LowLevelILFunction(
                owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
            action(view_obj, func_obj[instr])
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _medium_level_il_function_action(cls, view, func, action):
        try:
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(
                view_obj, core.BNGetMediumLevelILOwnerFunction(func))
            func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(
                owner.arch, core.BNNewMediumLevelILFunctionReference(func),
                owner)
            action(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _medium_level_il_instruction_action(cls, view, func, instr, action):
        try:
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(
                view_obj, core.BNGetMediumLevelILOwnerFunction(func))
            func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(
                owner.arch, core.BNNewMediumLevelILFunctionReference(func),
                owner)
            action(view_obj, func_obj[instr])
        except:
            binaryninja.log.log_error(traceback.format_exc())

    @classmethod
    def _default_is_valid(cls, view, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            return is_valid(view_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _address_is_valid(cls, view, addr, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            return is_valid(view_obj, addr)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _range_is_valid(cls, view, addr, length, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            return is_valid(view_obj, addr, length)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _function_is_valid(cls, view, func, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = binaryninja.filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryninja.binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            func_obj = function.Function(view_obj,
                                         core.BNNewFunctionReference(func))
            return is_valid(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _low_level_il_function_is_valid(cls, view, func, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(view_obj,
                                      core.BNGetLowLevelILOwnerFunction(func))
            func_obj = binaryninja.lowlevelil.LowLevelILFunction(
                owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
            return is_valid(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _low_level_il_instruction_is_valid(cls, view, func, instr, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(view_obj,
                                      core.BNGetLowLevelILOwnerFunction(func))
            func_obj = binaryninja.lowlevelil.LowLevelILFunction(
                owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
            return is_valid(view_obj, func_obj[instr])
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _medium_level_il_function_is_valid(cls, view, func, is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(
                view_obj, core.BNGetMediumLevelILOwnerFunction(func))
            func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(
                owner.arch, core.BNNewMediumLevelILFunctionReference(func),
                owner)
            return is_valid(view_obj, func_obj)
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def _medium_level_il_instruction_is_valid(cls, view, func, instr,
                                              is_valid):
        try:
            if is_valid is None:
                return True
            file_metadata = filemetadata.FileMetadata(
                handle=core.BNGetFileForView(view))
            view_obj = binaryview.BinaryView(
                file_metadata=file_metadata,
                handle=core.BNNewViewReference(view))
            owner = function.Function(
                view_obj, core.BNGetMediumLevelILOwnerFunction(func))
            func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(
                owner.arch, core.BNNewMediumLevelILFunctionReference(func),
                owner)
            return is_valid(view_obj, func_obj[instr])
        except:
            binaryninja.log.log_error(traceback.format_exc())
            return False

    @classmethod
    def register(cls, name, description, action, is_valid=None):
        """
		``register`` Register a plugin

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` as an argument
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(
                lambda ctxt, view: cls._default_action(view, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(
                lambda ctxt, view: cls._default_is_valid(view, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommand(name, description, action_obj,
                                     is_valid_obj, None)

    @classmethod
    def register_for_address(cls, name, description, action, is_valid=None):
        """
		``register_for_address`` Register a plugin to be called with an address argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and address as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_address`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_action(
                view, addr, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_is_valid(
                view, addr, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForAddress(name, description, action_obj,
                                               is_valid_obj, None)

    @classmethod
    def register_for_range(cls, name, description, action, is_valid=None):
        """
		``register_for_range`` Register a plugin to be called with a range argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and ``AddressRange`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_range`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.c_ulonglong,
            ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls.
                                _range_action(view, addr, length, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.c_ulonglong,
            ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls.
                                _range_is_valid(view, addr, length, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForRange(name, description, action_obj,
                                             is_valid_obj, None)

    @classmethod
    def register_for_function(cls, name, description, action, is_valid=None):
        """
		``register_for_function`` Register a plugin to be called with a function argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and a ``Function`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_function`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNFunction)
        )(lambda ctxt, view, func: cls._function_action(view, func, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(
                core.BNFunction))(lambda ctxt, view, func: cls.
                                  _function_is_valid(view, func, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForFunction(name, description, action_obj,
                                                is_valid_obj, None)

    @classmethod
    def register_for_low_level_il_function(cls,
                                           name,
                                           description,
                                           action,
                                           is_valid=None):
        """
		``register_for_low_level_il_function`` Register a plugin to be called with a low level IL function argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and a ``LowLevelILFunction`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNLowLevelILFunction))(
                lambda ctxt, view, func: cls._low_level_il_function_action(
                    view, func, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNLowLevelILFunction))(
                lambda ctxt, view, func: cls._low_level_il_function_is_valid(
                    view, func, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForLowLevelILFunction(
            name, description, action_obj, is_valid_obj, None)

    @classmethod
    def register_for_low_level_il_instruction(cls,
                                              name,
                                              description,
                                              action,
                                              is_valid=None):
        """
		``register_for_low_level_il_instruction`` Register a plugin to be called with a low level IL instruction argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and a ``LowLevelILInstruction`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(
                lambda ctxt, view, func, instr: cls.
                _low_level_il_instruction_action(view, func, instr, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNLowLevelILFunction),
            ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls.
                                _low_level_il_instruction_is_valid(
                                    view, func, instr, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForLowLevelILInstruction(
            name, description, action_obj, is_valid_obj, None)

    @classmethod
    def register_for_medium_level_il_function(cls,
                                              name,
                                              description,
                                              action,
                                              is_valid=None):
        """
		``register_for_medium_level_il_function`` Register a plugin to be called with a medium level IL function argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and a ``MediumLevelILFunction`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNMediumLevelILFunction))(
                lambda ctxt, view, func: cls._medium_level_il_function_action(
                    view, func, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNMediumLevelILFunction))(
                lambda ctxt, view, func: cls.
                _medium_level_il_function_is_valid(view, func, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForMediumLevelILFunction(
            name, description, action_obj, is_valid_obj, None)

    @classmethod
    def register_for_medium_level_il_instruction(cls,
                                                 name,
                                                 description,
                                                 action,
                                                 is_valid=None):
        """
		``register_for_medium_level_il_instruction`` Register a plugin to be called with a medium level IL instruction argument

		:param str name: name of the plugin
		:param str description: description of the plugin
		:param action: function to call with the ``BinaryView`` and a ``MediumLevelILInstruction`` as arguments
		:param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
		:rtype: None

		.. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin.
		"""
        binaryninja._init_plugins()
        action_obj = ctypes.CFUNCTYPE(
            None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(
                lambda ctxt, view, func, instr: cls.
                _medium_level_il_instruction_action(view, func, instr, action))
        is_valid_obj = ctypes.CFUNCTYPE(
            ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView),
            ctypes.POINTER(core.BNMediumLevelILFunction),
            ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls.
                                _medium_level_il_instruction_is_valid(
                                    view, func, instr, is_valid))
        cls._registered_commands.append((action_obj, is_valid_obj))
        core.BNRegisterPluginCommandForMediumLevelILInstruction(
            name, description, action_obj, is_valid_obj, None)

    @classmethod
    def get_valid_list(cls, context):
        """Dict of registered plugins"""
        commands = cls.list
        result = {}
        for cmd in commands:
            if cmd.is_valid(context):
                result[cmd.name] = cmd
        return result

    def is_valid(self, context):
        if context.view is None:
            return False
        if self.command.type == PluginCommandType.DefaultPluginCommand:
            if not self.command.defaultIsValid:
                return True
            return self.command.defaultIsValid(self.command.context,
                                               context.view.handle)
        elif self.command.type == PluginCommandType.AddressPluginCommand:
            if not self.command.addressIsValid:
                return True
            return self.command.addressIsValid(self.command.context,
                                               context.view.handle,
                                               context.address)
        elif self.command.type == PluginCommandType.RangePluginCommand:
            if context.length == 0:
                return False
            if not self.command.rangeIsValid:
                return True
            return self.command.rangeIsValid(self.command.context,
                                             context.view.handle,
                                             context.address, context.length)
        elif self.command.type == PluginCommandType.FunctionPluginCommand:
            if context.function is None:
                return False
            if not self.command.functionIsValid:
                return True
            return self.command.functionIsValid(self.command.context,
                                                context.view.handle,
                                                context.function.handle)
        elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand:
            if context.function is None:
                return False
            if not self.command.lowLevelILFunctionIsValid:
                return True
            return self.command.lowLevelILFunctionIsValid(
                self.command.context, context.view.handle,
                context.function.handle)
        elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand:
            if context.instruction is None:
                return False
            if not isinstance(context.instruction,
                              binaryninja.lowlevelil.LowLevelILInstruction):
                return False
            if not self.command.lowLevelILInstructionIsValid:
                return True
            return self.command.lowLevelILInstructionIsValid(
                self.command.context, context.view.handle,
                context.instruction.function.handle,
                context.instruction.instr_index)
        elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand:
            if context.function is None:
                return False
            if not self.command.mediumLevelILFunctionIsValid:
                return True
            return self.command.mediumLevelILFunctionIsValid(
                self.command.context, context.view.handle,
                context.function.handle)
        elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand:
            if context.instruction is None:
                return False
            if not isinstance(
                    context.instruction,
                    binaryninja.mediumlevelil.MediumLevelILInstruction):
                return False
            if not self.command.mediumLevelILInstructionIsValid:
                return True
            return self.command.mediumLevelILInstructionIsValid(
                self.command.context, context.view.handle,
                context.instruction.function.handle,
                context.instruction.instr_index)
        return False

    def execute(self, context):
        if not self.is_valid(context):
            return
        if self.command.type == PluginCommandType.DefaultPluginCommand:
            self.command.defaultCommand(self.command.context,
                                        context.view.handle)
        elif self.command.type == PluginCommandType.AddressPluginCommand:
            self.command.addressCommand(self.command.context,
                                        context.view.handle, context.address)
        elif self.command.type == PluginCommandType.RangePluginCommand:
            self.command.rangeCommand(self.command.context,
                                      context.view.handle, context.address,
                                      context.length)
        elif self.command.type == PluginCommandType.FunctionPluginCommand:
            self.command.functionCommand(self.command.context,
                                         context.view.handle,
                                         context.function.handle)
        elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand:
            self.command.lowLevelILFunctionCommand(self.command.context,
                                                   context.view.handle,
                                                   context.function.handle)
        elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand:
            self.command.lowLevelILInstructionCommand(
                self.command.context, context.view.handle,
                context.instruction.function.handle,
                context.instruction.instr_index)
        elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand:
            self.command.mediumLevelILFunctionCommand(self.command.context,
                                                      context.view.handle,
                                                      context.function.handle)
        elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand:
            self.command.mediumLevelILInstructionCommand(
                self.command.context, context.view.handle,
                context.instruction.function.handle,
                context.instruction.instr_index)

    def __repr__(self):
        return "<PluginCommand: %s>" % self.name
Esempio n. 5
0
class Platform(with_metaclass(_PlatformMetaClass, object)):
    """
	``class Platform`` contains all information related to the execution environment of the binary, mainly the
	calling conventions used.
	"""
    name = None

    def __init__(self, arch=None, handle=None):
        if handle is None:
            if arch is None:
                self.handle = None
                raise ValueError(
                    "platform must have an associated architecture")
            self._arch = arch
            self.handle = core.BNCreatePlatform(arch.handle,
                                                self.__class__.name)
        else:
            self.handle = handle
            self.__dict__["name"] = core.BNGetPlatformName(self.handle)
            self._arch = binaryninja.architecture.CoreArchitecture._from_cache(
                core.BNGetPlatformArchitecture(self.handle))

    def __del__(self):
        if self.handle is not None:
            core.BNFreePlatform(self.handle)

    def __repr__(self):
        return "<platform: %s>" % self.name

    def __str__(self):
        return self.name

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        return ctypes.addressof(self.handle.contents) == ctypes.addressof(
            other.handle.contents)

    def __ne__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        return not (self == other)

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    @property
    def default_calling_convention(self):
        """
		Default calling convention.

		:getter: returns a CallingConvention object for the default calling convention.
		:setter: sets the default calling convention
		:type: CallingConvention
		"""
        result = core.BNGetPlatformDefaultCallingConvention(self.handle)
        if result is None:
            return None
        return binaryninja.callingconvention.CallingConvention(handle=result)

    @default_calling_convention.setter
    def default_calling_convention(self, value):
        core.BNRegisterPlatformDefaultCallingConvention(
            self.handle, value.handle)

    @property
    def cdecl_calling_convention(self):
        """
		CallingConvention object for the cdecl calling convention
		"""
        result = core.BNGetPlatformCdeclCallingConvention(self.handle)
        if result is None:
            return None
        return binaryninja.callingconvention.CallingConvention(handle=result)

    @cdecl_calling_convention.setter
    def cdecl_calling_convention(self, value):
        """
		Sets the cdecl calling convention
		"""
        core.BNRegisterPlatformCdeclCallingConvention(self.handle,
                                                      value.handle)

    @property
    def stdcall_calling_convention(self):
        """
		CallingConvention object for the stdcall calling convention
		"""
        result = core.BNGetPlatformStdcallCallingConvention(self.handle)
        if result is None:
            return None
        return binaryninja.callingconvention.CallingConvention(handle=result)

    @stdcall_calling_convention.setter
    def stdcall_calling_convention(self, value):
        """
		Sets the stdcall calling convention
		"""
        core.BNRegisterPlatformStdcallCallingConvention(
            self.handle, value.handle)

    @property
    def fastcall_calling_convention(self):
        """
		CallingConvention object for the fastcall calling convention
		"""
        result = core.BNGetPlatformFastcallCallingConvention(self.handle)
        if result is None:
            return None
        return binaryninja.callingconvention.CallingConvention(handle=result)

    @fastcall_calling_convention.setter
    def fastcall_calling_convention(self, value):
        """
		Sets the fastcall calling convention
		"""
        core.BNRegisterPlatformFastcallCallingConvention(
            self.handle, value.handle)

    @property
    def system_call_convention(self):
        """
		CallingConvention object for the system call convention
		"""
        result = core.BNGetPlatformSystemCallConvention(self.handle)
        if result is None:
            return None
        return binaryninja.callingconvention.CallingConvention(handle=result)

    @system_call_convention.setter
    def system_call_convention(self, value):
        """
		Sets the system call convention
		"""
        core.BNSetPlatformSystemCallConvention(self.handle, value.handle)

    @property
    def calling_conventions(self):
        """
		List of platform CallingConvention objects (read-only)

		:getter: returns the list of supported CallingConvention objects
		:type: list(CallingConvention)
		"""
        count = ctypes.c_ulonglong()
        cc = core.BNGetPlatformCallingConventions(self.handle, count)
        result = []
        for i in range(0, count.value):
            result.append(
                binaryninja.callingconvention.CallingConvention(
                    handle=core.BNNewCallingConventionReference(cc[i])))
        core.BNFreeCallingConventionList(cc, count.value)
        return result

    @property
    def types(self):
        """List of platform-specific types (read-only)"""
        count = ctypes.c_ulonglong(0)
        type_list = core.BNGetPlatformTypes(self.handle, count)
        result = {}
        for i in range(0, count.value):
            name = types.QualifiedName._from_core_struct(type_list[i].name)
            result[name] = types.Type(core.BNNewTypeReference(
                type_list[i].type),
                                      platform=self)
        core.BNFreeTypeList(type_list, count.value)
        return result

    @property
    def variables(self):
        """List of platform-specific variable definitions (read-only)"""
        count = ctypes.c_ulonglong(0)
        type_list = core.BNGetPlatformVariables(self.handle, count)
        result = {}
        for i in range(0, count.value):
            name = types.QualifiedName._from_core_struct(type_list[i].name)
            result[name] = types.Type(core.BNNewTypeReference(
                type_list[i].type),
                                      platform=self)
        core.BNFreeTypeList(type_list, count.value)
        return result

    @property
    def functions(self):
        """List of platform-specific function definitions (read-only)"""
        count = ctypes.c_ulonglong(0)
        type_list = core.BNGetPlatformFunctions(self.handle, count)
        result = {}
        for i in range(0, count.value):
            name = types.QualifiedName._from_core_struct(type_list[i].name)
            result[name] = types.Type(core.BNNewTypeReference(
                type_list[i].type),
                                      platform=self)
        core.BNFreeTypeList(type_list, count.value)
        return result

    @property
    def system_calls(self):
        """List of system calls for this platform (read-only)"""
        count = ctypes.c_ulonglong(0)
        call_list = core.BNGetPlatformSystemCalls(self.handle, count)
        result = {}
        for i in range(0, count.value):
            name = types.QualifiedName._from_core_struct(call_list[i].name)
            t = types.Type(core.BNNewTypeReference(call_list[i].type),
                           platform=self)
            result[call_list[i].number] = (name, t)
        core.BNFreeSystemCallList(call_list, count.value)
        return result

    @property
    def type_libraries(self):
        count = ctypes.c_ulonglong(0)
        libs = core.BNGetPlatformTypeLibraries(self.handle, count)
        result = []
        for i in range(0, count.value):
            result.append(
                binaryninja.TypeLibrary(core.BNNewTypeLibraryReference(
                    libs[i])))
        core.BNFreeTypeLibraryList(libs, count.value)
        return result

    def get_type_libraries_by_name(self, name):
        count = ctypes.c_ulonglong(0)
        libs = core.BNGetPlatformTypeLibrariesByName(self.handle, name, count)
        result = []
        for i in range(0, count.value):
            result.append(
                binaryninja.TypeLibrary(core.BNNewTypeLibraryReference(
                    libs[i])))
        core.BNFreeTypeLibraryList(libs, count.value)
        return result

    def register(self, os):
        """
		``register`` registers the platform for given OS name.

		:param str os: OS name to register
		:rtype: None
		"""
        core.BNRegisterPlatform(os, self.handle)

    def register_calling_convention(self, cc):
        """
		``register_calling_convention`` register a new calling convention.

		:param CallingConvention cc: a CallingConvention object to register
		:rtype: None
		"""
        core.BNRegisterPlatformCallingConvention(self.handle, cc.handle)

    def get_related_platform(self, arch):
        result = core.BNGetRelatedPlatform(self.handle, arch.handle)
        if not result:
            return None
        return Platform(handle=result)

    def add_related_platform(self, arch, platform):
        core.BNAddRelatedPlatform(self.handle, arch.handle, platform.handle)

    def get_associated_platform_by_address(self, addr):
        new_addr = ctypes.c_ulonglong()
        new_addr.value = addr
        result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr)
        return Platform(handle=result), new_addr.value

    def get_type_by_name(self, name):
        name = types.QualifiedName(name)._get_core_struct()
        obj = core.BNGetPlatformTypeByName(self.handle, name)
        if not obj:
            return None
        return types.Type(obj, platform=self)

    def get_variable_by_name(self, name):
        name = types.QualifiedName(name)._get_core_struct()
        obj = core.BNGetPlatformVariableByName(self.handle, name)
        if not obj:
            return None
        return types.Type(obj, platform=self)

    def get_function_by_name(self, name, exactMatch=False):
        name = types.QualifiedName(name)._get_core_struct()
        obj = core.BNGetPlatformFunctionByName(self.handle, name, exactMatch)
        if not obj:
            return None
        return types.Type(obj, platform=self)

    def get_system_call_name(self, number):
        return core.BNGetPlatformSystemCallName(self.handle, number)

    def get_system_call_type(self, number):
        obj = core.BNGetPlatformSystemCallType(self.handle, number)
        if not obj:
            return None
        return types.Type(obj, platform=self)

    def generate_auto_platform_type_id(self, name):
        name = types.QualifiedName(name)._get_core_struct()
        return core.BNGenerateAutoPlatformTypeId(self.handle, name)

    def generate_auto_platform_type_ref(self, type_class, name):
        type_id = self.generate_auto_platform_type_id(name)
        return types.NamedTypeReference(type_class, type_id, name)

    def get_auto_platform_type_id_source(self):
        return core.BNGetAutoPlatformTypeIdSource(self.handle)

    def parse_types_from_source(self,
                                source,
                                filename=None,
                                include_dirs=[],
                                auto_type_source=None):
        """
		``parse_types_from_source`` parses the source string and any needed headers searching for them in
		the optional list of directories provided in ``include_dirs``.

		:param str source: source string to be parsed
		:param str filename: optional source filename
		:param include_dirs: optional list of string filename include directories
		:type include_dirs: list(str)
		:param str auto_type_source: optional source of types if used for automatically generated types
		:return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error)
		:rtype: TypeParserResult
		:Example:

			>>> platform.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n')
			({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:{'bar':
			<type: int32_t(int32_t x)>}}, '')
			>>>
		"""

        if filename is None:
            filename = "input"
        if not (isinstance(source, str) or isinstance(source, unicode)):
            raise AttributeError("Source must be a string")
        dir_buf = (ctypes.c_char_p * len(include_dirs))()
        for i in range(0, len(include_dirs)):
            dir_buf[i] = include_dirs[i].encode('charmap')
        parse = core.BNTypeParserResult()
        errors = ctypes.c_char_p()
        result = core.BNParseTypesFromSource(self.handle, source, filename,
                                             parse, errors, dir_buf,
                                             len(include_dirs),
                                             auto_type_source)
        error_str = errors.value.decode("utf-8")
        core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
        if not result:
            raise SyntaxError(error_str)
        type_dict = {}
        variables = {}
        functions = {}
        for i in range(0, parse.typeCount):
            name = types.QualifiedName._from_core_struct(parse.types[i].name)
            type_dict[name] = types.Type(core.BNNewTypeReference(
                parse.types[i].type),
                                         platform=self)
        for i in range(0, parse.variableCount):
            name = types.QualifiedName._from_core_struct(
                parse.variables[i].name)
            variables[name] = types.Type(core.BNNewTypeReference(
                parse.variables[i].type),
                                         platform=self)
        for i in range(0, parse.functionCount):
            name = types.QualifiedName._from_core_struct(
                parse.functions[i].name)
            functions[name] = types.Type(core.BNNewTypeReference(
                parse.functions[i].type),
                                         platform=self)
        core.BNFreeTypeParserResult(parse)
        return types.TypeParserResult(type_dict, variables, functions)

    def parse_types_from_source_file(self,
                                     filename,
                                     include_dirs=[],
                                     auto_type_source=None):
        """
		``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in
		the optional list of directories provided in ``include_dirs``.

		:param str filename: filename of file to be parsed
		:param include_dirs: optional list of string filename include directories
		:type include_dirs: list(str)
		:param str auto_type_source: optional source of types if used for automatically generated types
		:return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error)
		:rtype: TypeParserResult
		:Example:

			>>> file = "/Users/binja/tmp.c"
			>>> open(file).read()
			'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n'
			>>> platform.parse_types_from_source_file(file)
			({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:
			{'bar': <type: int32_t(int32_t x)>}}, '')
			>>>
		"""
        if not (isinstance(filename, str) and os.path.isfile(filename)
                and os.access(filename, os.R_OK)):
            raise AttributeError(
                "File {} doesn't exist or isn't readable".format(filename))
        dir_buf = (ctypes.c_char_p * len(include_dirs))()
        for i in range(0, len(include_dirs)):
            dir_buf[i] = include_dirs[i].encode('charmap')
        parse = core.BNTypeParserResult()
        errors = ctypes.c_char_p()
        result = core.BNParseTypesFromSourceFile(self.handle, filename, parse,
                                                 errors, dir_buf,
                                                 len(include_dirs),
                                                 auto_type_source)
        error_str = errors.value.decode("utf-8")
        core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
        if not result:
            raise SyntaxError(error_str)
        type_dict = {}
        variables = {}
        functions = {}
        for i in range(0, parse.typeCount):
            name = types.QualifiedName._from_core_struct(parse.types[i].name)
            type_dict[name] = types.Type(core.BNNewTypeReference(
                parse.types[i].type),
                                         platform=self)
        for i in range(0, parse.variableCount):
            name = types.QualifiedName._from_core_struct(
                parse.variables[i].name)
            variables[name] = types.Type(core.BNNewTypeReference(
                parse.variables[i].type),
                                         platform=self)
        for i in range(0, parse.functionCount):
            name = types.QualifiedName._from_core_struct(
                parse.functions[i].name)
            functions[name] = types.Type(core.BNNewTypeReference(
                parse.functions[i].type),
                                         platform=self)
        core.BNFreeTypeParserResult(parse)
        return types.TypeParserResult(type_dict, variables, functions)

    @property
    def arch(self):
        """ """
        return self._arch

    @arch.setter
    def arch(self, value):
        self._arch = value
Esempio n. 6
0
class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)):
	def __init__(self, name, desc, ver):
		self.name = name
		self.description = desc
		self.latest_version_num = ver

	@property
	def versions(self):
		"""List of versions (read-only)"""
		count = ctypes.c_ulonglong()
		errors = ctypes.c_char_p()
		versions = core.BNGetUpdateChannelVersions(self.name, count, errors)
		if errors:
			error_str = errors.value
			core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
			raise IOError(error_str)
		result = []
		for i in range(0, count.value):
			result.append(UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time))
		core.BNFreeUpdateChannelVersionList(versions, count.value)
		return result

	@property
	def latest_version(self):
		"""Latest version (read-only)"""
		count = ctypes.c_ulonglong()
		errors = ctypes.c_char_p()
		versions = core.BNGetUpdateChannelVersions(self.name, count, errors)
		if errors:
			error_str = errors.value
			core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
			raise IOError(error_str)
		result = None
		for i in range(0, count.value):
			if versions[i].version == self.latest_version_num:
				result = UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time)
				break
		core.BNFreeUpdateChannelVersionList(versions, count.value)
		return result

	@property
	def updates_available(self):
		"""Whether updates are available (read-only)"""
		errors = ctypes.c_char_p()
		result = core.BNAreUpdatesAvailable(self.name, None, None, errors)
		if errors:
			error_str = errors.value
			core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
			raise IOError(error_str)
		return result

	def __setattr__(self, name, value):
		try:
			object.__setattr__(self, name, value)
		except AttributeError:
			raise AttributeError("attribute '%s' is read only" % name)

	def __repr__(self):
		return "<channel: %s>" % self.name

	def __str__(self):
		return self.name

	def update_to_latest(self, progress = None):
		cb = UpdateProgressCallback(progress)
		errors = ctypes.c_char_p()
		result = core.BNUpdateToLatestVersion(self.name, errors, cb.cb, None)
		if errors:
			error_str = errors.value
			core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))
			raise IOError(error_str)
		return UpdateResult(result)
Esempio n. 7
0
class Transform(with_metaclass(_TransformMetaClass, object)):
    """
	``class Transform`` is an implementation of the TransformMetaClass that implements custom transformations. New 
	transformations may be added at runtime, so an instance of a transform is created like::

		>>> list(Transform)
		[<transform: Zlib>, <transform: StringEscape>, <transform: RawHex>, <transform: HexDump>, <transform: Base64>, <transform: Reverse>, <transform: CArray08>, <transform: CArrayA16>, <transform: CArrayA32>, <transform: CArrayA64>, <transform: CArrayB16>, <transform: CArrayB32>, <transform: CArrayB64>, <transform: IntList08>, <transform: IntListA16>, <transform: IntListA32>, <transform: IntListA64>, <transform: IntListB16>, <transform: IntListB32>, <transform: IntListB64>, <transform: MD4>, <transform: MD5>, <transform: SHA1>, <transform: SHA224>, <transform: SHA256>, <transform: SHA384>, <transform: SHA512>, <transform: AES-128 ECB>, <transform: AES-128 CBC>, <transform: AES-256 ECB>, <transform: AES-256 CBC>, <transform: DES ECB>, <transform: DES CBC>, <transform: Triple DES ECB>, <transform: Triple DES CBC>, <transform: RC2 ECB>, <transform: RC2 CBC>, <transform: Blowfish ECB>, <transform: Blowfish CBC>, <transform: CAST ECB>, <transform: CAST CBC>, <transform: RC4>, <transform: XOR>]
		>>> sha512=Transform['SHA512']
		>>> rawhex=Transform['RawHex']
		>>> rawhex.encode(sha512.encode("test string"))
		'10e6d647af44624442f388c2c14a787ff8b17e6165b83d767ec047768d8cbcb71a1a3226e7cc7816bc79c0427d94a9da688c41a3992c7bf5e4d7cc3e0be5dbac'
	"""
    transform_type = None
    name = None
    long_name = None
    group = None
    parameters = []
    _registered_cb = None

    def __init__(self, handle):
        if handle is None:
            self._cb = core.BNCustomTransform()
            self._cb.context = 0
            self._cb.getParameters = self._cb.getParameters.__class__(
                self._get_parameters)
            self._cb.freeParameters = self._cb.freeParameters.__class__(
                self._free_parameters)
            self._cb.decode = self._cb.decode.__class__(self._decode)
            self._cb.encode = self._cb.encode.__class__(self._encode)
            self._pending_param_lists = {}
            self.type = self.__class__.transform_type
            if not isinstance(self.type, str):
                self.type = TransformType(self.type)
            self.name = self.__class__.name
            self.long_name = self.__class__.long_name
            self.group = self.__class__.group
            self.parameters = self.__class__.parameters
        else:
            self.handle = handle
            self.type = TransformType(core.BNGetTransformType(self.handle))
            self.name = core.BNGetTransformName(self.handle)
            self.long_name = core.BNGetTransformLongName(self.handle)
            self.group = core.BNGetTransformGroup(self.handle)
            count = ctypes.c_ulonglong()
            params = core.BNGetTransformParameterList(self.handle, count)
            self.parameters = []
            for i in range(0, count.value):
                self.parameters.append(
                    TransformParameter(params[i].name, params[i].longName,
                                       params[i].fixedLength))
            core.BNFreeTransformParameterList(params, count.value)

    def __repr__(self):
        return "<transform: %s>" % self.name

    def __eq__(self, value):
        if not isinstance(value, Transform):
            return False
        return ctypes.addressof(self.handle.contents) == ctypes.addressof(
            value.handle.contents)

    def __ne__(self, value):
        if not isinstance(value, Transform):
            return True
        return ctypes.addressof(self.handle.contents) != ctypes.addressof(
            value.handle.contents)

    def _get_parameters(self, ctxt, count):
        try:
            count[0] = len(self.parameters)
            param_buf = (core.BNTransformParameterInfo *
                         len(self.parameters))()
            for i in range(0, len(self.parameters)):
                param_buf[i].name = self.parameters[i].name
                param_buf[i].longName = self.parameters[i].long_name
                param_buf[i].fixedLength = self.parameters[i].fixed_length
            result = ctypes.cast(param_buf, ctypes.c_void_p)
            self._pending_param_lists[result.value] = (result, param_buf)
            return result.value
        except:
            log.log_error(traceback.format_exc())
            count[0] = 0
            return None

    def _free_parameters(self, params, count):
        try:
            buf = ctypes.cast(params, ctypes.c_void_p)
            if buf.value not in self._pending_param_lists:
                raise ValueError(
                    "freeing parameter list that wasn't allocated")
            del self._pending_param_lists[buf.value]
        except:
            log.log_error(traceback.format_exc())

    def _decode(self, ctxt, input_buf, output_buf, params, count):
        try:
            input_obj = databuffer.DataBuffer(
                handle=core.BNDuplicateDataBuffer(input_buf))
            param_map = {}
            for i in range(0, count):
                data = databuffer.DataBuffer(
                    handle=core.BNDuplicateDataBuffer(params[i].value))
                param_map[params[i].name] = bytes(data)
            result = self.perform_decode(bytes(input_obj), param_map)
            if result is None:
                return False
            result = bytes(result)
            core.BNSetDataBufferContents(output_buf, result, len(result))
            return True
        except:
            log.log_error(traceback.format_exc())
            return False

    def _encode(self, ctxt, input_buf, output_buf, params, count):
        try:
            input_obj = databuffer.DataBuffer(
                handle=core.BNDuplicateDataBuffer(input_buf))
            param_map = {}
            for i in range(0, count):
                data = databuffer.DataBuffer(
                    handle=core.BNDuplicateDataBuffer(params[i].value))
                param_map[params[i].name] = bytes(data)
            result = self.perform_encode(bytes(input_obj), param_map)
            if result is None:
                return False
            result = bytes(result)
            core.BNSetDataBufferContents(output_buf, result, len(result))
            return True
        except:
            log.log_error(traceback.format_exc())
            return False

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    @abc.abstractmethod
    def perform_decode(self, data, params):
        if self.type == TransformType.InvertingTransform:
            return self.perform_encode(data, params)
        return None

    @abc.abstractmethod
    def perform_encode(self, data, params):
        return None

    def decode(self, input_buf, params={}):
        if isinstance(input_buf, int) or isinstance(input_buf,
                                                    numbers.Integral):
            return None
        input_buf = databuffer.DataBuffer(input_buf)
        output_buf = databuffer.DataBuffer()
        keys = list(params.keys())
        param_buf = (core.BNTransformParameter * len(keys))()
        data = []
        for i in range(0, len(keys)):
            data.append(databuffer.DataBuffer(params[keys[i]]))
            param_buf[i].name = keys[i]
            param_buf[i].value = data[i].handle
        if not core.BNDecode(self.handle, input_buf.handle, output_buf.handle,
                             param_buf, len(keys)):
            return None
        return str(output_buf)

    def encode(self, input_buf, params={}):
        if isinstance(input_buf, int) or isinstance(input_buf,
                                                    numbers.Integral):
            return None
        input_buf = databuffer.DataBuffer(input_buf)
        output_buf = databuffer.DataBuffer()
        keys = list(params.keys())
        param_buf = (core.BNTransformParameter * len(keys))()
        data = []
        for i in range(0, len(keys)):
            data.append(databuffer.DataBuffer(params[keys[i]]))
            param_buf[i].name = keys[i]
            param_buf[i].value = data[i].handle
        if not core.BNEncode(self.handle, input_buf.handle, output_buf.handle,
                             param_buf, len(keys)):
            return None
        return str(output_buf)
Esempio n. 8
0
class Transform(with_metaclass(_TransformMetaClass, object)):
    transform_type = None
    name = None
    long_name = None
    group = None
    parameters = []
    _registered_cb = None

    def __init__(self, handle):
        if handle is None:
            self._cb = core.BNCustomTransform()
            self._cb.context = 0
            self._cb.getParameters = self._cb.getParameters.__class__(
                self._get_parameters)
            self._cb.freeParameters = self._cb.freeParameters.__class__(
                self._free_parameters)
            self._cb.decode = self._cb.decode.__class__(self._decode)
            self._cb.encode = self._cb.encode.__class__(self._encode)
            self._pending_param_lists = {}
            self.type = self.__class__.transform_type
            if not isinstance(self.type, str):
                self.type = TransformType(self.type)
            self.name = self.__class__.name
            self.long_name = self.__class__.long_name
            self.group = self.__class__.group
            self.parameters = self.__class__.parameters
        else:
            self.handle = handle
            self.type = TransformType(core.BNGetTransformType(self.handle))
            self.name = core.BNGetTransformName(self.handle)
            self.long_name = core.BNGetTransformLongName(self.handle)
            self.group = core.BNGetTransformGroup(self.handle)
            count = ctypes.c_ulonglong()
            params = core.BNGetTransformParameterList(self.handle, count)
            self.parameters = []
            for i in range(0, count.value):
                self.parameters.append(
                    TransformParameter(params[i].name, params[i].longName,
                                       params[i].fixedLength))
            core.BNFreeTransformParameterList(params, count.value)

    def __repr__(self):
        return "<transform: %s>" % self.name

    def __eq__(self, value):
        if not isinstance(value, Transform):
            return False
        return ctypes.addressof(self.handle.contents) == ctypes.addressof(
            value.handle.contents)

    def __ne__(self, value):
        if not isinstance(value, Transform):
            return True
        return ctypes.addressof(self.handle.contents) != ctypes.addressof(
            value.handle.contents)

    def _get_parameters(self, ctxt, count):
        try:
            count[0] = len(self.parameters)
            param_buf = (core.BNTransformParameterInfo *
                         len(self.parameters))()
            for i in range(0, len(self.parameters)):
                param_buf[i].name = self.parameters[i].name
                param_buf[i].longName = self.parameters[i].long_name
                param_buf[i].fixedLength = self.parameters[i].fixed_length
            result = ctypes.cast(param_buf, ctypes.c_void_p)
            self._pending_param_lists[result.value] = (result, param_buf)
            return result.value
        except:
            log.log_error(traceback.format_exc())
            count[0] = 0
            return None

    def _free_parameters(self, params, count):
        try:
            buf = ctypes.cast(params, ctypes.c_void_p)
            if buf.value not in self._pending_param_lists:
                raise ValueError(
                    "freeing parameter list that wasn't allocated")
            del self._pending_param_lists[buf.value]
        except:
            log.log_error(traceback.format_exc())

    def _decode(self, ctxt, input_buf, output_buf, params, count):
        try:
            input_obj = databuffer.DataBuffer(
                handle=core.BNDuplicateDataBuffer(input_buf))
            param_map = {}
            for i in range(0, count):
                data = databuffer.DataBuffer(
                    handle=core.BNDuplicateDataBuffer(params[i].value))
                param_map[params[i].name] = str(data)
            result = self.perform_decode(str(input_obj), param_map)
            if result is None:
                return False
            result = str(result)
            core.BNSetDataBufferContents(output_buf, result, len(result))
            return True
        except:
            log.log_error(traceback.format_exc())
            return False

    def _encode(self, ctxt, input_buf, output_buf, params, count):
        try:
            input_obj = databuffer.DataBuffer(
                handle=core.BNDuplicateDataBuffer(input_buf))
            param_map = {}
            for i in range(0, count):
                data = databuffer.DataBuffer(
                    handle=core.BNDuplicateDataBuffer(params[i].value))
                param_map[params[i].name] = str(data)
            result = self.perform_encode(str(input_obj), param_map)
            if result is None:
                return False
            result = str(result)
            core.BNSetDataBufferContents(output_buf, result, len(result))
            return True
        except:
            log.log_error(traceback.format_exc())
            return False

    @property
    def list(self):
        """Allow tab completion to discover metaclass list property"""
        pass

    @abc.abstractmethod
    def perform_decode(self, data, params):
        if self.type == TransformType.InvertingTransform:
            return self.perform_encode(data, params)
        return None

    @abc.abstractmethod
    def perform_encode(self, data, params):
        return None

    def decode(self, input_buf, params={}):
        input_buf = databuffer.DataBuffer(input_buf)
        output_buf = databuffer.DataBuffer()
        keys = list(params.keys())
        param_buf = (core.BNTransformParameter * len(keys))()
        for i in range(0, len(keys)):
            data = databuffer.DataBuffer(params[keys[i]])
            param_buf[i].name = keys[i]
            param_buf[i].value = data.handle
        if not core.BNDecode(self.handle, input_buf.handle, output_buf.handle,
                             param_buf, len(keys)):
            return None
        return str(output_buf)

    def encode(self, input_buf, params={}):
        input_buf = databuffer.DataBuffer(input_buf)
        output_buf = databuffer.DataBuffer()
        keys = list(params.keys())
        param_buf = (core.BNTransformParameter * len(keys))()
        for i in range(0, len(keys)):
            data = databuffer.DataBuffer(params[keys[i]])
            param_buf[i].name = keys[i]
            param_buf[i].value = data.handle
        if not core.BNEncode(self.handle, input_buf.handle, output_buf.handle,
                             param_buf, len(keys)):
            return None
        return str(output_buf)