Exemple #1
0
    def write(self, offset, expr):
        """
        Write @expr at @offset
        @offset: integer (in bytes)
        @expr: Expr instance value
        """
        assert expr.size % 8 == 0
        assert offset <= self._mask
        for index in xrange(expr.size / 8):
            # Wrap write:
            # @32[EAX+0xFFFFFFFF] is ok and will write at 0xFFFFFFFF, 0, 1, 2
            request_offset = (offset + index) & self._mask
            # XXX TODO: only little endian here
            self._offset_to_expr[request_offset] = (index, expr)

            tmp = self.expr_simp(expr[index * 8: (index + 1) * 8])
            # Special case: Simplify slice of pointer (simplification is ok
            # here, as we won't store the simplified expression)
            if tmp.is_slice() and tmp.arg.is_mem() and tmp.start % 8 == 0:
                new_ptr = self.expr_simp(tmp.arg.arg + ExprInt(tmp.start / 8, tmp.arg.arg.size))
                tmp = ExprMem(new_ptr, tmp.stop - tmp.start)
            # Test if write to original value
            if tmp.is_mem():
                src_ptr, src_off = get_expr_base_offset(tmp.arg)
                if src_ptr == self.base and src_off == request_offset:
                    del self._offset_to_expr[request_offset]
Exemple #2
0
    def write(self, offset, expr):
        """
        Write @expr at @offset
        @offset: integer (in bytes)
        @expr: Expr instance value
        """
        assert expr.size % 8 == 0
        assert offset <= self._mask
        for index in xrange(expr.size / 8):
            # Wrap write:
            # @32[EAX+0xFFFFFFFF] is ok and will write at 0xFFFFFFFF, 0, 1, 2
            request_offset = (offset + index) & self._mask
            # XXX TODO: only little endian here
            self._offset_to_expr[request_offset] = (index, expr)

            tmp = self.expr_simp(expr[index * 8:(index + 1) * 8])
            # Special case: Simplify slice of pointer (simplification is ok
            # here, as we won't store the simplified expression)
            if tmp.is_slice() and tmp.arg.is_mem() and tmp.start % 8 == 0:
                new_ptr = self.expr_simp(tmp.arg.ptr +
                                         ExprInt(tmp.start /
                                                 8, tmp.arg.ptr.size))
                tmp = ExprMem(new_ptr, tmp.stop - tmp.start)
            # Test if write to original value
            if tmp.is_mem():
                src_ptr, src_off = get_expr_base_offset(tmp.ptr)
                if src_ptr == self.base and src_off == request_offset:
                    del self._offset_to_expr[request_offset]
Exemple #3
0
    def test_lb(self):
        """Test LB executon"""

        # LB Rn,(Rm)
        exec_instruction("LB R1, (R2)",
                         [(ExprId("R2", 32), ExprInt(0x10, 32)),
                          (ExprMem(ExprInt(0x10, 32), 8), ExprInt(0xF0, 8))],
                         [(ExprId("R1", 32), ExprInt(0xFFFFFFF0, 32))])

        # LB Rn[0-7],disp7(TP)
        exec_instruction("LB R7, 0x3(TP)",
                         [(ExprId("TP", 32), ExprInt(0x10, 32)),
                          (ExprMem(ExprInt(0x13, 32), 8), ExprInt(0xF0, 8))],
                         [(ExprId("R7", 32), ExprInt(0xFFFFFFF0, 32))])

        # LB Rn,disp16(Rm)
        exec_instruction(
            "LB R10, 0xF800(R2)",
            [(ExprId("R2", 32), ExprInt(0x10, 32)),
             (ExprMem(ExprInt(0xFFFFF810, 32), 8), ExprInt(0x4, 8))],
            [(ExprId("R10", 32), ExprInt(0x4, 32))])

        exec_instruction(
            "LB R10, 0xF800(R2)",
            [(ExprId("R2", 32), ExprInt(0x10, 32)),
             (ExprMem(ExprInt(0xFFFFF810, 32), 8), ExprInt(0xFE, 8))],
            [(ExprId("R10", 32), ExprInt(0xFFFFFFFE, 32))])
