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)
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)
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
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
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
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)
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)
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)