Plugins

Bip has it own systems of plugins refered as BipPlugin. All plugins should inherit of the BipPlugin class. It is still possible to use bip in classic IDA plugin, however the gui part of Bip is mostly link to BipPlugin.

A plugin is made for being load by the BipPluginManager and will be instantiated only once. Once loaded it is possible to get the plugin instance through the BipPluginManager object: get_plugin_manager()["PLUGINNAME"] .

A typicall implementation of a plugin will:

  • surcharge the to_load() classmethod for checking if the plugin should be loaded.
  • surcharge the load() method for making actions when it it loaded in IDA.
  • use some activity decorators for declaring actions.

For example of a plugin you can check the Overview or look at the printk plugin.

Implementation internals

This part as the goal to describe the internal of the BipPlugin: how are they loaded by the BipPluginManager and how the interface with BipActivity. It is not necessary to read it for using them or writing one.

Loading of the plugins

BipPlugin are made for being loaded by the BipPluginManager. BipPlugin present in a particular directory (bipplugin by default) will be loaded automatically by the BipPluginManager. For doing this, the BipPluginManager will search for all .py files present in the bipplugin directory and will search for classes which inherit from the BipPlugin class. When the BipPluginManager is loaded by IDA it will load all the plugins which has been found (this is done in the init() method).

It is also possible to load BipPlugin “by hand” using the addld_plugin() method. If this is done before the BipPluginManager is loaded by IDA, it will load the plugin later: the same way it is done for the ones in the bipplugin directory. If the BipPluginManager is already loaded, the plugin will be loaded immediately.

When a BipPlugin is loaded the following actions are made:

  1. The attributes of the class are check for objects which inherit from the BipActivity class and are stored in a _attributes list of the object (done by the BipPlugin constructor, implemented in the BipPlugin._init_activities() method).
  2. The class method BipPlugin.to_load() will be called: if it returns False the plugin will not be loaded, if it return True the manager continue its steps (done by BipPluginManager).
  3. The BipPlugin object is then created and the constructor will try to register its BipActivity (see Registering activities).
  4. The plugin is added in the list of instance maintain by the BipPluginManager.
  5. Finally the BipPlugin.load() method will be called (done by the BipPluginManager).

It is important to note that if the BipPluginManager has already been init by IDA this will all be made directly through the addld_plugin() method, but if the BipPluginManager has not yet been loaded the plugin will be loaded later. It is possible to use the is_ready() to check if the BipPluginManager has initialized and as loaded its plugins.

Note

Several loading of python scripts

BipPlugin should be loaded only once, it is important for not having problems with activities (see Registering activities) and to keep a unique reference to the actual object. However python files in the plugins directory are actually loaded twice by IDA which creates problem with the design explain before.

Registering activities

When a BipPlugin is created the BipActivity which are used must be registered. All BipPlugin will be instantiated by the BipPluginManager through the method load_all() or load_one(). Those methods will called the class method BipPlugin.to_load of the BipPlugin and if it returned true the constructor will be called follow by the BipPlugin.load() method.

When a plugin is instantiated, the __init__() constructor will call the _init_activities() which will create a dict of all the BipActivity objects define for the object and its class. Then the method _provide_plg_activities() will provide to the BipActivity object the plugin in itself.

Once the BipPlugin is instantiated, the BipPlugin.load() method will be called. This method will call _register_activities() which will take the dict of BipActivity and for each one call its register() method.

BipPlugin API

class bip.gui.BipPlugin

Class for representing a plugin in IDA.

All plugin should be instantiated only once. For adding a plugin the BipPluginManager should be used (it can be recuperated using the get_plugin_manager() function). The following code can be used for loading a new plugin:

class MyPlugin(BipPlugin): # define a new class for the plugin
    pass # implementation

bpm = get_plugin_manager() # get the BipPluginManager
bpm.addld_plugin("MyPlugin", MyPlugin, ifneeded=True) # add the plugin

Once finish developping a BipPlugin it can be directly set in the bipplugin folder for being loaded at start by the BipPluginManager, in that case there is no need to call the addld_plugin(). The BipPlugin.to_load() method can be rewritten for deciding when to load or not the plugin and the BipPlugin.load() method allow to make actions directly when the plugin is loaded. BipActivity and the associated decorators (menu(), shortcut(), …) can be used for registering actions in IDA.

