Example #1
0
 def detect_arbitrary_memory_access(self, tainted_record, individual,
                                    current_instruction):
     if current_instruction["op"] == "SSTORE":
         if tainted_record and tainted_record.stack:
             tainted_index = tainted_record.stack[-1]
             tainted_value = tainted_record.stack[-2]
             if tainted_index and tainted_value and is_expr(
                     tainted_index[0]) and is_expr(tainted_value[0]):
                 if get_vars(tainted_index[0]) and get_vars(
                         tainted_value[0]):
                     tainted_index_var = get_vars(tainted_index[0])[0]
                     tainted_value_var = get_vars(tainted_value[0])[0]
                     if tainted_index != tainted_value and "calldataload_" in str(
                             tainted_index[0]) and "calldataload_" in str(
                                 tainted_value[0]):
                         if len(str(tainted_index_var).split("_")) == 3:
                             transaction_index = int(
                                 str(tainted_index_var).split("_")[1])
                             argument_index = int(
                                 str(tainted_index_var).split("_")[2]) + 1
                             if type(individual.
                                     chromosome[transaction_index]
                                     ["arguments"][argument_index]
                                     ) is int and individual.chromosome[
                                         transaction_index]["arguments"][
                                             argument_index] > 2**128 - 1:
                                 return current_instruction["pc"]
     return None
Example #2
0
def rename_vars(pcs, global_states):
    ret_pcs = []
    vars_mapping = {}

    for expr in pcs:
        if is_expr(expr):
            list_vars = get_vars(expr)
            for var in list_vars:
                if var in vars_mapping:
                    expr = substitute(expr, (var, vars_mapping[var]))
                    continue
                var_name = var.decl().name()
                # check if a var is global
                if is_storage_var(var):
                    pos = get_storage_position(var)
                    # if it is not modified then keep the previous name
                    if pos not in global_states:
                        continue
                # otherwise, change the name of the variable
                new_var_name = var_name + '_old'
                new_var = BitVec(new_var_name, 256)
                vars_mapping[var] = new_var
                expr = substitute(expr, (var, vars_mapping[var]))
        ret_pcs.append(expr)

    ret_gs = {}
    # replace variable in storage expression
    for storage_addr in global_states:
        expr = global_states[storage_addr]
        # z3 4.1 makes me add this line
        if is_expr(expr):
            list_vars = get_vars(expr)
            for var in list_vars:
                if var in vars_mapping:
                    expr = substitute(expr, (var, vars_mapping[var]))
                    continue
                var_name = var.decl().name()
                # check if a var is global
                if var_name.startswith("Ia_store_"):
                    position = int(
                        var_name.split('_')[len(var_name.split('_')) - 1])
                    # if it is not modified
                    if position not in global_states:
                        continue
                # otherwise, change the name of the variable
                new_var_name = var_name + '_old'
                new_var = BitVec(new_var_name, 256)
                vars_mapping[var] = new_var
                expr = substitute(expr, (var, vars_mapping[var]))
        ret_gs[storage_addr] = expr

    return ret_pcs, ret_gs
Example #3
0
def rename_vars(pcs, global_states):
    ret_pcs = []
    vars_mapping = {}

    for expr in pcs:
        if is_expr(expr):
            list_vars = get_vars(expr)
            for var in list_vars:
                if var in vars_mapping:
                    expr = substitute(expr, (var, vars_mapping[var]))
                    continue
                var_name = var.decl().name()
                # check if a var is global
                if is_storage_var(var):
                    pos = get_storage_position(var)
                    # if it is not modified then keep the previous name
                    if pos not in global_states:
                        continue
                # otherwise, change the name of the variable
                new_var_name = var_name + '_old'
                new_var = BitVec(new_var_name, 256)
                vars_mapping[var] = new_var
                expr = substitute(expr, (var, vars_mapping[var]))
        ret_pcs.append(expr)

    ret_gs = {}
    # replace variable in storage expression
    for storage_addr in global_states:
        expr = global_states[storage_addr]
        # z3 4.1 makes me add this line
        if is_expr(expr):
            list_vars = get_vars(expr)
            for var in list_vars:
                if var in vars_mapping:
                    expr = substitute(expr, (var, vars_mapping[var]))
                    continue
                var_name = var.decl().name()
                # check if a var is global
                if var_name.startswith("Ia_store_"):
                    position = int(var_name.split('_')[len(var_name.split('_'))-1])
                    # if it is not modified
                    if position not in global_states:
                        continue
                # otherwise, change the name of the variable
                new_var_name = var_name + '_old'
                new_var = BitVec(new_var_name, 256)
                vars_mapping[var] = new_var
                expr = substitute(expr, (var, vars_mapping[var]))
        ret_gs[storage_addr] = expr

    return ret_pcs, ret_gs
 def detect_unhandled_exception(self, previous_instruction,
                                current_instruction, tainted_record):
     # Register all exceptions
     if previous_instruction and previous_instruction["op"] in [
             "CALL", "CALLCODE", "DELEGATECALL", "STATICCALL"
     ] and convert_stack_value_to_int(
             current_instruction["stack"][-1]) == 1:
         if tainted_record and tainted_record.stack and tainted_record.stack[
                 -1] and is_expr(tainted_record.stack[-1][0]):
             self.exceptions[tainted_record.stack[-1]
                             [0]] = previous_instruction["pc"]
     # Remove all handled exceptions
     elif current_instruction["op"] == "JUMPI" and self.exceptions:
         if tainted_record and tainted_record.stack and tainted_record.stack[
                 -2] and is_expr(tainted_record.stack[-2][0]):
             for var in get_vars(tainted_record.stack[-2][0]):
                 if var in self.exceptions:
                     del self.exceptions[var]
     # Report all unhandled exceptions at termination
     elif current_instruction["op"] in [
             "RETURN", "STOP", "SUICIDE", "SELFDESTRUCT"
     ] and self.exceptions:
         for exception in self.exceptions:
             return self.exceptions[exception]
     return None
