Last active
January 14, 2024 22:57
-
-
Save herrcore/4595a884345a60d3e9c1b6a8f17f93d9 to your computer and use it in GitHub Desktop.
Auto-DWORD! - IDA plugin for one-click bulk DWORD conversion
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
############################################################################################ | |
## | |
## Auto-DWORD! | |
## | |
## Updated for IDA 7.xx and Python 3 | |
## | |
## To install: | |
## Copy script into plugins directory, i.e: C:\Program Files\<ida version>\plugins | |
## | |
## To run: | |
## Highlight raw data and right click and select "Auto-DWORD" | |
## The data will be transformed into a list of DWORDS. | |
## | |
############################################################################################ | |
__AUTHOR__ = '@herrcore' | |
PLUGIN_NAME = "Auto-DWORD" | |
PLUGIN_HOTKEY = '' | |
VERSION = '1.0.0' | |
import os | |
import sys | |
import idc | |
import idaapi | |
import idautils | |
import ida_kernwin | |
import ida_bytes | |
#-------------------------------------------------------------------------- | |
# Setup Icon | |
#-------------------------------------------------------------------------- | |
D_ICON_DATA = b"".join([b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08', | |
b'\x04\x00\x00\x00\xb5\xfa7\xea\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca', | |
b'\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00\x00\x80', | |
b'\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00', | |
b'\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00', | |
b'\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xe5\n\x08\x00\x1f\x0fX', | |
b'\xbc\x03\xd0\x00\x00\x01\tIDAT(\xcfu\xce\xbf+\xc4\x01\x1c\xc6\xf1\xd7\xd7}', | |
b'\x17w\xc8 7\x9cRR\x16\x83\xc9\xa2\x18,\xcax\x94\xff\xc0z\xd9\x94\xc9\x7f\xc0', | |
b' \xc9\xe2O`1X,\x8c\xe2\x94\xb8(\xa9#\xd7\xfdH~\xdc\xa0\xfb\x9e\xe1~\xf8\xd1y', | |
b'\x96\xcf\xa7\xcf\xe7\xfd<=\x81^kF\xd5E6\x9chhFF pc\x9d\xa4\xacHE\xc9\xa2\x96', | |
b'\x96\x94UD.\x0c\x86\x889\xb7\xec\xc3C\x1b84-nG(\x08\xc1\x9bK1S\xbaE\x9e]y\xf1"', | |
b'\xe1]?a\xd3S7l\xc5\x11f\xf5\xd8r\xd6\n\x0b\xdb\xb11\xf76}\x8a\x99\xb7*\xa3', | |
b'\xdc8w\xf9\xab\x9a\x03w\xe6D\xff\x01p+\xd5Z;\x03)\xa5N@\xbd9\'M8j}\xc2\x1f', | |
b'\xef!i\x8c\x18\xb7-\'\xf1\x1b\x08\xe4\xed\x1bPsmO\xfe;\xf6\x1b\xa8\xd8\xedT', | |
b'\xa7\x01\xc4\x8d\xa9z\xf4\xda\xbc\xf6I\x89\x8b7Z%e\xd5\x14\x15\xa4\xdb\xb6', | |
b'\x05Ee\x91\xacd\xa8\xea\xd8\x93\xbaH\xb1\r\x14\x9c\xea\x12\xc8\xa9~\x01/\x11J', | |
b'\x96\xa8\x937\x1d\x00\x00\x00%tEXtdate:create\x002021-10-08T00:31:15+00:00', | |
b'\xe5r\x84=\x00\x00\x00%tEXtdate:modify\x002021-10-08T00:31:15+00:00\x94/<\x81', | |
b'\x00\x00\x00WzTXtRaw profile type iptc\x00\x00x\x9c\xe3\xf2\x0c\x08qV((\xcaO', | |
b'\xcb\xccI\xe5R\x00\x03#\x0b.c\x0b\x13#\x13K\x93\x14\x03\x13 D\x804\xc3d\x03#', | |
b'\xb3T \xcb\xd8\xd4\xc8\xc4\xcc\xc4\x1c\xc4\x07\xcb\x80H\xa0J.\x00\xea\x17\x11t', | |
b'\xf2B5\x95\x00\x00\x00\x00IEND\xaeB`\x82']) | |
D_ICON = ida_kernwin.load_custom_icon(data=D_ICON_DATA, format="png") | |
def PLUGIN_ENTRY(): | |
""" | |
Required plugin entry point for IDAPython Plugins. | |
""" | |
return auto_dword() | |
class auto_dword(idaapi.plugin_t): | |
""" | |
The IDA Plugin for Auto-DWORD. | |
""" | |
flags = idaapi.PLUGIN_PROC | idaapi.PLUGIN_HIDE | |
comment = "Make DWORDs" | |
help = "Highlight Assembly and right-click 'Auto-DWORD'" | |
wanted_name = PLUGIN_NAME | |
wanted_hotkey = PLUGIN_HOTKEY | |
#-------------------------------------------------------------------------- | |
# Plugin Overloads | |
#-------------------------------------------------------------------------- | |
def init(self): | |
""" | |
This is called by IDA when it is loading the plugin. | |
""" | |
# initialize the menu actions our plugin will inject | |
self._init_action_make_dwords() | |
# initialize plugin hooks | |
self._init_hooks() | |
# done | |
idaapi.msg("%s %s initialized...\n" % (self.wanted_name, VERSION)) | |
return idaapi.PLUGIN_KEEP | |
def run(self, arg): | |
""" | |
This is called by IDA when this file is loaded as a script. | |
""" | |
idaapi.msg("%s cannot be run as a script.\n" % self.wanted_name) | |
def term(self): | |
""" | |
This is called by IDA when it is unloading the plugin. | |
""" | |
# unhook our plugin hooks | |
self._hooks.unhook() | |
# unregister our actions & free their resources | |
self._del_action_make_dwords() | |
# done | |
idaapi.msg("%s terminated...\n" % self.wanted_name) | |
#-------------------------------------------------------------------------- | |
# Plugin Hooks | |
#-------------------------------------------------------------------------- | |
def _init_hooks(self): | |
""" | |
Install plugin hooks into IDA. | |
""" | |
self._hooks = Hooks() | |
self._hooks.ready_to_run = self._init_hexrays_hooks | |
self._hooks.hook() | |
def _init_hexrays_hooks(self): | |
""" | |
Install Hex-Rrays hooks (when available). | |
NOTE: This is called when the ui_ready_to_run event fires. | |
""" | |
if idaapi.init_hexrays_plugin(): | |
idaapi.install_hexrays_callback(self._hooks.hxe_callback) | |
#-------------------------------------------------------------------------- | |
# IDA Actions | |
#-------------------------------------------------------------------------- | |
ACTION_MAKE_DWORDS = "autodword:make_dwords" | |
def _init_action_make_dwords(self): | |
""" | |
Register the Auto-DWORD action with IDA. | |
""" | |
# Describe the action using python3 copy | |
action_desc = idaapi.action_desc_t( | |
self.ACTION_MAKE_DWORDS, # The action name. | |
"Auto-DWORD", # The action text. | |
IDACtxEntry(make_dwords), # The action handler. | |
PLUGIN_HOTKEY, # Optional: action shortcut | |
"Make selection DWORDs", # Optional: tooltip | |
D_ICON # Copy icon | |
) | |
# register the action with IDA | |
assert idaapi.register_action(action_desc), "Action registration failed" | |
def _del_action_make_dwords(self): | |
""" | |
Delete the bulk prefix action from IDA. | |
""" | |
idaapi.unregister_action(self.ACTION_MAKE_DWORDS) | |
#------------------------------------------------------------------------------ | |
# Plugin Hooks | |
#------------------------------------------------------------------------------ | |
class Hooks(idaapi.UI_Hooks): | |
def finish_populating_widget_popup(self, widget, popup): | |
""" | |
A right click menu is about to be shown. (IDA 7) | |
""" | |
inject_make_dwords_actions(widget, popup, idaapi.get_widget_type(widget)) | |
return 0 | |
def finish_populating_tform_popup(self, form, popup): | |
""" | |
A right click menu is about to be shown. (IDA 6.x) | |
""" | |
inject_make_dwords_actions(form, popup, idaapi.get_tform_type(form)) | |
return 0 | |
def hxe_callback(self, event, *args): | |
""" | |
HexRays event callback. | |
We lump this under the (UI) Hooks class for organizational reasons. | |
""" | |
# | |
# if the event callback indicates that this is a popup menu event | |
# (in the hexrays window), we may want to install our prefix menu | |
# actions depending on what the cursor right clicked. | |
# | |
if event == idaapi.hxe_populating_popup: | |
form, popup, vu = args | |
idaapi.attach_action_to_popup( | |
form, | |
popup, | |
auto_dword.ACTION_MAKE_DWORDS, | |
"Auto-DWORD", | |
idaapi.SETMENU_APP, | |
) | |
# done | |
return 0 | |
#------------------------------------------------------------------------------ | |
# Prefix Wrappers | |
#------------------------------------------------------------------------------ | |
def inject_make_dwords_actions(form, popup, form_type): | |
""" | |
Inject prefix actions to popup menu(s) based on context. | |
""" | |
# | |
# disassembly window | |
# | |
if form_type == idaapi.BWN_DISASMS: | |
# insert the prefix action entry into the menu | |
# | |
idaapi.attach_action_to_popup( | |
form, | |
popup, | |
auto_dword.ACTION_MAKE_DWORDS, | |
"Auto-DWORD", | |
idaapi.SETMENU_APP | |
) | |
# done | |
return 0 | |
#------------------------------------------------------------------------------ | |
# Make DWORDS | |
#------------------------------------------------------------------------------ | |
def make_dwords(): | |
""" | |
Make selection DWORDS | |
""" | |
start = idc.read_selection_start() | |
end = idc.read_selection_end() | |
if idaapi.BADADDR in (start, end): | |
ea = idc.here() | |
start = idaapi.get_item_head(ea) | |
end = idaapi.get_item_end(ea) | |
# Loop through selection and make DWORDs | |
ea = start | |
while ea < end: | |
ida_bytes.create_data(ea, ida_bytes.FF_DWORD, 4, idaapi.BADADDR) | |
ea += 4 | |
return | |
#------------------------------------------------------------------------------ | |
# IDA ctxt | |
#------------------------------------------------------------------------------ | |
class IDACtxEntry(idaapi.action_handler_t): | |
""" | |
A basic Context Menu class to utilize IDA's action handlers. | |
""" | |
def __init__(self, action_function): | |
idaapi.action_handler_t.__init__(self) | |
self.action_function = action_function | |
def activate(self, ctx): | |
""" | |
Execute the embedded action_function when this context menu is invoked. | |
""" | |
self.action_function() | |
return 1 | |
def update(self, ctx): | |
""" | |
Ensure the context menu is always available in IDA. | |
""" | |
return idaapi.AST_ENABLE_ALWAYS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment