Ejemplo n.º 1
0
def do_SIGN(op, stack, state):
    arg1, arg2 = pop_values(stack, state, 2)
    size = arg2

    if z3.is_bv(size):
        size = size.as_long()

    if not z3.is_bv(arg1):
        arg1 = z3.BitVecVal(arg1, SIZE)

    stack.append(z3.SignExt(SIZE - size, z3.Extract(size - 1, 0, arg1)))
Ejemplo n.º 2
0
    def __setitem__(self, addr, value):
        if isinstance(addr, int) or z3.is_bv(addr):
            return self.write(addr, value)
        elif isinstance(addr, str):
            addr = self.r2api.get_address(addr)
            return self.write(addr, value)
        elif isinstance(addr, slice):
            length = int(addr.stop - addr.start)

            if isinstance(value, list):
                self.write(addr.start, value[:length])
            elif z3.is_bv(value):
                new_val = z3.Extract(length * 8 - 1, 0, value)
                self.write(addr.start, new_val)
Ejemplo n.º 3
0
    def __setitem__(self, addr, value):
        if type(addr) == int or z3.is_bv(addr):
            return self.write(addr, value)
        elif type(addr) == str:
            addr = self.r2api.get_address(addr)
            return self.write(addr, value)
        elif type(addr) == slice:
            length = int(addr.stop - addr.start)

            if type(value) == list:
                self.write(addr.start, value[:length])
            elif z3.is_bv(value):
                new_val = z3.Extract(length * 8 - 1, 0, value)
                self.write(addr.start, new_val)
Ejemplo n.º 4
0
    def write(self, addr, data):

        if self._refs["count"] > 1:
            self.finish_clone()

        if type(addr) != int:
            addr = self.bv_to_int(addr)

        if z3.is_bv(data):
            length = int(data.size() / BYTE)
            data = self.unpack_bv(data, length)
        elif type(data) == bytes:
            data = list(data)
        elif type(data) == str:
            data = list(data.encode()) + [0]  # add null byte
        elif type(data) == int:
            data = self.unpack_bv(data, int(self.bits / 8))

        data = self.prepare_data(data)
        maddr = self.mask(addr)
        offset = addr - maddr
        length = len(data)

        if maddr != addr or length % self.chunklen != 0:
            prev_len = length + (self.chunklen - (length % self.chunklen))
            prev = self.read(maddr, prev_len)
            data = prev[:offset] + data + prev[offset + length:]

        chunks = int(length / self.chunklen) + min(1, length % self.chunklen)
        for chunk in range(chunks):
            o = chunk * self.chunklen
            caddr = maddr + o

            self._memory[caddr] = data[o:o + self.chunklen]
Ejemplo n.º 5
0
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef:
    if z3.is_bv(val):
        szdiff = size - val.size()

        if szdiff > 0:
            if signext:
                result = z3.SignExt(szdiff, val)
            else:
                result = z3.ZeroExt(szdiff, val)
        elif szdiff < 0:
            result = z3.Extract(size - 1, 0, val)
        else:
            result = val
    elif type(val) == int:
        result = z3.BitVecVal(val, size)
    elif z3.is_int(val):
        result = z3.Int2BV(val, size)
    elif z3.is_fp(val):
        # changing up this logic to align with r2ghidra impl
        result = z3.fpToIEEEBV(val)
        #result = val
    else:
        result = z3.BitVecVal(val, size)

    #return z3.simplify(result)
    return result
Ejemplo n.º 6
0
def decode_instruction(address, data):
    """
    data is the raw bytes, in little-endian, of at least the area containing
    all information about the current instruction.
    You can give more, but you need at least enough to fully decode the
    instruction, so 6 bytes should be enough.


    Reference: http://mspgcc.sourceforge.net/manual/x223.html
               https://en.wikipedia.org/wiki/MSP430#MSP430_CPU
    """

    is_single_operand_instruction = lambda x: (x >> 10) == 0b000100
    is_jump_instruction = lambda x: (x >> 13) == 0b001
    is_double_operand_instruction = lambda x: \
            not is_single_operand_instruction(x) and not is_jump_instruction(x)

    # turn a list of BitVecVals and ints into a list of ints
    unBVV = lambda l: [simplify(x).as_long() if is_bv(x) else x for x in data]

    data = unBVV(data)
    instruction = int.from_bytes(data[:2], 'little')

    if is_single_operand_instruction(instruction):
        return decode_single_operand_instruction(address, data)
    elif is_jump_instruction(instruction):
        return decode_jump_instruction(address, data)
    elif is_double_operand_instruction(instruction):
        return decode_double_operand_instruction(address, data)
    else:
        raise ValueError( \
            '0x{:x} does not look like a valid MSP430 instruction!'.format( \
                instruction))