Example #5
0
def efsmt(y, phi, maxloops=None):
    """Solving exists x. forall y. phi(x, y)"""
    vars = get_vars(phi)
    x = [item for item in vars if item not in y]
    esolver = Solver()
    fsolver = Solver()
    esolver.add(BoolVal(True))
    loops = 0
    while maxloops is None or loops <= maxloops:
        loops += 1
        eres = esolver.check()
        if eres == unsat:
            return unsat
        else:
            emodel = esolver.model()
            tau = [emodel.eval(var, True) for var in x]
            sub_phi = phi
            for i in range(len(x)):
                sub_phi = simplify(substitute(sub_phi, (x[i], tau[i])))
            fsolver.add(Not(sub_phi))
            if fsolver.check() == sat:
                fmodel = fsolver.model()
                sigma = [fmodel.eval(v, True) for v in y]
                sub_phi = phi
                for j in range(len(y)):
                    sub_phi = simplify(substitute(sub_phi, (y[j], sigma[j])))
                esolver.add(sub_phi)
            else:
                return sat
    return unknown
Example #6
0
def check_reentrancy_bug(memory, solver, path_condition: list = None):
    """This function is used to detect reentrancy vulnerabilities, 

    Args:
        path_condition: current path condition
        memory: current memory of Wasm
        solver: current z3 solver
    """
    list_solver = solver.units()
    for expr in list_solver:
        if not z3.is_expr(expr):
            continue
        vars = get_vars(expr)
        flag_empty = 0
        for var in vars:
            if var in global_vars.dict_symbolic_address:
                flag_empty += 1
                tmp_dict = global_vars.find_dict_root(var)
                if not tmp_dict:
                    continue
                for item in tmp_dict:
                    if item in global_vars.list_storageStore:
                        continue
                    else:
                        global_vars.find_reentrancy_detection()
        if flag_empty == 0:
            global_vars.find_reentrancy_detection()
Example #7
0
File: efsmt.py Project: nabice/z3
def efsmt(ys, phi, maxloops=None):
    """Solving exists xs. forall ys. phi(x, y)"""
    xs = [x for x in get_vars(phi) if x not in ys]
    E = Solver()
    F = Solver()
    E.add(BoolVal(True))
    loops = 0
    while maxloops is None or loops <= maxloops:
        loops += 1
        eres = E.check()
        if eres == sat:
            emodel = E.model()
            sub_phi = substitute(phi, [(x, emodel.eval(x, True)) for x in xs])
            F.push()
            F.add(Not(sub_phi))
            fres = F.check()
            if fres == sat:
                fmodel = F.model()
                sub_phi = substitute(phi,
                                     [(y, fmodel.eval(y, True)) for y in ys])
                E.add(sub_phi)
            else:
                return fres, [(x, emodel.eval(x, True)) for x in xs]
            F.pop()
        else:
            return eres
    return unknown
Example #8
0
def efsmt(y, phi, maxloops=None):
    """Solving exists x. forall y. phi(x, y)"""
    vars = get_vars(phi)
    x = [item for item in vars if item not in y]
    esolver = Solver()
    esolver.add(BoolVal(True))
    loops = 0
    while maxloops is None or loops <= maxloops:
        loops += 1
        eres = esolver.check()
        if eres == unsat:
            return unsat
        else:
            emodel = esolver.model()
            x_mappings = [(var, emodel.eval(var, model_completion=True)) for var in x]
            sub_phi = simplify(substitute(phi, x_mappings))
               
            fsolver = Solver()
            fsolver.add(Not(sub_phi))
            if fsolver.check() == sat:
                fmodel = fsolver.model()
                y_mappings = [(var, fmodel.eval(var, model_completion=True)) for var in y]
                sub_phi = simplify(substitute(phi, y_mappings))
                esolver.add(sub_phi)
            else:
                return sat
    return unknown
