示例#1
0
    def from_address(cls, address: int, view: BinaryView):
        if address == 0:
            return None

        property_t_type = view.types['property_t']
        property_t = Type.named_type_from_type(
            'property_t', property_t_type
        )

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

        members = get_structure_members(address, property_t_type, view)

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

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

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

        from_bytes = get_from_bytes(view)

        ivar_list_t_type = view.types['ivar_list_t']

        ivar_list_t = Type.named_type_from_type(
            'ivar_list_t', ivar_list_t_type
        )

        ivar_t = view.types['ivar_t']

        members = get_structure_members(address, ivar_list_t_type, view)

        view.define_user_data_var(address, ivar_list_t)

        ivars = {}
        start = address + ivar_list_t_type.width
        end = start + members['count'] * ivar_t.width
        step = ivar_t.width
        for ivar in range(start, end, step):
            new_ivar = Ivar.from_address(ivar, class_name, view)
            ivars[new_ivar.name] = new_ivar

        return cls(address, **members, ivars=ivars)
示例#3
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"))
示例#4
0
    def from_address(cls,
                     address: int,
                     self_type: str,
                     view: BinaryView,
                     is_class=False):
        if address == 0:
            return None

        method_list_t_type = view.get_type_by_name('method_list_t')

        method_list_t = Type.named_type_from_type('method_list_t',
                                                  method_list_t_type)

        method_t = view.get_type_by_name('method_t')

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

        members = get_structure_members(address, method_list_t_type, view)

        methods = dict()
        start = address + method_list_t_type.width
        end = start + members['count'] * method_t.width
        step = method_t.width
        for method_addr in range(start, end, step):
            method = Method.from_address(method_addr, self_type, view,
                                         is_class)
            if method is not None:
                methods[method.name] = method

        return cls(address, **members, methods=methods)
示例#5
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
示例#6
0
    def from_address(cls, address: int, view: BinaryView):
        if address == 0:
            return None

        property_list_t_type = view.types['property_list_t']

        property_list_t = Type.named_type_from_type(
            'property_list_t', property_list_t_type
        )

        property_t = view.types['property_t']

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

        members = get_structure_members(address, property_list_t_type, view)

        properties = dict()
        start = address + property_list_t_type.width
        end = start + members['count'] * property_t.width
        step = property_t.width
        for property_addr in range(start, end, step):
            property_ = Property.from_address(property_addr, view)
            if property_ is not None:
                properties[property_.name] = property_

        return cls(address, **members, properties=properties)
示例#7
0
    def from_address(cls, address: int, view: BinaryView):
        if address == 0:
            return None

        from_bytes = get_from_bytes(view)

        protocol_list_t_type = view.get_type_by_name('protocol_list_t')

        protocol_list_t = Type.named_type_from_type('protocol_list_t',
                                                    protocol_list_t_type)

        protocol_t = view.get_type_by_name('protocol_t')

        members = get_structure_members(address, protocol_list_t_type, view)

        view.define_user_data_var(address, protocol_list_t)

        protocols = {}
        start = address + protocol_list_t_type.width
        end = start + members['count'] * view.address_size
        step = view.address_size
        for protocol_ptr in range(start, end, step):
            if not view.get_data_var_at(protocol_ptr):
                view.define_user_data_var(protocol_ptr,
                                          Type.pointer(view.arch, protocol_t))
            protocol = Protocol.from_address(
                from_bytes(view.read(protocol_ptr, view.address_size)), view)

            protocols[protocol.name] = protocol

        return cls(address, **members, protocols=protocols)
示例#8
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)
示例#9
0
    def from_address(cls, address: int, view: BinaryView) -> Category:
        if address == 0:
            return None

        from .class_t import Class, ClassRO

        category_t_type = view.types['category_t']
        category_t = Type.named_type_from_type('category_t', category_t_type)

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

        members = get_structure_members(address, category_t_type, view)

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

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

        if members['cls'] is None:
            cls_offset = next(m.offset
                              for m in category_t_type.structure.members
                              if m.name == 'cls')
            cls_name = view.get_symbol_at(address + cls_offset)
            cls_name = cls_name.name if cls_name is not None else members[
                'name']

            class_match = re.match(
                r'_OBJC_(META)?CLASS_\$_(?P<classname>[_A-Za-z0-9=/]+)(@GOT)?',
                cls_name)
            if class_match is not None:
                cls_name = class_match.group('classname')
                cls_ = view.session_data['ClassNames'].get(cls_name)
                if cls_ is None:
                    cls_ = Class(None, view, None, None, None, {}, {})
                    cls_.vtable = ClassRO(address, *([None] * 11))
                    cls_.vtable.name = cls_name
                    view.session_data['ClassNames'][cls_name] = cls_

                members['cls'] = cls_
        else:
            cls_name = members['cls'].vtable.name

        members['instanceMethods'] = MethodList.from_address(
            members['instanceMethods'], cls_name, view)

        if members['cls'] is not None and not members['cls'].methods:
            members['cls']._methods = members['instanceMethods'].methods
        elif members['cls'] is not None:
            members['cls']._methods.update(members['instanceMethods'].methods)

        members['protocols'] = ProtocolList.from_address(
            members['protocols'], view)

        return cls(address, **members)