Ejemplo n.º 7
0
    def check_addr(self, bv, mode="r", length=None, data=None):

        if isinstance(bv, int):
            return
        elif z3.is_bv_value(bv):
            return

        bv = z3.simplify(bv)
        if z3.is_bv_value(bv):
            return 

        elif z3.is_bv(bv):

            mode_to_event = {
                "r": ESILSolveEvent.SymRead,
                "w": ESILSolveEvent.SymWrite,
                "x": ESILSolveEvent.SymExec,
                "f": ESILSolveEvent.SymFree
            }
            event = mode_to_event[mode]
            if event in self.events:
                # normalize everything to be bvs
                if isinstance(length, int):
                    length = BV(length, self.bits)

                if isinstance(data, list):
                    data = self.memory.pack_bv(data)

                ctx = EventContext(bv, length, data)
                for hook in self.events[event]:
                    hook(self, ctx)
Ejemplo n.º 8
0
    def write_con(self, addr, data):

        if self._refs["count"] > 1:
            self.finish_clone()

        if self.check_perms:
            self.check(addr, "w")

        if z3.is_bv(data):
            length = data.size() // 8
            data = self.unpack_bv(data, length)
        elif isinstance(data, bytes):
            data = list(data)
        elif isinstance(data, str):
            data = list(data.encode()) + [0]  # add null byte
        elif isinstance(data, int):
            data = self.unpack_bv(data, self.bits // 8)

        data = self.prepare_data(data)
        maddr = self.mask(addr)
        offset = addr - maddr
        length = len(data)

        if maddr != addr or length % self.chunklen != 0:
            prev_len = length + (self.chunklen - (length % self.chunklen))
            prev = self.read(maddr, prev_len)
            data = prev[:offset] + data + prev[offset + length:]

        chunks = length // self.chunklen + min(1, length % self.chunklen)
        for chunk in range(chunks):
            o = chunk * self.chunklen
            caddr = maddr + o

            self._memory[caddr] = data[o:o + self.chunklen]
Ejemplo n.º 9
0
    def __setitem__(self, key: str, val):
        """ Set register value """

        if self._refs["count"] > 1:
            self.finish_clone()

        if key in self.aliases:
            key = self.aliases[key]["reg"]

        if key not in self._registers:
            return

        register = self._registers[key]

        # hack for pcode, always weak set flags
        if register["type_str"] == "flg":
            self.weak_set(key, val)
            return

        reg_value = self.get_register_from_bounds(register)

        # idk this should be fine and its faster but gives complex answers
        if False and z3.is_bv(val) and val.size() == reg_value["size"]:
            reg_value["bv"] = z3.simplify(val)

        else:
            zero = z3.BitVecVal(0, reg_value["size"])
            new_reg = self.set_register_bits(register, reg_value, zero, val)
            reg_value["bv"] = z3.simplify(new_reg)
Ejemplo n.º 10
0
    def bv_to_int(self, bv):

        bv = z3.simplify(bv)
        if z3.is_bv_value(bv):
            return bv.as_long()

        # this is terrible and temporary
        elif z3.is_bv(bv):
            print("symbolic addr: %s" % bv)
            self.hit_symbolic_addr = True
            sat = self.solver.check()
            if sat == z3.sat:
                model = self.solver.model()

                try:
                    val = model.eval(bv, model_completion=True).as_long()
                    #print(val)
                    '''if self.multi_concretize:
                        self.solver.push()
                        self.solver.add(bv != val)
                        vals = solver.EvalMax(self.solver, bv)
                        if len(vals) > 0:
                            self.concrete_addrs.append({"bv": bv, "values": vals})
                        self.solver.pop()'''

                    self.solver.add(bv == val)
                    return val
                except:
                    # idk man i need a default value in case
                    # there are no constraints on the addr
                    self.solver.add(bv == self.default_addr)
                    return self.default_addr

            else:
                raise ESILUnsatException("no sat symbolic address found")
Ejemplo n.º 11
0
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef:
    if z3.is_bv(val):
        szdiff = size-val.size()
        if szdiff == 0:
            result = val
        elif szdiff > 0:
            if signext:
                result = z3.SignExt(szdiff, val)
            else:
                result = z3.ZeroExt(szdiff, val)
        elif szdiff < 0:
            result = z3.Extract(size-1, 0, val)

    elif isinstance(val, int):
        result = z3.BitVecVal(val, size)
    elif z3.is_int(val):
        result = z3.Int2BV(val, size)
    elif z3.is_fp(val):
        result = z3.fpToIEEEBV(val)
    else:
        result = z3.BitVecVal(val, size)

    if not z3.is_bv_value(result):
        return z3.simplify(result)
    else:
        return result
Ejemplo n.º 12
0
def do_SIGN(op, stack, state):
    arg1, arg2 = pop_values(stack, state, 2)
    size = arg2

    if z3.is_bv(size):
        size = size.as_long()

    szdiff = SIZE - size
    stack.append(z3.SignExt(szdiff, z3.Extract(size - 1, 0, arg1)))
Ejemplo n.º 13
0
def is_symbolic(state, val):
    """
    return whether or not a value is symbolic within a state
    """
    if not is_bv(val):
        return False

    val = simplify(val)
    return not isinstance(val, BitVecNumRef)
Ejemplo n.º 14
0
 def __getitem__(self, addr) -> z3.BitVecRef:
     length = self.chunklen
     if isinstance(addr, int) or z3.is_bv(addr):
         return self.read_bv(addr, length)
     elif isinstance(addr, str):
         addr = self.r2api.get_address(addr)
         return self.read_bv(addr, length)
     elif isinstance(addr, slice):
         length = int(addr.stop - addr.start)
         return self.read_bv(addr.start, length)
Ejemplo n.º 15
0
 def __getitem__(self, addr) -> z3.BitVecRef:
     length = self.chunklen
     if type(addr) == int or z3.is_bv(addr):
         return self.read_bv(addr, length)
     elif type(addr) == str:
         addr = self.r2api.get_address(addr)
         return self.read_bv(addr, length)
     elif type(addr) == slice:
         length = int(addr.stop - addr.start)
         return self.read_bv(addr.start, length)
def is_typed_bv_be32(bv_variable):
    if not z3.is_bv(bv_variable):
        return False
    if not bv_variable.decl().kind() == z3.Z3_OP_UNINTERPRETED:
        return False
    if bv_variable.size() != 32:
        return False
    if bv_variable.decl().name().endswith("_intbe:32"):
        return True
    return False
Ejemplo n.º 17
0
def get_bv(exp):
    """
    Ensures that the returned value is a binary vector by transforming the expression if necessary.
    :param exp: expression to transform into a binary vector
    :return: a binary vector
    """
    if is_bv(exp):
        return exp
    if type(exp) == int:
        return BitVecVal(exp, 256)
    raise ValueError("Bitvector or int needed")
Ejemplo n.º 18
0
def genmask(bits):
    
    if not isinstance(bits, int):
        bits = z3.simplify(bits)
        if z3.is_bv(bits):
            bits = bits.as_long()

    m = (2 << 63) - 1
    if(bits > 0 and bits < 64):
        m = (2 << bits) - 1
    
    return m
Ejemplo n.º 19
0
def path_specific_var(prefix, var, var_mapping):
    """If var is not fixed, returns a renamed copy that can be constrained
    without affecting the original var, or copies with different prefixes.
    var_mapping caches all path specific variables."""
    assert z3.is_const(var), var
    if var_is_fixed(var):
        # No ability or need to convert fixed values
        return var
    # Only currently need to support bitvecs, expand as needed.
    assert z3.is_bv(var), var
    return var_mapping.setdefault(var, z3.BitVec(prefix + str(var),
                                                 var.size()))
Ejemplo n.º 20
0
 def __k_bool__(self):
     if z3.is_int(self.value) or z3.is_real(self.value) or z3.is_bv(
             self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != 0, self.defaults),
                                         status=True)
     elif z3.is_string(self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != z3.StringVal(""), self.defaults),
                                         status=True)
     else:
         yield inference.InferenceResult(self, status=True)
