Example #1
0
    def exec_by_address(self, address: int, args: typing.List, init_constraints: typing.List = ()):
        """Executing a function depends on its address.

        Args:
            address: the address of function of store.
            args: the parameters.
            init_constraints: initial constraints for symbolic execution.

        Returns:
            r: the result.
        """
        # Invoke a function denoted by the function address with the provided arguments.
        func = self.store.funcs[self.module_instance.funcaddrs[address]]

        if not isinstance(func, WasmFunc):
            return None

        # Mapping check for Python val-type to WebAssembly val-type.
        for i, e in enumerate(func.functype.args):
            if e in [bin_format.i32, bin_format.i64]:
                assert isinstance(args[i], int) or isinstance(args[i], z3.BitVecRef)

            if e in [bin_format.f32, bin_format.f64]:
                assert isinstance(args[i], float) or isinstance(args[i], z3.FPRef)

            args[i] = sym_exec.Value(e, args[i])
        stack = sym_exec.Stack()
        stack.ext(args)
        logger.infoln(f'Running function address {address}({", ".join([str(e) for e in args])}):')
        r = sym_exec.call(self.module_instance, address, self.store, stack, init_constraints)
        if r:
            return r
        return None
Example #2
0
    def __init__(self, module: structure.Module, imps: typing.Dict = None):
        """Initilize Runtime object.

        Args:
            module: constructed by reading WASM file and simply store the content.
            imps: a dict, the key is the import name and the value is the pointer

        Returns:
            Runtime: instance of Runtime class.
        """
        self.module = module
        self.module_instance = sym_exec.ModuleInstance()
        self.store = sym_exec.Store()

        imps = imps if imps else {}
        externvals = []
        for e in self.module.imports:
            if e.kind == bin_format.extern_func:
                # The two if branch is used to detect the possibility of random vulnerability.
                # If the "tapos_block_num" is called while "send_inline"/"send_deferred" is related
                # and called, it could be considered a bug.
                if ((e.module in ('env',) and e.name in ('tapos_block_num', 'tapos_block_prefix'))
                        or (e.module in ('ethereum',) and e.name in ('getBlockNumber', 'getBlockHash', 'getBlockTimestamp'))):
                    global_vars.add_tapos_block_function_addr(len(self.store.funcs))
                if (e.module in ('env',) and e.name in ('send_inline', 'send_deferred')
                        or e.module in ('ethereum',) and e.name in ('call',)):  # current version does not include 'callCode', 'callDelegate', 'callStatic'
                    global_vars.add_send_token_function_addr(len(self.store.funcs))
                if e.module in ('env',) and e.name in ('eosio_assert',):
                    global_vars.eosio_assert_addrs.add(len(self.store.funcs))
                if e.module in ('env',) and e.name in ('action_data_size',):
                    global_vars.action_data_size_addrs.add(len(self.store.funcs))
                if e.module in ('env',) and e.name in ('read_action_data',):
                    global_vars.read_action_data_addrs.add(len(self.store.funcs))
                if e.module in ('ethereum',) and e.name in ('callDelegate',):
                    global_vars.add_call_delegate_addr(len(self.store.funcs))
                if e.module in ('ethereum',) and e.name in ('getCallValue',):
                    global_vars.add_get_call_value_addr(len(self.store.funcs))
                if e.module in ('ethereum',) and e.name in ('revert',):
                    global_vars.add_revert_addr(len(self.store.funcs))

                a = sym_exec.HostFunc(self.module.types[e.desc], None)
                self.store.funcs.append(a)
                externvals.append(sym_exec.ExternValue(e.kind, len(self.store.funcs) - 1))
                continue
            if e.kind == bin_format.extern_table:
                a = None
                self.store.tables.append(a)
                externvals.append(sym_exec.ExternValue(e.kind, len(self.store.tables) - 1))
                continue
            if e.kind == bin_format.extern_mem:
                a = None
                self.store.mems.append(a)
                externvals.append(sym_exec.ExternValue(e.kind, len(self.store.mems) - 1))
                continue
            if e.kind == bin_format.extern_global:
                a = sym_exec.GlobalInstance(sym_exec.Value(e.desc.valtype, None), e.desc.mut)
                self.store.globals.append(a)
                externvals.append(sym_exec.ExternValue(e.kind, len(self.store.globals) - 1))
                continue
        self.module_instance.instantiate(self.module, self.store, externvals)