Exemple #4
0
    def _resolve_mem_parts(self, expr):
        """For a given ExprMem @expr, get known/unknown parts from the store.
        @expr: ExprMem instance

        Return a list of (known, value) where known is a bool representing if
        the value has been resolved from the store or not.
        """

        # Extract known parts in symbols
        assert expr.size % 8 == 0
        ptr = expr.ptr
        known = []
        ptrs = []
        for index in xrange(expr.size / 8):
            offset = self.expr_simp(ptr + ExprInt(index, ptr.size))
            ptrs.append(offset)
            mem = ExprMem(offset, 8)
            known.append(mem in self.symbols)

        reads = merge_ptr_read(known, ptrs)
        out = []
        for is_known, ptr_value, size in reads:
            mem = ExprMem(ptr_value, size)
            if is_known:
                mem = self.symbols.read(mem)
            out.append((is_known, mem))
        return out
Exemple #5
0
    def test_sw(self):
        """Test SW execution"""

        # SW Rn,(Rm)
        exec_instruction(
            "SW R1, (R2)", [(ExprId("R1", 32), ExprInt(0x28071010, 32)),
                            (ExprId("R2", 32), ExprInt(0x10, 32))],
            [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32))])

        # SW Rn,disp7.align4(SP)
        exec_instruction(
            "SW R1, 4(SP)", [(ExprId("R1", 32), ExprInt(0x28071010, 32)),
                             (ExprId("SP", 32), ExprInt(0x10, 32))],
            [(ExprMem(ExprInt(0x14, 32), 32), ExprInt(0x28071010, 32))])

        # SW Rn,disp7.align4(TP)
        exec_instruction(
            "SW R1, 12(TP)", [(ExprId("R1", 32), ExprInt(0x28071010, 32)),
                              (ExprId("TP", 32), ExprInt(0x10, 32))],
            [(ExprMem(ExprInt(0x1c, 32), 32), ExprInt(0x28071010, 32))])

        # SW Rn,disp16(Rm)
        exec_instruction(
            "SW R10, 0xF800(R2)", [(ExprId("R10", 32), ExprInt(0xABC7, 32)),
                                   (ExprId("R2", 32), ExprInt(0x10, 32))],
            [(ExprMem(ExprInt(0xFFFFF810, 32), 32), ExprInt(0xABC7, 32))])

        # SW Rn,(abs24.align4)
        exec_instruction(
            "SW R10, (0x1010)", [(ExprId("R10", 32), ExprInt(0xABC7, 32))],
            [(ExprMem(ExprInt(0x1010, 32), 32), ExprInt(0xABC7, 32))])
Exemple #6
0
    def test_lh(self):
        """Test lh execution"""

        # LH Rn,(Rm)
        exec_instruction(
            "LH R1, (R2)",
            [(ExprId("R2", 32), ExprInt(0x10, 32)),
             (ExprMem(ExprInt(0x10, 32), 16), ExprInt(0xF517, 16))],
            [(ExprId("R1", 32), ExprInt(0xFFFFF517, 32))])

        # LH Rn[0-7],disp7.align2(TP)
        exec_instruction(
            "LH R1, 0x18(R2)",
            [(ExprId("R2", 32), ExprInt(0x10, 32)),
             (ExprMem(ExprInt(0x28, 32), 16), ExprInt(0xF517, 16))],
            [(ExprId("R1", 32), ExprInt(0xFFFFF517, 32))])

        # LH Rn,disp16(Rm)
        exec_instruction(
            "LH R9, 0xF000(R2)",
            [(ExprId("R2", 32), ExprInt(0x42, 32)),
             (ExprMem(ExprInt(0xFFFFF042, 32), 16), ExprInt(0x10, 16))],
            [(ExprId("R9", 32), ExprInt(0x10, 32))])

        exec_instruction(
            "LH R9, 0xF000(R2)",
            [(ExprId("R2", 32), ExprInt(0x42, 32)),
             (ExprMem(ExprInt(0xFFFFF042, 32), 16), ExprInt(0xABCD, 16))],
            [(ExprId("R9", 32), ExprInt(0xFFFFABCD, 32))])
Exemple #7
0
    def mem_read(self, expr_mem):
        if not expr_mem.ptr.is_int():
            return expr_mem
        dst_addr = int(expr_mem.ptr)

        # Split access in atomic accesses
        out = []
        for addr in xrange(dst_addr, dst_addr + (expr_mem.size / 8)):
            if addr in self.dse_memory_range:
                # Symbolize memory access
                out.append(self.dse_memory_to_expr(addr))
                continue
            atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8)
            if atomic_access in self.symbols:
                out.append(
                    super(EmulatedSymbExec, self).mem_read(atomic_access))
            else:
                # Get concrete value
                atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8)
                out.append(super(ESETrackModif, self).mem_read(atomic_access))

        if len(out) == 1:
            # Trivial case (optimization)
            return out[0]

        # Simplify for constant merging (ex: {ExprInt(1, 8), ExprInt(2, 8)})
        return self.expr_simp(ExprCompose(*out))
