示例#1
0
 def call_effects(self, addr, instr):
     assignblks, extra = super(IRADelModCallStack,
                               self).call_effects(addr, instr)
     if use_ida_stack:
         stk_before = idc.get_spd(instr.offset)
         stk_after = idc.get_spd(instr.offset + instr.l)
         stk_diff = stk_after - stk_before
         print(hex(stk_diff))
         call_assignblk = AssignBlock([
             ExprAssign(self.ret_reg, ExprOp('call_func_ret', addr)),
             ExprAssign(self.sp,
                        self.sp + ExprInt(stk_diff, self.sp.size))
         ], instr)
         return [call_assignblk], []
     else:
         if not dontmodstack:
             return assignblks, extra
         out = []
         for assignblk in assignblks:
             dct = dict(assignblk)
             dct = {
                 dst: src
                 for (dst, src) in viewitems(dct) if dst != self.sp
             }
             out.append(AssignBlock(dct, assignblk.instr))
     return out, extra
示例#2
0
    def block2assignblks(self, block):
        irblocks_list = super(mipsCGen, self).block2assignblks(block)
        for irblocks in irblocks_list:
            for blk_idx, irblock in enumerate(irblocks):
                has_breakflow = any(assignblock.instr.breakflow()
                                    for assignblock in irblock)
                if not has_breakflow:
                    continue

                irs = []
                for assignblock in irblock:
                    if self.ir_arch.pc not in assignblock:
                        irs.append(AssignBlock(assignments, assignblock.instr))
                        continue
                    assignments = dict(assignblock)
                    # Add internal branch destination
                    assignments[self.delay_slot_dst] = assignblock[
                        self.ir_arch.pc]
                    assignments[self.delay_slot_set] = m2_expr.ExprInt(1, 32)
                    # Replace IRDst with next instruction
                    dst_loc_key = self.ir_arch.get_next_instr(
                        assignblock.instr)
                    assignments[self.ir_arch.IRDst] = m2_expr.ExprLoc(
                        dst_loc_key, 32)
                    irs.append(AssignBlock(assignments, assignblock.instr))
                irblocks[blk_idx] = IRBlock(irblock.loc_key, irs)

        return irblocks_list
示例#3
0
文件: sem.py 项目: toyszyg/miasm
def udiv(ir, instr, a, b, c=None):
    e = []
    if c is None:
        b, c = a, b

    loc_div = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_except = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size)

    e.append(ExprAssign(ir.IRDst, ExprCond(c, loc_div, loc_except)))

    do_except = []
    do_except.append(
        ExprAssign(exception_flags,
                   ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size)))
    do_except.append(ExprAssign(ir.IRDst, loc_next))
    blk_except = IRBlock(loc_except.loc_key, [AssignBlock(do_except, instr)])

    r = ExprOp("udiv", b, c)
    do_div = []
    do_div.append(ExprAssign(a, r))
    dst = get_dst(a)
    if dst is not None:
        do_div.append(ExprAssign(ir.IRDst, r))

    do_div.append(ExprAssign(ir.IRDst, loc_next))
    blk_div = IRBlock(loc_div.loc_key, [AssignBlock(do_div, instr)])

    return e, [blk_div, blk_except]
示例#4
0
def gen_irblock(label, exprs_list):
    irs = []
    for exprs in exprs_list:
        if isinstance(exprs, AssignBlock):
            irs.append(exprs)
        else:
            irs.append(AssignBlock(exprs))

    irs.append(AssignBlock({IRDst: dummy}))
    irbl = IRBlock(label, irs)
    return irbl
示例#5
0
    def process(self, pending, merging_val, reached_funcs):
        if len(self.flat_loops) == 0:
            # add all reached functions
            for func_addr, possible_merge_vars, loc_key in self.possible_merge_funcs:
                reached_funcs.add(func_addr)
                for expr, val in possible_merge_vars:
                    pending.setdefault(func_addr,
                                       {}).setdefault(expr, set()).add(val)
            return None

        assert len(self.asmcfg.heads()) == 1

        # add merging var to the ircfg
        if self.pad:
            initial_block_bak = self.ircfg.blocks[LocKey(0)]
            if merging_val and self.merging_var:
                asgn_blk = AssignBlock(
                    [ExprAssign(self.merging_var, merging_val)])
            else:
                asgn_blk = AssignBlock()
            assignblks = tuple(
                [asgn_blk, *self.ircfg.blocks[LocKey(0)].assignblks])
            self.ircfg.blocks[LocKey(0)] = IRBlock(LocKey(0), assignblks)

        head = self.asmcfg.heads()[0]
        head_block = self.asmcfg.loc_key_to_block(head)
        new_head = self._deobfuscate_cff_loops(
            head_block, self.asmcfg.machine.mn.regs.regs_init)

        if self.pad:
            self.ircfg.blocks[LocKey(0)] = initial_block_bak
            if merging_val and self.merging_var:
                mode = self.asmcfg.mode
                fix_dct = {
                    self.asmcfg.machine.mn.regs.regs_init[self.ir_arch.sp]:
                    self.ir_arch.sp
                }
                mov = instruction_x86(
                    "MOV", mode,
                    [self.merging_var.replace_expr(fix_dct), merging_val])
                mov.additional_info = additional_info()
                mov.additional_info.g1.value = 0
                self.out_asmcfg.loc_key_to_block(LocKey(0)).lines.insert(
                    0, mov)

        loc_keys = self.relevant_nodes
        for func_addr, possible_merge_vars, loc_key in self.possible_merge_funcs:
            if loc_key in loc_keys:
                reached_funcs.add(func_addr)
                for expr, val in possible_merge_vars:
                    pending.setdefault(func_addr,
                                       {}).setdefault(expr, set()).add(val)

        return new_head
