Exemplo n.º 1
0
def locate_transfer(vm, name):
    """Using specific parameters to locate transfer function.

    Args:
        vm: virtual machine includes all env information
        name: the name of contract

    Returns:

    """
    if global_vars.apply_function_address is None:
        return

    # check whether the type is valid transfer type
    apply_func_type = structure.FunctionType()
    apply_func_type.args = bytearray([bin_format.i64, bin_format.i64, bin_format.i64])
    apply_func_type.rets = bytearray()

    apply_func = vm.store.funcs[vm.module_instance.funcaddrs[global_vars.apply_function_address]]
    global_vars.locate()
    if apply_func.functype == apply_func_type:
        params = [utils.eos_abi_to_int(name), utils.eos_abi_to_int('eosio.token'), utils.eos_abi_to_int('transfer')]
        global_vars.locate()
        try:
            vm.exec_by_address(global_vars.apply_function_address, params)
        except AssertionError as e:
            logger.println(f'unreachable transfer: {e}')
        except SystemExit as e:
            logger.debugln(f'transfer found')
    global_vars.sym_exec()
Exemplo n.º 2
0
def detect_fake_eos(vm, name) -> None:
    """Fake eos transfer vulnerability analysis function.

    Args:
        name: the name of current contract
        vm: WebAssembly module execution environment

    Returns:

    """
    if global_vars.apply_function_address is None:
        return

    global_vars.fake_detect()  # set flag for fake detection
    func_type = structure.FunctionType()
    func_type.args = bytearray(
        [bin_format.i64, bin_format.i64, bin_format.i64])
    func_type.rets = bytearray()
    apply_func = vm.store.funcs[vm.module_instance.funcaddrs[
        global_vars.apply_function_address]]
    global_vars.fake_detect()
    if apply_func.functype == func_type:
        params = utils.gen_symbolic_args(apply_func)
        global_vars.apply_params = params
        params[0] = utils.eos_abi_to_int(name)
        params[2] = utils.eos_abi_to_int('transfer')
        init_constraints = [
            params[0] != params[1],
            params[1] != utils.eos_abi_to_int('eosio.token')
        ]
        vm.exec_by_address(global_vars.apply_function_address, params,
                           init_constraints)
    global_vars.sym_exec()  # set the detection mode to False
Exemplo n.º 3
0
def fake_eos_analysis(store, frame, stack, expr, pc, solver=None):
    global_vars.pc = pc
    transfer_int64 = utils.eos_abi_to_int('transfer')
    action_param = 2
    end = len(expr.data)

    if _check_n_call(expr, pc):
        local_number = expr.data[pc + 7].immediate_arguments
        frame.locals[local_number] = Value.from_i64(
            _get_encoding(expr.data[pc + 4].immediate_arguments))
        pc = expr.composition[pc + 8][-1]

    elif expr.data[pc].code == bin_format.call and expr.data[
            pc].immediate_arguments in global_vars.eosio_assert_addrs:
        cond = stack.data[-2].n
        if utils.is_all_real(cond):
            if not cond:
                pc = end
        else:
            solver.push()
            solver.add(z3.simplify(cond == 1))
            if utils.check_sat(solver) == z3.unsat:
                pc = end
            solver.pop()

    elif ((expr.data[pc].code == bin_format.get_local
           and expr.data[pc].immediate_arguments == action_param
           and expr.data[pc + 1].code == bin_format.i64_const
           and expr.data[pc + 1].immediate_arguments == transfer_int64)
          or (expr.data[pc].code == bin_format.i64_const
              and expr.data[pc].immediate_arguments == transfer_int64
              and expr.data[pc + 1].code == bin_format.get_local
              and expr.data[pc + 1].immediate_arguments == action_param)):
        if (expr.data[pc + 2].code in (bin_format.i64_eq, bin_format.i64_ne)
                and expr.data[pc + 3].code == bin_format.br_if):
            transfer_block_pc = (_get_branch_pc(
                expr.data[pc + 3].immediate_arguments,
                stack) if expr.data[pc + 2].code == bin_format.i64_eq else pc +
                                 4)
            for i in range(transfer_block_pc, end - 2):
                if (expr.data[i].code == bin_format.call
                        and expr.data[i + 1].code == bin_format.drop
                        and expr.data[i + 2].code
                        in (bin_format.br, bin_format.end)):
                    global_vars.find_fake_eos_transfer()
                if expr.data[i].code not in (bin_format.get_local,
                                             bin_format.i32_const,
                                             bin_format.i32_store,
                                             bin_format.i64_load,
                                             bin_format.i64_store,
                                             bin_format.i32_add):
                    break

    global_vars.pc = pc
Exemplo n.º 4
0
def _get_encoding(data_index: int) -> int:
    string = global_vars.data_addr_dict[data_index]
    return utils.eos_abi_to_int(string)
Exemplo n.º 5
0
 def set_name_int64(self, name):
     self.contract_name_int64 = utils.eos_abi_to_int(name)