Example #1
0
    def __init__(self, ssa, head, cfg_liveness):
        self.cfg_liveness = cfg_liveness
        self.ssa = ssa
        self.head = head

        # Set of created variables
        self.copy_vars = set()
        # Virtual parallel copies

        # On loc_key's Phi node dst -> set((parent, src))
        self.phi_parent_sources = {}
        # On loc_key's Phi node, loc_key -> set(Phi dsts)
        self.phi_destinations = {}
        # Phi's dst -> new var
        self.phi_new_var = {}
        # For a new_var representing dst:
        # new_var -> set(parents of Phi's src in dst = Phi(src,...))
        self.new_var_to_srcs_parents = {}
        # new_var -> set(variables to be coalesced with, named "merge_set")
        self.merge_state = {}

        # Launch the algorithm in several steps
        self.isolate_phi_nodes_block()
        self.init_phis_merge_state()
        self.order_ssa_var_dom()
        self.aggressive_coalesce_block()
        self.insert_parallel_copy()
        self.replace_merge_sets()
        self.remove_assign_eq()
        remove_empty_assignblks(self.ssa.graph)
Example #2
0
def build_graph(verbose=False, simplify=False):
    start_addr = idc.ScreenEA()

    machine = guess_machine(addr=start_addr)
    dis_engine, ira = machine.dis_engine, machine.ira

    if verbose:
        print "Arch", dis_engine

    fname = idc.GetInputFile()
    if verbose:
        print fname

    bs = bin_stream_ida()
    mdis = dis_engine(bs)
    ir_arch = ira(mdis.loc_db)

    # populate symbols with ida names
    for addr, name in idautils.Names():
        if name is None:
            continue
        if (mdis.loc_db.get_offset_location(addr)
                or mdis.loc_db.get_name_location(name)):
            # Symbol alias
            continue
        mdis.loc_db.add_location(name, addr)

    if verbose:
        print "start disasm"
    if verbose:
        print hex(addr)

    asmcfg = mdis.dis_multiblock(start_addr)

    entry_points = set([start_addr])

    if verbose:
        print "generating graph"
        open('asm_flow.dot', 'w').write(asmcfg.dot())

        print "generating IR... %x" % start_addr

    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    if verbose:
        print "IR ok... %x" % start_addr

    for irb in ircfg.blocks.itervalues():
        irs = []
        for assignblk in irb:
            new_assignblk = {
                expr_simp(dst): expr_simp(src)
                for dst, src in assignblk.iteritems()
            }
            irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
        ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs)

    if verbose:
        out = ircfg.dot()
        open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
    title = "Miasm IR graph"

    if simplify:
        dead_simp(ir_arch, ircfg)

        ircfg.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch, ircfg)
            modified |= remove_empty_assignblks(ircfg)
            modified |= merge_blocks(ircfg, entry_points)
        title += " (simplified)"

    graph = GraphMiasmIR(ircfg, title, None)

    graph.Show()