Ejemplo n.º 21
0
    def step(self, enable_unsound_optimizations=True):
        """
        Tick the cpu forward one instruction.

        Returns a list of successor states.
        """
        instruction_pointer = self.cpu.registers[Register.R0]
        if z3.is_bv(instruction_pointer):
            instruction_pointer = z3.simplify(instruction_pointer).as_long()


# pull enough to encode any instruction
        raw_instruction = \
                self.memory[instruction_pointer : instruction_pointer + 6]
        instruction, instruction_length = \
                decode_instruction(instruction_pointer, raw_instruction)
        #print(instruction, instruction_length)

        step_functions = {
            Opcode.RRC: self.cpu.step_rrc,
            Opcode.SWPB: self.cpu.step_swpb,
            Opcode.RRA: self.cpu.step_rra,
            Opcode.SXT: self.cpu.step_sxt,
            Opcode.PUSH: self.cpu.step_push,
            Opcode.CALL: self.cpu.step_call,
            Opcode.RETI: self.cpu.step_reti,
            Opcode.JNZ: self.cpu.step_jnz,
            Opcode.JZ: self.cpu.step_jz,
            Opcode.JNC: self.cpu.step_jnc,
            Opcode.JC: self.cpu.step_jc,
            Opcode.JN: self.cpu.step_jn,
            Opcode.JGE: self.cpu.step_jge,
            Opcode.JL: self.cpu.step_jl,
            Opcode.JMP: self.cpu.step_jmp,
            Opcode.MOV: self.cpu.step_mov,
            Opcode.ADD: self.cpu.step_add,
            Opcode.ADDC: self.cpu.step_addc,
            Opcode.SUBC: self.cpu.step_subc,
            Opcode.SUB: self.cpu.step_sub,
            Opcode.CMP: self.cpu.step_cmp,
            Opcode.DADD: self.cpu.step_dadd,
            Opcode.BIT: self.cpu.step_bit,
            Opcode.BIC: self.cpu.step_bic,
            Opcode.BIS: self.cpu.step_bis,
            Opcode.XOR: self.cpu.step_xor,
            Opcode.AND: self.cpu.step_and,
        }
        self.cpu.registers[
            Register.R0] += instruction_length  # preincrement ip
        instruction_fn = step_functions[instruction.opcode]
        successor_states = instruction_fn(self, instruction, \
                enable_unsound_optimizations=enable_unsound_optimizations)
        return successor_states
