def deploy_contracts(self): # Gathering existing libraries self.contract_name_to_contract, lib_name_to_address = svm_utils.generate_contract_objects(self.contract_to_build_data, self.hash_to_func_name) self.swarm_hash_to_contract = svm_utils.resolve_swarmhashes(self.contract_name_to_contract) for contract in self.contract_name_to_contract.values(): swarm_hashes = tuple(contract.creation_disassembly.swarm_hashes) self.swarm_hash_tuple_to_contract[swarm_hashes] = contract for address, contract in self.address_to_contract.items(): int_address = int(address[2:], 16) account = Account(int_address, self.contract_name_to_contract[contract.name]) self.root_wstate.address_to_account[int_address] = account logging.info(f'Deployed contracts: {pprint.pformat(self.root_wstate.address_to_account)}') self.gen_to_wstates[self.root_wstate.gen].append(self.root_wstate) timestamp_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.TIMESTAMP, self.root_wstate.gen) timestamp_constraint = ULT(1438214400, timestamp_vec) self.root_wstate.constraints.append(timestamp_constraint)
from opcodes import BYTE, SHR, DIV from rule import Rule from z3 import BitVec, ULT """ byte(A, shr(B, X)) given A < B / 8 -> 0 """ rule = Rule() n_bits = 256 # Input vars X = BitVec('X', n_bits) A = BitVec('A', n_bits) B = BitVec('B', n_bits) # Non optimized result nonopt = BYTE(A, SHR(B, X)) # Optimized result opt = 0 rule.require(ULT(A, DIV(B, 8))) rule.check(nonopt, opt)
def visit_MLIL_CMP_ULT(self, expr): left = self.visit(expr.left) right = self.visit(expr.right) if None not in (left, right): return ULT(left, right)
def visit_MLIL_CMP_ULT(self, expr): left, right = self.visit_both_sides(expr) if right.size() != left.size(): right = ZeroExt(left.size() - right.size(), right) return ULT(left, right)
from opcodes import SIGNEXTEND, AND from rule import Rule from z3 import BitVec, BitVecVal, ULT """ Rule: AND(A, SIGNEXTEND(B, X)) -> AND(A, X) given B < WordSize / 8 - 1 AND A & (1 << ((B + 1) * 8) - 1) == A """ n_bits = 128 # Input vars X = BitVec('X', n_bits) A = BitVec('A', n_bits) B = BitVec('B', n_bits) rule = Rule() # Requirements rule.require(ULT(B, BitVecVal(n_bits // 8 - 1, n_bits))) rule.require((A & ((BitVecVal(1, n_bits) << ((B + 1) * 8)) - 1)) == A) rule.check(AND(A, SIGNEXTEND(B, X)), AND(A, X))
def lt_(self, global_state): state = global_state.mstate exp = ULT(util.pop_bitvec(state), util.pop_bitvec(state)) state.stack.append(exp) return [global_state]
def operate_LT(self, *values): s0 = hlp.convert_to_bitvec(values[0]) s1 = hlp.convert_to_bitvec(values[1]) return hlp.get_concrete_int(ULT(s0, s1))
SHL(B, AND(A, X)) -> AND(SHL(B, X), A << B) Requirements: B < BitWidth """ rule = Rule() n_bits = 128 # Input vars X = BitVec('X', n_bits) A = BitVec('A', n_bits) B = BitVec('B', n_bits) # Constants BitWidth = BitVecVal(n_bits, n_bits) # Requirements rule.require(ULT(B, BitWidth)) # Non optimized result nonopt_1 = SHL(B, AND(X, A)) nonopt_2 = SHL(B, AND(A, X)) # Optimized result Mask = SHL(B, A) opt = AND(SHL(B, X), Mask) rule.check(nonopt_1, opt) rule.check(nonopt_2, opt)
def LT(x, y): return If(ULT(x, y), BitVecVal(1, x.size()), BitVecVal(0, x.size()))
def sym_call_address(self, address, wstate, method=None, arguments=None, amount=None, timestamp=None): # Initialize the execution environment account = wstate.address_to_account[address] if account.typ == AccountType.LIBRARY: return [] child_wstate = wstate.child() logging.debug(BColors.GREEN + BColors.REVERSED + 'Starting SVM execution' + BColors.ENDC + ' with address: ' + hex(address) + ' contract: ' + account.contract.name) caller_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLER, child_wstate.gen) caller_constraint = z3.Or([caller_vec == p for p in self.possible_caller_addresses]) child_wstate.constraints.append(caller_constraint) calldata = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATA_ARRAY, child_wstate.gen, acc=account.id) if method is not None and method.name != Method.FALLBACK: calldata_0 = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATA, child_wstate.gen, index=0) calldata_4bytes, _ = svm_utils.split_bv(calldata_0, calldata_0.size() - 32) calldatasize = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATASIZE, child_wstate.gen, acc=account.id) entry_account = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.ENTRY_ACCOUNT, child_wstate.gen) method_constraint = z3.And(calldata_4bytes == method.idd, z3.ULE(4, calldatasize), entry_account == address) child_wstate.constraints.append(method_constraint) if arguments is not None and len(arguments): encoded_args = utils.abi_encode(method.inputs, arguments) for i, arg in enumerate(encoded_args): if arg is None: continue calldata_i = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATA, child_wstate.gen, index=4+32*i) child_wstate.constraints.append(calldata_i == z3.BitVecVal(arg, 256)) gasprice_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.GASPRICE, child_wstate.gen) callvalue_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLVALUE, child_wstate.gen) origin_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.ORIGIN, child_wstate.gen) timestamp_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.TIMESTAMP, child_wstate.gen) parent_timestamp_vec = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.TIMESTAMP, wstate.gen) callvalue_constraint = ULT(callvalue_vec, svm_utils.ETHER_LIMIT) timestamp_constraint = ULT(parent_timestamp_vec, timestamp_vec) entry_account = self.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.ENTRY_ACCOUNT, child_wstate.gen) child_wstate.constraints.append(callvalue_constraint) child_wstate.constraints.append(timestamp_constraint) child_wstate.constraints.append(entry_account == account.address) environment = Environment(active_address=address, sender=caller_vec, calldata=calldata, gasprice=gasprice_vec, callvalue=callvalue_vec, origin=origin_vec, calldata_type=CalldataType.UNDEFINED, disassembly=account.contract.disassembly, runtime_bytecode_bytes=list(account.contract.disassembly.bytecode), timestamp=timestamp_vec) gstate = GlobalState(child_wstate, environment) return self.executor.execute_gstate(gstate)
from opcodes import BYTE, DIV, SHR from rule import Rule from z3 import BitVec, UGE, ULE, ULT """ byte(A, shr(B, X)) given B % 8 == 0 && A < n_bits/8 && B <= n_bits && A >= B / 8 -> byte(A - B / 8, X) """ rule = Rule() n_bits = 256 # Input vars X = BitVec('X', n_bits) A = BitVec('A', n_bits) B = BitVec('B', n_bits) # Non optimized result nonopt = BYTE(A, SHR(B, X)) # Optimized result opt = BYTE(A - B / 8, X) rule.require(B % 8 == 0) rule.require(ULT(A, n_bits / 8)) rule.require(ULE(B, n_bits)) rule.require(UGE(A, DIV(B, 8))) rule.check(nonopt, opt)
from rule import Rule from z3 import BitVec, BitVecVal, If, UGE, ULT """ Rule: 1) SIGNEXTEND(A, X) -> X if A >= Pattern::WordSize / 8 - 1; 2) SIGNEXTEND(X, SIGNEXTEND(X, Y)) -> SIGNEXTEND(X, Y) 3) SIGNEXTEND(A, SIGNEXTEND(B, X)) -> SIGNEXTEND(min(A, B), X) """ n_bits = 128 # Input vars X = BitVec('X', n_bits) Y = BitVec('Y', n_bits) A = BitVec('A', n_bits) B = BitVec('B', n_bits) rule1 = Rule() # Requirements rule1.require(UGE(A, BitVecVal(n_bits // 8 - 1, n_bits))) rule1.check(SIGNEXTEND(A, X), X) rule2 = Rule() rule2.check(SIGNEXTEND(X, SIGNEXTEND(X, Y)), SIGNEXTEND(X, Y)) rule3 = Rule() rule3.check(SIGNEXTEND(A, SIGNEXTEND(B, X)), SIGNEXTEND(If(ULT(A, B), A, B), X))