Exemple #8
0
 def manage_mem(self, expr, state, cache, level):
     ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1)
     ret = ExprMem(ptr, expr.size)
     ret = self.get_mem_state(ret)
     if ret.is_mem() and not ret.arg.is_int() and ret.arg == ptr:
         ret = exprid_top(expr)
     assert expr.size == ret.size
     return ret
    def test_bsetm(self):
        """Test BSETM execution"""

        # BSETM (Rm),imm3
        exec_instruction("BSETM (R1), 1",
                         [(ExprId("R1", 32), ExprInt(0x28, 32)),
                          (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))],
                         [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x3, 8))])
Exemple #10
0
 def manage_mem(self, expr, state, cache, level):
     ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1)
     ret = ExprMem(ptr, expr.size)
     ret = self.get_mem_state(ret)
     if ret.is_mem() and not ret.arg.is_int() and ret.arg == ptr:
         ret = exprid_top(expr)
     assert expr.size == ret.size
     return ret
    def test_tas(self):
        """Test TAS execution"""

        # TAS Rn,(Rm)
        exec_instruction("TAS R0, (R1)",
                         [(ExprId("R1", 32), ExprInt(0x28, 32)),
                          (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x2, 8))],
                         [(ExprId("R0", 32), ExprInt(0x2, 32)),
                          (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))])
Exemple #12
0
def ldp(ir, instr, arg1, arg2, arg3):
    e = []
    addr, updt = get_mem_access(arg3)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    e.append(
        ExprAff(arg2,
                ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size)))
    if updt:
        e.append(updt)
    return e, []
def simp_mem(e_s, expr):
    "Common simplifications on ExprMem"

    # @32[x?a:b] => x?@32[a]:@32[b]
    if expr.arg.is_cond():
        cond = expr.arg
        ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size),
                       ExprMem(cond.src2, expr.size))
        return ret
    return expr
Exemple #14
0
def simp_mem(_, expr):
    """
    Common simplifications on ExprMem:
    @32[x?a:b] => x?@32[a]:@32[b]
    """
    if expr.ptr.is_cond():
        cond = expr.ptr
        ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size),
                       ExprMem(cond.src2, expr.size))
        return ret
    return expr
Exemple #15
0
    def reduce_op_field(self, node, _):
        """Reduce field operator (Struct or Union)"""

        if not node.expr.is_op('field'):
            return None
        assert len(node.args) == 2
        out = []
        assert isinstance(node.args[1].expr, ExprId)
        field = node.args[1].expr.name
        src, src_type = node.args[0].info
        struct_dst = src_type

        if isinstance(struct_dst, ObjCStruct):
            found = False
            for name, objtype, offset, _ in struct_dst.fields:
                if name != field:
                    continue
                expr = src + ExprInt(offset, src.size)
                if isinstance(objtype, ObjCArray):
                    # Case 4
                    pass
                elif isinstance(objtype, (ObjCStruct, ObjCUnion)):
                    # Case 1
                    pass
                else:
                    # Case 2
                    expr = ExprMem(expr, objtype.size * 8)
                assert not found
                found = True
                out = (expr, objtype)
        elif isinstance(struct_dst, ObjCUnion):
            found = False
            for name, objtype, offset, _ in struct_dst.fields:
                if name != field:
                    continue
                expr = src + ExprInt(offset, src.size)
                if isinstance(objtype, ObjCArray):
                    # Case 4
                    pass
                elif isinstance(objtype, (ObjCStruct, ObjCUnion)):
                    # Case 1
                    pass
                else:
                    # Case 2
                    expr = ExprMem(expr, objtype.size * 8)
                assert not found
                found = True
                out = (expr, objtype)
        else:
            raise NotImplementedError("unknown ObjC")
        assert found
        return out
