Exemplo n.º 1
0
    def test_demangle_ms(self):
        tests = ("??_V@YAPAXI@Z", "??_U@YAPAXI@Z")

        results = ("void* __cdecl operator delete[](uint32_t)",
                   "void* __cdecl operator new[](uint32_t)")
        for i, test in enumerate(tests):
            t, n = demangle_ms(Architecture['x86'], test)
            self.get_type_string(t, n) == results[i]
Exemplo n.º 2
0
def get_vtable_name(view, name):
    if name[:3] in [ '?AU', '?AV' ]:
        # demangle_ms doesn't support flags (UNDNAME_32_BIT_DECODE | UNDNAME_NAME_ONLY | UNDNAME_NO_ARGUMENTS | UNDNAME_NO_MS_KEYWORDS)
        demangle_type, demangle_name = demangle.demangle_ms(view.arch, '??_7{0}6B@'.format(name[3:]))

        if demangle_type is not None:
            return demangle.get_qualified_name(demangle_name)

    return 'vtable_{0}'.format(name)
Exemplo n.º 3
0
    def test_demangle_ms(self):
        tests = ("??_V@YAPAXI@Z", "??_U@YAPAXI@Z")

        oracle = ("void* __cdecl operator delete[](uint32_t)",
                  "void* __cdecl operator new[](uint32_t)")
        for i, test in enumerate(tests):
            t, n = demangle_ms(Architecture['x86'], test)
            result = self.get_type_string(t, n)
            assert result == oracle[
                i], f"oracle: {oracle[i]}\nresult: {result}"
def process_msvc_func(func):
    view = func.view
    arch = func.arch
    symbol = func.symbol

    mangled_name = symbol.raw_name

    if mangled_name.startswith('??_7') and not mangled_name.endswith(
            '@@6B@'):  # Skip buggy vtables
        return

    sym_type, sym_parts = demangle_ms(arch, mangled_name)

    if (sym_type is None) or (sym_type.type_class !=
                              TypeClass.FunctionTypeClass):
        return

    if isinstance(sym_parts, str):
        return

    params = [
        v.type for v in sym_type.parameters
        if v.type.type_class != TypeClass.VoidTypeClass
    ]
    return_type = sym_type.return_value

    tokens_before = [str(v) for v in sym_type.get_tokens_before_name()]

    convention = 'cdecl'

    if '__cdecl' in tokens_before:
        convention = 'cdecl'
    elif '__stdcall' in tokens_before:
        convention = 'stdcall'
    elif '__thiscall' in tokens_before:
        convention = 'thiscall'

    if (convention == 'thiscall') and len(sym_parts) >= 2:
        if 'static' not in tokens_before:
            type_name = '::'.join(sym_parts[:-1])
            this_type = Type.pointer(
                arch,
                Type.named_type(
                    NamedTypeReference(
                        NamedTypeReferenceClass.StructNamedTypeClass,
                        name=type_name)))
            params.insert(0, this_type)

    func.function_type = Type.function(return_type, params,
                                       arch.calling_conventions[convention],
                                       sym_type.has_variable_arguments)
Exemplo n.º 5
0
def fix_mangled_symbols(thread, view):
    for sym in view.symbols.values():
        if thread.cancelled:
            break
        if not isinstance(sym, Symbol):
            continue

        if sym.short_name.startswith('?') and not sym.raw_name.startswith('?'):
            demangled_type, demangled_name = demangle_ms(
                view.arch, sym.short_name)
            if demangled_type is not None:
                new_symbol = Symbol(
                    sym.type,
                    sym.address,
                    short_name=get_qualified_name(demangled_name),
                    full_name=get_qualified_name(demangled_name),
                    raw_name=sym.short_name,
                    binding=sym.binding,
                    namespace=sym.namespace,
                    ordinal=sym.ordinal)

                view.undefine_user_symbol(sym)
                view.define_user_symbol(new_symbol)
                view.define_user_data_var(new_symbol.address, demangled_type)

                sym = new_symbol

        # Create vtables
        if 'vftable\'' in sym.full_name:
            create_vtable(view, None, sym.address)

        # Create strings
        if sym.raw_name.startswith('??_C@_'):
            view.undefine_user_symbol(sym)
            ascii_string = view.get_ascii_string_at(sym.address)

            if (ascii_string is not None) and (ascii_string.start
                                               == sym.address):
                view.define_user_data_var(
                    sym.address, Type.array(Type.char(), ascii_string.length))

    for func in view.functions:
        if thread.cancelled:
            break
        process_msvc_func(func)
