def execute_message_call(laser_evm, callee_address: str) -> None: """Executes a message call transaction from all open states. :param laser_evm: :param callee_address: """ # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: if open_world_state[callee_address].deleted: log.debug("Can not execute dead contract, skipping.") continue next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( world_state=open_world_state, identifier=next_transaction_id, gas_price=symbol_factory.BitVecSym( "gas_price{}".format(next_transaction_id), 256), gas_limit=8000000, # block gas limit origin=symbol_factory.BitVecSym( "origin{}".format(next_transaction_id), 256), caller=symbol_factory.BitVecVal(ATTACKER_ADDRESS, 256), callee_account=open_world_state[callee_address], call_data=SymbolicCalldata(next_transaction_id), call_value=symbol_factory.BitVecSym( "call_value{}".format(next_transaction_id), 256), ) _setup_global_state_for_execution(laser_evm, transaction) laser_evm.exec()
def execute_message_call( laser_evm, callee_address, caller_address, origin_address, code, data, gas, gas_price, value, ): """ Executes a message call transaction from all open states """ open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( identifier=next_transaction_id, world_state=open_world_state, callee_account=open_world_state[callee_address], caller=caller_address, call_data=Calldata(next_transaction_id, data), gas_price=gas_price, call_value=value, origin=origin_address, call_data_type=CalldataType.SYMBOLIC, code=Disassembly(code), ) _setup_global_state_for_execution(laser_evm, transaction) laser_evm.exec()
def execute_message_call(laser_evm, callee_address): """ Executes a message call transaction from all open states """ open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: if open_world_state[callee_address].deleted: debug("Can not execute dead contract, skipping.") continue next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( world_state=open_world_state, callee_account=open_world_state[callee_address], caller=BitVec("caller{}".format(next_transaction_id), 256), identifier=next_transaction_id, call_data=Calldata(next_transaction_id), gas_price=BitVec("gas_price{}".format(next_transaction_id), 256), call_value=BitVec("call_value{}".format(next_transaction_id), 256), origin=BitVec("origin{}".format(next_transaction_id), 256), call_data_type=CalldataType.SYMBOLIC, ) _setup_global_state_for_execution(laser_evm, transaction) laser_evm.exec()
def execute_create(): global last_state global created_contract_account if not last_state and not created_contract_account: code_raw = [] for i in range(len(contract_init_code) // 2): code_raw.append(int(contract_init_code[2 * i:2 * (i + 1)], 16)) calldata = ConcreteCalldata(0, code_raw) world_state = WorldState() account = world_state.create_account(balance=1000000, address=101) account.code = Disassembly("60a760006000f000") environment = Environment(account, None, calldata, None, None, None) og_state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000)) og_state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)) laser = LaserEVM() states = [og_state] last_state = og_state for state in states: new_states, op_code = laser.execute_state(state) last_state = state if op_code == "STOP": break states.extend(new_states) created_contract_address = last_state.mstate.stack[-1].value created_contract_account = last_state.world_state.accounts[ created_contract_address] return last_state, created_contract_account
def get_state(): active_account = Account("0x0", code=Disassembly("60606040")) environment = Environment(active_account, None, None, None, None, None) state = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) ) return state
def get_state(): world_state = WorldState() account = world_state.create_account(balance=10, address=101) account.code = Disassembly("60606040") environment = Environment(account, None, None, None, None, None) state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000)) state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)) return state
def execute_message_call( laser_evm, callee_address, caller_address, origin_address, code, data, gas_limit, gas_price, value, track_gas=False, ) -> Union[None, List[GlobalState]]: """Execute a message call transaction from all open states. :param laser_evm: :param callee_address: :param caller_address: :param origin_address: :param code: :param data: :param gas_limit: :param gas_price: :param value: :param track_gas: :return: """ # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( world_state=open_world_state, identifier=next_transaction_id, gas_price=gas_price, gas_limit=gas_limit, origin=origin_address, code=Disassembly(code), caller=caller_address, callee_account=open_world_state[callee_address], call_data=ConcreteCalldata(next_transaction_id, data), call_value=value, ) _setup_global_state_for_execution(laser_evm, transaction) return laser_evm.exec(track_gas=track_gas)
def execute_message_call(laser_evm, callee_address): """ Executes a message call transaction from all open states """ open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: transaction = MessageCallTransaction( open_world_state, open_world_state[callee_address], BitVec("caller", 256), [], BitVec("gas_price", 256), BitVec("call_value", 256), BitVec("origin", 256), CalldataType.SYMBOLIC, ) _setup_global_state_for_execution(laser_evm, transaction) laser_evm.exec()
def test_codecopy_concrete(): # Arrange active_account = Account("0x0", code=Disassembly("60606040")) environment = Environment(active_account, None, None, None, None, None) og_state = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) og_state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)) og_state.mstate.stack = [2, 2, 2] instruction = Instruction("codecopy", dynamic_loader=None) # Act new_state = instruction.evaluate(og_state)[0] # Assert assert new_state.mstate.memory[2] == 96 assert new_state.mstate.memory[3] == 64
def execute_message_call(laser_evm, callee_address): """ Executes a message call transaction from all open states """ open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: try: open_world_state = open_states[0] open_world_state.accounts = deepcopy(open_world_state.accounts) for address, account in open_world_state.accounts.items(): account.reset_state() if not laser_evm.open_states: laser_evm.open_states.append(open_world_state) else: for address, account in open_world_state.accounts.items(): for added_world_state in laser_evm.open_states: if address not in added_world_state.accounts: for address_existing, account_existing in added_world_state.accounts.items( ): if account.code != account_existing.code: raise FoundDistinctGlobalWorldState() except FoundDistinctGlobalWorldState as f: laser_evm.open_states.append(open_world_state) open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: transaction = MessageCallTransaction( open_world_state, open_world_state[callee_address], BitVec("caller", 256), [], BitVec("gasprice", 256), BitVec("callvalue", 256), BitVec("origin", 256), CalldataType.SYMBOLIC, ) _setup_global_state_for_execution(laser_evm, transaction) laser_evm.exec()
def test_extcodecopy_fail(): # Arrange new_world_state = WorldState() new_account = new_world_state.create_account(balance=10, address=101) new_account.code = Disassembly("60616240") new_environment = Environment(new_account, None, None, None, None, None) state = GlobalState( new_world_state, new_environment, None, MachineState(gas_limit=8000000) ) state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) ) state.mstate.stack = [2, 2, 2, symbol_factory.BitVecSym("FAIL", 256)] instruction = Instruction("extcodecopy", dynamic_loader=None) # Act new_state = instruction.evaluate(state)[0] # Assert assert new_state.mstate.stack == [] assert new_state.mstate.memory._memory == state.mstate.memory._memory
def test_extcodecopy(): # Arrange new_world_state = WorldState() new_account = new_world_state.create_account(balance=10, address=101) new_account.code = Disassembly("60616240") ext_account = new_world_state.create_account(balance=1000, address=121) ext_account.code = Disassembly("6040404040") new_environment = Environment(new_account, None, None, None, None, None) state = GlobalState( new_world_state, new_environment, None, MachineState(gas_limit=8000000) ) state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) ) state.mstate.stack = [3, 0, 0, 121] instruction = Instruction("extcodecopy", dynamic_loader=None) # Act new_state = instruction.evaluate(state)[0] # Assert assert new_state.mstate.memory[0:3] == [96, 64, 64]
def execute_message_call(laser_evm, callee_address: str, priority=None) -> None: """ Executes a message call transaction from all open states """ # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here # TODO: if the function of openstate.node.funcname is not in priority list, dont add it # TODO: This is for deleting repeated variables read # copy the open states from last iteration to this iteration # The working list is always empty when an iteration is done open_states = laser_evm.open_states[:] del laser_evm.open_states[:] for open_world_state in open_states: if open_world_state[callee_address].deleted: debug("Can not execute dead contract, skipping.") continue next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( world_state=open_world_state, identifier=next_transaction_id, gas_price=BitVec("gas_price{}".format(next_transaction_id), 256), gas_limit=8000000, # block gas limit origin=BitVec("origin{}".format(next_transaction_id), 256), caller=BitVecVal(ATTACKER_ADDRESS, 256), callee_account=open_world_state[callee_address], call_data=SymbolicCalldata(next_transaction_id), call_data_type=CalldataType.SYMBOLIC, call_value=BitVec("call_value{}".format(next_transaction_id), 256), ) # the open states from last iterations are appended to work list here _setup_global_state_for_execution(laser_evm, transaction, open_world_state.node.function_name) laser_evm.exec(priority=None)
def heuristic_message_call_helper(laser_evm, callee_address: str, priority=None): jump = False open_states_copy = copy(laser_evm.open_states) for open_state in open_states_copy: name = open_state.node.function_name for priority_list in priority['RAW']: if name == priority_list.first.function_name: laser_evm.first_order_work_list.append(open_state) laser_evm.open_states.remove(open_state) jump = True break if jump: jump = False continue for priority_list in priority['WAR']: if name == priority_list.first.function_name: laser_evm.second_order_work_list.append(open_state) laser_evm.open_states.remove(open_state) jump = True break if jump: jump = False continue for priority_list in priority['WAW']: if name == priority_list.first.function_name: laser_evm.third_order_work_list.append(open_state) laser_evm.open_states.remove(open_state) jump = True break if jump: jump = False continue for priority_list in priority['RAR']: if name == priority_list.first.function_name: laser_evm.forth_order_work_list.append(open_state) laser_evm.open_states.remove(open_state) jump = True break if jump: jump = False continue laser_evm.ranking.append(laser_evm.first_order_work_list) laser_evm.ranking.append(laser_evm.second_order_work_list) laser_evm.ranking.append(laser_evm.third_order_work_list) laser_evm.ranking.append(laser_evm.forth_order_work_list) del laser_evm.open_states[:] for items in laser_evm.ranking: title = items[0] list1 = items[1:] for open_world_state in list1: if open_world_state[callee_address].deleted: debug("Can not execute dead contract, skipping.") continue last_func_called = open_world_state.node.function_name next_transaction_id = get_next_transaction_id() transaction = MessageCallTransaction( world_state=open_world_state, callee_account=open_world_state[callee_address], caller=BitVecVal(ATTACKER_ADDRESS, 256), identifier=next_transaction_id, call_data=SymbolicCalldata(next_transaction_id), gas_price=BitVec("gas_price{}".format(next_transaction_id), 256), call_value=BitVec("call_value{}".format(next_transaction_id), 256), origin=BitVec("origin{}".format(next_transaction_id), 256), call_data_type=CalldataType.SYMBOLIC, gas_limit=8000000, # block gas limit ) # the open states from last iterations are appended to work list here _setup_global_state_for_execution(laser_evm, transaction, last_func_called) laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm) # Execute the new open states added to the work list in Instruction.jumpi_ function if title == 'RAW': for gs in laser_evm.second_work_list: laser_evm.work_list.append(gs) laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm) elif title == 'WAR': for gs in laser_evm.third_work_list: laser_evm.work_list.append(gs) laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm) elif title == 'WAW': for gs in laser_evm.forth_work_list: laser_evm.work_list.append(gs) laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm)
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction from mythril.support.support_utils import get_code_hash from mythril.laser.smt import symbol_factory # Arrange world_state = WorldState() account = world_state.create_account(balance=10, address=101) account.code = Disassembly("60606040") world_state.create_account(balance=10, address=1000) environment = Environment(account, None, None, None, None, None) og_state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000)) og_state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)) instruction = Instruction("extcodehash", dynamic_loader=None) def test_extcodehash_no_account(): # If account does not exist, return 0 og_state.mstate.stack = [symbol_factory.BitVecVal(1, 256)] new_state = instruction.evaluate(og_state)[0] assert new_state.mstate.stack[-1] == 0 def test_extcodehash_no_code(): # If account code does not exist, return hash of empty set.