Esempio n. 1
0
    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
Esempio n. 2
0
    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)
Esempio n. 3
0
    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
Esempio n. 4
0
 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)
Esempio n. 5
0
 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)
Esempio n. 6
0
 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
Esempio n. 7
0
    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)
Esempio n. 8
0
    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)
Esempio n. 9
0
    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)')
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}")
Esempio n. 11
0
    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
Esempio n. 12
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)
)
Esempio n. 13
0
 def setUp(self):
     self.mevm = ManticoreEVM()
     self.mevm.verbosity(0)
     self.worksp = self.mevm.workspace
Esempio n. 14
0
 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
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)
Esempio n. 16
0
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"]
Esempio n. 17
0
 def setUp(self):
     self.mevm = ManticoreEVM()
Esempio n. 18
0
def manticore_verifier(
    source_code,
    contract_name,
    maxfail=None,
    maxt=3,
    maxcov=100,
    deployer=None,
    senders=None,
    psender=None,
    propre=r"crytic_.*",
    compile_args=None,
    outputspace_url=None,
    timeout=100,
):
    """ Verify solidity properties
    The results are dumped to stdout and to the workspace folder.

        $manticore-verifier property.sol  --contract TestToken --smt.solver yices --maxt 4
        # Owner account: 0xf3c67ffb8ab4cdd4d3243ad247d0641cd24af939
        # Contract account: 0x6f4b51ac2eb017600e9263085cfa06f831132c72
        # Sender_0 account: 0x97528a0c7c6592772231fd581e5b42125c1a2ff4
        # PSender account: 0x97528a0c7c6592772231fd581e5b42125c1a2ff4
        # Found 2 properties: crytic_test_must_revert, crytic_test_balance
        # Exploration will stop when some of the following happens:
        # * 4 human transaction sent
        # * Code coverage is greater than 100% meassured on target contract
        # * No more coverage was gained in the last transaction
        # * At least 2 different properties where found to be breakable. (1 for fail fast)
        # * 240 seconds pass
        # Starting exploration...
        Transactions done: 0. States: 1, RT Coverage: 0.0%, Failing properties: 0/2
        Transactions done: 1. States: 2, RT Coverage: 55.43%, Failing properties: 0/2
        Transactions done: 2. States: 8, RT Coverage: 80.48%, Failing properties: 1/2
        Transactions done: 3. States: 30, RT Coverage: 80.48%, Failing properties: 1/2
        No coverage progress. Stopping exploration.
        Coverage obtained 80.48%. (RT + prop)
        +-------------------------+------------+
        |      Property Named     |   Status   |
        +-------------------------+------------+
        |   crytic_test_balance   | failed (0) |
        | crytic_test_must_revert |   passed   |
        +-------------------------+------------+
        Checkout testcases here:./mcore_6jdil7nh

    :param maxfail: stop after maxfail properties are failing. All if None
    :param maxcov: Stop after maxcov % coverage is obtained in the main contract
    :param maxt: Max transaction count to explore
    :param deployer: (optional) address of account used to deploy the contract
    :param senders: (optional) a list of calles addresses for the exploration
    :param psender: (optional) address from where the property is tested
    :param source_code: A filename or source code
    :param contract_name: The target contract name defined in the source code
    :param propre: A regular expression for selecting properties
    :param outputspace_url: where to put the extended result
    :param timeout: timeout in seconds
    :return:
    """
    # Termination condition
    # Exploration will stop when some of the following happens:
    # * MAXTX human transaction sent
    # * Code coverage is greater than MAXCOV meassured on target contract
    # * No more coverage was gained in the last transaction
    # * At least MAXFAIL different properties where found to be breakable. (1 for fail fast)

    # Max transaction count to explore
    MAXTX = maxt
    # Max coverage % to get
    MAXCOV = maxcov
    # Max different properties fails
    MAXFAIL = maxfail

    config.get_group("smt").timeout = 120
    config.get_group("smt").memory = 16384
    config.get_group("evm").ignore_balance = True
    config.get_group("evm").oog = "ignore"

    print("# Welcome to manticore-verifier")
    # Main manticore manager object
    m = ManticoreEVM()
    # avoid all human level tx that are marked as constant (have no effect on the storage)
    filter_out_human_constants = FilterFunctions(regexp=r".*",
                                                 depth="human",
                                                 mutability="constant",
                                                 include=False)
    m.register_plugin(filter_out_human_constants)
    filter_out_human_constants.disable()

    # Avoid automatically exploring property
    filter_no_crytic = FilterFunctions(regexp=propre, include=False)
    m.register_plugin(filter_no_crytic)
    filter_no_crytic.disable()

    # Only explore properties (at human level)
    filter_only_crytic = FilterFunctions(regexp=propre,
                                         depth="human",
                                         fallback=False,
                                         include=True)
    m.register_plugin(filter_only_crytic)
    filter_only_crytic.disable()

    # And now make the contract account to analyze

    # User accounts. Transactions trying to break the property are send from one
    # of this
    senders = (None, ) if senders is None else senders

    user_accounts = []
    for n, address_i in enumerate(senders):
        user_accounts.append(
            m.create_account(balance=10**10,
                             address=address_i,
                             name=f"sender_{n}"))
    # the address used for deployment
    owner_account = m.create_account(balance=10**10,
                                     address=deployer,
                                     name="deployer")
    # the target contract account
    contract_account = m.solidity_create_contract(
        source_code,
        owner=owner_account,
        contract_name=contract_name,
        compile_args=compile_args,
        name="contract_account",
    )
    # the address used for checking porperties
    checker_account = m.create_account(balance=10**10,
                                       address=psender,
                                       name="psender")

    print(f"# Owner account: 0x{int(owner_account):x}")
    print(f"# Contract account: 0x{int(contract_account):x}")
    for n, user_account in enumerate(user_accounts):
        print(f"# Sender_{n} account: 0x{int(user_account):x}")
    print(f"# PSender account: 0x{int(checker_account):x}")

    properties = {}
    md = m.get_metadata(contract_account)
    for func_hsh in md.function_selectors:
        func_name = md.get_abi(func_hsh)["name"]
        if re.match(propre, func_name):
            properties[func_name] = []

    print(
        f"# Found {len(properties)} properties: {', '.join(properties.keys())}"
    )
    if not properties:
        print("I am sorry I had to run the init bytecode for this.\n"
              "Good Bye.")
        return
    MAXFAIL = len(properties) if MAXFAIL is None else MAXFAIL
    tx_num = 0  # transactions count
    current_coverage = None  # obtained coverge %
    new_coverage = 0.0

    print(f"""# Exploration will stop when some of the following happens:
# * {MAXTX} human transaction sent
# * Code coverage is greater than {MAXCOV}% meassured on target contract
# * No more coverage was gained in the last transaction
# * At least {MAXFAIL} different properties where found to be breakable. (1 for fail fast)
# * {timeout} seconds pass""")
    print("# Starting exploration...")
    print(
        f"Transactions done: {tx_num}. States: {m.count_ready_states()}, RT Coverage: {0.00}%, "
        f"Failing properties: 0/{len(properties)}")
    with m.kill_timeout(timeout=timeout):
        while not m.is_killed():
            # check if we found a way to break more than MAXFAIL properties
            broken_properties = sum(
                int(len(x) != 0) for x in properties.values())
            if broken_properties >= MAXFAIL:
                print(
                    f"Found {broken_properties}/{len(properties)} failing properties. Stopping exploration."
                )
                break

            # check if we sent more than MAXTX transaction
            if tx_num >= MAXTX:
                print(f"Max number of transactions reached ({tx_num})")
                break
            tx_num += 1

            # check if we got enough coverage
            new_coverage = m.global_coverage(contract_account)
            if new_coverage >= MAXCOV:
                print(
                    f"Current coverage({new_coverage}%) is greater than max allowed ({MAXCOV}%). Stopping exploration."
                )
                break

            # check if we have made coverage progress in the last transaction
            if current_coverage == new_coverage:
                print(f"No coverage progress. Stopping exploration.")
                break
            current_coverage = new_coverage

            # Make sure we didn't time out before starting first transaction
            if m.is_killed():
                print("Cancelled or timeout.")
                break

            # Explore all methods but the "crytic_" properties
            # Note: you may be tempted to get all valid function ids/hashes from the
            #  metadata and to constrain the first 4 bytes of the calldata here.
            #  This wont work because we also want to prevent the contract to call
            #  crytic added methods as internal transactions
            filter_no_crytic.enable()  # filter out crytic_porperties
            filter_out_human_constants.enable()  # Exclude constant methods
            filter_only_crytic.disable(
            )  # Exclude all methods that are not property checks

            symbolic_data = m.make_symbolic_buffer(320)
            symbolic_value = m.make_symbolic_value()
            caller_account = m.make_symbolic_value(160)
            args = tuple(
                (caller_account == address_i for address_i in user_accounts))

            m.constrain(OR(*args, False))
            m.transaction(
                caller=caller_account,
                address=contract_account,
                value=symbolic_value,
                data=symbolic_data,
            )

            # check if timeout was requested during the previous transaction
            if m.is_killed():
                print("Cancelled or timeout.")
                break

            m.clear_terminated_states()  # no interest in reverted states
            m.take_snapshot()  # make a copy of all ready states
            print(
                f"Transactions done: {tx_num}. States: {m.count_ready_states()}, "
                f"RT Coverage: {m.global_coverage(contract_account):3.2f}%, "
                f"Failing properties: {broken_properties}/{len(properties)}")

            # check if timeout was requested while we were taking the snapshot
            if m.is_killed():
                print("Cancelled or timeout.")
                break

            # And now explore all properties (and only the properties)
            filter_no_crytic.disable()  # Allow crytic_porperties
            filter_out_human_constants.disable(
            )  # Allow them to be marked as constants
            filter_only_crytic.enable(
            )  # Exclude all methods that are not property checks
            symbolic_data = m.make_symbolic_buffer(4)
            m.transaction(caller=checker_account,
                          address=contract_account,
                          value=0,
                          data=symbolic_data)

            for state in m.all_states:
                world = state.platform
                tx = world.human_transactions[-1]
                md = m.get_metadata(tx.address)
                """
                A is _broken_ if:
                     * is normal property
                     * RETURN False
                   OR:
                     * property name ends with 'revert'
                     * does not REVERT
                Property is considered to _pass_ otherwise
                """
                N = constrain_to_known_func_ids(state)
                for func_id in map(bytes, state.solve_n(tx.data[:4],
                                                        nsolves=N)):
                    func_name = md.get_abi(func_id)["name"]
                    if not func_name.endswith("revert"):
                        # Property does not ends in "revert"
                        # It must RETURN a 1
                        if tx.return_value == 1:
                            # TODO: test when property STOPs
                            return_data = ABI.deserialize(
                                "bool", tx.return_data)
                            testcase = m.generate_testcase(
                                state,
                                f"property {md.get_func_name(func_id)} is broken",
                                only_if=AND(tx.data[:4] == func_id,
                                            return_data == 0),
                            )
                            if testcase:
                                properties[func_name].append(testcase.num)
                    else:
                        # property name ends in "revert" so it MUST revert
                        if tx.result != "REVERT":
                            testcase = m.generate_testcase(
                                state,
                                f"Some property is broken did not reverted.(MUST REVERTED)",
                                only_if=tx.data[:4] == func_id,
                            )
                            if testcase:
                                properties[func_name].append(testcase.num)

            m.clear_terminated_states(
            )  # no interest in reverted states for now!
            m.goto_snapshot()
        else:
            print("Cancelled or timeout.")

    m.clear_terminated_states()
    m.clear_ready_states()
    m.clear_snapshot()

    if m.is_killed():
        print("Exploration ended by CTRL+C or timeout")

    print(f"Coverage obtained {new_coverage:3.2f}%. (RT + prop)")

    x = PrettyTable()
    x.field_names = ["Property Named", "Status"]
    for name, testcases in sorted(properties.items()):
        result = "passed"
        if testcases:
            result = f"failed ({testcases[0]})"
        x.add_row((name, result))
    print(x)

    m.clear_ready_states()

    workspace = os.path.abspath(m.workspace)[len(os.getcwd()) + 1:]
    print(f"Checkout testcases here:./{workspace}")
