Example #1
0
def enumerate_basicblocks_edges(instructions):
    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    edges = list()
    xrefs = enumerate_xref(instructions)
    # create the first block
    new_block = True

    for inst in instructions:
        if new_block:
            block = BasicBlock(start_offset=inst.offset,
                               start_instr=inst,
                               name='block_%x' % inst.offset)
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # next instruction in xrefs list
        if (inst.offset_end + 1) in xrefs:
            # absolute JUMP
            if inst.is_branch_unconditional:
                edges.append(
                    Edge(block.name, 'block_%x' % xref_of_instr(inst),
                         EDGE_UNCONDITIONAL))
            # conditionnal JUMPI / JUMPIF / ...
            elif inst.is_branch_conditional:
                edges.append(
                    Edge(block.name, 'block_%x' % xref_of_instr(inst),
                         EDGE_CONDITIONAL_TRUE))
                edges.append(
                    Edge(block.name, 'block_%x' % (inst.offset_end + 1),
                         EDGE_CONDITIONAL_FALSE))
            # Halt instruction : RETURN, STOP, RET, ...
            elif inst.is_halt:
                pass
            # just falls to the next instruction
            else:
                edges.append(
                    Edge(block.name, 'block_%x' % (inst.offset_end + 1),
                         EDGE_FALLTHROUGH))

            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True

    # add the last block
    basicblocks.append(block)
    edges = list(set(edges))

    return (basicblocks, edges)
Example #2
0
def enumerate_basicblocks_statically(instructions):

    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    xrefs = enumerate_xref(instructions)
    # create the first block
    new_block = True

    for inst in instructions:
        if new_block:
            block = BasicBlock(start_offset=inst.offset,
                               start_instr=inst,
                               name='block_%x' % inst.offset)
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # next instruction in list_ref
        if (inst.offset_end + 1) in xrefs:
            # absolute JUMP
            if inst.is_branch_unconditional:
                block.type = BASICBLOCK_UNCONDITIONAL
                logging.debug("unconditional %x : %s", inst.offset, inst.name)
            # conditionnal JUMPI / JUMPIF / ...
            elif inst.is_branch_conditional:
                block.type = BASICBLOCK_CONDITIONAL
                logging.debug("conditional %x : %s", inst.offset, inst.name)
            # Halt instruction : RETURN, STOP, RET, ...
            elif inst.is_halt:  # and inst != func.instructions[-1]:
                block.type = BASICBLOCK_TERMINAL
                logging.debug("terminal %x : %s", inst.offset, inst.name)
            # just falls to the next instruction
            else:
                block.type = BASICBLOCK_FALLTHROUGH
                logging.debug("fallthrough %x : %s", inst.offset, inst.name)

            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True

    # add the last block
    basicblocks.append(block)
    basicblocks = list(set(basicblocks))

    return basicblocks
Example #3
0
def enumerate_basicblocks_statically(instructions):
    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    index = 0

    # create the first block
    new_block = False
    end_block = False
    block = BasicBlock(instructions[0].offset,
                       instructions[0],
                       name='block_%x' % instructions[0].offset)

    for inst in instructions:
        if new_block:
            block = BasicBlock(inst.offset,
                               inst,
                               name='block_%x' % inst.offset)
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # absolute JUMP
        if inst.is_branch_unconditional:
            new_block = True

        # conditionnal JUMPI
        elif inst.is_branch_conditional:
            new_block = True

        # Halt instruction : RETURN, STOP, ...
        elif inst.is_halt:  # and inst != instructions[-1]:
            new_block = True

        # just falls to the next instruction
        elif inst != instructions[-1] and \
                instructions[index + 1].name == 'JUMPDEST':
            new_block = True

        # last instruction of the entire bytecode
        elif inst == instructions[-1]:
            end_block = True

        if new_block or end_block:
            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True
            end_block = False

        index += 1

    return basicblocks