Exemple #16
0
    def test_swcp(self):
        """Test SWCP execution"""

        # SWCP CRn,(Rm)
        exec_instruction(
            "SWCP C1, (R2)", [(ExprId("C1", 32), ExprInt(0x28071010, 32)),
                              (ExprId("R2", 32), ExprInt(0x11, 32))],
            [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32))])

        # SWCP CRn,disp16(Rm)
        exec_instruction(
            "SWCP C10, 0xF800(R2)", [(ExprId("C10", 32), ExprInt(0xABC7, 32)),
                                     (ExprId("R2", 32), ExprInt(0x11, 32))],
            [(ExprMem(ExprInt(0xFFFFF810, 32), 32), ExprInt(0xABC7, 32))])
Exemple #17
0
def test():
    struct_lookup = StructLookup()

    ptr = ExprId('ECX')
    int4 = ExprInt(4, 32)
    tests = [
        (ptr, StructLookup.FIELD_A_PTR),
        (ptr + int4, StructLookup.FIELD_A_PTR),
        (ptr + int4 * int4, StructLookup.FIELD_A_PTR),
        (ExprMem(ptr), StructLookup.FIELD_A),
        (ExprMem(ptr + int4 * int4), StructLookup.FIELD_A),
    ]

    for expr_in, result in tests:
        assert struct_lookup.reduce(expr_in).info == result
Exemple #18
0
    def test_lmcp(self):
        """Test LMCP execution"""

        # LMCP CRn[0-15],(Rm)
        exec_instruction(
            "LMCP C1, (R2)",
            [(ExprId("R2", 32), ExprInt(0x10, 32)),
             (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))],
            [(ExprId("C1", 32), ExprInt(0xABCD, 32))])

        # LMCP CRn[0-15],disp16(Rm)
        exec_instruction(
            "LMCP C9, 0xF000(R2)",
            [(ExprId("R2", 32), ExprInt(0x17, 32)),
             (ExprMem(ExprInt(0xFFFFF010, 32), 32), ExprInt(0x10, 32))],
            [(ExprId("C9", 32), ExprInt(0x10, 32))])
Exemple #19
0
def strh(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAssign(ExprMem(addr, 16), arg1[:16]))
    if updt:
        e.append(updt)
    return e, []
Exemple #20
0
def ldrs_size(ir, instr, arg1, arg2, size):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAssign(arg1, ExprMem(addr, size).signExtend(arg1.size)))
    if updt:
        e.append(updt)
    return e, []
Exemple #21
0
def l_str(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAssign(ExprMem(addr, arg1.size), arg1))
    if updt:
        e.append(updt)
    return e, []
Exemple #22
0
 def manage_mem(self, expr, state, cache, level):
     ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache,
                                                level + 1)
     ret = ExprMem(ptr, expr.size)
     ret = self.get_mem_state(ret)
     assert expr.size == ret.size
     return ret
Exemple #23
0
def strb(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, 8), arg1[:8]))
    if updt:
        e.append(updt)
    return e, []
Exemple #24
0
    def emulbloc(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.irs):
            new_assignblk = {}
            links = {}
            for dst, src in assignblk.iteritems():
                src = self.propag_expr_cst(src)
                if dst.is_mem():
                    ptr = dst.arg
                    ptr = self.propag_expr_cst(ptr)
                    dst = ExprMem(ptr, dst.size)
                new_assignblk[dst] = src

            for arg in assignblk.instr.args:
                new_arg = self.propag_expr_cst(arg)
                links[new_arg] = arg
            self.cst_propag_link[(irb.label, index)] = links

            self.eval_ir(assignblk)
            assignblks.append(AssignBlock(new_assignblk, assignblk.instr))
        self.ir_arch.blocks[irb.label] = IRBlock(irb.label, assignblks)
Exemple #25
0
def ldr(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    if updt:
        e.append(updt)
    return e, []
Exemple #26
0
    def reduce_op_memberof(self, node, _):
        """Reduce -> operator"""

        if not node.expr.is_op('->'):
            return None
        assert len(node.args) == 2
        out = []
        assert isinstance(node.args[1].expr, ExprId)
        field = node.args[1].expr.name
        src, src_type = node.args[0].info
        assert isinstance(src_type, (ObjCPtr, ObjCArray))
        struct_dst = src_type.objtype
        assert isinstance(struct_dst, ObjCStruct)

        found = False
        for name, objtype, offset, _ in struct_dst.fields:
            if name != field:
                continue
            expr = src + ExprInt(offset, src.size)
            if isinstance(objtype, (ObjCArray, ObjCStruct, ObjCUnion)):
                pass
            else:
                expr = ExprMem(expr, objtype.size * 8)
            assert not found
            found = True
            out = (expr, objtype)
        assert found
        return out
    def test_btstm(self):
        """Test BTSTM execution"""

        # BTSTM R0,(Rm),imm3
        exec_instruction("BTSTM R0, (R1), 1",
                         [(ExprId("R1", 32), ExprInt(0x28, 32)),
                          (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x2, 8))],
                         [(ExprId("R0", 32), ExprInt(0x2, 32))])