Example #3
0
def build_graph(start_addr,
                type_graph,
                simplify=False,
                dontmodstack=True,
                loadint=False,
                verbose=False):
    machine = guess_machine(addr=start_addr)
    dis_engine, ira = machine.dis_engine, machine.ira

    class IRADelModCallStack(ira):
        def call_effects(self, addr, instr):
            assignblks, extra = super(IRADelModCallStack,
                                      self).call_effects(addr, instr)
            if not dontmodstack:
                return assignblks, extra
            out = []
            for assignblk in assignblks:
                dct = dict(assignblk)
                dct = {
                    dst: src
                    for (dst, src) in dct.iteritems() if dst != self.sp
                }
                out.append(AssignBlock(dct, assignblk.instr))
            return out, extra

    if verbose:
        print "Arch", dis_engine

    fname = idc.GetInputFile()
    if verbose:
        print fname

    bs = bin_stream_ida()
    mdis = dis_engine(bs)
    ir_arch = IRADelModCallStack(mdis.loc_db)

    # populate symbols with ida names
    for addr, name in idautils.Names():
        if name is None:
            continue
        if (mdis.loc_db.get_offset_location(addr)
                or mdis.loc_db.get_name_location(name)):
            # Symbol alias
            continue
        mdis.loc_db.add_location(name, addr)

    if verbose:
        print "start disasm"
    if verbose:
        print hex(start_addr)

    asmcfg = mdis.dis_multiblock(start_addr)
    entry_points = set([mdis.loc_db.get_offset_location(start_addr)])
    if verbose:
        print "generating graph"
        open('asm_flow.dot', 'w').write(asmcfg.dot())
        print "generating IR... %x" % start_addr

    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    if verbose:
        print "IR ok... %x" % start_addr

    for irb in ircfg.blocks.itervalues():
        irs = []
        for assignblk in irb:
            new_assignblk = {
                expr_simp(dst): expr_simp(src)
                for dst, src in assignblk.iteritems()
            }
            irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
        ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs)

    if verbose:
        out = ircfg.dot()
        open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
    title = "Miasm IR graph"

    if simplify:
        dead_simp(ir_arch, ircfg)
        ircfg.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch, ircfg)
            modified |= remove_empty_assignblks(ircfg)
            modified |= merge_blocks(ircfg, entry_points)
        title += " (simplified)"

    if type_graph == TYPE_GRAPH_IR:
        graph = GraphMiasmIR(ircfg, title, None)
        graph.Show()
        return

    head = list(entry_points)[0]

    class IRAOutRegs(ira):
        def get_out_regs(self, block):
            regs_todo = super(IRAOutRegs, self).get_out_regs(block)
            out = {}
            for assignblk in block:
                for dst in assignblk:
                    reg = self.ssa_var.get(dst, None)
                    if reg is None:
                        continue
                    if reg in regs_todo:
                        out[reg] = dst
            return set(out.values())

    # Add dummy dependency to uncover out regs affectation
    for loc in ircfg.leaves():
        irblock = ircfg.blocks.get(loc)
        if irblock is None:
            continue
        regs = {}
        for reg in ir_arch.get_out_regs(irblock):
            regs[reg] = reg
        assignblks = list(irblock)
        new_assiblk = AssignBlock(regs, assignblks[-1].instr)
        assignblks.append(new_assiblk)
        new_irblock = IRBlock(irblock.loc_key, assignblks)
        ircfg.blocks[loc] = new_irblock

    ir_arch = IRAOutRegs(mdis.loc_db)
    ir_arch.ssa_var = {}
    modified = True
    ssa_forbidden_regs = set(
        [ir_arch.pc, ir_arch.IRDst, ir_arch.arch.regs.exception_flags])

    head = list(entry_points)[0]
    heads = set([head])
    all_ssa_vars = {}

    propagate_expr = PropagateExpr()

    ssa = SSADiGraph(ircfg)
    ssa.immutable_ids.update(ssa_forbidden_regs)
    ssa.ssa_variable_to_expr.update(all_ssa_vars)
    ssa.transform(head)
    all_ssa_vars.update(ssa.ssa_variable_to_expr)

    ir_arch.ssa_var.update(ssa.ssa_variable_to_expr)

    if simplify:

        while modified:
            ssa = SSADiGraph(ircfg)
            ssa.immutable_ids.update(ssa_forbidden_regs)
            ssa.ssa_variable_to_expr.update(all_ssa_vars)
            ssa.transform(head)
            all_ssa_vars.update(ssa.ssa_variable_to_expr)

            ir_arch.ssa_var.update(ssa.ssa_variable_to_expr)

            while modified:
                modified = False
                modified |= propagate_expr.propagate(ssa, head)
                modified |= ircfg.simplify(expr_simp)
                simp_modified = True
                while simp_modified:
                    simp_modified = False
                    simp_modified |= dead_simp(ir_arch, ircfg)
                    simp_modified |= remove_empty_assignblks(ircfg)
                    simp_modified |= load_from_int(ircfg, bs,
                                                   is_addr_ro_variable)
                    modified |= simp_modified

    ssa = SSADiGraph(ircfg)
    ssa.immutable_ids.update(ssa_forbidden_regs)
    ssa.ssa_variable_to_expr.update(all_ssa_vars)
    ssa.transform(head)
    all_ssa_vars.update(ssa.ssa_variable_to_expr)

    if type_graph == TYPE_GRAPH_IRSSA:
        graph = GraphMiasmIR(ssa.graph, title, None)
        graph.Show()
        return

    if type_graph == TYPE_GRAPH_IRSSAUNSSA:

        cfg_liveness = DiGraphLivenessSSA(ssa.graph)
        cfg_liveness.init_var_info(ir_arch)
        cfg_liveness.compute_liveness()

        UnSSADiGraph(ssa, head, cfg_liveness)
        if simplify:
            modified = True
            while modified:
                modified = False
                modified |= ssa.graph.simplify(expr_simp)
                simp_modified = True
                while simp_modified:
                    simp_modified = False
                    simp_modified |= dead_simp(ir_arch, ssa.graph)
                    simp_modified |= remove_empty_assignblks(ssa.graph)
                    simp_modified |= merge_blocks(ssa.graph, heads)
                    modified |= simp_modified
        graph = GraphMiasmIR(ssa.graph, title, None)
        graph.Show()
