def postprocess_func(fn, depth=0): func = { 'ea': fn.startEA, 'rva': ea_to_rva(fn.startEA), 'body': get_bytes_str(fn.startEA, fn.endEA) } # total aids switch_ea, switch = find_switch(fn.startEA) if switch and switch_ea != main_jumptable: sw = func['switch'] = {} res = idaapi.calc_switch_cases(switch_ea, switch) case_ids = [] for case in res.cases: for i in case: case_ids.append(int(i)) sw['cases'] = [i for i in set(case_ids)] else: func['switch'] = None return func
def _calc_cases(self): si = idaapi.get_switch_info_ex(self._ea) results = idaapi.calc_switch_cases(self._ea, si) if not results: raise SarkNotASwitch("Seems like 0x{:08X} is not a switch jump instruction.".format(self._ea)) return results
def InsSwitchInfo(i): switch_info = idaapi.get_switch_info_ex(i) if switch_info is None: return False, None, None cases = idaapi.calc_switch_cases(i, switch_info) return bool(cases), switch_info, cases
def _calc_cases(self): si = idaapi.get_switch_info(self._ea) results = idaapi.calc_switch_cases(self._ea, si) if not results: raise exceptions.SarkNotASwitch( "Seems like 0x{:08X} is not a switch jump instruction.".format( self._ea)) return results
def switch_cases(ea): '''ea_t -> {int : ea_t}''' # NOTE mutates d sw = get_switch_info(ea) ct = idaapi.calc_switch_cases(ea, sw) def make_cases(d, (case, target)): # this is lame, but the only way IDA marks the default case other than # by adding a comment like "jumptable ADDR default case" if idc.Name(target).startswith('def_'): d['default'] = target else: d['cases'][case] = target return d
print('[+] Found target function!') myfunc = func break def is_user_name(ea): f = idc.GetFlags(ea) return idc.hasUserName(f) for (startea, endea) in Chunks(myfunc): for head in Heads(startea, endea): switch_info = idaapi.get_switch_info_ex(head) if switch_info != None: num_cases = switch_info.get_jtable_size() # print(num_cases) # print 'good jump table found' results = idaapi.calc_switch_cases(head, switch_info) for idx in xrange(results.cases.size()): cur_case = results.cases[idx] ret = is_user_name(results.targets[idx]) if ret: name = idc.NameEx(BADADDR, results.targets[idx]) if "TARGET_" in name or "PRED_" in name: for cidx in xrange(len(cur_case)): number = int(cur_case[cidx]) name = name.replace("TARGET_", "").replace("PRED_", "") if name not in jump_table: jump_table[name] = number print(jump_table)
break def is_user_name(ea): f = idc.GetFlags(ea) return idc.hasUserName(f) for (startea, endea) in Chunks(myfunc): for head in Heads(startea, endea): switch_info = idaapi.get_switch_info_ex(head) if switch_info != None: num_cases = switch_info.get_jtable_size() # print(num_cases) # print 'good jump table found' results = idaapi.calc_switch_cases(head, switch_info) for idx in xrange(results.cases.size()): cur_case = results.cases[idx] ret = is_user_name(results.targets[idx]) if ret: name = idc.NameEx(BADADDR, results.targets[idx]) if "TARGET_" in name or "PRED_" in name: for cidx in xrange(len(cur_case)): number = int(cur_case[cidx]) name = name.replace("TARGET_", "").replace("PRED_", "") if name not in jump_table: jump_table[name] = number print(jump_table)
def run(): func_ea = find_pattern('48 89 74 24 ? 57 48 83 EC 50 8B F2 49 8B F8') output = {} output['rev'] = get_executable_watermark() output['clean_rev'] = get_clean_rev(output['rev']) if func_ea == ida_idaapi.BADADDR: log('couldn' 't find server opcode handler') return func_end_ea = idc.get_func_attr(func_ea, idc.FUNCATTR_END) output['size'] = func_size = func_end_ea - func_ea log('found opcode handler @ %x, end: %x, size: %x' % (func_ea, func_end_ea, func_size)) output['rva'] = ea_to_rva(func_ea) output['start_ea'] = func_ea output['end_ea'] = func_end_ea # find switch head, switch = find_switch(func_ea) global main_jumptable main_jumptable = head if switch == None: log('failed to find switch in opcode handler') return # get switch cases res = idaapi.calc_switch_cases(head, switch) # get basic blocks blocks = idaapi.FlowChart(idaapi.get_func(func_ea)) output['cases'] = case_infos = [] for idx, case in enumerate(res.cases): case_ea = res.targets[idx] rel_ea = case_ea - func_ea case_info = { 'rva': ea_to_rva(case_ea), 'start_ea': case_ea, 'rel_ea': rel_ea } block = find_block(case_ea, blocks) if block != None: case_info['end_ea'] = block.endEA case_info['size'] = block.endEA - case_ea # -1 to make it actually clickable in the output window and it goes to the right place #log('end: %x, size: %x' % ((block.endEA - 1), case_info['size']), 2) else: log('failed to get block for %x' % case_ea) continue case_info['opcodes'] = [int(oc) for oc in case] case_infos.append(case_info) log('got %d case info objs, switch blocks: %d' % (len(case_infos), len(res.cases))) for k, v in enumerate(case_infos): process_case(v, k) set_clipboard_json(output)