转:https://www.techbliss.org/threads/python-plugin-loader-tut-for-ida-pro-7-0.951/
Many things have changed from older ida pro to 7.0
Alot of functions have been added to 7.0 python sdk, and alot deprecated.
In this little tut, i will explain and brakedown, how to make a python plugin loader for ida pro 7.0 , put in the menu at start up, together with a custom icon, and load the real app.
plugin loader example is from the python editor app found
here
https://github.com/techbliss/Python_editor/blob/master/7.0/plugins/Python_editor.py There are many ways to write this, some have intire plugin code included in the plugin loader or elsewhere like i normally do.
Code (Python):
# Created by: Storm Shadow http://www.techbliss.org
import os
import ida_idaapi, ida_kernwin
import idc
from idc import *
from idaapi import *
import sys
sys.path.insert(0 , idaapi.idadir("plugins\\Code editor\\icons"))
import ico
from ico import *
PLUGIN_VERSION = "1.4"
IDAVERISONS = "IDA PRO 7.0+"
AUTHORS = "Storm Shadow"
DATE = "2017"
TWITTER = "Twitter @zadow28"
def banner():
banner_options = (PLUGIN_VERSION, AUTHORS, DATE, TWITTER, IDAVERISONS)
banner_titles = "Python Editor v%s - (c) %s - %s - %s - %s" % banner_options
# print plugin banner
print("---[" + banner_titles + "]---\n")
banner()
# 1) Create the handler class
class MyEditorHandler(idaapi.action_handler_t):
def __init__(self):
idaapi.action_handler_t.__init__(self)
# Run editor when invoked.
def activate(self, ctx):
g = globals()
idahome = idaapi.idadir("plugins\\Code editor")
IDAPython_ExecScript(idahome + "\\pyeditor.py", g)
def update(self, ctx):
return idaapi.AST_ENABLE_ALWAYS
class ripeye(idaapi.plugin_t):
flags = idaapi.PLUGIN_FIX
comment = "Run me"
help = "Python Editor"
wanted_name = "Python Editor"
wanted_hotkey = "" #the tooltip horkey goes away when setting it here DONT DO it! and only is shown in File/Plugins menu
def editor_menuaction(self):
action_desc = idaapi.action_desc_t(
'my:editoraction', # The action name. This acts like an ID and must be unique
'Python Editor!', # The action text.
MyEditorHandler(), # The action handler.
'Ctrl+H', # Optional: the action shortcut DO IT HERE!
'Script editor', # Optional: the action tooltip (available in menus/toolbar)
idaapi.load_custom_icon(":/ico/python.png") # hackish load action icon , if no custom icon use number from 1-150 from internal ida
)
# 3) Register the action
idaapi.register_action(action_desc)
idaapi.attach_action_to_menu(
'File/Editor...', # The relative path of where to add the action
'my:editoraction', # The action ID (see above)
idaapi.SETMENU_APP) # We want to append the action after the 'Manual instruction...
form = idaapi.get_current_tform()
idaapi.attach_action_to_popup(form, None, "my:editoraction", None)
def init(self):
"""
This is called by IDA when it is loading the plugin.
"""
#self._icon_id_file = idaapi.BADADDR
# attempt plugin initialization
try:
self._install_plugin()
# failed to initialize or integrate the plugin, log and skip loading
except Exception as e:
form = idaapi.get_current_tform()
pass
return PLUGIN_KEEP
def _install_plugin(self):
"""
Initialize & integrate the plugin into IDA.
"""
self.editor_menuaction()
self._init()
def term(self):
pass
def run(self, arg = 0):
#we need the calls again if we wanna load it via File/Plugins/editor
idaapi.msg("Python Editor Loaded to menu \n use Alt+E hot key to quick load ")
hackish = MyEditorHandler()
hackish.activate(self)
def PLUGIN_ENTRY():
return ripeye()
lets break it down
Code (Python):
import os
import ida_idaapi, ida_kernwin
import idc
from idc import *
from idaapi import *
import sys
This import the the modules from ida python folder.
in the old versions there was only idaapi.py idc.py and idautils.py, but now they have broken up those huge modules with smaller ones.
Code (Python):
sys.path.insert(0 , idaapi.idadir("plugins\\Code editor\\icons"))
import ico
from ico import *
idaapi.idadir is our ida pro root folder path, and we insert the icon path where we store the icon.
Be aware that i have converted the icons with
pyrcc5 , so i can import them also as modules.
You can also just have a *.png in the folder , then you wont need the import ico and from ico import *.
Code (Python):
PLUGIN_VERSION = "1.4"
IDAVERISONS = "IDA PRO 7.0+"
AUTHORS = "Storm Shadow"
DATE = "2017"
TWITTER = "Twitter @zadow28"
def banner():
banner_options = (PLUGIN_VERSION, AUTHORS, DATE, TWITTER, IDAVERISONS)
banner_titles = "Python Editor v%s - (c) %s - %s - %s - %s" % banner_options
# print plugin banner
print("---[" + banner_titles + "]---\n")
banner()
this is for printing the banner when ida loads, its not needed, but usefull for your users, and looks nice.
some of the code is taken from
Lighthoiuse pluginIf you add more options, remember to add them to banner_options and add an ekstra %s for each ekstra one.
Code (Python):
# 1) Create the handler class
class MyEditorHandler(idaapi.action_handler_t):
def __init__(self):
idaapi.action_handler_t.__init__(self)
# Run editor when invoked.
def activate(self, ctx):
g = globals()
idahome = idaapi.idadir("plugins\\Code editor")
IDAPython_ExecScript(idahome + "\\pyeditor.py", g)
def update(self, ctx):
return idaapi.AST_ENABLE_ALWAYS
Code (Python):
class MyEditorHandler(idaapi.action_handler_t):
This is the action handler callback.
It would be good if you name your class something unique, or else ida would give an error if you have two plugins named the same.
Code (Python):
idahome = idaapi.idadir("plugins\\Code editor")
Meaning ida root folder pluss plugins\\Code editor
Like ida pro\plugins\\Code editor
This is where you have your main plugin code.
Code (Python):
IDAPython_ExecScript(idahome + "\\pyeditor.py", g)
This is exencial , this is where we call our main plugin
Code (Text):
class ripeye(idaapi.plugin_t):
flags = idaapi.PLUGIN_FIX
comment = "Run me"
help = "Python Editor"
wanted_name = "Python Editor"
wanted_hotkey = ""
idaapi.PLUGIN_FIX = this plugin would be fixed at startup, ther are many other option like only proccessors etc., but we wanna have it fixed.
Wanted hotkey= we do not wanna set it here, since this is the hotkey for File\plugins in ida, and only one can be there, and we wanna have out hotkey present on screen on File menu.
the hotkey would work but just displayed one place.
Code (Python):
def editor_menuaction(self):
action_desc = idaapi.action_desc_t(
'my:editoraction', # The action name. This acts like an ID and must be unique
'Python Editor!', # The action text.
MyEditorHandler(), # The action handler from first class.
'Ctrl+H', # Optional: the action shortcut DO IT HERE!
'Script editor', # Optional: the action tooltip (available in menus/toolbar)
idaapi.load_custom_icon(":/ico/python.png") # hackish load action icon , if no custom icon use number from 1-150 from internal ida
)
this is the menu for the action we create.
it is explained in the qutoes, but
idaapi.load_custom_icon(":/ico/python.png") we can load now since we imported the ico module at the begining, it could also be number from 1-150 internal icons from ida pro.
But explainen earlier you could do also
idaapi.load_custom_icon(idahome + "\\my_icon.png")
Be aware that the action name have also to be unique for each plugin.
also explained here
Augmenting IDA UI with your own actions. Code (Python):
# 3) Register the action
idaapi.register_action(action_desc)
idaapi.attach_action_to_menu(
'File/Editor...', # The relative path of where to add the action
'my:editoraction', # The action ID (see above)
idaapi.SETMENU_APP) # We want to append the action after the 'Manual instruction...
form = idaapi.get_current_tform()
idaapi.attach_action_to_popup(form, None, "my:editoraction", None)
idaapi.register_action(action_desc) we register the action and make sure it is set in the menu.
be aware of the unique acion ID again.
Code (Python):
def init(self):
"""
This is called by IDA when it is loading the plugin.
"""
#self._icon_id_file = idaapi.BADADDR
# attempt plugin initialization
try:
self._install_plugin()
# failed to initialize or integrate the plugin, log and skip loading
except Exception as e:
form = idaapi.get_current_tform()
pass
return PLUGIN_KEEP
we try to run the function self._install_plugin() at start else pass.
Code (Python):
def _install_plugin(self):
"""
Initialize & integrate the plugin into IDA.
"""
self.editor_menuaction()
self._init()
this is called from previous function.
self.editor_menuaction() = action memory pointer class
self._init = the init class pointer is called.
Code (Python):
def run(self, arg = 0):
#we need the calls again if we wanna load it via File/Plugins/editor
idaapi.msg("Python Editor Loaded to menu \n use Alt+E hot key to quick load ")
hackish = MyEditorHandler()
hackish.activate(self)
We make equal function as the MyEditorHandle.activate() from breakup 2.
this is for loading the plugin if we choose to click File\plugins\myplugin instead of File\myplugin.
Code (Python):
def PLUGIN_ENTRY():
return ripeye()
wraps up the plugin class , remember to have unique class names , since you cant have the same class two times and