Example #4
0
    if args.defuse:
        reachings = ReachingDefinitions(ircfg_a)
        open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot())

    out = ircfg.dot()
    open('graph_irflow_raw.dot', 'w').write(out)
    out = ircfg_a.dot()
    open('graph_irflow.dot', 'w').write(out)

    if args.simplify > 1:

        ircfg_a.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch_a, ircfg_a)
            modified |= remove_empty_assignblks(ircfg_a)
            modified |= merge_blocks(ircfg_a, entry_points)

        open('graph_irflow_reduced.dot', 'w').write(ircfg_a.dot())

    if args.ssa:
        if len(entry_points) != 1:
            raise RuntimeError("Your graph should have only one head")
        head = list(entry_points)[0]
        ssa = SSADiGraph(ircfg_a)
        ssa.transform(head)

        open("ssa.dot", "wb").write(ssa.graph.dot())
Example #5
0
def build_graph(verbose=False, simplify=False, ssa=False, ssa_simplify=False):
    start_addr = idc.ScreenEA()

    machine = guess_machine(addr=start_addr)
    dis_engine, ira = machine.dis_engine, machine.ira

    if verbose:
        print "Arch", dis_engine

    fname = idc.GetInputFile()
    if verbose:
        print fname

    bs = bin_stream_ida()
    mdis = dis_engine(bs)
    ir_arch = ira(mdis.loc_db)

    # populate symbols with ida names
    for addr, name in idautils.Names():
        if name is None:
            continue
        if (mdis.loc_db.get_offset_location(addr)
                or mdis.loc_db.get_name_location(name)):
            # Symbol alias
            continue
        mdis.loc_db.add_location(name, addr)

    if verbose:
        print "start disasm"
    if verbose:
        print hex(addr)

    asmcfg = mdis.dis_multiblock(start_addr)

    entry_points = set([mdis.loc_db.get_offset_location(start_addr)])
    if verbose:
        print "generating graph"
        open('asm_flow.dot', 'w').write(asmcfg.dot())

        print "generating IR... %x" % start_addr

    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    if verbose:
        print "IR ok... %x" % start_addr

    for irb in ircfg.blocks.itervalues():
        irs = []
        for assignblk in irb:
            new_assignblk = {
                expr_simp(dst): expr_simp(src)
                for dst, src in assignblk.iteritems()
            }
            irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
        ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs)

    if verbose:
        out = ircfg.dot()
        open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
    title = "Miasm IR graph"

    if simplify:
        dead_simp(ir_arch, ircfg)

        ircfg.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch, ircfg)
            modified |= remove_empty_assignblks(ircfg)
            modified |= merge_blocks(ircfg, entry_points)
        title += " (simplified)"

    graph = GraphMiasmIR(ircfg, title, None)

    if ssa:
        if len(entry_points) != 1:
            raise RuntimeError("Your graph should have only one head")
        head = list(entry_points)[0]
        ssa = SSADiGraph(ircfg)
        ssa.transform(head)
        title += " (SSA)"
        graph = GraphMiasmIR(ssa.graph, title, None)

    if ssa_simplify:

        class IRAOutRegs(ira):
            def get_out_regs(self, block):
                regs_todo = super(self.__class__, self).get_out_regs(block)
                out = {}
                for assignblk in block:
                    for dst in assignblk:
                        reg = self.ssa_var.get(dst, None)
                        if reg is None:
                            continue
                        if reg in regs_todo:
                            out[reg] = dst
                return set(out.values())

        # Add dummy dependency to uncover out regs affectation
        for loc in ircfg.leaves():
            irblock = ircfg.blocks.get(loc)
            if irblock is None:
                continue
            regs = {}
            for reg in ir_arch.get_out_regs(irblock):
                regs[reg] = reg
            assignblks = list(irblock)
            new_assiblk = AssignBlock(regs, assignblks[-1].instr)
            assignblks.append(new_assiblk)
            new_irblock = IRBlock(irblock.loc_key, assignblks)
            ircfg.blocks[loc] = new_irblock

        ir_arch = IRAOutRegs(mdis.loc_db)

        def is_addr_ro_variable(bs, addr, size):
            """
            Return True if address at @addr is a read-only variable.
            WARNING: Quick & Dirty

            @addr: integer representing the address of the variable
            @size: size in bits

            """
            try:
                _ = bs.getbytes(addr, size / 8)
            except IOError:
                return False
            return True

        ir_arch.ssa_var = {}
        index = 0
        modified = True
        ssa_forbidden_regs = set(
            [ir_arch.pc, ir_arch.IRDst, ir_arch.arch.regs.exception_flags])

        head = list(entry_points)[0]
        heads = set([head])
        all_ssa_vars = set()

        propagate_expr = PropagateExpr()

        while modified:
            ssa = SSADiGraph(ircfg)
            ssa.immutable_ids.update(ssa_forbidden_regs)

            ssa.transform(head)

            all_ssa_vars.update(ssa._ssa_variable_to_expr)

            ssa_regs = [reg for reg in ssa.expressions if reg.is_id()]
            ssa_forbidden_regs.update(ssa_regs)

            ir_arch.ssa_var.update(ssa._ssa_variable_to_expr)

            while modified:
                index += 1
                modified = False
                modified |= propagate_expr.propagate(ssa, head)
                modified |= ircfg.simplify(expr_simp)
                simp_modified = True
                while simp_modified:
                    index += 1
                    simp_modified = False
                    simp_modified |= dead_simp(ir_arch, ircfg)
                    index += 1
                    simp_modified |= remove_empty_assignblks(ircfg)
                    simp_modified |= merge_blocks(ircfg, heads)
                    simp_modified |= load_from_int(ircfg, bs,
                                                   is_addr_ro_variable)
                    modified |= simp_modified
                    index += 1

        merge_blocks(ircfg, heads)
        ssa = SSADiGraph(ircfg)
        ssa.immutable_ids.update(ssa_forbidden_regs)
        ssa.transform(head)
        all_ssa_vars.update(ssa._ssa_variable_to_expr)
        ssa._ssa_variable_to_expr = all_ssa_vars
        dead_simp(ir_arch, ssa.graph)

        title += " (SSA Simplified)"
        graph = GraphMiasmIR(ssa.graph, title, None)

    graph.Show()
