示例#1
0
def _define_classes(view: BinaryView, class_t: Type):
    __objc_data = view.sections.get('__objc_data')

    if __objc_data is None:
        raise KeyError('This binary has no __objc_data section')

    for addr in range(__objc_data.start, __objc_data.end, class_t.width):
        current_class = Class.from_address(addr, view)

        log_debug(f"Created {current_class}")

    __objc_classrefs = view.sections.get('__objc_classrefs')

    if __objc_classrefs is None:
        raise KeyError('This binary has no __objc_classrefs section')

    for addr in range(__objc_classrefs.start, __objc_classrefs.end,
                      view.address_size):
        view.define_user_data_var(addr, Type.pointer(view.arch, class_t))

        class_addr = int.from_bytes(
            view.read(addr, view.address_size),
            "little" if view.endianness is Endianness.LittleEndian else "big")

        class_ = view.session_data['ClassList'].get(
            class_addr) if class_addr else None

        if class_ is not None:
            log_debug(f"{addr:x} points to {class_!r}")
            view.define_user_symbol(
                Symbol(SymbolType.DataSymbol, addr,
                       f"_OBJC_CLASS_$_{class_.vtable.name}@GOT"))
示例#2
0
    def __create_class_name_type(bv: BinaryView, vmt: DelphiVMT, out_struct: types.Structure) -> bool:
        vmt_offsets = vmt.vmt_offsets

        if not vmt.seek_to_vmt_offset(vmt_offsets.cVmtClassName):
            return False

        class_name_ptr = vmt.read_ptr()

        if class_name_ptr is None:
            return False

        if not vmt.seek_to_code(class_name_ptr):
            return False

        class_name_len = vmt.read8()

        if class_name_len is None:
            return False

        class_name_struct = types.Structure()
        class_name_struct.append(Type.int(1, False), 'length')
        class_name_struct.append(Type.array(Type.char(), class_name_len), 'value')
        struct_type = Type.structure_type(class_name_struct)

        bv.define_user_data_var(class_name_ptr, struct_type)
        out_struct.append(Type.pointer(bv.arch, struct_type), 'cVmtClassName')

        # Create Symbole for class name
        class_name_sym = Symbol(SymbolType.DataSymbol, class_name_ptr, f'{vmt.class_name}Name')
        bv.define_user_symbol(class_name_sym)

        return True
示例#3
0
    def from_address(cls, address: int, class_name: str, view: BinaryView):
        if address == 0:
            return None

        from_bytes = get_from_bytes(view)

        ivar_t_type = view.types['ivar_t']
        ivar_t = Type.named_type_from_type(
            'ivar_t', ivar_t_type
        )

        members = get_structure_members(address, ivar_t_type, view)
        member_dict = {m.name: m for m in ivar_t_type.structure.members}

        # x64 uses uint64_t for offset, but everything else
        # uses uint32_t
        ivar_offset_type = (
            member_dict['offset'].type.target
            if view.arch != Architecture['x86_64']
            else Type.int(8, False)
        )
        ivar_offset_type.const = True

        if view.get_data_var_at(address) is None:
            view.define_user_data_var(address, ivar_t)

        if members['name'] != 0:
            name_string = view.get_ascii_string_at(members['name'], 1)
            if name_string is not None:
                members['name'] = name_string.value
        else:
            members['name'] = ''

        if members['type']:
            type_string = view.get_ascii_string_at(members['type'], 1).value
            members['type'] = _lookup_type(type_string, view)

        if not members['type']:
            members['type'] = Type.pointer(view.arch, Type.void())

        if members['offset']:
            view.define_user_data_var(members['offset'], ivar_offset_type)
            view.define_user_symbol(
                Symbol(
                    SymbolType.DataSymbol,
                    members['offset'],
                    f'{members["name"]}_offset',
                    namespace=class_name
                )
            )
            members['offset'] = from_bytes(
                view.read(members['offset'],
                          member_dict['offset'].type.target.width)
            )
        else:
            members['offset'] = None

        return cls(address, **members)
