Replace HexRaysCodeXplorer and HexraysInvertIf with HexRaysPyTools
This commit is contained in:
279
plugins/HexRaysPyTools.py
Normal file
279
plugins/HexRaysPyTools.py
Normal file
@@ -0,0 +1,279 @@
|
||||
import logging
|
||||
import HexRaysPyTools.Actions as Actions
|
||||
import HexRaysPyTools.Core.Cache
|
||||
from HexRaysPyTools.Core.TemporaryStructure import *
|
||||
import HexRaysPyTools.Forms as Forms
|
||||
import idaapi
|
||||
import HexRaysPyTools.Core.NegativeOffsets as NegativeOffsets
|
||||
import HexRaysPyTools.Core.Helper as Helper
|
||||
import HexRaysPyTools.Core.Cache as Cache
|
||||
import HexRaysPyTools.Core.Const as Const
|
||||
from HexRaysPyTools.Core.SpaghettiCode import SpaghettiVisitor, SwapThenElseVisitor
|
||||
from HexRaysPyTools.Core.StructXrefs import *
|
||||
|
||||
potential_negatives = {}
|
||||
|
||||
|
||||
def hexrays_events_callback(*args):
|
||||
global potential_negatives
|
||||
|
||||
hexrays_event = args[0]
|
||||
|
||||
if hexrays_event == idaapi.hxe_populating_popup:
|
||||
form, popup, hx_view = args[1:]
|
||||
item = hx_view.item # current ctree_item_t
|
||||
|
||||
if Actions.GuessAllocation.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.GuessAllocation.name, None)
|
||||
|
||||
if Actions.RecastItemRight.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RecastItemRight.name, None)
|
||||
|
||||
if Actions.RecastItemLeft.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RecastItemLeft.name, None)
|
||||
|
||||
if Actions.RenameOther.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RenameOther.name, None)
|
||||
|
||||
if Actions.RenameInside.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RenameInside.name, None)
|
||||
|
||||
if Actions.RenameOutside.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RenameOutside.name, None)
|
||||
|
||||
if Actions.RenameUsingAssert.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RenameUsingAssert.name, None)
|
||||
|
||||
if Actions.SwapThenElse.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.SwapThenElse.name, None)
|
||||
|
||||
if Actions.ShallowScanVariable.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.ShallowScanVariable.name, None)
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.DeepScanVariable.name, None)
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RecognizeShape.name, None)
|
||||
|
||||
if Actions.CreateNewField.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.CreateNewField.name, None)
|
||||
|
||||
if Actions.FindFieldXrefs.check(item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.FindFieldXrefs.name, None)
|
||||
|
||||
if Actions.PropagateName.check(hx_view.cfunc, item):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.PropagateName.name, None)
|
||||
|
||||
if item.citype == idaapi.VDI_FUNC:
|
||||
# If we clicked on function
|
||||
if not hx_view.cfunc.entry_ea == idaapi.BADADDR: # Probably never happen
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.AddRemoveReturn.name, None)
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.ConvertToUsercall.name, None)
|
||||
if Actions.DeepScanReturn.check(hx_view):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.DeepScanReturn.name, None)
|
||||
|
||||
elif item.citype == idaapi.VDI_LVAR:
|
||||
# If we clicked on argument
|
||||
local_variable = hx_view.item.get_lvar() # idaapi.lvar_t
|
||||
if local_variable.is_arg_var:
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.RemoveArgument.name, None)
|
||||
|
||||
elif item.citype == idaapi.VDI_EXPR:
|
||||
if item.e.op == idaapi.cot_num:
|
||||
# number_format = item.e.n.nf # idaapi.number_format_t
|
||||
# print "(number) flags: {0:#010X}, type_name: {1}, opnum: {2}".format(
|
||||
# number_format.flags,
|
||||
# number_format.type_name,
|
||||
# number_format.opnum
|
||||
# )
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.GetStructureBySize.name, None)
|
||||
elif item.e.op == idaapi.cot_var:
|
||||
# Check if we clicked on variable that is a pointer to a structure that is potentially part of
|
||||
# containing structure
|
||||
if item.e.v.idx in potential_negatives:
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.SelectContainingStructure.name, None)
|
||||
if Actions.ResetContainingStructure.check(hx_view.cfunc.get_lvars()[item.e.v.idx]):
|
||||
idaapi.attach_action_to_popup(form, popup, Actions.ResetContainingStructure.name, None)
|
||||
|
||||
elif hexrays_event == idaapi.hxe_double_click:
|
||||
hx_view = args[1]
|
||||
item = hx_view.item
|
||||
if item.citype == idaapi.VDI_EXPR and item.e.op == idaapi.cot_memptr:
|
||||
# Look if we double clicked on expression that is member pointer. Then get tinfo_t of the structure.
|
||||
# After that remove pointer and get member name with the same offset
|
||||
if item.e.x.op == idaapi.cot_memref and item.e.x.x.op == idaapi.cot_memptr:
|
||||
vtable_tinfo = item.e.x.type.get_pointed_object()
|
||||
method_offset = item.e.m
|
||||
class_tinfo = item.e.x.x.x.type.get_pointed_object()
|
||||
vtable_offset = item.e.x.x.m
|
||||
elif item.e.x.op == idaapi.cot_memptr:
|
||||
vtable_tinfo = item.e.x.type.get_pointed_object()
|
||||
method_offset = item.e.m
|
||||
class_tinfo = item.e.x.x.type.get_pointed_object()
|
||||
vtable_offset = item.e.x.m
|
||||
else:
|
||||
func_offset = item.e.m
|
||||
struct_tinfo = item.e.x.type.get_pointed_object()
|
||||
func_ea = Helper.get_virtual_func_address(Helper.get_member_name(struct_tinfo, func_offset))
|
||||
if func_ea:
|
||||
idaapi.jumpto(func_ea)
|
||||
return 0
|
||||
|
||||
func_name = Helper.get_member_name(vtable_tinfo, method_offset)
|
||||
func_ea = Helper.get_virtual_func_address(func_name, class_tinfo, vtable_offset)
|
||||
if func_ea:
|
||||
idaapi.open_pseudocode(func_ea, 0)
|
||||
return 1
|
||||
|
||||
elif hexrays_event == idaapi.hxe_maturity:
|
||||
cfunc, level_of_maturity = args[1:]
|
||||
|
||||
if level_of_maturity == idaapi.CMAT_BUILT:
|
||||
# print '=' * 40
|
||||
# print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
|
||||
# print '=' * 40
|
||||
# print cfunc
|
||||
|
||||
# First search for CONTAINING_RECORD made by Ida
|
||||
visitor = NegativeOffsets.SearchVisitor(cfunc)
|
||||
visitor.apply_to(cfunc.body, None)
|
||||
negative_lvars = visitor.result
|
||||
|
||||
# Second get saved information from comments
|
||||
lvars = cfunc.get_lvars()
|
||||
for idx in xrange(len(lvars)):
|
||||
result = NegativeOffsets.parse_lvar_comment(lvars[idx])
|
||||
if result and result.tinfo.equals_to(lvars[idx].type().get_pointed_object()):
|
||||
negative_lvars[idx] = result
|
||||
|
||||
# Third make an analysis of local variables that a structure pointers and have reference that pass
|
||||
# through structure boundaries. This variables will be considered as potential pointers to substructure
|
||||
# and will get a menu on right click that helps to select Containing Structure from different libraries
|
||||
|
||||
structure_pointer_variables = {}
|
||||
for idx in set(range(len(lvars))) - set(negative_lvars.keys()):
|
||||
if lvars[idx].type().is_ptr():
|
||||
pointed_tinfo = lvars[idx].type().get_pointed_object()
|
||||
if pointed_tinfo.is_udt():
|
||||
structure_pointer_variables[idx] = pointed_tinfo
|
||||
|
||||
if structure_pointer_variables:
|
||||
visitor = NegativeOffsets.AnalyseVisitor(structure_pointer_variables, potential_negatives)
|
||||
visitor.apply_to(cfunc.body, None)
|
||||
|
||||
if negative_lvars:
|
||||
visitor = NegativeOffsets.ReplaceVisitor(negative_lvars)
|
||||
visitor.apply_to(cfunc.body, None)
|
||||
|
||||
elif level_of_maturity == idaapi.CMAT_TRANS1:
|
||||
|
||||
visitor = SwapThenElseVisitor(cfunc.entry_ea)
|
||||
visitor.apply_to(cfunc.body, None)
|
||||
|
||||
elif level_of_maturity == idaapi.CMAT_TRANS2:
|
||||
# print '=' * 40
|
||||
# print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
|
||||
# print '=' * 40
|
||||
# print cfunc
|
||||
visitor = SpaghettiVisitor()
|
||||
visitor.apply_to(cfunc.body, None)
|
||||
|
||||
elif level_of_maturity == idaapi.CMAT_FINAL:
|
||||
StructXrefVisitor(cfunc).process()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
class MyPlugin(idaapi.plugin_t):
|
||||
# flags = idaapi.PLUGIN_HIDE
|
||||
flags = 0
|
||||
comment = "Plugin for automatic classes reconstruction"
|
||||
help = "This is help"
|
||||
wanted_name = "HexRaysPyTools"
|
||||
wanted_hotkey = "Alt-F8"
|
||||
|
||||
@staticmethod
|
||||
def init():
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
print "[ERROR] Failed to initialize Hex-Rays SDK"
|
||||
return idaapi.PLUGIN_SKIP
|
||||
|
||||
Cache.temporary_structure = TemporaryStructureModel()
|
||||
# Actions.register(Actions.CreateVtable)
|
||||
Actions.register(Actions.ShowGraph)
|
||||
Actions.register(Actions.ShowClasses)
|
||||
Actions.register(Actions.GetStructureBySize)
|
||||
Actions.register(Actions.RemoveArgument)
|
||||
Actions.register(Actions.AddRemoveReturn)
|
||||
Actions.register(Actions.ConvertToUsercall)
|
||||
Actions.register(Actions.ShallowScanVariable, Cache.temporary_structure)
|
||||
Actions.register(Actions.DeepScanVariable, Cache.temporary_structure)
|
||||
Actions.register(Actions.DeepScanReturn, Cache.temporary_structure)
|
||||
Actions.register(Actions.DeepScanFunctions, Cache.temporary_structure)
|
||||
Actions.register(Actions.RecognizeShape)
|
||||
Actions.register(Actions.CreateNewField)
|
||||
Actions.register(Actions.SelectContainingStructure, potential_negatives)
|
||||
Actions.register(Actions.ResetContainingStructure)
|
||||
Actions.register(Actions.RecastItemRight)
|
||||
Actions.register(Actions.RecastItemLeft)
|
||||
Actions.register(Actions.RenameOther)
|
||||
Actions.register(Actions.RenameInside)
|
||||
Actions.register(Actions.RenameOutside)
|
||||
Actions.register(Actions.RenameUsingAssert)
|
||||
Actions.register(Actions.SwapThenElse)
|
||||
Actions.register(Actions.FindFieldXrefs)
|
||||
Actions.register(Actions.PropagateName)
|
||||
Actions.register(Actions.GuessAllocation)
|
||||
|
||||
idaapi.attach_action_to_menu('View/Open subviews/Local types', Actions.ShowClasses.name, idaapi.SETMENU_APP)
|
||||
idaapi.install_hexrays_callback(hexrays_events_callback)
|
||||
|
||||
Const.init()
|
||||
XrefStorage().open()
|
||||
|
||||
return idaapi.PLUGIN_KEEP
|
||||
|
||||
@staticmethod
|
||||
def run(arg):
|
||||
tform = idaapi.find_tform("Structure Builder")
|
||||
if tform:
|
||||
idaapi.switchto_tform(tform, True)
|
||||
else:
|
||||
Forms.StructureBuilder(Cache.temporary_structure).Show()
|
||||
|
||||
@staticmethod
|
||||
def term():
|
||||
if Cache.temporary_structure:
|
||||
Cache.temporary_structure.clear()
|
||||
# Actions.unregister(Actions.CreateVtable)
|
||||
Actions.unregister(Actions.ShowGraph)
|
||||
Actions.unregister(Actions.ShowClasses)
|
||||
Actions.unregister(Actions.GetStructureBySize)
|
||||
Actions.unregister(Actions.RemoveArgument)
|
||||
Actions.unregister(Actions.AddRemoveReturn)
|
||||
Actions.unregister(Actions.ConvertToUsercall)
|
||||
Actions.unregister(Actions.ShallowScanVariable)
|
||||
Actions.unregister(Actions.DeepScanVariable)
|
||||
Actions.unregister(Actions.DeepScanReturn)
|
||||
Actions.unregister(Actions.DeepScanFunctions)
|
||||
Actions.unregister(Actions.RecognizeShape)
|
||||
Actions.unregister(Actions.CreateNewField)
|
||||
Actions.unregister(Actions.SelectContainingStructure)
|
||||
Actions.unregister(Actions.ResetContainingStructure)
|
||||
Actions.unregister(Actions.RecastItemRight)
|
||||
Actions.unregister(Actions.RecastItemLeft)
|
||||
Actions.unregister(Actions.RenameOther)
|
||||
Actions.unregister(Actions.RenameInside)
|
||||
Actions.unregister(Actions.RenameOutside)
|
||||
Actions.unregister(Actions.RenameUsingAssert)
|
||||
Actions.unregister(Actions.SwapThenElse)
|
||||
Actions.unregister(Actions.FindFieldXrefs)
|
||||
Actions.unregister(Actions.PropagateName)
|
||||
Actions.unregister(Actions.GuessAllocation)
|
||||
idaapi.term_hexrays_plugin()
|
||||
XrefStorage().close()
|
||||
|
||||
|
||||
def PLUGIN_ENTRY():
|
||||
idaapi.notify_when(idaapi.NW_OPENIDB, Cache.init_demangled_names)
|
||||
idaapi.notify_when(idaapi.NW_OPENIDB, Cache.init_imported_ea)
|
||||
idaapi.notify_when(idaapi.NW_OPENIDB, Cache.reset_touched_functions)
|
||||
Helper.extend_ida()
|
||||
return MyPlugin()
|
||||
Reference in New Issue
Block a user