Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
The simplest possible IDA plugin with multiple actions
##############################################################################
#
# Name: hello_world_plugin.py
# Auth: @cmatthewbrooks
# Desc: A test plugin to learn how to make these work; Specifically, how to
# have multiple actions within the same plugin.
#
# In plain English, IDA will look for the PLUGIN_ENTRY function which
# should return a plugin object. This object can contain all the
# functionality itself, or it can have multiple actions.
#
# To register actions, use the idaaapi.register_action() function with
# an argument of type idaapi.action_desc_t.
#
# A helpful hint from IDA support, don't register actions inside the
# Edit/Plugins sub-menu. It's dynamic and can be wiped out and built
# within a session. It's better to register actions' menu locations
# elsewhere.
#
#
# With help from:
#
# http://www.hexblog.com/?p=886
# https://github.com/fireeye/flare-ida/blob/master/plugins/
# https://github.com/mwrlabs/win_driver_plugin/
#
##############################################################################
import idaapi
# Define callbacks which are the actions I actually
# want to perform
def hello_mars():
print('Hello Mars!')
def hello_earth():
print('Hello Earth!')
# Define the action_handler_t object that fires the
# callback function when each action is activated
class ActionHandler(idaapi.action_handler_t):
def __init__(self, callback):
idaapi.action_handler_t.__init__(self)
self.callback = callback
def activate(self, ctx):
self.callback()
return 1
def update(self, ctx):
return idaapi.AST_ENABLE_ALWAYS
# Define a method to register all the actions when
# the plugin is initialized
def register_actions():
actions = [
{
'id': 'hello:earth',
'name': 'Hello Earth',
'hotkey': 'Ctrl+Alt+E',
'comment': 'Print Hello Earth',
'callback': hello_earth,
'menu_location': 'Edit/Hello World/Hello Earth'
},
{
'id': 'hello:mars',
'name': 'Hello Mars',
'hotkey': 'Ctrl+Alt+M',
'comment': 'Print Hello Mars',
'callback': hello_mars,
'menu_location': 'Edit/Hello World/Hello Mars'
}
]
for action in actions:
if not idaapi.register_action(idaapi.action_desc_t(
action['id'], # Must be the unique item
action['name'], # The name the user sees
ActionHandler(action['callback']), # The function to call
action['hotkey'], # A shortcut, if any (optional)
action['comment'] # A comment, if any (optional)
)):
print('Failed to register ' + action['id'])
if not idaapi.attach_action_to_menu(
action['menu_location'], # The menu location
action['id'], # The unique function ID
0):
print('Failed to attach to menu '+ action['id'])
# Define the plugin class itself which is returned by
# the PLUGIN_ENTRY method that scriptable plugins use
# to be recognized within IDA
class HelloWorldPlugin(idaapi.plugin_t):
# Use the HIDE flag to avoid the entry in
# Edit/Plugins since this plugin's run()
# method has no functionality...it's all
# in the actions.
flags = idaapi.PLUGIN_HIDE
comment = 'A test plugin'
help = 'No help - this is just a test'
wanted_name = 'Hello World'
wanted_hotkey = ''
def init(self):
print('HelloWorldPlugin init')
register_actions()
# Return KEEP instead of OK to keep the
# plugin loaded since it registers
# callback actions and hotkeys
#
# Use OK if the functionality is
# all in the plugin and it does
# one thing then completes.
return idaapi.PLUGIN_KEEP
def run(self, arg):
print('HelloWorldPlugin run')
def term(self):
print('HelloWorldPlugin term')
# The PLUGIN_ENTRY method is what IDA calls when
# scriptable plugins are loaded. It needs to
# return a plugin of type idaapi.plugin_t
def PLUGIN_ENTRY():
try:
return HelloWorldPlugin()
except Exception, err:
import traceback
print('Error: %s\n%s' % str((err), traceback.format_exc()))
raise
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.