示例#6
0
文件: sem.py 项目: toyszyg/miasm
def add_condition_expr(ir, instr, cond, instr_ir, extra_ir):
    if cond == COND_AL:
        return instr_ir, extra_ir
    if not cond in tab_cond:
        raise ValueError('unknown condition %r' % cond)
    cond = tab_cond[cond]

    loc_next = ir.get_next_loc_key(instr)
    loc_next_expr = ExprLoc(loc_next, 32)
    loc_do = ir.loc_db.add_location()
    loc_do_expr = ExprLoc(loc_do, 32)

    dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr)
    assert (isinstance(instr_ir, list))

    has_irdst = False
    for e in instr_ir:
        if e.dst == ir.IRDst:
            has_irdst = True
            break
    if not has_irdst:
        instr_ir.append(ExprAssign(ir.IRDst, loc_next_expr))
    e_do = IRBlock(loc_do, [AssignBlock(instr_ir, instr)])
    e = [ExprAssign(ir.IRDst, dst_cond)]
    return e, [e_do] + extra_ir
示例#7
0
    def _recog_init(self, merging_var_candidates):
        # recognize cff loops and initiate deobfuscation
        self._merging_var_candidates = merging_var_candidates
        self.ircfg = self.ir_arch.new_ircfg_from_asmcfg(self.asmcfg)
        self.asmcfg.rebuild_edges()

        # TODO put constant propagation here when fixed in Miasm
        # simp = IRCFGSimplifierSSA(self.ir_arch)
        # from datetime import datetime
        # startTime = datetime.now()
        # ssa = simp.ircfg_to_ssa(self.ircfg, LocKey(0))
        # simp.do_propagate_expressions(ssa, LocKey(0))
        # self.ircfg = simp.ssa_to_unssa(ssa, LocKey(0))
        # print(datetime.now() - startTime)

        # init_infos = self.ir_arch.arch.regs.regs_init
        # cst_propag_link = cst_prop.propagate_cst_expr(self.ir_arch, self.ircfg, self.asmcfg.func_addr, init_infos)

        # raise Exception("test")

        self._normalize_ircfg(self.conn)
        irb_bak = None
        if merging_var_candidates:
            self.pad = True
            new_line = AssignBlock([ExprAssign(k, k) for k in merging_var_candidates])
            irb_bak = self.ircfg.blocks[LocKey(0)]
            new_irb = IRBlock(LocKey(0), tuple([new_line, *self.ircfg.blocks[LocKey(0)].assignblks]))
            self.ircfg.blocks[LocKey(0)] = new_irb

        self.analyses = Analyses(self.ircfg, self.asmcfg)
        return irb_bak
示例#8
0
def sanitize_graph_head(ircfg, head):
    """
    In multiple algorithm, the @head of the ircfg may not have predecessors.
    The function transform the @ircfg in order to ensure this property
    @ircfg: IRCFG instance
    @head: the location of the graph's head
    """

    if not ircfg.predecessors(head):
        return
    original_edges = ircfg.predecessors(head)
    sub_head = ircfg.loc_db.add_location()

    # Duplicate graph, replacing references to head by sub_head
    replaced_expr = {
        ExprLoc(head, ircfg.IRDst.size): ExprLoc(sub_head, ircfg.IRDst.size)
    }
    ircfg.simplify(lambda expr: expr.replace_expr(replaced_expr))
    # Duplicate head block
    ircfg.add_irblock(IRBlock(ircfg.loc_db, sub_head,
                              list(ircfg.blocks[head])))

    # Remove original head block
    ircfg.del_node(head)

    for src in original_edges:
        ircfg.add_edge(src, sub_head)

    # Create new head, jumping to sub_head
    assignblk = AssignBlock({ircfg.IRDst: ExprLoc(sub_head, ircfg.IRDst.size)})
    new_irblock = IRBlock(ircfg.loc_db, head, [assignblk])
    ircfg.add_irblock(new_irblock)
示例#9
0
    def eval_updt_irblock(self, irb, step=False):
        """
        Symbolic execution of the @irb on the current state
        @irb: IRBlock instance
        @step: display intermediate steps
        """
        assignblks = []
        for index, assignblk in enumerate(irb):
            new_assignblk = {}
            links = {}
            for dst, src in viewitems(assignblk):
                src = self.propag_expr_cst(src)
                if dst.is_mem():
                    ptr = dst.ptr
                    ptr = self.propag_expr_cst(ptr)
                    dst = ExprMem(ptr, dst.size)
                new_assignblk[dst] = src

            if assignblk.instr is not None:
                for arg in assignblk.instr.args:
                    new_arg = self.propag_expr_cst(arg)
                    links[new_arg] = arg
                self.cst_propag_link[(irb.loc_key, index)] = links

            self.eval_updt_assignblk(assignblk)
            assignblks.append(AssignBlock(new_assignblk, assignblk.instr))
        self.ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, assignblks)
