def sym_exec(self, main_address=None, creation_code=None, contract_name=None, code_extension=None): logging.debug("Starting LASER execution") self.time = datetime.now() if main_address: logging.info("Starting message call transaction to {}".format(main_address)) execute_message_call(self, main_address) elif creation_code: logging.info("Starting contract creation transaction") created_account = execute_contract_creation(self, creation_code, contract_name=contract_name, code_extension=code_extension) logging.info("Finished contract creation, found {} open states".format(len(self.open_states))) if len(self.open_states) == 0: print("No contract was created during the execution of contract creation " "Try to increase the resources for creation exection (max-depth or create_timeout)") printd("Finished outer creation") # Reset code coverage self.coverage = {} self.time = datetime.now() logging.info("Starting message call transaction") execute_message_call(self, created_account.address) #self.time = datetime.now() #execute_message_call(self, created_account.address) logging.info("Finished symbolic execution") logging.info("%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states) for code, coverage in self.coverage.items(): cov = reduce(lambda sum_, val: sum_ + 1 if val else sum_, coverage[1]) / float(coverage[0]) * 100 logging.info("Achieved {} coverage for code: {}".format(cov, code))
def sym_exec( self, main_address=None, creation_code=None, contract_name=None ) -> None: """ :param main_address: :param creation_code: :param contract_name: """ log.debug("Starting LASER execution") for hook in self._start_sym_exec_hooks: hook() time_handler.start_execution(self.execution_timeout) self.time = datetime.now() if main_address: log.info("Starting message call transaction to {}".format(main_address)) self._execute_transactions(main_address) elif creation_code: log.info("Starting contract creation transaction") created_account = execute_contract_creation( self, creation_code, contract_name ) log.info( "Finished contract creation, found {} open states".format( len(self.open_states) ) ) if len(self.open_states) == 0: log.warning( "No contract was created during the execution of contract creation " "Increase the resources for creation execution (--max-depth or --create-timeout)" ) self._execute_transactions(created_account.address) log.info("Finished symbolic execution") if self.requires_statespace: log.info( "%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states, ) for code, coverage in self.coverage.items(): cov = sum(coverage[1]) / float(coverage[0]) * 100 log.info("Achieved {:.2f}% coverage for code: {}".format(cov, code)) if self.iprof is not None: log.info("Instruction Statistics:\n{}".format(self.iprof)) for hook in self._stop_sym_exec_hooks: hook()
def test_create(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol")) laser_evm = svm.LaserEVM({}) laser_evm.time = datetime.now() execute_contract_creation(laser_evm, contract.creation_code) resulting_final_state = laser_evm.open_states[0] for address, created_account in resulting_final_state.accounts.items(): created_account_code = created_account.code actual_code = Disassembly(contract.code) for i in range(len(created_account_code.instruction_list)): found_instruction = created_account_code.instruction_list[i] actual_instruction = actual_code.instruction_list[i] assert found_instruction["opcode"] == actual_instruction["opcode"]
def sym_exec(self, main_address=None, creation_code=None, contract_name=None): logging.debug("Starting LASER execution") self.time = datetime.now() if main_address: logging.info( "Starting message call transaction to {}".format(main_address)) execute_message_call(self, main_address) elif creation_code: logging.info("Starting contract creation transaction") created_account = execute_contract_creation( self, creation_code, contract_name) logging.info( "Finished contract creation, found {} open states".format( len(self.open_states))) if len(self.open_states) == 0: logging.warning( "No contract was created during the execution of contract creation " "Increase the resources for creation execution (--max-depth or --create-timeout)" ) # Reset code coverage self.coverage = {} for i in range(self.max_transaction_count): initial_coverage = self._get_covered_instructions() self.time = datetime.now() logging.info( "Starting message call transaction, iteration: {}".format( i)) execute_message_call(self, created_account.address) end_coverage = self._get_covered_instructions() if end_coverage == initial_coverage: break logging.info("Finished symbolic execution") logging.info( "%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states, ) for code, coverage in self.coverage.items(): cov = (reduce(lambda sum_, val: sum_ + 1 if val else sum_, coverage[1]) / float(coverage[0]) * 100) logging.info("Achieved {} coverage for code: {}".format(cov, code))
def sym_exec(self, main_address=None, creation_code=None, contract_name=None, priority=None) -> None: logging.debug("Starting LASER execution") self.time = datetime.now() if main_address: logging.info( "Starting message call transaction to {}".format(main_address)) self._execute_transactions(main_address, priority) elif creation_code: logging.info("Starting contract creation transaction") created_account = execute_contract_creation( self, creation_code, contract_name) logging.info( "Finished contract creation, found {} open states".format( len(self.open_states))) if len(self.open_states) == 0: logging.warning( "No contract was created during the execution of contract creation " "Increase the resources for creation execution (--max-depth or --create-timeout)" ) self._execute_transactions(created_account.address, priority) logging.info("Finished symbolic execution") logging.info( "%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states, ) for code, coverage in self.coverage.items(): cov = (reduce(lambda sum_, val: sum_ + 1 if val else sum_, coverage[1]) / float(coverage[0]) * 100) logging.info("Achieved {:.2f}% coverage for code: {}".format( cov, code))
def execute_state(self, global_state): instructions = global_state.environment.code.instruction_list try: op_code = instructions[global_state.mstate.pc]['opcode'] except IndexError: self.open_states.append(global_state.world_state) return [], None self._execute_pre_hook(op_code, global_state) try: self._measure_coverage(global_state) if self.prepostprocessor: global_state = self.prepostprocessor.preprocess(global_state) op_code = global_state.get_current_instruction()['opcode'] new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(global_state) if self.prepostprocessor: new_global_states = self.prepostprocessor.postprocess(global_state, new_global_states) except CreateNewContractSignal as c: laser_evm = LaserEVM(self.accounts, self.dynamic_loader, self.max_depth, self.execution_timeout, self.create_timeout, strategy=DepthFirstSearchStrategy, prepostprocessor=self.prepostprocessor) laser_evm.open_states = [self.world_state] printd("Start subconstruction") code_extension = SymbolicCodeExtension("calldata", "Subcontract", c.extension_byte_size, c.predefined_map) created_account = execute_contract_creation(laser_evm, c.bytecode, contract_name="Subcontract", code_extension=code_extension, callvalue=c.callvalue) if laser_evm.open_states: created_account = laser_evm.open_states[0].accounts[created_account.address] paused_state = c.paused_state paused_state.accounts[created_account.address] = created_account # Computing address from hex str returned to z3 BitVec representation address_as_int = 0 new_address = created_account.address.replace("0x", "") i = 0 while i < len(new_address): address_as_int *= 256 address_as_int += int(new_address[i:i + 2], 16) i += 2 paused_state.mstate.stack.append(BitVecVal(address_as_int, 256)) paused_state.mstate.pc += 1 # Because the post code of instruction wrapper was not executed after Signal new_global_states = [paused_state] if self.prepostprocessor: new_global_states = self.prepostprocessor.postprocess(global_state, new_global_states) printd("End subcontruction") except TransactionStartSignal as e: printd("Transaction start") # Setup new global state new_global_state = e.transaction.initial_global_state() new_global_state.transaction_stack = copy(global_state.transaction_stack) + [(e.transaction, global_state)] new_global_state.node = global_state.node new_global_state.mstate.constraints = global_state.mstate.constraints return [new_global_state], op_code except TransactionEndSignal as e: printd("Transaction end") transaction, return_global_state = e.global_state.transaction_stack.pop() if return_global_state is None: if not isinstance(transaction, ContractCreationTransaction) or transaction.return_data: e.global_state.world_state.node = global_state.node self.open_states.append(e.global_state.world_state) new_global_states = [] else: # First execute the post hook for the transaction ending instruction self._execute_post_hook(op_code, [e.global_state]) # Resume execution of the transaction initializing instruction op_code = return_global_state.environment.code.instruction_list[return_global_state.mstate.pc]['opcode'] # Set execution result in the return_state return_global_state.last_return_data = transaction.return_data return_global_state.world_state = copy(global_state.world_state) return_global_state.environment.active_account = \ global_state.accounts[return_global_state.environment.active_account.address] #if self.prepostprocessor: # global_state = self.prepostprocessor.preprocess(global_state) # op_code = global_state.get_current_instruction()['opcode'] # Execute the post instruction handler new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(return_global_state, True) #if self.prepostprocessor: # new_global_states = self.prepostprocessor.postprocess(global_state, new_global_states) # In order to get a nice call graph we need to set the nodes here for state in new_global_states: state.node = global_state.node self._execute_post_hook(op_code, new_global_states) # Todo Maybe also filter here return new_global_states, op_code
def sym_exec( self, world_state: WorldState = None, target_address: int = None, creation_code: str = None, contract_name: str = None, ) -> None: """ Starts symbolic execution There are two modes of execution. Either we analyze a preconfigured configuration, in which case the world_state and target_address variables must be supplied. Or we execute the creation code of a contract, in which case the creation code and desired name of that contract should be provided. :param world_state The world state configuration from which to perform analysis :param target_address The address of the contract account in the world state which analysis should target :param creation_code The creation code to create the target contract in the symbolic environment :param contract_name The name that the created account should be associated with """ pre_configuration_mode = target_address is not None scratch_mode = creation_code is not None and contract_name is not None if pre_configuration_mode == scratch_mode: raise ValueError( "Symbolic execution started with invalid parameters") log.debug("Starting LASER execution") for hook in self._start_sym_exec_hooks: hook() time_handler.start_execution(self.execution_timeout) self.time = datetime.now() if pre_configuration_mode: self.open_states = [world_state] log.info("Starting message call transaction to {}".format( target_address)) self._execute_transactions( symbol_factory.BitVecVal(target_address, 256)) elif scratch_mode: log.info("Starting contract creation transaction") created_account = execute_contract_creation( self, creation_code, contract_name, world_state=world_state) log.info("Finished contract creation, found {} open states".format( len(self.open_states))) if len(self.open_states) == 0: log.warning( "No contract was created during the execution of contract creation " "Increase the resources for creation execution (--max-depth or --create-timeout)" ) self._execute_transactions(created_account.address) log.info("Finished symbolic execution") if self.requires_statespace: log.info( "%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states, ) if self.iprof is not None: log.info("Instruction Statistics:\n{}".format(self.iprof)) for hook in self._stop_sym_exec_hooks: hook()