Esempio n. 1
0
    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))
Esempio n. 2
0
    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()
Esempio n. 3
0
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"]
Esempio n. 4
0
    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))
Esempio n. 5
0
    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))
Esempio n. 6
0
    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
Esempio n. 7
0
    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()