示例#10
0
def exec_instruction(mn_str, init_values, results, index=0, offset=0):
    """Symbolically execute an instruction and check the expected results."""

    # Assemble and disassemble the instruction
    instr = mn_mep.fromstring(mn_str, "b")
    instr.mode = "b"
    mn_bin = mn_mep.asm(instr)[index]
    try:
        instr = mn_mep.dis(mn_bin, "b")
    except Disasm_Exception:
        assert (False)  # miasm don't know what to do

    # Specify the instruction offset and compute the destination label
    instr.offset = offset
    loc_db = LocationDB()
    if instr.dstflow():
        instr.dstflow2label(loc_db)

    # Get the IR
    im = Lifter_MEPb(loc_db)
    iir, eiir = im.get_ir(instr)

    # Filter out IRDst
    iir = [
        ir for ir in iir
        if not (isinstance(ir, ExprAssign) and isinstance(ir.dst, ExprId)
                and ir.dst.name == "IRDst")
    ]

    # Prepare symbolic execution
    sb = SymbolicExecutionEngine(LifterModelCallMepb(loc_db), regs_init)

    # Assign int values before symbolic evaluation
    for expr_id, expr_value in init_values:
        sb.symbols[expr_id] = expr_value

    # Execute the IR
    ab = AssignBlock(iir)
    sb.eval_updt_assignblk(ab)

    # Check if expected expr_id were modified
    matched_results = 0
    for expr_id, expr_value in results:

        result = sb.eval_expr(expr_id)
        if isinstance(result, ExprLoc):
            addr = loc_db.get_location_offset(result.loc_key)
            if expr_value.arg == addr:
                matched_results += 1
                continue
        elif result == expr_value:
            matched_results += 1
            continue

    # Ensure that all expected results were verified
    if len(results) is not matched_results:
        print("Expected:", results)
        print("Modified:", [r for r in sb.modified(mems=False)])
        assert (False)
示例#11
0
 def call_effects(self, addr, instr):
     call_assignblk = AssignBlock([
         ExprAssign(
             self.ret_reg,
             ExprOp('call_func_ret', addr, self.sp, self.arch.regs.R15)),
         ExprAssign(self.sp, ExprOp('call_func_stack', addr, self.sp))
     ], instr)
     return [call_assignblk], []
示例#12
0
 def call_effects(self, addr, instr):
     assignblks, extra = super(IRADelModCallStack,
                               self).call_effects(addr, instr)
     out = []
     for assignblk in assignblks:
         dct = dict(assignblk)
         dct = {dst: src for (dst, src) in viewitems(dct) if dst != self.sp}
         out.append(AssignBlock(dct, assignblk.instr))
     return out, extra
示例#13
0
 def call_effects(self, ad, instr):
     print(hex(instr.offset), instr)
     stk_before = idc.get_spd(instr.offset)
     stk_after = idc.get_spd(instr.offset + instr.l)
     stk_diff = stk_after - stk_before
     print(hex(stk_diff))
     call_assignblk = AssignBlock([
         ExprAssign(self.ret_reg, ExprOp('call_func_ret', ad)),
         ExprAssign(self.sp, self.sp + ExprInt(stk_diff, self.sp.size))
     ], instr)
     return [call_assignblk], []
示例#14
0
    def insert_parallel_copy(self):
        """
        Naive Out-of-SSA from CSSA (without coalescing for now)
        - Replace Phi
        - Create room for parallel copies in Phi's parents
        """
        ircfg = self.ssa.graph

        for irblock in list(viewvalues(ircfg.blocks)):
            if not irblock_has_phi(irblock):
                continue

            # Replace Phi with Phi's dst = new_var
            parallel_copies = {}
            for dst in self.phi_destinations[irblock.loc_key]:
                new_var = self.phi_new_var[dst]
                parallel_copies[dst] = new_var

            assignblks = list(irblock)
            assignblks[0] = AssignBlock(parallel_copies, irblock[0].instr)
            new_irblock = IRBlock(irblock.loc_db, irblock.loc_key, assignblks)
            ircfg.blocks[irblock.loc_key] = new_irblock

            # Insert new_var = src in each Phi's parent, at the end of the block
            parent_to_parallel_copies = {}
            parallel_copies = {}
            for dst in irblock[0]:
                new_var = self.phi_new_var[dst]
                for parent, src in self.phi_parent_sources[dst]:
                    parent_to_parallel_copies.setdefault(parent,
                                                         {})[new_var] = src

            for parent, parallel_copies in viewitems(
                    parent_to_parallel_copies):
                parent = ircfg.blocks[parent]
                assignblks = list(parent)
                assignblks.append(
                    AssignBlock(parallel_copies, parent[-1].instr))
                new_irblock = IRBlock(parent.loc_db, parent.loc_key,
                                      assignblks)
                ircfg.blocks[parent.loc_key] = new_irblock