Example #9
0
def all_solns(problem, limit=10):
    if not isinstance(problem, Solvable):
        problem = Problem(problem, get_vars(z3.And(*problem)))
    s = z3.Solver()
    s.add(*problem.constraints())
    for _ in range(limit):
        if s.check() != z3.sat:
            return
        soln = s.model()
        yield Solution(soln)
        s.add(negate(problem, soln))
    print(f"Warning: Terminated early after {limit} solutions.")
Example #10
0
    def detect_integer_overflow(self, previous_instruction, current_instruction, tainted_record):
        if previous_instruction and previous_instruction["op"] == "ADD":
            a = convert_stack_value_to_int(previous_instruction["stack"][-2])
            b = convert_stack_value_to_int(previous_instruction["stack"][-1])
            c = convert_stack_value_to_int(current_instruction["stack"][-1])
            if a + b != c:
                if tainted_record and tainted_record.stack and tainted_record.stack[-1]:
                    if get_vars(tainted_record.stack[-1][0]):
                        self.overflows[previous_instruction["pc"]] = get_vars(tainted_record.stack[-1][0])

        elif previous_instruction and previous_instruction["op"] == "MUL":
            a = convert_stack_value_to_int(previous_instruction["stack"][-2])
            b = convert_stack_value_to_int(previous_instruction["stack"][-1])
            c = convert_stack_value_to_int(current_instruction["stack"][-1])
            if a * b != c:
                if tainted_record and tainted_record.stack and tainted_record.stack[-1]:
                    if get_vars(tainted_record.stack[-1][0]):
                        self.overflows[previous_instruction["pc"]] = get_vars(tainted_record.stack[-1][0])

        elif previous_instruction and previous_instruction["op"] == "SUB":
            a = convert_stack_value_to_int(previous_instruction["stack"][-2])
            b = convert_stack_value_to_int(previous_instruction["stack"][-1])
            c = convert_stack_value_to_int(current_instruction["stack"][-1])
            if a - b != c:
                if tainted_record and tainted_record.stack and tainted_record.stack[-1]:
                    if get_vars(tainted_record.stack[-1][0]):
                        self.underflows[previous_instruction["pc"]] = get_vars(tainted_record.stack[-1][0])

        if current_instruction and current_instruction["op"] == "SSTORE":
            if tainted_record and tainted_record.stack and tainted_record.stack[-2]:
                for pc in self.overflows:
                    for var1 in get_vars(tainted_record.stack[-2][0]):
                        for var2 in self.overflows[pc]:
                            if var1 == var2:
                                return pc, "overflow"
                for pc in self.underflows:
                    for var1 in get_vars(tainted_record.stack[-2][0]):
                        for var2 in self.underflows[pc]:
                            if var1 == var2:
                                return pc, "underflow"
        return None, None
Example #11
0
File: emu.py Project: xcode2010/ctf
 def load(self):
     index = regs[self.value]
     if isinstance(index, int):
         return mem[index]
     else:
         var, = get_vars(index)
         result = None
         for i in reversed(range(16)):
             index_i = substitute(index, (var, z3.BitVecVal(i, 4)))
             index_i = eval(str(index_i))
             mem_val = mem[index_i]
             if isinstance(mem_val, int):
                 mem_val = z3.BitVecVal(mem_val, 16)
             elif mem_val.size() != 16:
                 mem_val = z3.ZeroExt(16 - mem_val.size(), mem_val)
             if result is None:
                 result = mem_val
             else:
                 result = ite(var == i, mem_val, result)
         return result
Example #12
0
def get_all_vars(list_of_storage_exprs):
    ret_vars = []
    for expr in list_of_storage_exprs:
        ret_vars += get_vars(list_of_storage_exprs[expr])
    return ret_vars
Example #13
0
def has_storage_vars(expr, storage_vars):
    list_vars = get_vars(expr)
    for var in list_vars:
        if var in storage_vars:
            return True
    return False
Example #14
0
def is_in_expr(var, expr):
    list_vars = get_vars(expr)
    set_vars = set(i.decl().name() for i in list_vars)
    return var in set_vars
Example #15
0
def is_in_expr(var, expr):
    list_vars = get_vars(expr)
    set_vars = set(i.decl().name() for i in list_vars)
    return var in set_vars
Example #16
0
def get_all_vars(exprs):
    ret_vars = []
    for expr in exprs:
        if is_expr(expr):
            ret_vars += get_vars(expr)
    return ret_vars
Example #17
0
def has_storage_vars(expr, storage_vars):
    list_vars = get_vars(expr)
    for var in list_vars:
        if var in storage_vars:
            return True
    return False
Example #18
0
def get_all_vars(exprs):
    ret_vars = []
    for expr in exprs:
        if is_expr(expr):
            ret_vars += get_vars(expr)
    return ret_vars