|
|
@@ -0,0 +1,162 @@ |
|
|
############################################################################## |
|
|
# |
|
|
# 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 |