112 lines
3.0 KiB
Python
112 lines
3.0 KiB
Python
""" Forcibly change the width of an lvar.
|
|
Useful for making an lvar smaller (which Hex-Rays does not let you do apparently)
|
|
Tags (for search engines):
|
|
IDA Pro Hex-Rays make stack variable smaller force variable size decrease width delete variable split up break up variable into smaller
|
|
"""
|
|
|
|
import idautils
|
|
import idaapi
|
|
import idc
|
|
import ida_hexrays
|
|
|
|
import traceback
|
|
|
|
force_width_actname = "forcelvarwidth:forcewidth"
|
|
|
|
class force_width_action_handler_t(idaapi.action_handler_t):
|
|
def __init__(self, callback_info):
|
|
idaapi.action_handler_t.__init__(self)
|
|
self.callback_info = callback_info
|
|
|
|
def activate(self, ctx):
|
|
vdui = idaapi.get_widget_vdui(ctx.widget)
|
|
self.callback_info.gui_action_callback(vdui)
|
|
return 1
|
|
|
|
def update(self, ctx):
|
|
return idaapi.AST_ENABLE_FOR_WIDGET if \
|
|
ctx.widget_type == idaapi.BWN_PSEUDOCODE else \
|
|
idaapi.AST_DISABLE_FOR_WIDGET
|
|
|
|
|
|
class hexrays_callback_info(object):
|
|
|
|
def __init__(self):
|
|
self.vu = None
|
|
return
|
|
|
|
def load(self):
|
|
return
|
|
|
|
def save(self):
|
|
return
|
|
|
|
def do_force_width(self, cfunc, insn):
|
|
|
|
if insn.opname != 'if':
|
|
return False
|
|
|
|
cif = insn.details
|
|
|
|
if not cif.ithen or not cif.ielse:
|
|
return False
|
|
|
|
idaapi.qswap(cif.ithen, cif.ielse)
|
|
cond = idaapi.cexpr_t(cif.expr)
|
|
notcond = idaapi.lnot(cond)
|
|
|
|
cif.expr.swap(notcond)
|
|
|
|
return True
|
|
|
|
def gui_action_callback(self, vu):
|
|
|
|
cfunc = vu.cfunc.__deref__()
|
|
|
|
if not vu.get_current_item(idaapi.USE_KEYBOARD):
|
|
print "Force lvar width: you don't have anything selected"
|
|
return False
|
|
|
|
badlv = vu.item.get_lvar()
|
|
if not badlv:
|
|
print "Force lvar width: you don't have an lvar selected"
|
|
return False
|
|
|
|
new_width = idc.AskLong(badlv.width, "Enter the new width for " + badlv.name)
|
|
if new_width == None: # cancelled
|
|
print "Force lvar width: operation cancelled"
|
|
return False
|
|
|
|
if new_width <= 0:
|
|
print "Force lvar width: not allowed. Non-positive width will crash IDA"
|
|
return False
|
|
|
|
badlv.set_width(new_width)
|
|
print 'Set the type in IDA (Y) for it to apply'
|
|
idaapi.process_ui_action('hx:SetType')
|
|
|
|
# vu.refresh_ctext()
|
|
print 'Force lvar width: OK.'
|
|
return True
|
|
|
|
def event_callback(self, event, *args):
|
|
|
|
if event == idaapi.hxe_populating_popup:
|
|
widget, phandle, vu = args
|
|
res = idaapi.attach_action_to_popup(vu.ct, None, force_width_actname)
|
|
|
|
return 0
|
|
|
|
if idaapi.init_hexrays_plugin():
|
|
i = hexrays_callback_info()
|
|
idaapi.register_action(
|
|
idaapi.action_desc_t(
|
|
force_width_actname,
|
|
"Force lvar width",
|
|
force_width_action_handler_t(i),
|
|
"Shift-W"))
|
|
idaapi.install_hexrays_callback(i.event_callback)
|
|
else:
|
|
print 'Force lvar width: hexrays is not available.'
|
|
|