Example #6
0
def build_graph(verbose=False, simplify=False, ssa=False, ssa_simplify=False):
    start_addr = idc.ScreenEA()

    machine = guess_machine(addr=start_addr)
    dis_engine, ira = machine.dis_engine, machine.ira


    if verbose:
        print "Arch", dis_engine

    fname = idc.GetInputFile()
    if verbose:
        print fname

    bs = bin_stream_ida()
    mdis = dis_engine(bs)
    ir_arch = ira(mdis.loc_db)

    # populate symbols with ida names
    for addr, name in idautils.Names():
        if name is None:
            continue
        if (mdis.loc_db.get_offset_location(addr) or
            mdis.loc_db.get_name_location(name)):
            # Symbol alias
            continue
        mdis.loc_db.add_location(name, addr)

    if verbose:
        print "start disasm"
    if verbose:
        print hex(addr)

    asmcfg = mdis.dis_multiblock(start_addr)

    entry_points = set([mdis.loc_db.get_offset_location(start_addr)])
    if verbose:
        print "generating graph"
        open('asm_flow.dot', 'w').write(asmcfg.dot())

        print "generating IR... %x" % start_addr

    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    if verbose:
        print "IR ok... %x" % start_addr

    for irb in ircfg.blocks.itervalues():
        irs = []
        for assignblk in irb:
            new_assignblk = {
                expr_simp(dst): expr_simp(src)
                for dst, src in assignblk.iteritems()
            }
            irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
        ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs)

    if verbose:
        out = ircfg.dot()
        open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
    title = "Miasm IR graph"

    if simplify:
        dead_simp(ir_arch, ircfg)

        ircfg.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch, ircfg)
            modified |= remove_empty_assignblks(ircfg)
            modified |= merge_blocks(ircfg, entry_points)
        title += " (simplified)"

    graph = GraphMiasmIR(ircfg, title, None)

    if ssa:
        if len(entry_points) != 1:
            raise RuntimeError("Your graph should have only one head")
        head = list(entry_points)[0]
        ssa = SSADiGraph(ircfg)
        ssa.transform(head)
        title += " (SSA)"
        graph = GraphMiasmIR(ssa.graph, title, None)

    if ssa_simplify:
        class IRAOutRegs(ira):
            def get_out_regs(self, block):
                regs_todo = super(self.__class__, self).get_out_regs(block)
                out = {}
                for assignblk in block:
                    for dst in assignblk:
                        reg = self.ssa_var.get(dst, None)
                        if reg is None:
                            continue
                        if reg in regs_todo:
                            out[reg] = dst
                return set(out.values())

        # Add dummy dependecy to uncover out regs affectation
        for loc in ircfg.leaves():
            irblock = ircfg.blocks.get(loc)
            if irblock is None:
                continue
            regs = {}
            for reg in ir_arch.get_out_regs(irblock):
                regs[reg] = reg
            assignblks = list(irblock)
            new_assiblk = AssignBlock(regs, assignblks[-1].instr)
            assignblks.append(new_assiblk)
            new_irblock = IRBlock(irblock.loc_key, assignblks)
            ircfg.blocks[loc] = new_irblock



        ir_arch = IRAOutRegs(mdis.loc_db)

        def is_addr_ro_variable(bs, addr, size):
            """
            Return True if address at @addr is a read-only variable.
            WARNING: Quick & Dirty

            @addr: integer representing the address of the variable
            @size: size in bits

            """
            try:
                _ = bs.getbytes(addr, size/8)
            except IOError:
                return False
            return True


        ir_arch.ssa_var = {}
        index = 0
        modified = True
        ssa_forbidden_regs = set([
            ir_arch.pc,
            ir_arch.IRDst,
            ir_arch.arch.regs.exception_flags
        ])

        head = list(entry_points)[0]
        heads = set([head])
        all_ssa_vars = set()

        propagate_expr = PropagateExpr()


        while modified:
            ssa = SSADiGraph(ircfg)
            ssa.immutable_ids.update(ssa_forbidden_regs)

            ssa.transform(head)

            all_ssa_vars.update(ssa._ssa_variable_to_expr)

            ssa_regs = [reg for reg in ssa.expressions if reg.is_id()]
            ssa_forbidden_regs.update(ssa_regs)


            ir_arch.ssa_var.update(ssa._ssa_variable_to_expr)

            while modified:
                index += 1
                modified = False
                modified |= propagate_expr.propagate(ssa, head)
                modified |= ircfg.simplify(expr_simp)
                simp_modified = True
                while simp_modified:
                    index += 1
                    simp_modified = False
                    simp_modified |= dead_simp(ir_arch, ircfg)
                    index += 1
                    simp_modified |= remove_empty_assignblks(ircfg)
                    simp_modified |= merge_blocks(ircfg, heads)
                    simp_modified |= load_from_int(ircfg, bs, is_addr_ro_variable)
                    modified |= simp_modified
                    index += 1


        merge_blocks(ircfg, heads)
        ssa = SSADiGraph(ircfg)
        ssa.immutable_ids.update(ssa_forbidden_regs)
        ssa.transform(head)
        all_ssa_vars.update(ssa._ssa_variable_to_expr)
        ssa._ssa_variable_to_expr = all_ssa_vars
        dead_simp(ir_arch, ssa.graph)

        title += " (SSA Simplified)"
        graph = GraphMiasmIR(ssa.graph, title, None)


    graph.Show()