Exemplo n.º 6
0
def load_map_file(thread, view, filename):
    lines = open(filename, 'r').readlines()
    symbols = parse_map_file(lines)
    arch = view.arch

    for name, addr in symbols:
        if not view.is_valid_offset(addr):
            continue

        current_sym = view.get_symbol_at(addr)

        if current_sym is not None:
            if not current_sym.auto:
                continue

            if current_sym.type not in [
                    SymbolType.DataSymbol, SymbolType.FunctionSymbol
            ]:
                continue

            view.undefine_user_symbol(current_sym)

        sym_type, sym_parts = demangle_ms(arch, name)

        if sym_type is None:
            sym_type = Type.void()

        if isinstance(sym_parts, str):
            sym_parts = [sym_parts]

        sym_name = '::'.join(sym_parts)

        if view.is_offset_executable(addr):
            view.create_user_function(addr)
            view.define_user_symbol(
                Symbol(SymbolType.FunctionSymbol,
                       addr,
                       sym_name,
                       raw_name=name))
        else:
            view.define_data_var(addr, sym_type)
            view.define_user_symbol(
                Symbol(SymbolType.DataSymbol, addr, sym_name, raw_name=name))

    fix_mangled_symbols(thread, view)
Exemplo n.º 7
0
def demangle_name(bv, name, max_size=64):
    res = name
    if bv.platform.name.startswith("linux-") or bv.platform.name.startswith(
            "mac-"):
        _, demangled = demangle.demangle_gnu3(bv.arch, name)
        if not isinstance(demangled, list):
            res = demangled
        else:
            res = demangle.simplify_name_to_string(
                demangle.get_qualified_name(demangled))
    elif bv.platform.name.startswith("windows-"):
        _, demangled = demangle.demangle_ms(bv.arch, name)
        if not isinstance(demangled, list):
            res = demangled
        else:
            res = demangle.simplify_name_to_string(
                demangle.get_qualified_name(demangled))

    if len(res) > max_size:
        res = res[:max_size // 2 - 3] + "..." + res[-max_size // 2:]
    return res
Exemplo n.º 8
0
def process_msvc_func(func):
    arch = func.arch
    plat = func.platform

    sym_type, sym_parts = demangle_ms(arch, func.symbol.raw_name)

    if (sym_type is None) or (sym_type.type_class !=
                              TypeClass.FunctionTypeClass):
        return

    if isinstance(sym_parts, str):
        return

    params = [
        v.type for v in sym_type.parameters
        if v.type.type_class != TypeClass.VoidTypeClass
    ]
    return_type = sym_type.return_value

    tokens_before = [str(v) for v in sym_type.get_tokens_before_name()]

    is_member = ('public:' in tokens_before) or (
        'protected:' in tokens_before) or ('private:' in tokens_before)
    is_static = 'static' in tokens_before
    is_virtual = 'virtual' in tokens_before

    convention = plat.default_calling_convention

    if '__cdecl' in tokens_before:
        convention = plat.cdecl_calling_convention
    elif '__stdcall' in tokens_before:
        convention = plat.stdcall_calling_convention
    elif '__fastcall' in tokens_before:
        convention = plat.fastcall_calling_convention
    elif '__thiscall' in tokens_before:
        convention = arch.calling_conventions['thiscall']

    if return_type.type_class == TypeClass.NamedTypeReferenceClass and return_type.named_type_reference.type_class in {
            NamedTypeReferenceClass.ClassNamedTypeClass,
            NamedTypeReferenceClass.StructNamedTypeClass,
            NamedTypeReferenceClass.UnionNamedTypeClass
    }:
        # TODO: This should only added for large/non trivial types
        return_type = Type.pointer(arch, return_type)
        params.insert(0, FunctionParameter(return_type, name="retptr"))

    if len(sym_parts) >= 2 and (is_member or is_virtual) and not is_static:
        type_name = '::'.join(sym_parts[:-1])
        this_type = Type.pointer(
            arch,
            Type.named_type(
                NamedTypeReference(
                    NamedTypeReferenceClass.StructNamedTypeClass,
                    name=type_name)))
        params.insert(0, FunctionParameter(this_type, name="this"))

        if (sym_parts[-1] == sym_parts[-2]) and (return_type.type_class
                                                 == TypeClass.VoidTypeClass):
            return_type = this_type

    func_type = Type.function(return_type, params, convention,
                              sym_type.has_variable_arguments)

    func.function_type = func_type