Note

BipPlugin and BipActivity

All BipPlugin have an attribute _activities corresponding to a dict of name (corresponding to the orginal name of the method) as key and with objects which inherit from BipActivity. This dictionary is created by the constructor of this object and the activities are launch when the plugin is loaded.

Todo

make a way to dynamically add and get activities

__init__()

Constructor for a BipPlugin object. This constructor should not be called directly but should be use by the BipPluginManager . In particular this should avoid to have several time the same plugin register.

Warning

Instentiating several time the same plugin class can create problems in particular link to its BipActivity

In particular this constructor is in charge to provide itself for its BipActivity objects. Subclasses should call this constructor (using super).

_init_activities()

Internal methods which look for the object which inherit from BipActivity and add them to the _activities dictionary.

This functions iter on all items in the object __dict__ and the associated class for finding the BipActivity.

_provide_plg_activities()

Iterate on all BipActivity of this object and set their plugin property with this object.

This is an internal method and should not be called directly. The constructor of a BipPlugin call this function.

Internally this will iterate on the _activities property (dict) for providing the plugin.

_register_activities()

Internal method which will parcour all the BipActivity object which are associated with this plugin and register all of them.

This method is not made for being called directly and should be call by the BipPlugin.load() function.

classmethod to_load()

Class method allowing to test if this plugin should be loaded. At that point the plugin object has not been loaded yet, this allow to test if the plugin is made for working in this environment (python version, OS, IDA version, …).

This method can be called several time.

By default always return True.

Returns:A boolean value indicating if the plugin should be loaded (True) or not (False).
load()

Method which will be called by the BipPluginManager when the plugin must be loaded.

This method can be surcharge by a Plugin for allowing to take actions at the moment where it will be loaded.

Note

This method is in charge of calling _register_activities() which allow to activate the BipActivity link to this plugin. A plugin should ensure to call this method using super.

__weakref__

list of weak references to the object (if defined)

Activity decorators

Here is an overview of the currently available decorators, for more information on how they work see Activities and Actions:

Decorator Name Description Usage example
shortcut() Register a “hot-key” which will call the function when triggered. @shortcut("Ctrl-H")
menu() Register an entry in a menu in IDA. @menu("Edit/Plugins/", "PRINTNAME")
bip.gui.shortcut(shortcut_str)

Decorator for defining a method of a BipPlugin as a shortcut. This decorator expect a string in argument representing the shortcut it wants to register.

The method which is decorated should only take self in argument which will be the BipPlugin object.

An example of usage is the following:

class MyPlugin(BipPlugin):
    
    def my_method(self): # a method inside the plugin
        print("Hello from MyPlugin.my_method")
    
    @shortcut("Ctrl-H")
    def my_shortcut(self):
        # self is the MyPlugin object
        self.my_method() # call the method before

# Pressing Ctrl-H will trigger a call to my_shortcut which will
# call my_method and print "Hello from MyPlugin.my_method". It
# is also possible to use mp.my_shortcut directly as a function.

Internally this decorator will define a BipAction object and define its handler as a call to the method decorated with the plugin as argument. Accessing (without call) to the MyPlugin.my_shortcut attribute will return a BipActivityContainer object which will contain a BipAction object corresponding to the shortcut define.

Parameters:shortcut (str) – The string representation of the shortcut.
bip.gui.menu(menu_path, menu_entry=None)

Decorator for defining a method of a BipPlugin as an entry in the menu of IDA. This decorator expect a string in argument representing the path in the menu it wants to register (ex.: Options/).

Warning

Using this decorator for registering an entry in Edit/Plugins/ may create problems if the plugin is loaded during IDA initialisation and the entry may not be present in IDA. For more information see the documentation of attach_to_menu().

The method which is decorated should only take self in argument which will be the BipPlugin object. Internally this will create and add a BipAction (for more information about the internal see shortcut()).

Parameters:
  • menu_path (str) – The path at which the action should be registered.
  • menu_entry (str) – The name which will apear in the menu for this action. If it is None (default) the name of the function will be used. Internaly this is the label of the BipAction.