Example #7
0
        reachings = ReachingDefinitions(ircfg_a)
        open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot())

    out = ircfg.dot()
    open('graph_irflow_raw.dot', 'w').write(out)
    out = ircfg_a.dot()
    open('graph_irflow.dot', 'w').write(out)

    if args.simplify > 1:

        ircfg_a.simplify(expr_simp)
        modified = True
        while modified:
            modified = False
            modified |= dead_simp(ir_arch_a, ircfg_a)
            modified |= remove_empty_assignblks(ircfg_a)
            modified |= merge_blocks(ircfg_a, entry_points)

        open('graph_irflow_reduced.dot', 'w').write(ircfg_a.dot())

    if args.ssa and not args.propagexpr:
        if len(entry_points) != 1:
            raise RuntimeError("Your graph should have only one head")
        head = list(entry_points)[0]
        ssa = SSADiGraph(ircfg_a)
        ssa.transform(head)

        open("ssa.dot", "wb").write(ssa.graph.dot())


Example #8
0
args = parser.parse_args()


machine = Machine("x86_32")

cont = Container.from_stream(open(args.filename))
ira, dis_engine = machine.ira, machine.dis_engine
mdis = dis_engine(cont.bin_stream)
ir_arch = ira(mdis.loc_db)
addr = int(args.address, 0)

asmcfg = mdis.dis_multiblock(addr)
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)
entry_points = set([mdis.loc_db.get_offset_location(addr)])

init_infos = ir_arch.arch.regs.regs_init
cst_propag_link = propagate_cst_expr(ir_arch, ircfg, addr, init_infos)

if args.simplify:
    ircfg.simplify(expr_simp)
    modified = True
    while modified:
        modified = False
        modified |= dead_simp(ir_arch, ircfg)
        modified |= remove_empty_assignblks(ircfg)
        modified |= merge_blocks(ircfg, entry_points)


open("%s.propag.dot" % args.filename, 'w').write(ircfg.dot())