def check(ctree_item): lvar = ctree_item.get_lvar() if lvar is not None: return "LOCAL" if Helper.is_legal_type(lvar.type()) else None if ctree_item.citype == idaapi.VDI_EXPR: gvar = ctree_item.it.to_specific_type if gvar.op == idaapi.cot_obj and Helper.is_legal_type(gvar.type): return "GLOBAL"
def check(cfunc, ctree_item): if ctree_item.citype == idaapi.VDI_EXPR: expression = ctree_item.it.to_specific_type child = None while expression and expression.op not in (idaapi.cot_asg, idaapi.cit_return, idaapi.cot_call): child = expression.to_specific_type expression = cfunc.body.find_parent_of(expression) if expression: expression = expression.to_specific_type if expression.op == idaapi.cot_asg and \ expression.x.op in (idaapi.cot_var, idaapi.cot_obj, idaapi.cot_memptr, idaapi.cot_memref) \ and expression.y.op == idaapi.cot_cast: if expression.x.op == idaapi.cot_var: variable = cfunc.get_lvars()[expression.x.v.idx] idaapi.update_action_label( RecastItemLeft.name, 'Recast Variable "{0}"'.format(variable.name)) return RECAST_LOCAL_VARIABLE, expression.y.x.type, variable elif expression.x.op == idaapi.cot_obj: idaapi.update_action_label(RecastItemLeft.name, 'Recast Global') return RECAST_GLOBAL_VARIABLE, expression.y.x.type, expression.x.obj_ea elif expression.x.op == idaapi.cot_memptr: idaapi.update_action_label(RecastItemLeft.name, 'Recast Field') return RECAST_STRUCTURE, expression.x.x.type.get_pointed_object( ).dstr(), expression.x.m, expression.y.x.type elif expression.x.op == idaapi.cot_memref: idaapi.update_action_label(RecastItemLeft.name, 'Recast Field') return RECAST_STRUCTURE, expression.x.x.type.dstr( ), expression.x.m, expression.y.x.type elif expression.op == idaapi.cit_return: child = child or expression.creturn.expr if child.op == idaapi.cot_cast: idaapi.update_action_label(RecastItemLeft.name, "Recast Return") return RECAST_RETURN, child.x.type, None elif expression.op == idaapi.cot_call: if child and child.op == idaapi.cot_cast: if child.cexpr.x.op == idaapi.cot_memptr: idaapi.update_action_label( RecastItemLeft.name, 'Recast Virtual Function') return RECAST_STRUCTURE, child.cexpr.x.x.type.get_pointed_object( ).dstr(), child.cexpr.x.m, child.type arg_index, _ = Helper.get_func_argument_info( expression, child.cexpr) idaapi.update_action_label(RecastItemLeft.name, "Recast Argument") return (RECAST_ARGUMENT, arg_index, expression.x.type.get_pointed_object(), child.x.type, expression.x.obj_ea)
def activate(self, ctx): hx_view = idaapi.get_tform_vdui(ctx.form) variable = hx_view.item.get_lvar() # lvar_t if variable and Helper.is_legal_type(variable.type()): index = list(hx_view.cfunc.get_lvars()).index(variable) scanner = ShallowSearchVisitor( hx_view.cfunc, self.temporary_structure.main_offset, index) scanner.process() for field in scanner.candidates: self.temporary_structure.add_row(field) scanner.clear()
def check(cfunc, ctree_item): if ctree_item.citype != idaapi.VDI_EXPR: return False expression = ctree_item.it.to_specific_type if expression.op == idaapi.cot_var: lvar = ctree_item.get_lvar() # Check if it's either variable with user name or argument with not standard `aX` name if lvar.has_user_name or lvar.is_arg_var and re.search("a\d*$", lvar.name) is None: parent = cfunc.body.find_parent_of(expression).to_specific_type if parent.op == idaapi.cot_call: arg_index, _ = Helper.get_func_argument_info(parent, expression) func_tinfo = parent.x.type.get_pointed_object() func_data = idaapi.func_type_data_t() func_tinfo.get_func_details(func_data) if arg_index < func_tinfo.get_nargs() and lvar.name.lstrip('_') != func_data[arg_index].name: return func_tinfo, parent.x.obj_ea, arg_index, lvar.name.lstrip('_')
def check(cfunc, ctree_item): if ctree_item.citype != idaapi.VDI_EXPR: return False expression = ctree_item.it.to_specific_type if expression.op == idaapi.cot_var: lvar = ctree_item.get_lvar() parent = cfunc.body.find_parent_of(expression).to_specific_type if parent.op == idaapi.cot_call: arg_index, _ = Helper.get_func_argument_info(parent, expression) func_tinfo = parent.x.type.get_pointed_object() if func_tinfo.get_nargs() < arg_index: return func_data = idaapi.func_type_data_t() func_tinfo.get_func_details(func_data) name = func_data[arg_index].name if name and re.search("a\d*$", name) is None and name != 'this' and name != lvar.name: return name, lvar
def activate(self, ctx): for idx in ctx.chooser_selection: func_ea = idaapi.getn_func(idx - 1).startEA try: cfunc = idaapi.decompile(func_ea) if cfunc is None: continue FunctionTouchVisitor(cfunc).process() lvars = cfunc.get_lvars() if not (lvars and lvars[0].is_arg_var and Helper.is_legal_type(lvars[0].type())): continue scanner = DeepSearchVisitor(cfunc, 0, 0) scanner.process() for field in scanner.candidates: self.temporary_structure.add_row(field) except idaapi.DecompilationFailure: print "[Warning] Failed to decompile function at 0x{0:08X}".format(func_ea)
def scan(self, hx_view, variable): if variable and Helper.is_legal_type(variable.type()): definition_address = None if variable.is_arg_var else variable.defea index = list(hx_view.cfunc.get_lvars()).index(variable) # index = list(hx_view.cfunc.get_lvars()).index(variable) if FunctionTouchVisitor(hx_view.cfunc).process(): hx_view.refresh_view(True) # Because index of the variable can be changed after touching, we would like to calculate it appropriately lvars = hx_view.cfunc.get_lvars() if definition_address: index = next(x for x in xrange(len(lvars)) if lvars[x].defea == definition_address) scanner = DeepSearchVisitor(hx_view.cfunc, self.temporary_structure.main_offset, index) scanner.process() for field in scanner.candidates: self.temporary_structure.add_row(field) scanner.clear()
def check(cfunc, ctree_item): if ctree_item.citype == idaapi.VDI_EXPR: expression = ctree_item.it.to_specific_type child = None while expression and expression.op not in (idaapi.cot_asg, idaapi.cit_return, idaapi.cot_call): child = expression.to_specific_type expression = cfunc.body.find_parent_of(expression) if expression: expression = expression.to_specific_type if expression.op == idaapi.cot_asg and \ expression.x.op in (idaapi.cot_var, idaapi.cot_obj, idaapi.cot_memptr, idaapi.cot_memref): right_expr = expression.y right_tinfo = right_expr.x.type if right_expr.op == idaapi.cot_cast else right_expr.type # Check if both left and right parts of expression are of the same types. # If no then we can recast then. if right_tinfo.dstr() == expression.x.type.dstr(): return if expression.x.op == idaapi.cot_var: variable = cfunc.get_lvars()[expression.x.v.idx] idaapi.update_action_label( RecastItemLeft.name, 'Recast Variable "{0}"'.format(variable.name)) return RECAST_LOCAL_VARIABLE, right_tinfo, variable elif expression.x.op == idaapi.cot_obj: idaapi.update_action_label(RecastItemLeft.name, 'Recast Global') return RECAST_GLOBAL_VARIABLE, right_tinfo, expression.x.obj_ea elif expression.x.op == idaapi.cot_memptr: idaapi.update_action_label(RecastItemLeft.name, 'Recast Field') return RECAST_STRUCTURE, expression.x.x.type.get_pointed_object( ).dstr(), expression.x.m, right_tinfo elif expression.x.op == idaapi.cot_memref: idaapi.update_action_label(RecastItemLeft.name, 'Recast Field') return RECAST_STRUCTURE, expression.x.x.type.dstr( ), expression.x.m, right_tinfo elif expression.op == idaapi.cit_return: idaapi.update_action_label(RecastItemLeft.name, "Recast Return") child = child or expression.creturn.expr if child.op == idaapi.cot_cast: return RECAST_RETURN, child.x.type, None func_tinfo = idaapi.tinfo_t() cfunc.get_func_type(func_tinfo) rettype = func_tinfo.get_rettype() print func_tinfo.get_rettype().dstr(), child.type.dstr() if func_tinfo.get_rettype().dstr() != child.type.dstr(): return RECAST_RETURN, child.type, None elif expression.op == idaapi.cot_call: if expression.x.op == idaapi.cot_memptr: # TODO: Recast arguments of virtual functions return if child and child.op == idaapi.cot_cast: if child.cexpr.x.op == idaapi.cot_memptr: idaapi.update_action_label( RecastItemLeft.name, 'Recast Virtual Function') return RECAST_STRUCTURE, child.cexpr.x.x.type.get_pointed_object( ).dstr(), child.cexpr.x.m, child.type arg_index, _ = Helper.get_func_argument_info( expression, child.cexpr) idaapi.update_action_label(RecastItemLeft.name, "Recast Argument") return (RECAST_ARGUMENT, arg_index, expression.x.type.get_pointed_object(), child.x.type, expression.x.obj_ea)
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.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 hx_view.item.get_lvar() and Helper.is_legal_type(hx_view.item.get_lvar().type()): 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 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) 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: return 0 udt_member = idaapi.udt_member_t() udt_member.offset = method_offset * 8 vtable_tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) func_ea = Helper.get_virtual_func_address(udt_member.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_TRANS2: # print '=' * 40 # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16 # print '=' * 40 # print cfunc visitor = SpaghettiVisitor() visitor.apply_to(cfunc.body, None) return 0
def hexrays_events_callback(*args): if fDebug: pydevd.settrace('localhost', port=31337, stdoutToServer=True, stderrToServer=True, suspend=False) hexrays_event = args[0] from HexRaysPyTools.Config import hex_pytools_config if hexrays_event == idaapi.hxe_populating_popup: form, popup, hx_view = args[1:] item = hx_view.item # current ctree_item_t for ac in hex_pytools_config.actions_refs.values(): if ac.ForPopup and hex_pytools_config[ac.name] and ac.check(hx_view.cfunc,item): idaapi.attach_action_to_popup(form, popup, ac.name, None) # if Actions.RecastStructMember.check(hx_view.cfunc,item): # if hex_pytools_config[Actions.RecastStructMember.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RecastStructMember.name, None) # # if Actions.SimpleCreateStruct.check(hx_view.cfunc,item): # if hex_pytools_config[Actions.SimpleCreateStruct.name]: # idaapi.attach_action_to_popup(form, popup, Actions.SimpleCreateStruct.name, None) # # if Actions.RecastItemRight.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.RecastItemRight.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RecastItemRight.name, None) # # if Actions.RecastItemLeft.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.RecastItemLeft.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RecastItemLeft.name, None) # # if Actions.RenameOther.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.RenameOther.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RenameOther.name, None) # # if Actions.RenameInside.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.RenameInside.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RenameInside.name, None) # # if Actions.RenameOutside.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.RenameOutside.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RenameOutside.name, None) # # if Actions.SwapThenElse.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.SwapThenElse.name]: # idaapi.attach_action_to_popup(form, popup, Actions.SwapThenElse.name, None) # # if Actions.ShallowScanVariable.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.ShallowScanVariable.name]: # idaapi.attach_action_to_popup(form, popup, Actions.ShallowScanVariable.name, None) # if hex_pytools_config[Actions.DeepScanVariable.name]: # idaapi.attach_action_to_popup(form, popup, Actions.DeepScanVariable.name, None) # if hex_pytools_config[Actions.RecognizeShape.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RecognizeShape.name, None) # # if Actions.CreateNewField.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.CreateNewField.name]: # idaapi.attach_action_to_popup(form, popup, Actions.CreateNewField.name, None) # # if Actions.CreateVtable.check(hx_view.cfunc, item): # if hex_pytools_config[Actions.CreateVtable.name]: # idaapi.attach_action_to_popup(form, popup, Actions.CreateVtable.name, None) # # if Actions.AddRemoveReturn.check(hx_view.cfunc, item) and hex_pytools_config[Actions.AddRemoveReturn.name]: # idaapi.attach_action_to_popup(form, popup, Actions.AddRemoveReturn.name, None) # if Actions.ConvertToUsercall.check(hx_view.cfunc, item) and hex_pytools_config[Actions.ConvertToUsercall.name]: # idaapi.attach_action_to_popup(form, popup, Actions.ConvertToUsercall.name, None) # if Actions.DeepScanReturn.check(hx_view.cfunc, item) and hex_pytools_config[Actions.DeepScanReturn.name]: # idaapi.attach_action_to_popup(form, popup, Actions.DeepScanReturn.name, None) # # if Actions.RemoveArgument.check(hx_view.cfunc,item) and hex_pytools_config[Actions.RemoveArgument.name]: # idaapi.attach_action_to_popup(form, popup, Actions.RemoveArgument.name, None) # # if Actions.GetStructureBySize.check(hx_view.cfunc,item) and hex_pytools_config[Actions.GetStructureBySize.name]: # idaapi.attach_action_to_popup(form, popup, Actions.GetStructureBySize.name, None) # # if Actions.SelectContainingStructure.check(hx_view.cfunc,item) and hex_pytools_config[Actions.SelectContainingStructure.name]: # idaapi.attach_action_to_popup(form, popup, Actions.SelectContainingStructure.name, None) # # if Actions.ResetContainingStructure.check(hx_view.cfunc,item): # if hex_pytools_config[Actions.ResetContainingStructure.name]: # 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: return 0 #print vtable_tinfo.get_type_name() #print method_offset udt_member = idaapi.udt_member_t() udt_member.offset = method_offset * 8 vtable_tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) func_ea = Helper.get_virtual_func_address(udt_member.name, class_tinfo, vtable_offset) if func_ea: idaapi.open_pseudocode(func_ea, 0) return 1 n = Netnode("$ VTables") vt_name = vtable_tinfo.get_type_name() if vt_name in n: l = n[vt_name] #print l info = idaapi.get_inf_structure() if info.is_32bit(): ptr_size = 4 elif info.is_64bit(): ptr_size = 8 else: ptr_size = 2 if method_offset%ptr_size == 0 and method_offset/ptr_size < len(l): idaapi.open_pseudocode(l[method_offset/ptr_size] + idaapi.get_imagebase(), 0) 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: return 0 # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16 # print '=' * 40 # print cfunc visitor = SpaghettiVisitor() visitor.apply_to(cfunc.body, None) return 0
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()