-
-
Save peta909/0868cf5b9845d90d201b885aeec134bf to your computer and use it in GitHub Desktop.
The simplest possible IDA plugin with multiple actions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################## | |
# | |
# 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