Esempio n. 19
0
def init_workspace(test_name, cpus=1):
    workspace = test_name
    assert not isdir(workspace), "Workspace folder already exists"
    m = ManticoreEVM(procs=cpus, workspace_url=workspace)
    m.verbosity(3)
    return m
Esempio n. 20
0
    def __run_manticore(self, trace):
        self.print('[.] Running Manticore')

        consts = manticoreConfig.get_group('core')
        consts.procs = self.procs

        output_path = self.__create_output_path()
        manticore = ManticoreEVM(workspace_url=output_path)

        if self.force_loop_limit:
            loop_delimiter = LoopDepthLimiter(
                loop_count_threshold=self.loop_limit)
            manticore.register_plugin(loop_delimiter)

        if self.avoid_constant_txs:
            filter_nohuman_constants = FilterFunctions(regexp=r'.*',
                                                       depth='human',
                                                       mutability='constant',
                                                       include=False)
            manticore.register_plugin(filter_nohuman_constants)

        self.print('[...] Creating user accounts')
        for num in range(0, self.amount_user_accounts):
            account_name = 'user_account_' + str(num)
            manticore.create_account(balance=self.user_initial_balance,
                                     name=account_name)

        self.print('[...] Creating a contract and its library dependencies')
        with open(self.contract_path, 'r') as contract_file:
            source_code = contract_file.read()
        try:
            contract_account = manticore.solidity_create_contract(
                source_code,
                owner=manticore.get_account('user_account_0'),
                args=self.contract_args,
                contract_name=self.contract_name)
        except:
            raise Exception('Check contract arguments')

        if contract_account is None:
            raise Exception(
                'Contract account is None, check contract arguments')

        self.print('[...] Calling functions in trace')

        function_types = {}

        function_signatures = manticore.get_metadata(
            contract_account).function_signatures
        for signature in function_signatures:
            signature_parts = signature.split('(')
            name = str(signature_parts[0])
            types = str(signature_parts[1].replace(')', ''))
            function_types[name] = types

        for function_name in trace:
            if function_name == '':  # FIXME, check VeriSol trace
                manticore.transaction(caller=manticore.make_symbolic_address(),
                                      address=contract_account,
                                      value=manticore.make_symbolic_value(),
                                      data=manticore.make_symbolic_buffer(
                                          self.fallback_data_size))
            else:
                function_to_call = getattr(contract_account, function_name)
                types = function_types[function_name]
                if len(types) > 0:
                    function_to_call(
                        manticore.make_symbolic_arguments(
                            function_types[function_name]))
                else:
                    function_to_call()

        self.print('[...] Processing output')

        throw_states = []

        for state in manticore.terminated_states:
            if str(state.context['last_exception']) == 'THROW':
                throw_states.append(state)

        if len(throw_states) == 0:
            raise Exception('Manticore couldn\'t confirm the counterexample')

        if self.verbose:
            for state in throw_states:
                manticore.generate_testcase(state)

        self.print('[-] Look for full output in:', manticore.workspace)
Esempio n. 21
0
    def setUp(self):
        evm_consts = config.get_group("evm")
        evm_consts.sha3 = evm_consts.sha3.concretize

        self.mevm = ManticoreEVM()
        self.worksp = self.mevm.workspace
Esempio n. 22
0
 def setUp(self):
     self.mevm = ManticoreEVM()
     self.worksp = self.mevm.workspace