Exemple #28
0
def ldaxrb(ir, instr, arg1, arg2):
    # TODO XXX no memory lock implemented
    assert arg2.is_op('preinc')
    assert len(arg2.args) == 1
    ptr = arg2.args[0]
    e = []
    e.append(ExprAssign(arg1, ExprMem(ptr, 8).zeroExtend(arg1.size)))
    return e, []
Exemple #29
0
def stlxrb(ir, instr, arg1, arg2, arg3):
    assert arg3.is_op('preinc')
    assert len(arg3.args) == 1
    ptr = arg3.args[0]
    e = []
    e.append(ExprAssign(ExprMem(ptr, 8), arg2[:8]))
    # TODO XXX here, force update success
    e.append(ExprAssign(arg1, ExprInt(0, arg1.size)))
    return e, []
Exemple #30
0
    def test_smcpi(self):
        """Test SMCPI execution"""

        # SMCPI CRn[0-15],(Rm+)
        exec_instruction(
            "SMCPI C1, (R2+)", [(ExprId("C1", 32), ExprInt(0x28071010, 32)),
                                (ExprId("R2", 32), ExprInt(0x17, 32))],
            [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32)),
             (ExprId("R2", 32), ExprInt(0x1F, 32))])
Exemple #31
0
 def eval_exprmem(self, expr, **kwargs):
     """[DEV]: Evaluate an ExprMem using the current state
     This function first evaluate the memory pointer value.
     Override 'mem_read' to modify the effective memory accesses
     """
     ptr = self.eval_expr_visitor(expr.ptr, **kwargs)
     mem = ExprMem(ptr, expr.size)
     ret = self.mem_read(mem)
     return ret
Exemple #32
0
    def test_lwcpi(self):
        """Test LWCPI execution"""

        # LWCPI CRn[0-15],(Rm+)
        exec_instruction(
            "LWCPI C1, (R2+)",
            [(ExprId("R2", 32), ExprInt(0x11, 32)),
             (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))],
            [(ExprId("C1", 32), ExprInt(0xABCD, 32)),
             (ExprId("R2", 32), ExprInt(0x15, 32))])
Exemple #33
0
    def propagate(self, ssa, head):
        defuse = SSADefUse.from_ssa(ssa)
        to_replace = {}
        node_to_reg = {}
        for node in defuse.nodes():
            lbl, index, reg = node
            src = defuse.get_node_target(node)
            if expr_has_call(src):
                continue
            if src.is_op('Phi'):
                continue
            if reg.is_mem():
                continue
            to_replace[reg] = src
            node_to_reg[node] = reg

        modified = False
        for node, reg in node_to_reg.iteritems():
            for successor in defuse.successors(node):
                if not self.propagation_allowed(ssa, to_replace, node, successor):
                    continue

                loc_a, index_a, reg_a = node
                loc_b, index_b, reg_b = successor
                block = ssa.graph.blocks[loc_b]

                replace = {reg_a: to_replace[reg_a]}
                # Replace
                assignblks = list(block)
                assignblk = block[index_b]
                out = {}
                for dst, src in assignblk.iteritems():
                    if src.is_op('Phi'):
                        out[dst] = src
                        continue

                    if src.is_mem():
                        ptr = src.ptr
                        ptr = ptr.replace_expr(replace)
                        new_src = ExprMem(ptr, src.size)
                    else:
                        new_src = src.replace_expr(replace)

                    if dst.is_id():
                        new_dst = dst
                    elif dst.is_mem():
                        ptr = dst.ptr
                        ptr = ptr.replace_expr(replace)
                        new_dst = ExprMem(ptr, dst.size)
                    else:
                        new_dst = dst.replace_expr(replace)
                        if not (new_dst.is_id() or new_dst.is_mem()):
                            new_dst = dst
                    if src != new_src or dst != new_dst:
                        modified = True
                    out[new_dst] = new_src
                out = AssignBlock(out, assignblk.instr)
                assignblks[index_b] = out
                new_block = IRBlock(block.loc_key, assignblks)
                ssa.graph.blocks[block.loc_key] = new_block
        return modified