示例#4
0
    def from_address(cls, address: int, view: BinaryView) -> Class:
        if address == 0:
            return None
        elif address in view.session_data['ClassList']:
            return view.session_data['ClassList'][address]
        else:
            new_class = cls(address, view, None, None, None, {}, {})
            view.session_data['ClassList'][address] = new_class

        from_bytes = get_from_bytes(view)

        members = get_structure_members(address,
                                        view.get_type_by_name('class_t'), view)

        isa = Class.from_address(members['isa'], view)
        new_class.isa = isa

        superclass = Class.from_address(members['superclass'], view)
        new_class.superclass = superclass

        vtable = ClassRO.from_address(members['vtable'], view,
                                      new_class.is_meta)
        new_class.vtable = vtable

        class_t = Type.named_type_from_type('class_t',
                                            view.get_type_by_name('class_t'))

        view.define_user_data_var(address, class_t)

        if not new_class.is_meta:
            view.session_data['ClassNames'][vtable.name] = new_class
        else:
            view.session_data['ClassNames'][f"{vtable.name}_meta"] = new_class

        if not new_class.is_meta:
            new_class.define_type()
            symbol_name = f'_OBJC_CLASS_$_{vtable.name}'
        else:
            symbol_name = f'_OBJC_METACLASS_$_{vtable.name}'

        view.define_user_symbol(
            Symbol(SymbolType.DataSymbol, address, symbol_name))

        if vtable and vtable.baseMethods is not None:
            new_class._methods = vtable.baseMethods.methods

        if vtable and vtable.baseProtocols is not None:
            new_class._protocols = vtable.baseProtocols.protocols

        return new_class
示例#5
0
    def from_address(cls,
                     address: int,
                     self_type: str,
                     view: BinaryView,
                     is_class=False):
        if address == 0:
            return None

        if self_type not in view.types:
            view.define_user_type(self_type, Type.structure_type(Structure()))

        method_t_type = view.get_type_by_name('method_t')
        method_t = Type.named_type_from_type('method_t', method_t_type)

        if view.get_data_var_at(address) is None:
            view.define_user_data_var(address, method_t)

        members = get_structure_members(address, method_t_type, view)

        members['name'] = (view.get_ascii_string_at(members['name'], 1).value
                           if members['name'] else '')

        members['types'] = parse_function_type(
            view.get_ascii_string_at(members['types'], 1).value
            if members['types'] else '', self_type, view, is_class)

        members['imp'] = view.get_function_at(members['imp'])

        if members['imp'] is not None:
            if not is_class:
                method_name = f'-[{self_type} {members["name"]}]'
            else:
                method_name = f'+[{self_type} {members["name"]}]'

            if view.symbols.get(method_name):
                namespace = f'{members["imp"].start}'
            else:
                namespace = None

            view.define_user_symbol(
                Symbol(SymbolType.FunctionSymbol,
                       members['imp'].start,
                       method_name,
                       namespace=namespace))

            if members['types'] is not None:
                members['imp'].function_type = members['types']

        return cls(address, **members)
示例#6
0
    def _add_vmt_methods(bv: BinaryView, vmt: DelphiVMT, out_struct: types.Structure) -> bool:
        offset_ptr_size = vmt.offset_ptr_size

        if not vmt.seek_to_vmt_offset(vmt.vmt_offsets.cVmtParent + offset_ptr_size):
            return False

        for _ in range(len(vmt.virtual_methods)):
            value = vmt.read_ptr()

            if value == 0:
                continue

            if value not in vmt.virtual_methods:
                prev_offset = vmt.br_offset - offset_ptr_size
                raise RuntimeError(
                    f'Invalid method address detected at 0x{prev_offset:08x} ({vmt.class_name})')

            # Create function if not exists
            if bv.get_function_at(value) is None:
                bv.create_user_function(value)

            function = bv.get_function_at(value)

            # Set method name if not already set
            function_name = function.name
            method_name = vmt.virtual_methods[value]

            if function_name.startswith('sub_'):
                bv.define_user_symbol(Symbol(
                    SymbolType.FunctionSymbol,
                    value,
                    method_name
                ))

            # Add field to structure
            field_type = Type.pointer(
                bv.arch,
                Type.function(
                    function.return_type,
                    [(Type.void() if x.type is None else x.type) for x in function.parameter_vars],
                    function.calling_convention
                )
            )

            field_name = method_name.split('.')[-1]
            out_struct.append(field_type, field_name)

        return True