Example #4
0
def enumerate_basicblocks_statically(instructions):
    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    index = 0

    # create the first block
    new_block = False
    block = BasicBlock(instructions[0].offset,
                       instructions[0],
                       name='block_%x' % instructions[0].offset)

    for inst in instructions:
        if new_block:
            block = BasicBlock(inst.offset,
                               inst,
                               name='block_%x' % inst.offset)
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # absolute JUMP
        if inst.is_branch_unconditional:
            block.type = BASICBLOCK_UNCONDITIONAL
            logging.debug("unconditional %x : %s", inst.offset, inst.name)

        # conditionnal JUMPI
        elif inst.is_branch_conditional:
            block.type = BASICBLOCK_CONDITIONAL
            logging.debug("conditional %x : %s", inst.offset, inst.name)

        # Halt instruction : RETURN, STOP, ...
        elif inst.is_halt:  # and inst != instructions[-1]:
            block.type = BASICBLOCK_TERMINAL
            logging.debug("terminal %x : %s", inst.offset, inst.name)

        # just falls to the next instruction
        elif inst != instructions[-1] and \
                instructions[index + 1].name == 'JUMPDEST':
            block.type = BASICBLOCK_FALLTHROUGH
            logging.debug("fallthrough %x : %s", inst.offset, inst.name)

        # last instruction of the entire bytecode
        elif inst == instructions[-1]:
            block.type = BASICBLOCK_TERMINAL

        if block.type != BASICBLOCK_DEFAULT:
            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True

        index += 1

    return basicblocks
Example #5
0
def enum_blocks_edges(function_id, instructions):

    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    edges = list()

    branches = []
    xrefs = []

    intent = 0
    blocks_tmp = []
    blocks_list = []
    # remove last instruction that is 'end' for the funtion
    tt = instructions[:-1]
    for index, inst in enumerate(tt):

        if inst.is_block_terminator:
            start, name = blocks_tmp.pop()
            blocks_list.append((intent, start, inst.offset_end, name))
            intent -= 1
        if inst.is_block_starter:  # in ['block', 'loop']:
            blocks_tmp.append((inst.offset, inst.name))
            intent += 1
        if inst.is_branch:
            branches.append((intent, inst))

    blocks_list = sorted(blocks_list, key=lambda tup: tup[1])

    for depth, inst in branches:
        d2 = int(inst.operand_interpretation.split(' ')[1])
        rep = next(((i, s, e, n) for i, s, e, n in blocks_list if (i == (depth - d2) and s < inst.offset and e > inst.offset_end)), None)
        if rep:
            i, start, end, name = rep
            if name == 'loop':
                value = start  # else name == 'block'
            elif name == 'block':
                value = end
            else:
                value = None
            inst.xref = value
            xrefs.append(value)

    # remove "block" instruction - not usefull graphicaly
    # instructions = [x for x in instructions if x.name not in ['block', 'loop']]

    # enumerate blocks

    new_block = True

    for index, inst in enumerate(instructions):

        # creation of a block
        if new_block:
            block = BasicBlock(inst.offset,
                               inst,
                               name=format_bb_name(function_id, inst.offset))
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # next instruction is a jump target
        if index < (len(instructions) - 1) and \
           instructions[index + 1].offset in xrefs:
            new_block = True
        # absolute jump - br
        elif inst.is_branch_unconditional:
            new_block = True
        # conditionnal jump - br_if
        elif inst.is_branch_conditional:
            new_block = True
        # end of a block
        elif index < (len(instructions) - 1) and \
                inst.name in ['end']:  # is_block_terminator
            new_block = True
        elif index < (len(instructions) - 1) and \
                instructions[index + 1].name == 'else':  # is_block_terminator
            new_block = True
        # start of a block
        elif index < (len(instructions) - 1) and \
                instructions[index + 1].is_block_starter:
            new_block = True
        # last instruction of the bytecode
        elif inst.offset == instructions[-1].offset:
            new_block = True

        if new_block:
            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True

    # TODO: detect and remove end instruction that end loop

    # enumerate edges
    for index, block in enumerate(basicblocks):
        # get the last instruction
        inst = block.end_instr

        # unconditional jump - br
        if inst.is_branch_unconditional:
            edges.append(Edge(block.name, format_bb_name(function_id, inst.xref), EDGE_UNCONDITIONAL))
        # conditionnal jump - br_if
        elif inst.is_branch_conditional:
            if inst.name == 'if':
                edges.append(Edge(block.name, format_bb_name(function_id, inst.offset_end + 1), EDGE_CONDITIONAL_TRUE))
                # if 'else' in [i.name for i in basicblocks[index + 1].instructions]:
                #    edges.append(Edge(block.name, format_bb_name(function_id, basicblocks[index + 2].start_instr.offset), EDGE_CONDITIONAL_FALSE))
                edges.append(Edge(block.name, format_bb_name(function_id, basicblocks[index + 2].start_instr.offset), EDGE_CONDITIONAL_FALSE)) 
            else:
                edges.append(Edge(block.name, format_bb_name(function_id, inst.xref), EDGE_CONDITIONAL_TRUE))
                edges.append(Edge(block.name, format_bb_name(function_id, inst.offset_end + 1), EDGE_CONDITIONAL_FALSE))
        elif inst.offset != instructions[-1].offset:
            # EDGE_FALLTHROUGH
            edges.append(Edge(block.name, format_bb_name(function_id, inst.offset_end + 1), EDGE_FALLTHROUGH))

    # prevent duplicate edges
    edges = list(set(edges))
    return basicblocks, edges