Ejemplo n.º 22
0
def genmask(bits):

    if type(bits) != int:
        bits = z3.simplify(bits)
        if z3.is_bv(bits):
            bits = bits.as_long()

    m = (2 << 63) - 1
    if (bits > 0 and bits < 64):
        m = (2 << bits) - 1

    return m
Ejemplo n.º 23
0
def prepare(val):
    if z3.is_bv(val):
        #print(val)
        szdiff = SIZE - val.size()
        #print(szdiff, val.size())
        if szdiff > 0:
            return z3.ZeroExt(szdiff, val)
        else:
            return val
    elif z3.is_int(val):
        return z3.Int2BV(val, SIZE)
    else:
        return z3.BitVecVal(val, SIZE)
Ejemplo n.º 24
0
    def data_to_bv(self, data):
        if z3.is_bv(data):
            return data
        elif isinstance(data, list):
            data = self.pack_bv(data)
        elif isinstance(data, bytes):
            data = self.pack_bv(list(data))
        elif isinstance(data, str):
            data = self.pack_bv(list(data.encode()) + [0])  # add null byte
        elif isinstance(data, int):
            data = BV(data, self.bits)

        return data
Ejemplo n.º 25
0
    def constrain_bytes(self, bv, regex: Union[str, bytes]):

        # if its a bytes expr just constrain beginning to those values
        if type(regex) == bytes:
            for i in range(len(regex)):
                self.constrain(z3.Extract(7 + i * 8, i * 8, bv) == regex[i])

            return

        all_bytes = "".join([chr(x) for x in range(256)])

        if z3.is_bv(bv):
            bv = [
                z3.Extract(b * 8 + 7, b * 8, bv)
                for b in range(int(bv.size() / 8))
            ]

        # this is gross and could probably break
        opts = []
        new_regex = regex[:]
        negate = False
        if len(regex) > 2 and regex[:2] == "[^":
            negate = True
            new_regex = new_regex.replace("[^", "[")

        dashes = [i for i, c in enumerate(regex) if c == "-"]
        for d in dashes:
            if regex[d - 1] != "\\" and len(regex) > d:
                x = ord(regex[d - 1])
                y = ord(regex[d + 1])
                opts.append([x, y])
                new_regex = new_regex.replace(regex[d - 1:d + 2], "")

        vals = []
        if new_regex != "[]":
            vals = [
                ord(x) for x in re.findall(new_regex, all_bytes, re.DOTALL)
            ]

        for b in bv:
            or_vals = []
            for val in vals:
                or_vals.append(b == val)

            for opt in opts:
                or_vals.append(z3.And(b >= opt[0], b <= opt[1]))

            if negate:
                self.constrain(z3.Not(z3.Or(*or_vals)))
            else:
                self.constrain(z3.Or(*or_vals))