示例#7
0
    def create_vmt_struct(bv: BinaryView, vmt: DelphiVMT) -> bool:
        if not vmt.is_valid:
            return False

        vmt_struct = types.Structure()

        if not BNHelpers._add_vmt_fields(bv, vmt, vmt_struct):
            return False

        if not BNHelpers._add_vmt_methods(bv, vmt, vmt_struct):
            return False

        struct_type = Type.structure_type(vmt_struct)
        bv.define_user_data_var(vmt.start, struct_type)
        # bv.define_user_type(f'vmt{vmt.class_name}', struct_type)

        # Create Symbole for VMT
        vmt_sym = Symbol(SymbolType.DataSymbol, vmt.start, f'vmt{vmt.class_name}')
        bv.define_user_symbol(vmt_sym)
        return True
示例#8
0
def parse_added_methods(view: BinaryView, class_addMethod: int):
    log_debug(f"parse_added_methods(view, {class_addMethod:x})")
    xrefs = view.get_code_refs(class_addMethod)

    for xref in xrefs:
        mlil = xref.function.mlil
        log_debug(f"{xref.address:x} Getting add_method_call")
        add_method_call = xref.function.get_low_level_il_at(xref.address).mlil

        log_debug(f"{xref.address:x} {add_method_call.operation!r}")
        if add_method_call.operation not in (
                MediumLevelILOperation.MLIL_CALL,
                MediumLevelILOperation.MLIL_CALL_UNTYPED):
            continue

        class_param = add_method_call.params[0]
        if class_param.operation != MediumLevelILOperation.MLIL_VAR:
            log_debug(f"class_param is {class_param.operation!r}")
            continue

        cls_ = class_param.src.type

        log_debug(f"Checking {cls_!r}")
        if cls_.target is not None and cls_.target.named_type_reference is not None:
            class_name = cls_.target.named_type_reference.name
        else:
            log_debug(f"cls_ is {cls_}->{cls_.target}")
            continue

        log_debug("Getting selector_param")
        selector_param = add_method_call.params[1]
        if selector_param.operation == MediumLevelILOperation.MLIL_CONST:
            selector_ptr = selector_param
        elif selector_param.operation != MediumLevelILOperation.MLIL_VAR:
            log_debug(f"selector_param {selector_param.operation!r}")
            continue
        else:
            selector_ptr = None

            log_debug("Getting get_method_call")
            get_method_call = mlil.get_ssa_var_definition(
                selector_param.ssa_form.src)

            while get_method_call.operation != MediumLevelILOperation.MLIL_CALL:
                if get_method_call.operation != MediumLevelILOperation.MLIL_SET_VAR:
                    log_debug(f"get_method_call {get_method_call.operation!r}")
                    break

                if get_method_call.src.operation != MediumLevelILOperation.MLIL_VAR:
                    log_debug(f"get_method_call.src {get_method_call.src!r}")
                    break

                get_method_call = mlil.get_ssa_var_definition(
                    get_method_call.ssa_form.src.src
                )
                log_debug(f"{get_method_call!r}")
            else:
                log_debug(f"Found {get_method_call!r}")
                selector_ptr = get_method_call.params[1]

        if selector_ptr is None:
            log_debug("selector_ptr is None")
            continue

        if selector_ptr.operation not in (
                MediumLevelILOperation.MLIL_CONST,
                MediumLevelILOperation.MLIL_CONST_PTR):
            log_debug(f"selector_ptr {selector_ptr.operation!r}")
            continue

        selector_str = view.get_ascii_string_at(selector_ptr.constant, 1)

        if selector_str is None:
            log_debug("selector_str is None")
            continue

        selector = selector_str.value

        method_string = f"-[{class_name} {selector}]"

        log_debug(f"method_string is {method_string}")

        method_ptr = add_method_call.params[2]

        if method_ptr.operation not in (
                MediumLevelILOperation.MLIL_CONST,
                MediumLevelILOperation.MLIL_CONST_PTR):
            log_debug(f"method_ptr.operation {method_ptr.operation!r}")
            continue

        log_debug("Defining {method_string} @ {method_ptr.constant}")
        view.define_user_symbol(
            Symbol(
                SymbolType.FunctionSymbol,
                method_ptr.constant,
                method_string
            )
        )