Exemple #1
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
    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)
def fix_printfs(view: BinaryView):
    printf = view.get_symbols_by_name('_printf')

    if not printf:
        printf = view.get_symbols_by_name('printf')

    if not printf:
        return

    for sym in printf:
        function = view.get_function_at(sym.address)
        if not function:
            continue

        xrefs = view.get_code_refs(function.start)

        for xref in xrefs:
            caller: Function = xref.function

            call_mlil = caller.get_low_level_il_at(xref.address).mlil
            print(call_mlil)
            if call_mlil is None:
                continue

            fmt_operand = call_mlil.params[0]
            if fmt_operand.operation == MediumLevelILOperation.MLIL_VAR:
                log.log_warn(
                    f"Potential format string bug: {fmt_operand.address:x}")
                continue

            elif fmt_operand.operation in (
                    MediumLevelILOperation.MLIL_CONST_PTR,
                    MediumLevelILOperation.MLIL_CONST):
                fmt_address = fmt_operand.constant
                fmt = view.get_ascii_string_at(fmt_address, 2)

                if fmt is None:
                    continue

                fmt_value = fmt.value

            else:
                continue

            specifiers = fmt_value.split('%')

            param_types = []

            for specifier in specifiers[1:]:
                if not specifier:
                    continue

                if specifier.startswith('d'):
                    param_types.append(Type.int(4, sign=True))
                elif specifier.startswith('s'):
                    param_types.append(Type.pointer(view.arch, Type.char()))
                elif specifier.startswith('p'):
                    param_types.append(Type.pointer(view.arch, Type.void()))
                else:
                    log.log_warn(
                        f'Unknown format specifier: {specifier}; skipping')
                    param_types.append(Type.pointer(view.arch, Type.void()))

            param_idx = 1
            params = [
                FunctionParameter(Type.pointer(view.arch, Type.char()), 'fmt')
            ]
            for param in param_types:
                params.append(FunctionParameter(param, f'arg{param_idx}'))
                param_idx += 1

            caller.set_call_type_adjustment(xref.address,
                                            Type.function(Type.int(4), params))
            )
            if sign_bit:
                full_width_value |= full_width_mask ^ ((1 << ((size + offset) * 8)) - 1)

        self._state.regs[full_width_reg] = full_width_value


if __name__ == '__main__':
    bv = BinaryView()

    # bv.write(0, b'\x89\xd8\x90\x90\x90')
    # bv.write(0, b'\xb8\x01\x00\x00\x00')
    bv.write(0, b'\x01 \xa0\xe3')

    # bv.platform = Architecture['x86'].standalone_platform
    bv.platform = Architecture['armv7'].standalone_platform

    bv.create_user_function(0)

    bv.update_analysis_and_wait()

    function = bv.get_function_at(0)

    emu = InstructionEmulator(bv, {'r2': 1337})

    print(emu._state.regs)

    emu.execute(function.llil[0])

    print(emu._state.regs)