def markStructFromToolkit(func_ea, structOff, structName): f = Function.Function(func_ea) toolkitMovs = FuncAnalyzer.traceRegVar(f.func_ea, f.func_ea + f.getSize(withPool=False), 10, 0) for trace_ea in toolkitMovs: # lock into the register in question insn = Instruction.Insn(trace_ea) if insn.isComputationalInsn(): regWrites = FuncAnalyzer.traceRegWrites(f.func_ea, f.func_ea + f.getSize(withPool=False), insn.ops[0].reg) # TODO: traceRegWrites messes up insn insn = Instruction.Insn(trace_ea) # find the relevent register variable to trace regVarIdx = FuncAnalyzer.getRegWriteIndex(trace_ea, regWrites) insn = Instruction.Insn(trace_ea) # trace all reads to this register variable in particular # print('args', f.func_ea, f.func_ea + f.getSize(withPool=False), # insn.ops[0].reg, regVarIdx) toolkitAccesses = FuncAnalyzer.traceRegVar(f.func_ea, f.func_ea + f.getSize(withPool=False), insn.ops[0].reg, regVarIdx) # those now will represent all registers R10 moved to, and thus, all of those accesses # are accesses to the R10 struct for access in toolkitAccesses: # now mark with Toolkit enum accessInsn = Instruction.Insn(access) if accessInsn.ops[1].type == ida_ua.o_displ: if accessInsn.ops[1].addr == structOff: # print(hex(access), idc.GetDisasm(access)) structAcccesses = FuncAnalyzer.traceRegVar(f.func_ea, f.func_ea + f.getSize(withPool=False), accessInsn.ops[0].reg, regVarIdx+1) for structAccess in structAcccesses: # print(hex(structAccess), idc.GetDisasm(structAccess)) idc.op_enum(structAccess, 1, idc.get_enum(structName), 0) return True
def rename_constant(arg_ea, fct_name, arg_name, arg_enums): """ Rename constants to values from standard enumerations. """ instruction = idc.print_insn_mnem(arg_ea) if instruction == 'push': op_num = 0 elif instruction == 'mov': op_num = 1 else: raise RenamingException('Constant: unhandled instruction ' + instruction) op_val = idc.get_operand_value(arg_ea, op_num) # NULL if op_val == 0: targetid = idc.get_enum_member_by_name('NULL_{}_{}'.format( arg_name, fct_name)) serial = 0 enumid = idc.get_enum(NULL_ENUM_NAME) constid = idc.get_enum_member(enumid, 0, serial, -1) while constid != idaapi.BADADDR: if constid == targetid: idc.op_enum(arg_ea, op_num, enumid, serial) return serial = serial + 1 constid = idc.get_enum_member(enumid, 0, serial, -1) # All other constants op_type = idc.get_operand_type(arg_ea, op_num) if op_type == idaapi.o_imm: # only one choice if len(arg_enums) == 1: enumid = idc.get_enum(arg_enums[0]) idc.op_enum(arg_ea, op_num, enumid, 0) return for enum in arg_enums: enumid = idc.get_enum(enum) constid = get_constant_id(enumid, op_val) if constid == idaapi.BADADDR: # Not in this enum continue else: # Found the right enum idc.op_enum(arg_ea, op_num, enumid, 0) return
def OpEnum(ea, n, enumid): return idc.op_enum(ea, n, enumid, 0)
def activate(self, ctx): # print("ctx.cur_ea : 0x%x" % ctx.cur_ea) # print("ctx.cur_extracted_ea : 0x%x" % ctx.cur_extracted_ea) # Extract selected enum instruction = idc.GetDisasm(ctx.cur_ea) selection = ctx.cur_extracted_ea # correctly parse the selected value as int (hex or decimal) # since ctx.cur_extracted_ea has a bug (IDA always consider # the selected value as hex) if instruction.find("{0:X}h".format(selection)) != -1: # print("hex value found !") selected_value = ctx.cur_extracted_ea elif instruction.find("{0:d}".format(selection)) != -1: # print("int value found !") selected_value = int("%x" % ctx.cur_extracted_ea) else: # print("nothing selected !") return 1 # next power of two for masking selected_value_mask = self.shift_bit_length(selected_value) - 1 # print("selected_value : 0x%X" % selected_value) # print("selected_value mask : 0x%X" % selected_value_mask) # query magnum db url = SearchMagicNumber.MAGNUMDB_QUERY.format( value=selected_value, key=SearchMagicNumber.MAGNUMDB_KEY) answer = urlopen(url) results = json.loads(answer.read()) # Let the user select the best answer c = ChooseMagicNumber(selected_value, results["Items"]) selected_index = c.Show(modal=True) if selected_index < 0: return # Apply the newly found enum selected_item = results["Items"][selected_index] selected_name = selected_item["Title"].encode('ascii') selected_value = int(selected_item["Value"]) # serial is important since several entries can have the same value entryid, serial = self._manager.add_magnumdb_entry( selected_name, selected_value) # locate the operand where to apply the enum insn = idautils.DecodeInstruction(ctx.cur_ea) try: # ida < 7.4 operands = insn.Operands except AttributeError: # ida 7.4 operands = insn.ops for op in filter(lambda o: o.type == idaapi.o_imm, operands): # heuristic : the selected immediate is the first in the instruction with # the same exact value (we are using a mask since IDA loves to set FFFFFFFF to high words) if op.value & selected_value_mask == selected_value: # Apply the enum op_enum(ctx.cur_ea, op.n, idaapi.get_enum("_IDA_MAGNUMDB"), serial) break return 1