In IDA Pro 5.6 we added support for loader scripts, last month we added processor module scripts support, and now by adding support for scriptable plugins (for the next version of IDA) it will be possible to write all sort of IDA Pro extensions using scripting languages.
(A plugin script written using IDC)
Apart from writing scripts, writing plugin modules using the SDK is the second easiest extension to code for IDA Pro. In short, plugins are DLLs that export the PLUGIN symbol which is an instance of plugin_t (check loader.hpp):
- init/run/term callbacks: These callbacks are called when IDA initializes, invokes and terminates the plugin.
- flags: The plugin flags describe the kind of the plugin. A plugin could have no flags (flags = 0) which means that this is an ordinary plugin. Or the plugin could act as a processor module extension, thus the PLUGIN_PROC flag. Another type of plugins are the debugger plugins which use the PLUGIN_DBG flag.
- Description and hotkey: The remaining plugin_t entries are used to designate a name, help text, comment, and a hotkey for the plugin.
The init callback is called when the plugin is loaded by IDA. It decides whether to load the plugin or skip it by returning one of the following constants:
- PLUGIN_OK: Plugin agrees to work with the current database but will be loaded only when it is about to be invoked.
- PLUGIN_SKIP: Plugin does not want to work with the current database. For example a plugin may choose to work with certain input file types.
- PLUGIN_KEEP: Plugin agrees to work with the current database and will remain loaded until the database is closed. It is important to return this value if you hook to notification events or register any sort of callbacks.
A plugin can be invoked using its hotkey or programmatically using the RunPlugin() (in IDC) or run_plugin() (in the SDK / loader.hpp). Upon invocation, the run callback:
int idaapi run(int arg)
is executed. Before explaining the use of the arg argument, it is important to know that plugins can also be configured in the plugins.cfg file, which has the following format:
; plugin_name filename hotkey arg [flags] Extract_File extract 0 1 Extract_Block extract 0 2 Extract_Item extract Alt-F8 3
(In this example, the ‘extract’ plugin provide at least 3 different functionalities depending on the passed argument value)
If a plugin is not present in plugins.cfg and is invoked using the “Edit/Plugins” menu or with the hotkey described in its PLUGIN entry then run() will be invoked with arg=0. Configured plugins, when invoked, will pass to the run() the argument value specified in the configuration file.
Scriptable plugins behave exactly like a native plugin (written using the SDK). To write a plugin using a scripting language, declare a function called PLUGIN_ENTRY that returns a plugin_t instance (or an object containing all attributes of a plugin_t object). This is an example script written in IDAPython:
import idaapi class myplugin_t(idaapi.plugin_t): flags = idaapi.PLUGIN_UNL comment = "This is a comment" help = "This is help" wanted_name = "My Python plugin" wanted_hotkey = "Alt-F8" def init(self): idaapi.msg("init() called!\n") return idaapi.PLUGIN_OK def run(self, arg): idaapi.msg("run() called with %d!\n" % arg) def term(self): idaapi.msg("term() called!\n") def PLUGIN_ENTRY(): return myplugin_t()
In this example, the plugin flag PLUGIN_UNL instructs IDA to directly unload the plugin after it has been invoked. This flag is very useful if your plugin script does a specific task and finishes. On the other hand, if your script works with forms (choosers, custom viewers, etc.), or registers callbacks (hotkeys, event notifications, etc.) then this flag should not be used and init() should return PLUGIN_KEEP (as discussed earlier) instead of PLUGIN_OK.
Scriptable plugins are so easy to write, and deploy (a simply copy/paste in the plugins folder) and very useful in case you want your plugin to load and unload automatically like native plugins.