示例#10
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
示例#11
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)
示例#12
0
    def from_address(cls, address: int, view: BinaryView, is_meta=False):
        from .protocol_t import ProtocolList
        if address == 0:
            return None

        elif address in view.session_data['ClassROList']:
            return view.session_data['ClassROList']

        from_bytes = partial(int.from_bytes,
                             byteorder=("little" if view.endianness
                                        == Endianness.LittleEndian else "big"))

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

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

        members = {
            m.name: from_bytes(view.read(address + m.offset, m.type.width))
            for m in view.types['class_ro_t'].structure.members
        }

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

        members['ivarLayout'] = (view.get_ascii_string_at(
            members['ivarLayout'], 1).value
                                 if members['ivarLayout'] != 0 else '')

        members['ivars'] = IvarList.from_address(members['ivars'],
                                                 members['name'], view)

        members['baseMethods'] = MethodList.from_address(
            members['baseMethods'], members['name'], view, is_meta)

        members['baseProtocols'] = ProtocolList.from_address(
            members['baseProtocols'], view)

        members['baseProperties'] = PropertyList.from_address(
            members['baseProperties'], view)

        new_class_ro = cls(address, **members)

        view.session_data['ClassROList'][address] = new_class_ro
        return new_class_ro
示例#13
0
def _define_protocols(view: BinaryView):
    __objc_protorefs = view.get_section_by_name('__objc_protorefs')

    if __objc_protorefs is None:
        return

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

    for address in range(__objc_protorefs.start, __objc_protorefs.end,
                         view.address_size):
        view.define_user_data_var(address, Type.pointer(view.arch, protocol_t))

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

        new_protocol = Protocol.from_address(protocol_ptr, view)
示例#14
0
def _define_categories(view: BinaryView):
    __objc_catlist = view.sections.get('__objc_catlist')

    if __objc_catlist is None:
        return

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

    for address in range(__objc_catlist.start, __objc_catlist.end,
                         view.address_size):
        view.define_user_data_var(address, Type.pointer(view.arch, category_t))

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

        new_category = Category.from_address(category_ptr, view)
示例#15
0
def _define_selectors(view: BinaryView):
    __objc_selrefs = view.sections.get('__objc_selrefs')

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

    SEL = view.get_type_by_name('SEL')
    if SEL is None:
        raise TypeError('The SEL type is not defined!')

    for addr in range(__objc_selrefs.start, __objc_selrefs.end, SEL.width):
        view.define_user_data_var(addr, SEL)
        selector = int.from_bytes(view.read(addr, SEL.width), "little")
        if selector != 0:
            name = view.get_ascii_string_at(selector, 3)
            if name is not None:
                view.define_user_data_var(
                    name.start, Type.array(Type.char(), name.length + 1))
示例#16
0
def make_struct_here(view: BinaryView, address: int, length: int):
    structure_name = f"struct_{address:x}"

    structure = StructureBuilder()
    structure.width = length

    add_members(view, structure, address, length)

    structure_type = Type.structure_type(structure)

    view.begin_undo_actions()

    view.define_user_type(structure_name, structure_type)

    named_type = Type.named_type_from_type(structure_name, structure_type)

    view.define_user_data_var(address, named_type)

    view.commit_undo_actions()
示例#17
0
    def from_address(cls, address: int, view: BinaryView) -> Protocol:
        if address == 0:
            return None

        from .class_t import Class

        from_bytes = partial(int.from_bytes,
                             byteorder=("little" if view.endianness
                                        == Endianness.LittleEndian else "big"))

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

        if not view.get_data_var_at(address):
            view.define_user_data_var(address, protocol_t)

        members = {
            m.name: from_bytes(view.read(address + m.offset, m.type.width))
            for m in view.get_type_by_name('protocol_t').structure.members
        }

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

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

        if members['name'] not in view.types:
            view.define_user_type(members['name'],
                                  Type.structure_type(Structure()))

        members['protocols'] = ProtocolList.from_address(
            members['protocols'], view)

        members['instanceMethods'] = MethodList.from_address(
            members['instanceMethods'], members['name'], view)

        members['optionalInstanceMethods'] = MethodList.from_address(
            members['optionalInstanceMethods'], members['name'], view)

        new_protocol = cls(address, **members)
        view.session_data['Protocols'][new_protocol.name] = new_protocol
        return new_protocol
示例#18
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
示例#19
0
def define_cfstrings_plugin(view: BinaryView):
    log_debug("define_cfstrings_plugin")

    from_bytes = _get_from_bytes(view)

    cfstring_type = view.get_type_by_name('CFString')
    if cfstring_type is None:
        cfstring_type = view.platform.parse_types_from_source(
            _cfstring_definition).types['CFString']

        view.define_user_type('CFString', cfstring_type)

        wchar_type = view.platform.parse_types_from_source(
            _wchar_definition).types['wchar']

    cfstring = Type.named_type_from_type('CFString', cfstring_type)

    __cfstring = view.get_section_by_name('__cfstring')

    if __cfstring is None:
        return

    buffer = cfstring_type.structure['buffer']
    length = cfstring_type.structure['length']

    for addr in range(__cfstring.start, __cfstring.end, cfstring_type.width):
        view.define_user_data_var(addr, cfstring)

        for xref in view.get_data_refs(addr):
            view.define_user_data_var(xref, Type.pointer(view.arch, cfstring))

        string_pointer = from_bytes(
            view.read(addr + buffer.offset, buffer.type.width))

        string_length = from_bytes(
            view.read(addr + length.offset, length.type.width), ) + 1

        string_section = view.get_sections_at(string_pointer)

        if not string_section:
            return

        if string_section[0].name == '__ustring':
            char_type = wchar_type
        else:
            char_type = Type.char()

        view.define_user_data_var(string_pointer,
                                  Type.array(char_type, string_length))