示例#15
0
 def _convert_phi(self):
     """Inserts corresponding phi functions inplace
     into IRBlock at the beginning"""
     for loc_key in self._phinodes:
         irblock = self.get_block(loc_key)
         if irblock is None:
             continue
         assignblk = AssignBlock(self._phinodes[loc_key])
         if irblock_has_phi(irblock):
             # If first block contains phi, we are updating an existing ssa form
             # so update phi
             assignblks = list(irblock.assignblks)
             out = dict(assignblks[0])
             out.update(dict(assignblk))
             assignblks[0] = AssignBlock(out, assignblk.instr)
             new_irblock = IRBlock(self.ircfg.loc_db, loc_key, assignblks)
         else:
             # insert at the beginning
             new_irblock = IRBlock(self.ircfg.loc_db, loc_key,
                                   [assignblk] + list(irblock.assignblks))
         self.ircfg.blocks[loc_key] = new_irblock
示例#16
0
def casp(ir, instr, arg1, arg2, arg3):
    # XXX TODO: memory barrier
    e = []
    if arg1.size == 32:
        regs = gpregs32_expr
    else:
        regs = gpregs64_expr
    index1 = regs.index(arg1)
    index2 = regs.index(arg2)

    # TODO endianness
    comp_value = ExprCompose(regs[index1], regs[index1 + 1])
    new_value = ExprCompose(regs[index2], regs[index2 + 1])
    assert arg3.is_op('preinc')
    ptr = arg3.args[0]
    data = ExprMem(ptr, comp_value.size)

    loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size)

    e.append(
        ExprAssign(
            ir.IRDst,
            ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do,
                     loc_store)))

    e_store = []
    e_store.append(ExprAssign(data, new_value))
    e_store.append(ExprAssign(ir.IRDst, loc_do))
    blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)])

    e_do = []
    e_do.append(ExprAssign(regs[index1], data[:data.size // 2]))
    e_do.append(ExprAssign(regs[index1 + 1], data[data.size // 2:]))
    e_do.append(ExprAssign(ir.IRDst, loc_next))
    blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)])

    return e, [blk_store, blk_do]
示例#17
0
文件: depgraph.py 项目: tly000/miasm
def gen_irblock(label, exprs_list):
    """ Returns an IRBlock.
    Used only for tests purpose
    """
    irs = []
    for exprs in exprs_list:
        if isinstance(exprs, AssignBlock):
            irs.append(exprs)
        else:
            irs.append(AssignBlock(exprs))

    irbl = IRBlock(loc_db, label, irs)
    return irbl
示例#18
0
    def eval_updt_expr(self, expr):
        """
        Evaluate @expr and apply side effect if needed (ie. if expr is an
        assignment). Return the evaluated value
        """

        # Update value if needed
        if expr.is_aff():
            ret = self.eval_expr(expr.src)
            self.eval_updt_assignblk(AssignBlock([expr]))
        else:
            ret = self.eval_expr(expr)

        return ret
示例#19
0
文件: codegen.py 项目: trufae/miasm
 def assignblk_to_irbloc(self, instr, assignblk):
     """
     Ensure IRDst is always set in the head @assignblk of the @instr
     @instr: an instruction instance
     @assignblk: Assignblk instance
     """
     new_assignblk = dict(assignblk)
     if self.ir_arch.IRDst not in assignblk:
         offset = instr.offset + instr.l
         loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset)
         dst = ExprLoc(loc_key, self.ir_arch.IRDst.size)
         new_assignblk[self.ir_arch.IRDst] = dst
     irs = [AssignBlock(new_assignblk, instr)]
     return IRBlock(self.ir_arch.get_loc_key_for_instr(instr), irs)
示例#20
0
文件: unssa.py 项目: w4kfu/miasm
def add_out_reg_end(ir_arch_a, ircfg_a):
    # Add dummy dependency to uncover out regs affectation
    for loc in ircfg_a.leaves():
        irblock = ircfg_a.blocks.get(loc)
        if irblock is None:
            continue
        regs = {}
        for reg in ir_arch_a.get_out_regs(irblock):
            regs[reg] = reg
        assignblks = list(irblock)
        new_assiblk = AssignBlock(regs, assignblks[-1].instr)
        assignblks.append(new_assiblk)
        new_irblock = IRBlock(loc_db, irblock.loc_key, assignblks)
        ircfg_a.blocks[loc] = new_irblock
示例#21
0
    def call_effects(self, ad, instr):
        call_assignblk = AssignBlock([
            ExprAssign(
                self.ret_reg,
                ExprOp(
                    'call_func_ret',
                    ad,
                    self.arch.regs.R0,
                    self.arch.regs.R1,
                    self.arch.regs.R2,
                    self.arch.regs.R3,
                )),
            ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)),
        ], instr)

        cond = instr.additional_info.cond
        if cond == 14:  # COND_ALWAYS:
            return [call_assignblk], []

        # Call is a conditional instruction
        cond = tab_cond[cond]

        loc_next = self.get_next_loc_key(instr)
        loc_next_expr = ExprLoc(loc_next, 32)
        loc_do = self.loc_db.add_location()
        loc_do_expr = ExprLoc(loc_do, 32)
        dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr)

        call_assignblks = [
            call_assignblk,
            AssignBlock([ExprAssign(self.IRDst, loc_next_expr)], instr),
        ]
        e_do = IRBlock(loc_do, call_assignblks)
        assignblks_out = [
            AssignBlock([ExprAssign(self.IRDst, dst_cond)], instr)
        ]
        return assignblks_out, [e_do]
