Skip to content

Instantly share code, notes, and snippets.

@herrcore
Last active January 14, 2024 22:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save herrcore/4595a884345a60d3e9c1b6a8f17f93d9 to your computer and use it in GitHub Desktop.
Save herrcore/4595a884345a60d3e9c1b6a8f17f93d9 to your computer and use it in GitHub Desktop.
Auto-DWORD! - IDA plugin for one-click bulk DWORD conversion
############################################################################################
##
## 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