class EthDetectorTest(unittest.TestCase): """ Subclasses must assign this class variable to the class for the detector """ DETECTOR_CLASS = None def setUp(self): self.mevm = ManticoreEVM() self.mevm.verbosity(0) self.worksp = self.mevm.workspace def tearDown(self): self.mevm = None shutil.rmtree(self.worksp) def _test(self, name, should_find): """ Tests DetectInvalid over the consensys benchmark suit """ mevm = self.mevm filename = os.path.join(THIS_DIR, 'binaries', 'detectors', '{}.sol'.format(name)) self.mevm.register_detector(self.DETECTOR_CLASS()) mevm.multi_tx_analysis(filename, contract_name='DetectThis', args=(mevm.make_symbolic_value(), )) expected_findings = set(((c, d) for b, c, d in should_find)) actual_findings = set(((c, d) for a, b, c, d in mevm.global_findings)) self.assertEqual(expected_findings, actual_findings)
def _find_test_cases(self): print('Finding test cases ...') self._main_evm = ManticoreEVM(workspace_url=self._args.workspace) if self._args.quick_mode: self._args.avoid_constant = True self._args.exclude_all = True self._args.only_alive_testcases = True consts_evm = config.get_group("evm") consts_evm.oog = "ignore" consts.skip_reverts = True if consts.skip_reverts: self._main_evm.register_plugin(SkipRevertBasicBlocks()) if consts.explore_balance: self._main_evm.register_plugin(KeepOnlyIfStorageChanges()) if self._args.limit_loops: self._main_evm.register_plugin(LoopDepthLimiter()) with self._main_evm.kill_timeout(): self._main_evm.multi_tx_analysis( self._args.argv[0], contract_name=self._args.contract, tx_limit=self._args.txlimit, tx_use_coverage=not self._args.txnocoverage, tx_send_ether=not self._args.txnoether, tx_account=self._args.txaccount, tx_preconstrain=self._args.txpreconstrain, compile_args=vars(self._args), ) self._test_cases = list(self._main_evm.all_states)
def test_graceful_handle_no_alive_states(self): """ If there are no alive states, or no initial states, we should not crash. issue #795 """ # initiate the blockchain m = ManticoreEVM() source_code = ''' contract Simple { function f(uint a) payable public { if (a == 65) { revert(); } } } ''' # Initiate the accounts user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) contract_account.f(1) # it works contract_account.f(65) # it works with self.assertRaises(NoAliveStates): contract_account.f( m.SValue) # no alive states, but try to run a tx anyway
class EthDetectorTest(unittest.TestCase): """ Subclasses must assign this class variable to the class for the detector """ DETECTOR_CLASS = None def setUp(self): self.mevm = ManticoreEVM() self.mevm.verbosity(0) self.worksp = self.mevm.workspace def tearDown(self): self.mevm = None shutil.rmtree(self.worksp) def _test(self, name, should_find, use_ctor_sym_arg=False): """ Tests DetectInvalid over the consensys benchmark suit """ mevm = self.mevm dir = os.path.join(THIS_DIR, 'binaries', 'detectors') filepath = os.path.join(dir, f'{name}.sol') if use_ctor_sym_arg: ctor_arg = (mevm.make_symbolic_value(),) else: ctor_arg = () self.mevm.register_detector(self.DETECTOR_CLASS()) mevm.multi_tx_analysis(filepath, contract_name='DetectThis', args=ctor_arg, working_dir=dir) expected_findings = set(((finding, at_init) for finding, at_init in should_find)) actual_findings = set(((finding, at_init) for _addr, _pc, finding, at_init in mevm.global_findings)) self.assertEqual(expected_findings, actual_findings)
def setUp(self): evm_consts = config.get_group("evm") self.saved_sha3 = evm_consts.sha3 evm_consts.sha3 = evm_consts.sha3.fake self.mevm = ManticoreEVM() self.worksp = self.mevm.workspace
def test_run_solc(self): source_a = ''' import "./B.sol"; contract A { function callB(B _b) public { _b.fromA(); } function fromB() public { revert(); } } ''' source_b = ''' import "./A.sol"; contract B { function callA(A _a) public { _a.fromB(); } function fromA() public { revert(); } } ''' d = tempfile.mkdtemp() try: with open(os.path.join(d, 'A.sol'), 'w') as a, open(os.path.join(d, 'B.sol'), 'w') as b: a.write(source_a) a.flush() b.write(source_b) b.flush() output, warnings = ManticoreEVM._run_solc(a) source_list = output.get('sourceList', []) self.assertIn(os.path.split(a.name)[-1], source_list) self.assertIn(os.path.split(b.name)[-1], source_list) finally: shutil.rmtree(d)
def test_run_solc_with_remappings(self): source_a = ''' import "test/B.sol"; contract A { function callB(B _b) public { _b.fromA(); } function fromB() public { revert(); } } ''' source_b = ''' import "../A.sol"; contract B { function callA(A _a) public { _a.fromB(); } function fromA() public { revert(); } } ''' d = tempfile.mkdtemp() lib_dir = os.path.join(d, 'lib') os.makedirs(lib_dir) try: with open(os.path.join(d, 'A.sol'), 'w') as a, open(os.path.join(lib_dir, 'B.sol'), 'w') as b: a.write(source_a) a.flush() b.write(source_b) b.flush() output, warnings = ManticoreEVM._run_solc( a, solc_remaps=['test=lib']) source_list = output.get('sourceList', []) self.assertIn("A.sol", source_list) self.assertIn("lib/B.sol", source_list) finally: shutil.rmtree(d)
class EthRetVal(unittest.TestCase): """ https://consensys.net/diligence/evm-analyzer-benchmark-suite/ """ def setUp(self): self.mevm = ManticoreEVM() self.mevm.verbosity(0) self.worksp = self.mevm.workspace def tearDown(self): self.mevm = None shutil.rmtree(self.worksp) def _test(self, name, should_find): """ Tests DetectInvalid over the consensys benchmark suit """ mevm = self.mevm filename = os.path.join(THIS_DIR, 'binaries', 'detectors', '{}.sol'.format(name)) self.mevm.register_detector(DetectUnusedRetVal()) mevm.multi_tx_analysis(filename, contract_name='DetectThis', args=(mevm.make_symbolic_value(), )) expected_findings = set(((c, d) for b, c, d in should_find)) actual_findings = set(((c, d) for a, b, c, d in mevm.global_findings)) self.assertEqual(expected_findings, actual_findings) def test_retval_ok(self): name = inspect.currentframe().f_code.co_name[5:] self._test(name, set()) def test_retval_not_ok(self): name = inspect.currentframe().f_code.co_name[5:] self._test( name, set([(337, 'Returned value at CALL instruction is not used', False) ])) def test_retval_crazy(self): name = inspect.currentframe().f_code.co_name[5:] self._test(name, set()) def test_retval_lunatic(self): name = inspect.currentframe().f_code.co_name[5:] self._test(name, set())
class EthDetectorTest(unittest.TestCase): """ Subclasses must assign this class variable to the class for the detector """ DETECTOR_CLASS = None def setUp(self): self.mevm = ManticoreEVM() self.mevm.register_plugin(KeepOnlyIfStorageChanges()) log.set_verbosity(0) self.worksp = self.mevm.workspace def tearDown(self): self.mevm = None shutil.rmtree(self.worksp) def _test(self, name, should_find, use_ctor_sym_arg=False): """ Tests DetectInvalid over the consensys benchmark suit """ mevm = self.mevm dir = os.path.join(THIS_DIR, "contracts", "detectors") filepath = os.path.join(dir, f"{name}.sol") if use_ctor_sym_arg: ctor_arg = (mevm.make_symbolic_value(),) else: ctor_arg = () self.mevm.register_detector(self.DETECTOR_CLASS()) with self.mevm.kill_timeout(240): mevm.multi_tx_analysis( filepath, contract_name="DetectThis", args=ctor_arg, compile_args={"solc_working_dir": dir}, ) mevm.finalize() expected_findings = set(((finding, at_init) for finding, at_init in should_find)) actual_findings = set( ((finding, at_init) for _addr, _pc, finding, at_init in mevm.global_findings) ) self.assertEqual(expected_findings, actual_findings)
def test_parse_tx(self): m = ManticoreEVM() source_code = ''' contract C{ mapping(address => uint) balances; function test1(address to, uint val){ balances[to] = val; } } ''' user_account = m.create_account(balance=1000, name='user_account') contract_account = m.solidity_create_contract(source_code, owner=user_account, name='contract_account') calldata = binascii.unhexlify(b'9de4886f9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d') returndata = b'' md = m.get_metadata(contract_account) self.assertEqual(md.parse_tx(calldata, returndata), 'test1(899826498278242188854817720535123270925417291165, 71291600040229971300002528024956868756719167029433602173313100742126907268509)')
class EthBenchmark(unittest.TestCase): """ https://consensys.net/diligence/evm-analyzer-benchmark-suite/ """ def setUp(self): self.mevm = ManticoreEVM() self.mevm.verbosity(0) self.worksp = self.mevm.workspace def tearDown(self): self.mevm = None shutil.rmtree(self.worksp) def _test_assert(self, name, should_find): """ Tests DetectInvalid over the consensys benchmark suit """ mevm = self.mevm d = DetectInvalid() mevm.register_detector(d) filename = os.path.join(THIS_DIR, 'binaries', 'benchmark', '{}.sol'.format(name)) mevm.multi_tx_analysis(filename, tx_limit=3) actual_findings = set(((b, c, d) for a, b, c, d in d.global_findings)) self.assertEqual(should_find, actual_findings) def test_assert_minimal(self): self._test_assert('assert_minimal', set([(95, 'INVALID intruction', False)])) def test_assert_constructor(self): self._test_assert('assert_constructor', set([(23L, 'INVALID intruction', True)])) def test_assert_multitx_1(self): self._test_assert('assert_multitx_1', set()) def test_assert_multitx_2(self): self._test_assert('assert_multitx_2', set([(150, 'INVALID intruction', False)]))
def manticore(self): if self._manticore is None: if self._assigned_manticore is None: # we do lazy evaluation of ManticoreClient.manticore so self.log_directory will be assigned already if self.log_directory is None: workspace = None else: workspace = self.log_directory self._assigned_manticore = ManticoreEVM( workspace_url=workspace) self._manticore = threadwrapper.MainThreadWrapper( self._assigned_manticore, _CONTROLLER) self._finalize_manticore() return self._manticore
def test_int_ovf(self): mevm = ManticoreEVM() mevm.register_detector(DetectIntegerOverflow()) filename = os.path.join(THIS_DIR, 'binaries/int_overflow.sol') mevm.multi_tx_analysis(filename, tx_limit=1) self.assertEqual(len(mevm.global_findings), 3) all_findings = ''.join([x[2] for x in mevm.global_findings]) self.assertIn('Unsigned integer overflow at SUB instruction', all_findings) self.assertIn('Unsigned integer overflow at ADD instruction', all_findings) self.assertIn('Unsigned integer overflow at MUL instruction', all_findings)
def test_int_ovf(self): mevm = ManticoreEVM() mevm.register_detector(IntegerOverflow()) filename = os.path.join(THIS_DIR, 'binaries/int_overflow.sol') mevm.multi_tx_analysis(filename) self.assertEqual(len(mevm.global_findings), 3) all_findings = ''.join(map(lambda x: x[2], mevm.global_findings)) self.assertIn('underflow at SUB', all_findings) self.assertIn('overflow at ADD', all_findings) self.assertIn('overflow at MUL', all_findings)
def _run_test_case_on_contract(self, contract_code, conc_txs): m2 = ManticoreEVM() owner_account = m2.create_account( balance=10**10, name="owner", address=self._main_evm.accounts.get('owner').address) attacker_account = m2.create_account( balance=10**10, name="attacker", address=self._main_evm.accounts.get('attacker').address) try: call_args = get_argument_from_create_transaction( self._main_evm, conc_txs[0]) create_value = m2.make_symbolic_value() m2.constrain(create_value == conc_txs[0].value) contract_account = solidity_create_contract_with_zero_price( m2, contract_code, owner=owner_account, args=call_args, balance=create_value, gas=0, ) except Exception as e: return m2 for conc_tx in conc_txs[1:]: try: m2.transaction( caller=conc_tx.caller, address=contract_account, value=conc_tx.value, data=conc_tx. data, # data has all needed metadata like function id ([:4]) and argument passed to function gas=0, price=0) except Exception as e: return m2 return m2
def scenario1(): m = ManticoreEVM() market = initialize(m, parameters={'pr_fl': 10**6}, market_owner_token_balance=10**21) bob = init_user(m, market, 'bob', 100 * ONE_ETH) eve = init_user(m, market, 'eve', 100 * ONE_ETH) calls_support(market, [(eve, 1 * ONE_ETH), (bob, 10 * ONE_ETH)]) market.reserve_contract.withdraw(caller=eve.account) print("[+] Eve called support") check_balance(m, market, eve) print(f"[+] Look for results in {m.workspace}")
def test_end_instruction_trace(self): """ Make sure that the trace files are correct, and include the end instructions """ class TestPlugin(Plugin): """ Record the pcs of all end instructions encountered. Source of truth. """ def will_evm_execute_instruction_callback(self, state, instruction, arguments): if isinstance(state.platform.current.last_exception, Create): name = 'init' else: name = 'rt' # collect all end instructions based on whether they are in init or rt if instruction.semantics in ('REVERT', 'STOP', 'RETURN'): with self.locked_context(name) as d: d.append(state.platform.current.pc) mevm = ManticoreEVM() p = TestPlugin() mevm.register_plugin(p) filename = os.path.join(THIS_DIR, 'binaries/int_overflow.sol') mevm.multi_tx_analysis(filename, tx_limit=1) worksp = mevm.workspace listdir = os.listdir(worksp) def get_concatenated_files(directory, suffix): paths = [ os.path.join(directory, f) for f in listdir if f.endswith(suffix) ] concatenated = ''.join(open(path).read() for path in paths) return concatenated all_init_traces = get_concatenated_files(worksp, 'init.trace') all_rt_traces = get_concatenated_files(worksp, 'rt.trace') # make sure all init end insns appear somewhere in the init traces for pc in p.context['init']: self.assertIn(':0x{:x}'.format(pc), all_init_traces) # and all rt end insns appear somewhere in the rt traces for pc in p.context['rt']: self.assertIn(':0x{:x}'.format(pc), all_rt_traces)
def test_emit_did_execute_end_instructions(self): class TestDetector(Detector): def did_evm_execute_instruction_callback(self, state, instruction, arguments, result): if instruction.semantics in ('REVERT', 'STOP'): with self.locked_context('insns', dict) as d: d[instruction.semantics] = True mevm = ManticoreEVM() p = TestDetector() mevm.register_detector(p) filename = os.path.join(THIS_DIR, 'binaries/int_overflow.sol') mevm.multi_tx_analysis(filename, tx_limit=1) self.assertIn('insns', p.context) context = p.context['insns'] self.assertIn('STOP', context) self.assertIn('REVERT', context)
def test(): #!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = "Raz0r" __email__ = "*****@*****.**" """ This is a solution to the PolySwarm's smart contract hacking challenge done with manticore. Please refer to https://raz0r.name/writeups/polyswarm-smart-contract-hacking-challenge-writeup/ for a complete walk through. """ import binascii from manticore.ethereum import ManticoreEVM, ABI m = ManticoreEVM() m.context["solved"] = False # Set up accounts with original addresses owner_account = m.create_account( balance=1000, name="owner", address=0xBC7DDD20D5BCEB395290FD7CE3A9DA8D8B485559) attacker_account = m.create_account( balance=1000, name="attacker", address=0x762C808237A69D786A85E8784DB8C143EB70B2FB, ) cashmoney_contract = m.create_account( balance=1000, name="CashMoney", address=0x64BA926175BC69BA757EF53A6D5EF616889C9999, ) # Create WinnerLog contract using its init bytecode file = "" if __name__ == "__main__": file = "winnerlog.bin" else: file = "test_polyswarm_challenge/winnerlog.bin" with open(file, "rb") as f: bytecode = f.read() winnerlog_contract = m.create_contract( init=bytecode, owner=owner_account, name="WinnerLog", address=0x2E4D2A597A2FCBDF6CC55EB5C973E76AA19AC410, ) # Allow cashmoney_contract to call logWinner() on winnerlog_contract m.transaction( caller=owner_account, address=winnerlog_contract, data=binascii.unhexlify( b"c3e8512400000000000000000000000064ba926175bc69ba757ef53a6d5ef616889c9999" ), value=0, ) # Prepare symbready_statesand call logWinner() with that symbolic buffer symbolic_data = m.make_symbolic_buffer(64) calldata = ABI.function_call("logWinner(address,uint256,bytes)", attacker_account, 0, symbolic_data) m.transaction( caller=cashmoney_contract, address=winnerlog_contract, data=calldata, value=0, gas=10000000, ) # Look for a running state that is not reverted for state in m.ready_states: world = state.platform result = state.solve_one(symbolic_data) print("[+] FOUND: {}".format(binascii.hexlify(result))) with m.locked_context() as context: context["solved"] = True break assert m.context["solved"]
def setUp(self): self.mevm = ManticoreEVM()
class EthPluginsTests(unittest.TestCase): def setUp(self): self.mevm = ManticoreEVM() def tearDown(self): # shutil.rmtree(self.mevm.workspace) del self.mevm @unittest.skip("failing") def test_verbose_trace(self): source_code = """contract X {}""" self.mevm.register_plugin(VerboseTrace()) # owner address is hardcodded so the contract address is predictable owner = self.mevm.create_account( balance=1000, address=0xAFB6D63079413D167770DE9C3F50DB6477811BDB ) # Initialize contract so it's constructor function will be traced self.mevm.solidity_create_contract(source_code, owner=owner, gas=90000) files = set(os.listdir(self.mevm.workspace)) # self.assertEqual(len(files), 0) # just a sanity check? workspace # contains .state_id and other config files # Shall produce a verbose trace file with self.assertLogs("manticore.core.manticore", level="INFO") as cm: self.mevm.finalize() prefix = "\x1b[34mINFO:\x1b[0m:m.c.manticore" # self.assertEqual(f'{prefix}:Generated testcase No. 0 - RETURN', cm.output[0]) self.assertEqual(f"{prefix}:Results in {self.mevm.workspace}", cm.output[0]) # self.assertEqual(f'{prefix}:Total time: {self.mevm._last_run_stats["time_elapsed"]}', cm.output[2]) self.assertEqual(len(cm.output), 1) import re files = set((f for f in os.listdir(self.mevm.workspace) if re.match(r"[^.].*", f))) expected_files = { "global_X.runtime_visited", "global_X_runtime.bytecode", "test_00000000.verbose_trace", "global_X.sol", "global_X.runtime_asm", "global_X.init_asm", "global_X.init_visited", "test_00000000.constraints", "command.sh", "global_X_init.bytecode", "test_00000000.tx", "test_00000000.pkl", "manticore.yml", "global.summary", "test_00000000.summary", "test_00000000.tx.json", "test_00000000.logs", "test_00000000.trace", } self.assertEqual(files, expected_files) result_vt_path = os.path.join(self.mevm.workspace, "test_00000000.verbose_trace") expected_vt_path = os.path.join(THIS_DIR, "data/verbose_trace_plugin_out") with open(result_vt_path) as res_fp, open(expected_vt_path) as exp_fp: res = res_fp.readlines() exp = exp_fp.readlines() self.assertEqual(len(res), len(exp)) self.assertEqual(len(res), 204) # Till line 184 the outputs shall be the same # Next there is a CODESIZE instruction that concretizes to different values each run # and as a result, the values in memory might differ. # # For some reason even setting `(set-option :random-seed 1)` in z3 doesn't help for i in range(184): self.assertEqual(res[i], exp[i], f"Difference on line {i}") till = 130 # number of chars that doesn't differ for i in range(184, 188): self.assertEqual(res[i][:till], exp[i][:till], f"Difference on line {i}") for i in range(188, 195): self.assertEqual(res[i], exp[i], f"Difference on line {i}") for i in range(195, 200): self.assertEqual(res[i][:till], exp[i][:till], f"Difference on line {i}") for i in range(200, len(res)): self.assertEqual(res[i], exp[i], f"Difference on line {i}")
from manticore.ethereum import ABI, ManticoreEVM ################ Script ####################### m = ManticoreEVM() m.verbosity(0) # The contract account to analyze contract_source_code = """ pragma solidity ^0.4.15; contract Reentrance { mapping (address => uint) userBalance; function getBalance(address u) constant returns(uint){ return userBalance[u]; } function addToBalance() payable{ userBalance[msg.sender] += msg.value; } function withdrawBalance(){ // send userBalance[msg.sender] ethers to msg.sender // if mgs.sender is a contract, it will call its fallback function if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){ revert(); } userBalance[msg.sender] = 0; } } //Function signatures:
from manticore.ethereum import ManticoreEVM # initiate the blockchain m = ManticoreEVM() source_code = ''' pragma solidity^0.4.20; contract Simple { function f(uint a) payable { if (a == 65) { throw; } } } ''' # Initiate the accounts user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) # Call f(a), with a symbolic value contract_account.f(m.SValue, caller=user_account) # Check if an execution ends with a REVERT or INVALID for state in m.terminated_states: last_tx = state.platform.transactions[-1] if last_tx.result in ['REVERT', 'INVALID']: print "Error found in f() execution (see %s)"%m.workspace m.generate_testcase(state, 'BugFound')
def setUp(self): self.mevm = ManticoreEVM() self.mevm.verbosity(0) self.worksp = self.mevm.workspace
from manticore.ethereum import ManticoreEVM, Detector ################ Script ####################### m = ManticoreEVM() m.verbosity(3) # And now make the contract account to analyze # https://capturetheether.com/challenges/math/mapping/ source_code = ''' pragma solidity ^0.4.21; contract MappingChallenge { bool public isComplete; uint256[] map; function set(uint256 key, uint256 value) public payable { // Expand dynamic array as needed if (map.length <= key) { map.length = key + 1; } map[key] = value; } } ''' print("Source code:\n", source_code) class StopAtDepth(Detector): ''' This just abort explorations too deep ''' def will_start_run_callback(self, *args):
from manticore.ethereum import ManticoreEVM from manticore.core.smtlib import Operators, solver from manticore.ethereum.abi import ABI ETHER = 10**18 m = ManticoreEVM() # initiate the blockchain # Generate the accounts user_account = m.create_account(balance=1000 * ETHER) with open('exercise_2.sol') as f: contract = m.solidity_create_contract(f, owner=user_account) #First add won't overflow uint256 representation value_0 = m.make_symbolic_value() contract.add(value_0, caller=user_account) #Potential overflow value_1 = m.make_symbolic_value() contract.add(value_1, caller=user_account) contract.sellerBalance(caller=user_account) for state in m.ready_states: # Check if input0 > sellerBalance # last_return is the data returned sellerBalance_tx = state.platform.transactions[-1] # retrieve last_return and input0 in a similar format seller_balance = ABI.deserialize("uint", sellerBalance_tx.return_data) condition = Operators.UGT(value_0, seller_balance)
from manticore.ethereum import ManticoreEVM, ABI from manticore.core.smtlib import Operators, solver m = ManticoreEVM() # initiate the blockchain with open('overflow.sol') as f: source_code = f.read() # Generate the accounts user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) # First add won't overflow uint256 representation value_0 = m.make_symbolic_value() contract_account.add(value_0) # Potential overflow value_1 = m.make_symbolic_value() contract_account.add(value_1) contract_account.sellerBalance() for state in m.running_states: # Check if input0 > sellerBalance # last_return is the data returned last_return = state.platform.transactions[-1].return_data last_return = ABI.deserialize("uint", last_return) state.constrain(Operators.UGT(value_0, last_return)) if state.is_feasible(): print("Overflow found! see {}".format(m.workspace)) m.generate_testcase(state, 'OverflowFound')
from manticore.ethereum import ManticoreEVM from manticore.core.smtlib import solver m = ManticoreEVM() # initiate the blockchain source_code = ''' pragma solidity ^0.4.20; contract UnprotectedWallet{ address public owner; modifier onlyowner { require(msg.sender==owner); _; } function UnprotectedWallet() public { owner = msg.sender; } function changeOwner(address _newOwner) public { owner = _newOwner; } function deposit() payable public { } function withdraw() onlyowner public { msg.sender.transfer(this.balance); } } ''' # Generate the accounts. Creator has 10 ethers; attacker 0
from manticore.ethereum import ManticoreEVM, ABI from manticore.core.smtlib import Operators, solver ###### Initialization ###### m = ManticoreEVM() with open('my_token.sol') as f: source_code = f.read() # Create one user account # And deploy the contract user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) ###### Exploration ###### # - Call balances[user] # - Call transfer with symbolic values # - Call balances[user] # Later we will compare the result of the first call to balances to the second contract_account.balances(user_account) symbolic_val = m.make_symbolic_value() symbolic_to = m.make_symbolic_value() # Transfer is called with symbolic values # Manticore will fork and create state at each condition executed contract_account.transfer(symbolic_to, symbolic_val) contract_account.balances(user_account) # Check of properties ######
def setUp(self): self.mevm = ManticoreEVM() self.mevm.register_plugin(KeepOnlyIfStorageChanges()) self.mevm.verbosity(0) self.worksp = self.mevm.workspace
from manticore.ethereum import ManticoreEVM # initiate the blockchain m = ManticoreEVM() source_code = ''' pragma solidity^0.4.20; contract Simple { function f(uint a) payable public { if (a == 65) { revert(); } } } ''' # Initiate the accounts user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account, balance=0) # Call f(a), with a symbolic value contract_account.f(m.SValue, user_account) print "Results are in %s" % m.workspace m.finalize() # stop the exploration
from manticore.ethereum import ManticoreEVM ################ Script ####################### m = ManticoreEVM() # And now make the contract account to analyze source_code = """ contract C { uint n; function C(uint x) { n = x; } function f(uint x) payable returns (bool) { if (x == n) { return true; } else{ return false; } } } """ user_account = m.create_account(balance=1000) print("[+] Creating a user account", user_account) contract_account = m.solidity_create_contract(source_code, owner=user_account, args=[42]) print("[+] Creating a contract account", contract_account) print("[+] Source code:") print(source_code)
from manticore.ethereum import ManticoreEVM m = ManticoreEVM() with open('example.sol') as f: source_code = f.read() user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account) symbolic_var = m.make_symbolic_value() contract_account.f(symbolic_var) print("Results are in {}".format(m.workspace)) m.finalize() # stop the exploration
from manticore.ethereum import ManticoreEVM, evm from binascii import unhexlify, hexlify ################ Script ####################### # Bytecode only based analisys # No solidity, no compiler, no metadata m = ManticoreEVM() init_bytecode = unhexlify( b"608060405234801561001057600080fd5b506101cc806100206000396000f30060806040527f41000000000000000000000000000000000000000000000000000000000000006000366000818110151561003557fe5b905001357f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610135577fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab6040518080602001828103825260088152602001807f476f7420616e204100000000000000000000000000000000000000000000000081525060200191505060405180910390a161019e565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab6040518080602001828103825260128152602001807f476f7420736f6d657468696e6720656c7365000000000000000000000000000081525060200191505060405180910390a15b0000a165627a7a72305820fd5ec850d8409e19cfe593b9ee3276cc3ac12b0e3406d965317dc9c1aeb7f2670029" ) user_account = m.create_account(balance=1000) print("[+] Creating a user account", user_account) print("[+] Init bytecode:", hexlify(init_bytecode)) print("[+] EVM init assembler:") for instr in evm.EVMAsm.disassemble_all(init_bytecode[:-44]): print(hex(instr.pc), instr) contract_account = m.create_contract(owner=user_account, init=init_bytecode) print("[+] Creating a contract account", contract_account) print("[+] Now the symbolic values") symbolic_data = m.make_symbolic_buffer(320) symbolic_value = m.make_symbolic_value() m.transaction(caller=user_account, address=contract_account, data=symbolic_data, value=symbolic_value) #Let seth know we are not sending more transactions
from manticore.ethereum import ManticoreEVM ################ Script ####################### m = ManticoreEVM() m.verbosity(0) #The contract account to analyze contract_source_code = ''' pragma solidity ^0.4.15; contract Reentrance { mapping (address => uint) userBalance; function getBalance(address u) constant returns(uint){ return userBalance[u]; } function addToBalance() payable{ userBalance[msg.sender] += msg.value; } function withdrawBalance(){ // send userBalance[msg.sender] ethers to msg.sender // if mgs.sender is a contract, it will call its fallback function if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){ revert(); } userBalance[msg.sender] = 0; } } '''
si_level_address = int(sys.argv[2], 16) if len(sys.argv)>2 else "<SI ctf level address>" sol_file = sys.argv[3] if len(sys.argv)>3 else "../SI_ctf_levels/Lottery.sol" gas = 100000 # Set the amount of ETH you want to obtain from the contract contract_balance = ??? # Set the amount of ETH we need to send in our transaction (msg.value) to play. msg_value = ??? # Read in the contract source with open(sol_file, "r") as f: contract_src = f.read() # Instantiate manticore's Ethereum Virtual Machine m = ManticoreEVM() # m.verbosity(0) # Create an account for your wallet address on the EVM with funds to # both deploy the contract and to play the lottery user_account = m.create_account(address=from_address, balance=contract_balance+msg_value) # Create the Lottery CTF level contract on the EVM using wallet contract_account = m.solidity_create_contract( contract_src, contract_name="Lottery", owner=user_account, balance=contract_balance, args=(0,0) )
from manticore.ethereum import ManticoreEVM m = ManticoreEVM() with open('example.sol') as f: source_code = f.read() user_account = m.create_account(balance=1000) contract_account = m.solidity_create_contract(source_code, owner=user_account) symbolic_var = m.make_symbolic_value() contract_account.f(symbolic_var) ## Check if an execution ends with a REVERT or INVALID for state in m.terminated_states: last_tx = state.platform.transactions[-1] if last_tx.result in ['REVERT', 'INVALID']: print('Throw found {}'.format(m.workspace)) m.generate_testcase(state, 'ThrowFound')