示例#22
0
    def call_effects(self, ad, instr):
        call_assignblk = AssignBlock([
            ExprAssign(
                self.ret_reg,
                ExprOp(
                    'call_func_ret',
                    ad,
                    self.arch.regs.A0,
                    self.arch.regs.A1,
                    self.arch.regs.A2,
                    self.arch.regs.A3,
                )),
        ], instr)

        return [call_assignblk], []
示例#23
0
 def remove_assign_eq(self):
     """
     Remove trivial expressions (a=a) in the current graph
     """
     for irblock in list(viewvalues(self.ssa.graph.blocks)):
         assignblks = list(irblock)
         for i, assignblk in enumerate(assignblks):
             out = {}
             for dst, src in viewitems(assignblk):
                 if dst == src:
                     continue
                 out[dst] = src
             assignblks[i] = AssignBlock(out, assignblk.instr)
         self.ssa.graph.blocks[irblock.loc_key] = IRBlock(
             irblock.loc_db, irblock.loc_key, assignblks)
示例#24
0
 def call_effects(self, ad, instr):
     call_assignblks = AssignBlock([
         ExprAssign(
             self.ret_reg,
             ExprOp(
                 'call_func_ret',
                 ad,
                 self.sp,
                 self.arch.regs.R3,
                 self.arch.regs.R4,
                 self.arch.regs.R5,
             )),
         ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)),
     ], instr)
     return [call_assignblks], []
示例#25
0
    def call_effects(self, addr, *args):
        #print(*args)
        if all(isinstance(arg, Expr) for arg in args):
            call_assignblk = [
                ExprAssign(self.ret_reg, ExprOp('call_func', addr, *args)),
            ]

            return call_assignblk
        else:
            call_assignblk = AssignBlock([
                ExprAssign(self.ret_reg, ExprOp('call_func_ret', addr,
                                                self.sp)),
                ExprAssign(self.sp, ExprOp('call_func_stack', addr, self.sp))
            ], args)

            return [call_assignblk], []
示例#26
0
 def addIRBlock(self, newIRCFG, state, lockey):
     assignBlocks = []
     lastAssign = None
     lastIndex = None
     for dst, src in state.items():
         newAssign = AssignBlock({dst: src})
         if dst == newIRCFG._irdst:
             lastAssign = newAssign
             lastIndex = len(assignBlocks)
         assignBlocks.append(newAssign)
     tmp = assignBlocks[-1]
     assignBlocks[-1] = lastAssign
     assignBlocks[lastIndex] = tmp
     newIRBlock = IRBlock(lockey, assignBlocks)
     newIRCFG.add_irblock(newIRBlock)
     return newIRBlock
示例#27
0
 def simplify(self):
     simplifier = IRCFGSimplifierCommon(self.custom_ira1)
     simplifier.simplify(self.ircfg, self.head)
     for loc in self.ircfg.leaves():
         irblock = self.ircfg.blocks.get(loc)
         if irblock is None:
             continue
         regs = {}
         for reg in self.custom_ira1.get_out_regs(irblock):
             regs[reg] = reg
         assignblks = list(irblock)
         newAssignBlk = AssignBlock(regs, assignblks[-1].instr)
         assignblks.append(newAssignBlk)
         newIrBlock = IRBlock(irblock.loc_key, assignblks)
         self.ircfg.blocks[loc] = newIrBlock
     simplifier = CustomIRCFGSimplifierSSA(self.custom_ira2)
     simplifier.simplify(self.ircfg, self.head)
示例#28
0
    def remove_phi(self):
        """
        Remove phi operators in @ifcfg
        @ircfg: IRDiGraph instance
        """

        for irblock in list(viewvalues(self.ssa.graph.blocks)):
            assignblks = list(irblock)
            out = {}
            for dst, src in viewitems(assignblks[0]):
                if src.is_op('Phi'):
                    assert set([dst]) == set(src.args)
                    continue
                out[dst] = src
            assignblks[0] = AssignBlock(out, assignblks[0].instr)
            self.ssa.graph.blocks[irblock.loc_key] = IRBlock(
                irblock.loc_db, irblock.loc_key, assignblks)
示例#29
0
    def _fix_no_def_var(self, head):
        """
        Replace phi source variables which are not ssa vars by ssa vars.
        @head: loc_key of the graph head
        """
        var_to_insert = set()
        for loc_key in self._phinodes:
            for dst, sources in viewitems(self._phinodes[loc_key]):
                for src in sources.args:
                    if src in self.ssa_variable_to_expr:
                        continue
                    var_to_insert.add(src)
        var_to_newname = {}
        newname_to_var = {}
        for var in var_to_insert:
            new_var = self._transform_var_lhs(var)
            var_to_newname[var] = new_var
            newname_to_var[new_var] = var

        # Replace non modified node used in phi with new variable
        self.ircfg.simplify(lambda expr: expr.replace_expr(var_to_newname))

        if newname_to_var:
            irblock = self.ircfg.blocks[head]
            assignblks = list(irblock)
            assignblks[0:0] = [
                AssignBlock(newname_to_var, assignblks[0].instr)
            ]
            self.ircfg.blocks[head] = IRBlock(self.ircfg.loc_db, head,
                                              assignblks)

        # Updt structure
        for loc_key in self._phinodes:
            for dst, sources in viewitems(self._phinodes[loc_key]):
                self._phinodes[loc_key][dst] = sources.replace_expr(
                    var_to_newname)

        for var, (loc_key, index) in list(viewitems(self.ssa_to_location)):
            if loc_key == head:
                self.ssa_to_location[var] = loc_key, index + 1

        for newname, var in viewitems(newname_to_var):
            self.ssa_to_location[newname] = head, 0
            self.ssa_variable_to_expr[newname] = var
            self.expressions[newname] = var
