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
BipActivity
class and are stored in a_attributes
list of the object (done by theBipPlugin
constructor, implemented in theBipPlugin._init_activities()
method). - The class method
BipPlugin.to_load()
will be called: if it returnsFalse
the plugin will not be loaded, if it returnTrue
the manager continue its steps (done byBipPluginManager
). - The
BipPlugin
object 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
BipPluginManager
should 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
BipPlugin
it can be directly set in thebipplugin
folder 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.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 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
BipPlugin
object. 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
BipActivity
In particular this constructor is in charge to provide itself for its
BipActivity
objects. Subclasses should call this constructor (usingsuper
).
-
_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 theBipActivity
.
-
_provide_plg_activities
()¶ Iterate on all
BipActivity
of this object and set theirplugin
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 theBipActivity
link 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
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 theBipPlugin
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 theMyPlugin.my_shortcut
attribute will return aBipActivityContainer
object which will contain aBipAction
object corresponding to the shortcut define.Parameters: shortcut (str) – The string representation of the shortcut.
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 ofattach_to_menu()
.The method which is decorated should only take
self
in argument which will be theBipPlugin
object. 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 thelabel
of theBipAction
.