Ejemplo n.º 26
0
    def _concretize(self, value):
        if is_bv(value):  # try to simplify and deal with BV's that come in...
            value = simplify(value)
            if isinstance(value, BitVecNumRef):
                value = value.as_long(
                )  # if this succeeds, we had a single value! yay
            else:
                # symbolic lengths
                # TODO: deal with symbolic values
                raise ValueError(
                    'Tried to concretize symbolic data in an input... much danger, much scare, much fail!'
                )

        return value
def get_children_of(z3from):
    children = z3from.children()
    children_converted = []
    found_one_bv = False
    found_one_not_bv = False
    for child in children:
        converted_child = from_bv_to_int_domain(child)
        if z3.is_bv(converted_child):
            found_one_bv = True
        else:
            found_one_not_bv = True
        children_converted.append(converted_child)
    #if some of the children are still bv but not all of them, its a problem
    if found_one_bv and found_one_not_bv:
        return children
    return children_converted
Ejemplo n.º 28
0
 def bv_length(e):
     li = [-1]
     if e in seen:
         return -1
     if (z3.is_bv(e) and
             z3.is_const(e) and
             e.decl().kind() == z3.Z3_OP_UNINTERPRETED):
         li.append(e.size())
     seen.add(e)
     if z3.is_app(e):
         for ch in e.children():
             li.append(bv_length(ch))
     elif z3.is_quantifier(e):
         for ch in e.body().children():
             li.append(bv_length(ch))
     return max(li)
Ejemplo n.º 29
0
def try_bool(b):
    # Just ignore attributes here
    if isinstance(b, Value):
        b = b.value
    if z3.is_bv(b) or isinstance(b, int):
        b = (b != 0)
    b = try_simplify(b)
    if isinstance(b, bool):
        return (b, None)
    # HACK: z3 python interface has bug/weird behavior where (x == y) is
    # always False for unknown x and y, so use is_true and is_false instead
    if z3.is_true(b):
        return (True, None)
    if z3.is_false(b):
        return (False, None)
    return (None, b)
Ejemplo n.º 30
0
def extend(value, width, signed=None):
    if not is_z3(value):
        return value
    # XXX range check
    if not z3.is_bv(value):
        value = z3.Int2BV(value, width)
    assert value.size() > 0
    diff = try_simplify(width - value.size())
    if diff > 0:
        if signed is None:
            # XXX default to unsigned
            signed = False
        if signed:
            return z3.SignExt(diff, value)
        else:
            return z3.ZeroExt(diff, value)
    return value
Ejemplo n.º 31
0

def parse_int_params(name):
    things = name.split("[")[1:]
    #    print "things:".format(things)
    if not all(t.endswith("]") for t in things):
        raise SyntaxError()
    return [int(t[:-1]) for t in things]


def is_solver_sort(name):
    return name.startswith("bv[") and name.endswith("]") or name == "int"


relations_dict = {
    "<": (lambda x, y: z3.ULT(x, y) if z3.is_bv(x) else x < y),
    "<=": (lambda x, y: z3.ULE(x, y) if z3.is_bv(x) else x <= y),
    ">": (lambda x, y: z3.UGT(x, y) if z3.is_bv(x) else x > y),
    ">=": (lambda x, y: z3.UGE(x, y) if z3.is_bv(x) else x >= y),
}


def relations(name):
    return relations_dict.get(name)


functions_dict = {
    "+": (lambda x, y: x + y),
    "-": my_minus,
    "*": (lambda x, y: x * y),
    "concat": (lambda x, y: z3.Concat(x, y)),
Ejemplo n.º 32
0
#sorts = {}
#sorts = {"S":S,
#         "Int":z3.IntSort()}

def parse_int_params(name):
    things = name.split('[')[1:]
#    print "things:".format(things)
    if not all(t.endswith(']') for t in things):
        raise SyntaxError()
    return [int(t[:-1]) for t in things]
    

def is_solver_sort(name):
    return name.startswith('bv[') and name.endswith(']') or name == 'int'

relations_dict = {'<':(lambda x,y: z3.ULT(x, y) if z3.is_bv(x) else x < y),
             '<=':(lambda x,y: z3.ULE(x, y) if z3.is_bv(x) else x <= y),
             '>':(lambda x,y: z3.UGT(x, y) if z3.is_bv(x) else x > y),
             '>=':(lambda x,y: z3.UGE(x, y) if z3.is_bv(x) else x >= y),
             }

def relations(name):
    return relations_dict.get(name)

functions_dict = {"+":(lambda x,y: x + y),
             "-":my_minus,
             "*":(lambda x,y: x * y),
             "concat":(lambda x,y: z3.Concat(x,y)),
             }