示例#30
0
    def del_dst_zr(self, instr, instr_ir, extra_ir):
        "Writes to zero register are discarded"
        regs_to_fix = [WZR, XZR]
        instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]

        new_irblocks = []
        for irblock in extra_ir:
            irs = []
            for assignblk in irblock:
                new_dsts = {
                    dst: src
                    for dst, src in viewitems(assignblk)
                    if dst not in regs_to_fix
                }
                irs.append(AssignBlock(new_dsts, assignblk.instr))
            new_irblocks.append(IRBlock(irblock.loc_key, irs))

        return instr_ir, new_irblocks
示例#31
0
文件: symbexec.py 项目: cea-sec/miasm
    def test_ClassDef(self):
        from miasm.expression.expression import ExprInt, ExprId, ExprMem, \
            ExprCompose, ExprAssign
        from miasm.arch.x86.sem import ir_x86_32
        from miasm.core.locationdb import LocationDB
        from miasm.ir.symbexec import SymbolicExecutionEngine
        from miasm.ir.ir import AssignBlock


        loc_db = LocationDB()
        ira = ir_x86_32(loc_db)
        ircfg = ira.new_ircfg()

        id_x = ExprId('x', 32)
        id_a = ExprId('a', 32)
        id_b = ExprId('b', 32)
        id_c = ExprId('c', 32)
        id_d = ExprId('d', 32)
        id_e = ExprId('e', 64)

        class CustomSymbExec(SymbolicExecutionEngine):
            def mem_read(self, expr):
                if expr == ExprMem(ExprInt(0x1000, 32), 32):
                    return id_x
                return super(CustomSymbExec, self).mem_read(expr)

        sb = CustomSymbExec(ira,
                            {
                                ExprMem(ExprInt(0x4, 32), 8): ExprInt(0x44, 8),
                                ExprMem(ExprInt(0x5, 32), 8): ExprInt(0x33, 8),
                                ExprMem(ExprInt(0x6, 32), 8): ExprInt(0x22, 8),
                                ExprMem(ExprInt(0x7, 32), 8): ExprInt(0x11, 8),

                                ExprMem(ExprInt(0x20, 32), 32): id_x,

                                ExprMem(ExprInt(0x40, 32), 32): id_x,
                                ExprMem(ExprInt(0x44, 32), 32): id_a,

                                ExprMem(ExprInt(0x54, 32), 32): ExprInt(0x11223344, 32),

                                ExprMem(id_a, 32): ExprInt(0x11223344, 32),
                                id_a: ExprInt(0, 32),
                                id_b: ExprInt(0, 32),

                                ExprMem(id_c, 32): ExprMem(id_d + ExprInt(0x4, 32), 32),
                                ExprMem(id_c + ExprInt(0x4, 32), 32): ExprMem(id_d + ExprInt(0x8, 32), 32),

                            })


        self.assertEqual(sb.eval_expr(ExprInt(1, 32)-ExprInt(1, 32)), ExprInt(0, 32))

        ## Test with unknown mem + integer
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0, 32), 32)), ExprMem(ExprInt(0, 32), 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(1, 32), 32)), ExprCompose(ExprMem(ExprInt(1, 32), 24), ExprInt(0x44, 8)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(2, 32), 32)), ExprCompose(ExprMem(ExprInt(2, 32), 16), ExprInt(0x3344, 16)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(3, 32), 32)), ExprCompose(ExprMem(ExprInt(3, 32), 8), ExprInt(0x223344, 24)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 32)), ExprInt(0x11223344, 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(5, 32), 32)), ExprCompose(ExprInt(0x112233, 24), ExprMem(ExprInt(8, 32), 8)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(6, 32), 32)), ExprCompose(ExprInt(0x1122, 16), ExprMem(ExprInt(8, 32), 16)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(7, 32), 32)), ExprCompose(ExprInt(0x11, 8), ExprMem(ExprInt(8, 32), 24)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(8, 32), 32)), ExprMem(ExprInt(8, 32), 32))

        ## Test with unknown mem + integer
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x50, 32), 32)), ExprMem(ExprInt(0x50, 32), 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x51, 32), 32)), ExprCompose(ExprMem(ExprInt(0x51, 32), 24), ExprInt(0x44, 8)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x52, 32), 32)), ExprCompose(ExprMem(ExprInt(0x52, 32), 16), ExprInt(0x3344, 16)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x53, 32), 32)), ExprCompose(ExprMem(ExprInt(0x53, 32), 8), ExprInt(0x223344, 24)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x54, 32), 32)), ExprInt(0x11223344, 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x55, 32), 32)), ExprCompose(ExprInt(0x112233, 24), ExprMem(ExprInt(0x58, 32), 8)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x56, 32), 32)), ExprCompose(ExprInt(0x1122, 16), ExprMem(ExprInt(0x58, 32), 16)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x57, 32), 32)), ExprCompose(ExprInt(0x11, 8), ExprMem(ExprInt(0x58, 32), 24)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x58, 32), 32)), ExprMem(ExprInt(0x58, 32), 32))



        ## Test with unknown mem + id
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1D, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1D, 32), 24), id_x[:8]))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1E, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1E, 32), 16), id_x[:16]))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1F, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1F, 32), 8), id_x[:24]))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x20, 32), 32)), id_x)
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x21, 32), 32)), ExprCompose(id_x[8:], ExprMem(ExprInt(0x24, 32), 8)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x22, 32), 32)), ExprCompose(id_x[16:], ExprMem(ExprInt(0x24, 32), 16)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x23, 32), 32)), ExprCompose(id_x[24:], ExprMem(ExprInt(0x24, 32), 24)))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x24, 32), 32)), ExprMem(ExprInt(0x24, 32), 32))


        ## Partial read
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 8)), ExprInt(0x44, 8))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x20, 32), 8)), id_x[:8])
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x23, 32), 8)), id_x[24:])


        ## Merge
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x40, 32), 64)), ExprCompose(id_x, id_a))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x42, 32), 32)), ExprCompose(id_x[16:], id_a[:16]))

        # Merge memory
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x100, 32), 32)), ExprMem(ExprInt(0x100, 32), 32))
        self.assertEqual(sb.eval_expr(ExprMem(id_c + ExprInt(0x2, 32), 32)), ExprMem(id_d  + ExprInt(0x6, 32), 32))

        ## Unmodified read
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 8)), ExprInt(0x44, 8))

        ## Modified read
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1000, 32), 32)), id_x)


        ## Apply_change / eval_ir / apply_expr

        ## x = a (with a = 0x0)
        assignblk = AssignBlock({id_x:id_a})
        sb.eval_updt_assignblk(assignblk)
        self.assertEqual(sb.eval_expr(id_x), ExprInt(0, 32))

        ## x = a (without replacing 'a' with 0x0)
        sb.apply_change(id_x, id_a)
        self.assertEqual(sb.eval_expr(id_x), id_a)

        ## x = a (with a = 0x0)
        self.assertEqual(sb.eval_updt_expr(assignblk.dst2ExprAssign(id_x)), ExprInt(0, 32))
        self.assertEqual(sb.eval_expr(id_x), ExprInt(0, 32))
        self.assertEqual(sb.eval_updt_expr(id_x), ExprInt(0, 32))

        sb.dump()

        ## state
        reads = set()
        for dst, src in sb.modified():
            reads.update(ExprAssign(dst, src).get_r())

        self.assertEqual(reads, set([
            id_x, id_a,
            ExprMem(id_d + ExprInt(0x4, 32), 32),
            ExprMem(id_d + ExprInt(0x8, 32), 32),
        ]))

        # Erase low id_x byte with 0xFF
        sb.apply_change(ExprMem(ExprInt(0x20, 32), 8), ExprInt(0xFF, 8))
        state = dict(sb.modified(ids=False))
        self.assertEqual(state[ExprMem(ExprInt(0x20, 32), 8)], ExprInt(0xFF, 8))
        self.assertEqual(state[ExprMem(ExprInt(0x21, 32), 24)], id_x[8:32])

        # Erase high id_x byte with 0xEE
        sb.apply_change(ExprMem(ExprInt(0x23, 32), 8), ExprInt(0xEE, 8))

        state = dict(sb.modified(ids=False))
        self.assertEqual(state[ExprMem(ExprInt(0x20, 32), 8)], ExprInt(0xFF, 8))
        self.assertEqual(state[ExprMem(ExprInt(0x21, 32), 16)], id_x[8:24])
        self.assertEqual(state[ExprMem(ExprInt(0x23, 32), 8)], ExprInt(0xEE, 8))

        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x22, 32), 32)), ExprCompose(id_x[16:24], ExprInt(0xEE, 8), ExprMem(ExprInt(0x24, 32), 16)))

        # Erase low byte of 0x11223344 with 0xFF at 0x54
        sb.apply_change(ExprMem(ExprInt(0x54, 32), 8), ExprInt(0xFF, 8))

        # Erase low byte of 0x11223344 with 0xFF at id_a
        sb.apply_change(ExprMem(id_a + ExprInt(0x1, 32), 8), ExprInt(0xFF, 8))
        state = dict(sb.modified(ids=False))
        self.assertEqual(state[ExprMem(id_a + ExprInt(0x1, 32), 8)], ExprInt(0xFF, 8))
        self.assertEqual(state[ExprMem(id_a + ExprInt(0x2, 32), 16)], ExprInt(0x1122, 16))

        # Write uint32_t at 0xFFFFFFFE
        sb.apply_change(ExprMem(ExprInt(0xFFFFFFFE, 32), 32), ExprInt(0x11223344, 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0, 32), 16)), ExprInt(0x1122, 16))

        # Revert memory to original value at 0x42
        sb.apply_change(ExprMem(ExprInt(0x42, 32), 32), ExprMem(ExprInt(0x42, 32), 32))
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x42, 32), 32)), ExprMem(ExprInt(0x42, 32), 32))

        # Revert memory to original value at c + 0x2
        sb.apply_change(ExprMem(id_c + ExprInt(0x2, 32), 32), ExprMem(id_c + ExprInt(0x2, 32), 32))
        self.assertEqual(sb.eval_expr(ExprMem(id_c + ExprInt(0x2, 32), 32)), ExprMem(id_c + ExprInt(0x2, 32), 32))

        # Test del symbol
        del sb.symbols[id_a]
        sb.dump()
        del sb.symbols[ExprMem(id_a, 8)]
        print("*"*40, 'Orig:')
        sb.dump()

        sb_cp = sb.symbols.copy()
        print("*"*40, 'Copy:')
        sb_cp.dump()

        # Add symbol at address limit
        sb.apply_change(ExprMem(ExprInt(0xFFFFFFFE, 32), 32), id_c)
        sb.dump()
        found = False
        for dst, src in viewitems(sb.symbols):
            if dst == ExprMem(ExprInt(0xFFFFFFFE, 32), 32) and src == id_c:
                found = True
        assert found


        # Add symbol at address limit
        sb.apply_change(ExprMem(ExprInt(0x7FFFFFFE, 32), 32), id_c)
        sb.dump()
        found = False
        for dst, src in viewitems(sb.symbols):
            if dst == ExprMem(ExprInt(0x7FFFFFFE, 32), 32) and src == id_c:
                found = True
        assert found



        # Add truncated symbol at address limit
        sb.apply_change(ExprMem(ExprInt(0xFFFFFFFC, 32), 64), id_e)
        # Revert parts of memory
        sb.apply_change(ExprMem(ExprInt(0xFFFFFFFC, 32), 16), ExprMem(ExprInt(0xFFFFFFFC, 32), 16))
        sb.apply_change(ExprMem(ExprInt(0x2, 32), 16), ExprMem(ExprInt(0x2, 32), 16))
        sb.dump()
        found = False
        for dst, src in viewitems(sb.symbols):
            if dst == ExprMem(ExprInt(0xFFFFFFFE, 32), 32) and src == id_e[16:48]:
                found = True
        assert found


        sb_empty = SymbolicExecutionEngine(ira)
        sb_empty.dump()


        # Test memory full
        print('full')
        arch_addr8 = ir_x86_32(loc_db)
        ircfg = arch_addr8.new_ircfg()
        # Hack to obtain tiny address space
        arch_addr8.addrsize = 5
        sb_addr8 = SymbolicExecutionEngine(arch_addr8)
        sb_addr8.dump()
        # Fulfill memory
        sb_addr8.apply_change(ExprMem(ExprInt(0, 5), 256), ExprInt(0, 256))
        sb_addr8.dump()
        variables = list(viewitems(sb_addr8.symbols))
        assert variables == [(ExprMem(ExprInt(0, 5), 256), ExprInt(0, 256))]

        print(sb_addr8.symbols.symbols_mem)

        sb_addr8.apply_change(ExprMem(ExprInt(0x5, 5), 256), ExprInt(0x123, 256))
        sb_addr8.dump()
        variables = list(viewitems(sb_addr8.symbols))
        assert variables == [(ExprMem(ExprInt(0x5, 5), 256), ExprInt(0x123, 256))]
        print(sb_addr8.symbols.symbols_mem)

        print('dump')
        sb_addr8.symbols.symbols_mem.dump()


        sb.dump()
        try:
            del sb.symbols.symbols_mem[ExprMem(ExprInt(0xFFFFFFFF, 32), 32)]
        except KeyError:
            # ok
            pass
        else:
            raise RuntimeError("Should raise error!")


        del sb.symbols.symbols_mem[ExprMem(ExprInt(0xFFFFFFFF, 32), 16)]
        sb.dump()
        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0xFFFFFFFE, 32), 32)),
                         ExprCompose(id_e[16:24], ExprMem(ExprInt(0xFFFFFFFF, 32), 16), id_e[40:48]))
        sb.symbols.symbols_mem.delete_partial(ExprMem(ExprInt(0xFFFFFFFF, 32), 32))

        self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0xFFFFFFFE, 32), 32)),
                         ExprCompose(id_e[16:24], ExprMem(ExprInt(0xFFFFFFFF, 32), 24)))

        sb.dump()

        assert ExprMem(ExprInt(0xFFFFFFFE, 32), 8) in sb.symbols
        assert ExprMem(ExprInt(0xFFFFFFFE, 32), 32) not in sb.symbols
        assert sb.symbols.symbols_mem.contains_partial(ExprMem(ExprInt(0xFFFFFFFE, 32), 32))
        assert not sb.symbols.symbols_mem.contains_partial(ExprMem(ExprInt(0xFFFFFFFF, 32), 8))

        assert list(sb_addr8.symbols) == [ExprMem(ExprInt(0x5, 5), 256)]