Example #6
0
def enumerate_basicblocks_edges(function_id, instructions):
    """
    Return a list of basicblock after
    statically parsing given instructions
    """

    basicblocks = list()
    edges = list()
    labels = []

    intent = 0
    # find label first
    for index, inst in enumerate(instructions):
        if inst.is_block_starter:
            if inst.name in ['block', 'loop']:
                intent += 1
        elif inst.name in ['end']:
            if intent > 0:
                intent -= 1
                #tmp_labels.append({'intent': intent,
                #                   'offset': inst.offset_end})
                labels.append(inst.offset_end)
    # print(function_id)
    # print(labels)
    '''
    #e = [{'intent': 0, 'offset': 15}, {'intent': 1, 'offset': 17}, {'intent': 0, 'offset': 56}]
    tmp_list = []
    for index, x in enumerate(tmp_labels):
        if x.get('intent') == 0:
            labels += tmp_list[::-1]
            tmp_list = []
        tmp_list.append(x.get('offset'))
    labels += tmp_list[::-1]
    print(labels)
    '''

    # remove "block" instruction - not usefull graphicaly
    instructions = [x for x in instructions if x.name not in ['block', 'loop']]
    # create the first block
    new_block = False
    end_block = False
    block = BasicBlock(instructions[0].offset,
                       instructions[0],
                       name=format_bb_name(function_id,
                                           instructions[0].offset))

    for index, inst in enumerate(instructions):
        if new_block:
            block = BasicBlock(inst.offset,
                               inst,
                               name=format_bb_name(function_id, inst.offset))
            new_block = False

        # add current instruction to the basicblock
        block.instructions.append(inst)

        # absolute jump - br
        # br is *always* followed by end instruction
        if inst.is_branch_unconditional:
            end_block = True
            jump_offset = int(inst.operand_interpretation.split(' ')[1])
            if instructions[index + 1].name == 'end':
                end_block = False
            edges.append(
                Edge(block.name,
                     format_bb_name(function_id, labels[jump_offset] + 1),
                     EDGE_UNCONDITIONAL))

        # conditionnal jump - br_if
        elif inst.is_branch_conditional:
            end_block = True
            jump_offset = int(inst.operand_interpretation.split(' ')[1])
            edges.append(
                Edge(block.name,
                     format_bb_name(function_id, labels[jump_offset] + 1),
                     EDGE_CONDITIONAL_TRUE))
            edges.append(
                Edge(
                    block.name,
                    format_bb_name(function_id,
                                   instructions[index + 1].offset),
                    EDGE_CONDITIONAL_FALSE))

        # end of a block
        elif index < (len(instructions) - 1) and \
                inst.name in ['end', 'else']:  # is_block_terminator
            end_block = True
            if not instructions[index - 1].is_branch_unconditional:
                edges.append(
                    Edge(
                        block.name,
                        format_bb_name(function_id,
                                       instructions[index + 1].offset),
                        EDGE_FALLTHROUGH))

        # start of a block
        elif index < (len(instructions) - 1) and \
                instructions[index + 1].is_block_starter:
            end_block = True
            edges.append(
                Edge(
                    block.name,
                    format_bb_name(function_id,
                                   instructions[index + 1].offset),
                    EDGE_FALLTHROUGH))

        # last instruction of the entire bytecode
        elif inst == instructions[-1]:
            end_block = True

        if end_block:
            block.end_offset = inst.offset_end
            block.end_instr = inst
            basicblocks.append(block)
            new_block = True
            end_block = False

    edges = list(set(edges))
    return basicblocks, edges