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:
- The attributes of the class are check for objects which inherit from the
BipActivityclass and are stored in a_attributeslist of the object (done by theBipPluginconstructor, implemented in theBipPlugin._init_activities()method). - The class method
BipPlugin.to_load()will be called: if it returnsFalsethe plugin will not be loaded, if it returnTruethe manager continue its steps (done byBipPluginManager). - The
BipPluginobject is then created and the constructor will try to register itsBipActivity(see Registering activities). - The plugin is added in the list of instance maintain by the
BipPluginManager. - Finally the
BipPlugin.load()method will be called (done by theBipPluginManager).
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
BipPluginManagershould be used (it can be recuperated using theget_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
BipPluginit can be directly set in thebippluginfolder for being loaded at start by theBipPluginManager, in that case there is no need to call theaddld_plugin(). TheBipPlugin.to_load()method can be rewritten for deciding when to load or not the plugin and theBipPlugin.load()method allow to make actions directly when the plugin is loaded.BipActivityand the associated decorators (menu(),shortcut(), …) can be used for registering actions in IDA.Note
BipPlugin and BipActivity
All
BipPluginhave an attribute_activitiescorresponding to a dict ofname(corresponding to the orginal name of the method) as key and with objects which inherit fromBipActivity. 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
BipPluginobject. This constructor should not be called directly but should be use by theBipPluginManager. 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
BipActivityIn particular this constructor is in charge to provide itself for its
BipActivityobjects. Subclasses should call this constructor (usingsuper).
-
_init_activities()¶ Internal methods which look for the object which inherit from
BipActivityand add them to the_activitiesdictionary.This functions iter on all items in the object
__dict__and the associated class for finding theBipActivity.
-
_provide_plg_activities()¶ Iterate on all
BipActivityof this object and set theirpluginproperty with this object.This is an internal method and should not be called directly. The constructor of a
BipPlugincall this function.Internally this will iterate on the
_activitiesproperty (dict) for providing the plugin.
-
_register_activities()¶ Internal method which will parcour all the
BipActivityobject 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
BipPluginManagerwhen 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 theBipActivitylink to this plugin. A plugin should ensure to call this method usingsuper.
-
__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
BipPluginas a shortcut. This decorator expect a string in argument representing the shortcut it wants to register.The method which is decorated should only take
selfin argument which will be theBipPluginobject.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
BipActionobject and define its handler as a call to the method decorated with the plugin as argument. Accessing (without call) to theMyPlugin.my_shortcutattribute will return aBipActivityContainerobject which will contain aBipActionobject corresponding to the shortcut define.Parameters: shortcut (str) – The string representation of the shortcut.
Decorator for defining a method of a
BipPluginas 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 ofattach_to_menu().The method which is decorated should only take
selfin argument which will be theBipPluginobject. Internally this will create and add aBipAction(for more information about the internal seeshortcut()).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 thelabelof theBipAction.