def dref_range_fixer(startEA, endEA): for line in sark.lines(startEA, endEA): for xref in line.xrefs_to: if xref.iscode or xref.frm == idc.BADADDR or str(xref.type) != 'Data_Text': # only try to fix data references from code in ROM of the Data_Text type (as created by the dumb seq xref routine above) continue logger.debug("fixing xref (type:%s) to %s from ROM:%x" % (xref.type, safe_name(line.ea), xref.frm)) sark.Line(xref.frm).comments.repeat = str(sark.Line(xref.frm).comments.repeat).replace("0x%x" % line.ea, safe_name(line.ea)) return
def apply_enum_by_name(enum, member_name): member_value = enum.members[member_name].value for line in sark.lines(*sark.get_selection()): for operand in line.insn.operands: if operand.type.is_imm: if operand.imm == member_value: idc.OpEnumEx(line.ea, operand.n, enum.eid, enum.members[member_name].serial) elif operand.type.is_displ or operand.type.is_phrase: if operand.addr == member_value: idc.OpEnumEx(line.ea, operand.n, enum.eid, enum.members[member_name].serial)
def _get_min_block_ranges(rgs, reg): if len(rgs) == 0: return rgs debug('Ranges before:') for s, e in rgs: debug('\t%x:%x' % (s, e)) rgs_d = {} rgs_new = [] rgs_new2 = [] #assumption - rgs is sorted s_first_blk, _ = rgs[0] func_start = sark.Function(s_first_blk).start_ea #if range between ranges (or between function start and first range) doesn't contain the reg - add it as range curr_s = func_start for s_blk, e_blk in rgs: dontextend = False for l in sark.lines(curr_s, s_blk): if (oregami_gen.proc_ops.is_load(l.ea, reg) or oregami_gen.proc_ops.is_store(l.ea, reg) ): #reg was used in line - range cannot include this dontextend = True break if not dontextend: rgs_new += [(curr_s, s_blk)] rgs_new += [(s_blk, e_blk)] curr_s = e_blk #if ranges are right after each other - make them one range while len(rgs_new) > 0: #print rgs_new s_blk, e_blk = rgs_new[0] rgs_new = rgs_new[1:] #while next ranges are consecutive, eat them up while len(rgs_new) > 0: s_blk2, e_blk2 = rgs_new[0] if e_blk != s_blk2: break e_blk = e_blk2 rgs_new = rgs_new[1:] rgs_new2 += [(s_blk, e_blk)] debug('Ranges after:') for s, e in rgs_new2: debug('\t%x:%x' % (s, e)) return rgs_new2
def avr_dumb_seq_load_xrefs(startEA, endEA): prev = None for line in sark.lines(startEA, endEA): if prev is None: prev = line continue try: curr_insn = line.insn prev_insn = prev.insn except sark.exceptions.SarkNoInstruction: logger.debug("skipping @ 0x%x" % line.ea) prev = line continue if (len(prev_insn.operands) != 2 or len(curr_insn.operands) != 2 or str(prev_insn.operands[1]) == '' or str(curr_insn.operands[1]) == '' ): logger.debug("filtering: %s && %s" % (prev, line)) prev = line continue logger.debug("testing %s && %s" % (prev, line)) if (is_latter_of_rxN_sequential_instructions(prev, line, 0) and str(prev_insn.operands[1].type) == 'Immediate_Value' and str(curr_insn.operands[1].type) == 'Immediate_Value' ): idc.OpHex(prev.ea, 1) idc.OpHex(line.ea, 1) if prev_insn.mnem == 'subi' and curr_insn.mnem == 'sbci': word = (int(curr_insn.operands[1].text, 0) + 1) * -256 + int(prev_insn.operands[1].text, 0) * -1 address = ram_segment.startEA + word if (address > ram_segment.startEA + 0x2000 and address < ram_segment.endEA and str(prev_insn.operands[0]) != 'YL' and str(prev_insn.operands[0].reg) != 'r28' # ignore indexed access into stack ): result = add_dref(line.ea, address, dr_T) logger.info("%s adding dref to %s at ROM:%x \"%s\"" % ("Success" if result else "Error", safe_name(address), line.ea, line)) line.comments.repeat = "indexed access into %s" % safe_name(address) else: word = int(curr_insn.operands[1].text, 0) * 256 + int(prev_insn.operands[1].text, 0) address = ram_segment.startEA + word if address >= ram_segment.startEA and address < ram_segment.endEA: result = add_dref(line.ea, address, dr_T) logger.info("%s adding dref to %s at ROM:%x \"%s\"" % ("Success" if result else "Error", safe_name(address), line.ea, line)) if address <= ram_segment.startEA + 32: line.comments.repeat = "possible %s" % sark.Line(address).comments.repeat # use the ioport name in the comments else: line.comments.repeat = safe_name(address) prev = line
def get_common_value(): values = defaultdict(int) for line in sark.lines(*sark.get_selection()): for operand in line.insn.operands: if operand.type.is_imm: values[operand.imm] += 1 elif operand.type.is_displ or operand.type.is_phrase: values[operand.addr] += 1 # Ignore 0 as it is usually not interesting values[0] = 0 # Get the most common value common_value = max(values.iteritems(), key=lambda x: x[1])[0] return common_value
def get_refs_blk(ea, blk_ea, dir, initstage, reg): superdebug = False if blk_ea == 0x801e7788: superdebug = True print 'Entered SUPER' blk = CodeBlock(blk_ea) if dir == FW: lines = sark.lines(start=ea, end=blk.end_ea) elif dir == BK: lines = sark.lines(start=blk.start_ea, end=ea, reverse=True) found_lines = {} found_breaks = {} found_outbreaks = {} stop = False for l in lines: if superdebug: print 'SUPER: %x' % l.ea if stop: break op = '' if proc_ops.is_load(l.ea, reg): op += 'r' if proc_ops.is_store(l.ea, reg): op += 'w' if op == '': continue if dir == FW: if op == 'r': initstage = False elif op == 'w': #found_breaks[l.ea] = op found_outbreaks[l.ea] = op stop = True break elif op == 'rw': if not initstage: found_breaks[l.ea] = op stop = True break elif dir == BK: if op == 'r': if initstage: #found_breaks[l.ea] = op found_outbreaks[l.ea] = op stop = True break elif op == 'w': initstage = False stop = True elif op == 'rw': initstage = True found_lines[l.ea] = op return found_lines, found_breaks, found_outbreaks, stop, initstage
def _get_min_block_ranges(rgs, reg): if len(rgs) == 0: return rgs logger.debug('Ranges before:') for s, e in rgs: logger.debug('\t%x:%x' % (s, e)) rgs_new = [] rgs_new2 = [] # assumption - rgs is sorted s_first_blk, _ = rgs[0] func_start = sark.Function(s_first_blk).start_ea # if range between ranges (or between function start and first range) # doesn't contain the reg - add it as range curr_s = func_start for s_blk, e_blk in rgs: dont_extend = False for line in sark.lines(curr_s, s_blk): # if not code - i.e. a switch-case table, then no reason to # check further if not line.is_code: continue # Trial - if ea not in function, dont_extend if ((not is_func(line.ea)) or (sark.Function(line.ea).start_ea != func_start)): dont_extend = True break opbits = RegInstruction(line.ea) \ .get_reg_op_bits(reg, op_mask=UsageBits.OP_RW | UsageBits.USAGE_MASK) if bool(opbits & UsageBits.USAGE_EXPLICIT) and \ bool(opbits & UsageBits.OP_RW): # reg was used in line - range cannot include this dont_extend = True break if (not dont_extend) and (curr_s < s_blk): rgs_new += [(curr_s, s_blk)] rgs_new += [(s_blk, e_blk)] curr_s = e_blk # if ranges are right after each other - make them one range while len(rgs_new) > 0: # print rgs_new s_blk, e_blk = rgs_new[0] rgs_new = rgs_new[1:] # while next ranges are consecutive, eat them up while len(rgs_new) > 0: s_blk2, e_blk2 = rgs_new[0] if e_blk != s_blk2: break e_blk = e_blk2 rgs_new = rgs_new[1:] rgs_new2 += [(s_blk, e_blk)] logger.debug('Ranges after:') for s, e in rgs_new2: logger.debug('\t%x:%x' % (s, e)) return rgs_new2
from collections import OrderedDict from collections import Counter import random import idaapi, idc, idautils, ida_kernwin import sark import json start = 0x01440E80 end = 0x01594280 CONST_LEN = 6 VFTABLE_LEN = 12 METHODS_LIMIT = 1040 COLOR_GREEN = 0x008000 COLOR_DARK_CYAN = 0x8B8B00 COLOR_ORANGE = 0x00A5FF # FFA500 lines = sark.lines(start, end) class VtableClass: def __init__(self, line): self.class_lines = [] self.ea = line.ea self.line = line self.current_line = line self.functions_addr = [] self.functions = {} self.get_base_name() self.get_methods() def get_base_name(self): self.raw_name = self.line.name
#stringify print("Looking for possible strings in %s segment..." % (idc.SegName(ram_segment.startEA))) counter = 0 for s in idautils.Strings(): if s.ea >= ram_segment.startEA and s.ea < ram_segment.endEA: if not idc.isASCII(idc.GetFlags(s.ea)) and idc.MakeStr( s.ea, idc.BADADDR): counter += 1 print "created %d new ASCII strings" % counter #datify print "Converting remaining data in RAM to words..." for line in sark.lines(ram_segment.startEA, ram_segment.endEA): flags = idc.GetFlags(line.ea) if (idc.isUnknown(flags) or idc.isByte(flags)) and line.ea % 2 == 0: idc.MakeWord(line.ea) val = Word(line.ea) if val > 31: #ignore data references to small values (like r0-r31) idc.OpOff(line.ea, 0, ram_segment.startEA) print "all lines in 0x%x - 0x%x are now words" % (ram_segment.startEA, ram_segment.endEA) #pointify print "looking for off_{} to rename to {}_ptr" counter = 0