Пример #1
0
def resetBlocks():
    p = idaapi.node_info_t()
    p.bg_color = 0xFFFFCC
    #fname = idaapi.get_root_filename()
    fname = idc.eval_idc("ARGV[1]")
    funs_file = fname + '.funs'
    if not os.path.isfile(funs_file):
        print('No file at %s\n Creating the database files needed by RESim.' %
              funs_file)
        resimUtils.dumpFuns(fname=fname)
    funs_fh = open(funs_file)
    fun_json = json.load(funs_fh)
    print('funs_file %s' % funs_file)
    for fun in fun_json:
        fun_addr = int(fun)
        #print('fun_addr 0x%x' % fun_addr)
        f = idaapi.get_func(fun_addr)
        #print('fun addr 0x%x' % fun_addr)
        #print('fun is %s' % str(f))
        if f is None:
            #print('no function found for 0x%x' % fun_addr)
            continue
        #print('doing function found for 0x%x' % fun_addr)
        graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
        for bb in graph:
            ida_graph.set_node_info(
                fun_addr, bb.id, p,
                idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def getIntrs(func):
	blocks = [(v.startEA, v.endEA) for v in ida_gdl.FlowChart(func)]
	sumcalls = 0
	for bl in blocks:
		callnum = calInsts(bl)
		sumcalls += callnum
	return sumcalls	
Пример #3
0
 def init_blk_cfg(self):
     """
     初始化基本块CFG
     """
     func_t = ida_funcs.get_func(self.trace_addr)
     if func_t:
         self.cfg = ida_gdl.FlowChart(func_t)
     else:
         self.cfg = []
def getfunc_consts(func):
	strings = []
	consts = []
	blocks = [(v.startEA, v.endEA) for v in ida_gdl.FlowChart(func)]
	for bl in blocks:
		strs, conts = getBBconsts(bl)
		strings += strs
		consts += conts
	return strings, consts
Пример #5
0
def using_FlowChart(ea, p=True):
    f = ida_gdl.FlowChart(ida_funcs.get_func(ea))

    for block in f:
        out(p, "%x - %x [%d]:" % (block.start_ea, block.end_ea, block.id))
        for succ_block in block.succs():
            out_succ(p, succ_block.start_ea, succ_block.end_ea)

        for pred_block in block.preds():
            out_pred(p, pred_block.start_ea, pred_block.end_ea)
Пример #6
0
def find_ret_block(ea):
    """
    寻找函数返回块,不支持多返回函数
    """

    func = ida_funcs.get_func(ea)
    f = ida_gdl.FlowChart(func)
    for block in f:
        if ida_gdl.is_ret_block(block.type):
            return block
    return None
Пример #7
0
 def getBlocks(self, function_offset):
     blocks = []
     function_chart = ida_gdl.FlowChart(ida_funcs.get_func(function_offset))
     for block in function_chart:
         extracted_block = []
         for instruction in idautils.Heads(block.start_ea, block.end_ea):
             if ida_bytes.is_code(ida_bytes.get_flags(instruction)):
                 extracted_block.append(instruction)
         if extracted_block:
             blocks.append(extracted_block)
     return sorted(blocks)
Пример #8
0
def obtain_block_sequence(func):
    control_blocks = {}
    main_blocks = {}
    blocks = [(v.startEA, v.endEA) for v in ida_gdl.FlowChart(func)]
    for bl in blocks:
        base = bl[0]
        end = idc.PrevHead(bl[1])
        control_ea = checkCB(bl)
        control_blocks[control_ea] = bl
        control_blocks[end] = bl
        if func.startEA <= base <= func.endEA:
            main_blocks[base] = bl
        x = sorted(main_blocks)
    return control_blocks, x
Пример #9
0
    def data(self):
        adjacencies = {}
        seen = set()

        for node in ida_gdl.FlowChart(ida_funcs.get_func(self.offset)):
            if node.id in seen:
                continue
            seen.add(node.id)

            adjacencies[node.id] = [succ.id for succ in node.succs()]

        if len(adjacencies) > 1:
            return adjacencies
        else:
            return None
Пример #10
0
    def data(self):
        sizes_hist = defaultdict(int)
        seen = set()

        for node in ida_gdl.FlowChart(ida_funcs.get_func(self.offset)):
            if node.id in seen:
                continue
            seen.add(node.id)

            node_size = node.endEA - node.startEA
            sizes_hist[node_size] += 1

        if sum(sizes_hist.values()) < 5:
            return None

        return sizes_hist
Пример #11
0
def get_funcs(ea):
    funcs = {}
    # Get current ea
    # Loop from start to end in the current segment
    plt_func, plt_data = processpltSegs()
    for funcea in idautils.Functions(idc.get_segm_start(ea)):
        funcname = get_unified_funcname(funcea)
        if funcname in plt_func:
            continue
        func = ida_funcs.get_func(funcea)
        blocks = ida_gdl.FlowChart(func)
        funcs[funcname] = []
        for bl in blocks:
            start = bl.startEA
            end = bl.endEA
            funcs[funcname].append((start, end))
    return funcs
Пример #12
0
    def data(self):
        func = ida_funcs.get_func(self.offset)

        def clean(asm):
            """This removes markers of function offsets, including hidden variable
      length offsets that are of different length on 32 and 64 bit address IDA.
      Otherwise, IDA of different offset lengths will truncate incorrect number
      of bytes"""
            hex_chars = int(log(ida_idaapi.BADADDR + 1, 2) / 4)
            pattern = (
                r"\x01(.{1})\x01\([0-9a-zA-Z]{%s}([\w\s!@$?_]*?)\x02\1\x02\)"
                "" % hex_chars)
            replace = "\x01\g<1>\g<2>\x02\g<1>"
            return re.sub(pattern, replace, asm)

        # make sure only nodes inside the function are accounted for
        # this solves cascaded functions (when multiple functions share same ends)
        def node_contained(node):
            return (ida_funcs.func_contains(func, node.startEA)
                    and ida_funcs.func_contains(func, node.endEA - 1))

        nodes = filter(node_contained, ida_gdl.FlowChart(func))
        node_ids = map(lambda n: n.id, nodes)

        nodes_data = []
        for node in nodes:
            assembly = [
                clean(ida_lines.generate_disasm_line(ea))
                for ea in idautils.Heads(node.startEA, node.endEA)
            ]
            successive_nodes = [
                succ.id for succ in node.succs() if succ.id in node_ids
            ]
            serialized_node = {
                'id': node.id,
                'type': node.type,
                'start': node.startEA,
                'end': node.endEA,
                'successive': successive_nodes,
                'assembly': assembly
            }
            nodes_data.append(serialized_node)

        return nodes_data
Пример #13
0
    def _data(cls, offset):
        flow_chart = ida_gdl.FlowChart(ida_funcs.get_func(offset))

        nodes = {}
        for node in flow_chart:
            assembly = [
                ida_lines.generate_disasm_line(ea)
                for ea in idautils.Heads(node.startEA, node.endEA)
            ]
            successive_nodes = [succ.id for succ in node.succs()]
            serialized_node = {
                'id': node.id,
                'type': node.type,
                'start': node.startEA,
                'end': node.endEA,
                'successive': successive_nodes,
                'assembly': assembly
            }
            nodes[node.id] = serialized_node

        return nodes
Пример #14
0
def find_all_ioctls():
    """
    From the currently selected address attempts to traverse all blocks inside the current function to find all immediate values which
    are used for a comparison/sub immediately before a jz. Returns a list of address, second operand pairs.
    """    
    
    ioctls = []
    # Find the currently selected function and get a list of all of it's basic blocks
    addr = idc.get_screen_ea()
    f = idaapi.get_func(addr)
    fc = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
    for block in fc:
        # grab the last two instructions in the block 
        last_inst = idc.prev_head(block.end_ea)
        penultimate_inst = idc.prev_head(last_inst)
        # If the penultimate instruction is cmp or sub against an immediate value immediately preceding a 'jz' 
        # then it's a decent guess that it's an IOCTL code (if this is a dispatch function)
        if idc.print_insn_mnem(penultimate_inst) in ['cmp', 'sub'] and idc.get_operand_type(penultimate_inst, 1) == 5:
            if idc.print_insn_mnem(last_inst) == 'jz':
                value = get_operand_value(penultimate_inst)
                ioctls.append((penultimate_inst, value))
                ioctl_tracker.add_ioctl(penultimate_inst, value)
    return ioctls
def has_only_one_basic_block(func):
    if func is None:
        return False
    return ida_gdl.FlowChart(func).size == 1
def get_tl_dr_api_table(dispatcher):
    """Retrieves function tables for TL/DR API calls

    :param dispatcher: Dispatcher of the TL/DR calls
    :type dispatcher: int
    :return: Driver API function table and Trustlet API function table
    :rtype: (int, int)
    """

    def get_cmp(func_start, func_end):
        """Retrives the address of the CMP within the dispatching function

        :param func_start: Beginning of the dispatching function
        :type func_start: int
        :param func_end: Ending of the dispatching function
        :type func_end: int
        :return: Address of the CMP within the dispatching function
        :rtype: int
        """

        cmp_addr = -1
        insn_ea = func_start
        insn = ida_ua.insn_t()
        insn_len = 0

        while insn_ea < func_end:
            insn_len = max(1, ida_ua.decode_insn(insn, insn_ea))
            if insn.itype == ida_allins.ARM_cmp and \
                    insn.ops[1].type == ida_ua.o_imm and \
                    insn.ops[1].value == 0x1000:
                cmp_addr = insn_ea
                break
            insn_ea += insn_len
        return cmp_addr

    def find_dr_tl_addr(blocks_info):
        """Retrieves the address of the tables defining the DR/TL API calls

        :param blocks_info: List of tuples defining the current blocks to process. Each tuple is defined with the form (BasicBlock, bool), where bool defines if the Basic Block belongs to a branch dealing with the driver case.
        :type blocks_info: list(tuple(ida_gdl.BasicBlock, bool))
        :return: The address of the DrApi and TlApi tables
        :rtype: (int, int)
        """

        tl_table = -1
        dr_table = -1
        new_blocks = []
        is_dr_branch = False
        is_dr_block = False

        def analyze_block(block):
            """Analyze a basic bloc and return its successors, if it's correspond to a basic bloc treating the Driver case and the address for the DR/TL API table if one is loaded

            :param block: Basic block to analyze
            :type block: ida_gdl.BasicBlock
            :return: Successors Basic Blocks, if it deals with Secure Driver case, and the address of the table loaded if loaded
            :rtype: (Generator, bool, int)
            """

            loaded_value = -1
            is_dr_table = False
            insn = ida_ua.insn_t()
            insn_ea = block.start_ea
            insn_len = 0

            while insn_ea < block.end_ea:
                insn_len = max(1, ida_ua.decode_insn(insn, insn_ea))
                if insn.itype == ida_allins.ARM_sub and \
                        insn.ops[2].type == ida_ua.o_imm and \
                        insn.ops[2].value == 0x1000:
                    is_dr_table = True
                if insn.itype == ida_allins.ARM_ldr and \
                        insn.ops[1].type == ida_ua.o_mem:
                    pool_value = ida_bytes.get_dword(insn.ops[1].addr)
                    value = ida_bytes.get_dword(pool_value)
                    if value > 0x1000:
                        loaded_value = pool_value
                insn_ea += insn_len
            return block.succs(), is_dr_table, loaded_value

        # Walk through every Basic Block of the function using the previously defined function until we find the value of the DR/TL API tables
        while True:
            new_blocks = []

            for block, is_dr_branch in blocks_info:
                successors, is_dr_block, loaded_value = analyze_block(block)
                new_blocks += [(successor, is_dr_block) for successor in successors]
                if loaded_value != -1 and not is_dr_branch:
                    tl_table = loaded_value
                if loaded_value != -1 and is_dr_branch:
                    dr_table = loaded_value

            blocks_info = new_blocks
            if dr_table != -1 and tl_table != -1:
                return dr_table, tl_table

    func = ida_funcs.get_func(dispatcher)
    func_start, func_end = func.start_ea, func.end_ea

    # First, locate the CMP.W R1, 0x1000
    cmp_addr = -1
    cmp_addr = get_cmp(func_start, func_end)
    if cmp_addr == -1:
        print("[!] %#x - Couldn't find tl/dr api check" % dispatcher)

    # Second, get the basic blocks containing the table for drapi and tlapi
    fc = ida_gdl.FlowChart(func)
    for block in fc:
        if block.start_ea <= cmp_addr and block.end_ea >= cmp_addr:
            bb = block
            break

    # Third, locate the drApi and tlApi function tables
    dr_table, tl_table = find_dr_tl_addr([(bb, False)])
    return dr_table, tl_table
Пример #17
0
simicsString = gdbProt.Evalx('SendGDBMonitor("%s");' % command)
print('so stuff: %s' % simicsString)
if ':' in simicsString:
    adders = simicsString.split(':')[1]
    start = adders.split('-')[0]
    try:
        start_hex = int(start, 16)
    except ValueError:
        print('could not get hex from %s' % start)
        exit(1)
else:
    exit(1)

fun_json = json.load(funs_fh)
print('funs_file %s' % funs_file)
for fun in fun_json:
    fun_addr = int(fun) + start_hex
    #print('fun_addr 0x%x' % fun_addr)
    f = idaapi.get_func(fun_addr)
    #print('fun addr 0x%x' % fun_addr)
    #print('fun is %s' % str(f))
    if f is None:
        #print('no function found for 0x%x' % fun_addr)
        continue
    print('doing function found for 0x%x' % fun_addr)
    graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
    for bb in graph:
        ida_graph.set_node_info(fun_addr, bb.id, p,
                                idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
        #print('funx 0x%x set bb_id %d' % (fun_addr, bb.id))
Пример #18
0
def doColor(latest_hits_file, all_hits_file, pre_hits_file):
    with open(latest_hits_file) as funs_fh:
        latest_hits_json = json.load(funs_fh)
    print('loaded blocks from %s, got %d functions' % (latest_hits_file, len(latest_hits_json)))
    with open(all_hits_file) as funs_fh:
        all_hits_json = json.load(funs_fh)
    print('loaded blocks from %s, got %d functions' % (all_hits_file, len(all_hits_json)))
    with open(pre_hits_file) as funs_fh:
        pre_hits_json = json.load(funs_fh)
    print('loaded blocks from %s, got %d functions' % (pre_hits_file, len(pre_hits_json)))
    p = idaapi.node_info_t()
    ''' New hits '''
    p.bg_color =  new_hit_color
    num_new = 0
    edges = OrderedDict()
    for fun in latest_hits_json:
        fun_addr = int(fun)
        f = idaapi.get_func(fun_addr)
        #print('fun addr 0x%x' % fun_addr)
        graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
        ''' get edges leaving all hit blocks '''
        ''' edges[branch_to] = branch_from '''
        ''' retain order of hits in list of branches not taken '''
        for bb_addr in latest_hits_json[fun]:
            ''' get the BB and check its branch-to's '''
            block = getBB(graph, bb_addr)
            if block is not None:
                for s in block.succs():
                    if s.start_ea not in latest_hits_json[fun] and not (fun in pre_hits_json and s.start_ea in pre_hits_json[fun]) and s.start_ea not in edges:
                        #print('added edges[0%x] block 0x%x block.end_ea 0x%x bb_addr was 0x%x ' % (s.start_ea, block.start_ea, block.end_ea, bb_addr))
                        ''' branch from block was not hit ''' 
                        edges[s.start_ea] = block.start_ea
                                          
        for bb in latest_hits_json[fun]:
            block = getBB(graph, bb)
            if block is not None:
                bb_id = block.id
                if fun not in all_hits_json or bb not in all_hits_json[fun]:
                    ''' first time bb has been hit in any data session '''
                    p.bg_color =  new_hit_color
                    ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
                    print('new hit fun 0x%x bb: 0x%x bb_id: %d block.start_ea 0x%x end 0x%x' % (fun_addr, bb, bb_id, block.start_ea, block.end_ea))
                    num_new += 1
                elif bb in all_hits_json[fun]:
                    ''' also hit in earlier data session '''
                    p.bg_color =  old_hit_color
                    ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
                    #print('old hit fun 0x%x bb: 0x%x' % (fun_addr, bb))
                else:
                    print('impossible')
                    exit(1)

    print('Data run generated %d new hits' % num_new)
    print('Unhit edges')

    ''' Not hit on recent data session, but hit previously '''
    p.bg_color =  not_hit_color
    for fun in all_hits_json:
        fun_addr = int(fun)
        f = idaapi.get_func(fun_addr)
        #print('fun addr 0x%x' % fun_addr)
        if f is None:
            print('unable to get function from addr 0x%x' % fun_addr)
            continue
        graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
        for bb in all_hits_json[fun]:
            bb_id = getBBId(graph, bb)
            if bb_id is not None:
                if fun not in latest_hits_json or bb not in latest_hits_json[fun]:
                    ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
                    #print('not hit fun 0x%x bb: 0x%x' % (fun_addr, bb))

    ''' Hit prior to start of any data session, i.e., IO setup '''
    p.bg_color =  pre_hit_color
    for fun in pre_hits_json:
        fun_addr = int(fun)
        f = idaapi.get_func(fun_addr)
        #print('fun addr 0x%x' % fun_addr)
        graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS)
        for bb in pre_hits_json[fun]:
            bb_id = getBBId(graph, bb)
            if bb_id is not None:
                if (fun not in latest_hits_json or bb not in latest_hits_json[fun]) and (fun not in all_hits_json or bb not in all_hits_json[fun]):
                    ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
                    #print('not hit fun 0x%x bb: 0x%x' % (fun_addr, bb))
    return edges
def getBasicBlocks(func):
	blocks = [(v.startEA, v.endEA) for v in ida_gdl.FlowChart(func)]
	return len(blocks)
Пример #20
0
# Step Nr. 5: Let user change offset (optional)
offset = ida_kernwin.ask_long(0, "Add offset (if it's hex prepend a 0x)")

# Step Nr. 6: Retrieve covered blocks
engine = create_engine(database_string)
with engine.connect() as con:
    #blocksDB = con.execute('SELECT Offset FROM covered_blocks WHERE ModuleID = %d' % selected_module)
    blocksDistinctDB = con.execute(
        'SELECT DISTINCT Offset FROM covered_blocks WHERE ModuleID = %d ORDER BY Offset ASC'
        % selected_module[0])
print "Found ? block(s) (%d distinct)" % (blocksDistinctDB.rowcount)

# Step Nr. 7: Color the currently loaded binary
for (bb, ) in blocksDistinctDB:
    absPos = bb + offset
    if not rawModule:
        absPos += ida_nalt.get_imagebase()
    print absPos

    f = ida_funcs.get_func(absPos)
    if f is None:
        continue
    fc = ida_gdl.FlowChart(f)
    # Highlight the complete function
    idc.set_color(absPos, idc.CIC_FUNC, 0xFFF000)
    for block in fc:
        if block.start_ea <= absPos and block.end_ea > absPos:
            #print "Setting colour for %x" % absPos
            for i in Heads(block.start_ea, block.end_ea):
                idc.set_color(i, CIC_ITEM, 0xFFAA00)