Skip to content

complex_block.py

ofrak.core.complex_block

ComplexBlock (MemoryRegion) dataclass

A collection of basic blocks and data words that represent a logical unit of code (usually a function).

Attributes:

Name Type Description
virtual_address int

the lowest virtual address in the complex block

size int

the size of the complex block

name str

the complex block's name

get_basic_blocks(self) async

Get complex block's basic blocks.

Returns:

Type Description
Iterable[ofrak.core.basic_block.BasicBlock]

basic blocks

Source code in ofrak/core/complex_block.py
async def get_basic_blocks(self) -> Iterable[BasicBlock]:
    """
    Get complex block's basic blocks.

    :return: basic blocks
    """
    return await self.resource.get_descendants_as_view(
        BasicBlock,
        r_filter=ResourceFilter.with_tags(BasicBlock),
        r_sort=ResourceSort(Addressable.VirtualAddress),
    )

get_assembly(self) async

Get the complex block's instructions as an assembly string.

Returns:

Type Description
str

the complex block's assembly

Source code in ofrak/core/complex_block.py
async def get_assembly(self) -> str:
    """
    Get the complex block's instructions as an assembly string.

    :return: the complex block's assembly
    """
    bbs = await self.get_basic_blocks()
    bb_assemblies = [bb_r.get_assembly() for bb_r in bbs]
    return "\n".join(await asyncio.gather(*bb_assemblies))

get_data_words(self) async

Get the complex block's data words.

Returns:

Type Description
Iterable[ofrak.core.data.DataWord]

the data words in the complex block

Source code in ofrak/core/complex_block.py
async def get_data_words(self) -> Iterable[DataWord]:
    """
    Get the complex block's [data words][ofrak.core.data.DataWord].

    :return: the data words in the complex block
    """
    return await self.resource.get_descendants_as_view(
        DataWord,
        r_filter=ResourceFilter.with_tags(DataWord),
        r_sort=ResourceSort(Addressable.VirtualAddress),
    )

get_mode(self) async

Get the complex block's mode.

Returns:

Type Description
InstructionSetMode

the mode of the complex block

Exceptions:

Type Description
ValueError

if the basic blocks in the complex block have more than one mode

Source code in ofrak/core/complex_block.py
async def get_mode(self) -> InstructionSetMode:
    """
    Get the complex block's [mode][ofrak_type.architecture.InstructionSetMode].

    :raises ValueError: if the basic blocks in the complex block have more than one mode
    :return: the mode of the complex block
    """
    await self.resource.unpack()
    bb_modes = {bb.mode for bb in await self.get_basic_blocks()}
    if len(bb_modes) == 1:
        return bb_modes.pop()
    elif len(bb_modes) > 1:
        raise ValueError(
            f"Multiple modes present in complex block! Not all basic blocks have "
            f"the same mode; found modes {bb_modes}"
        )
    else:
        raise ValueError("No basic blocks found in complex block! Perhaps it was not unpacked")

ComplexBlockAnalyzer (Analyzer, ABC)

Analyze a complex block and extract its virtual address, size, and name.

analyze(self, resource, config=None) async

Analyze a complex block resource and extract its virtual address, size, and name.

Parameters:

Name Type Description Default
resource Resource

the complex block resource

required
config None

Returns:

Type Description
ComplexBlock

the analyzed complex block

Source code in ofrak/core/complex_block.py
@abstractmethod
async def analyze(self, resource: Resource, config=None) -> ComplexBlock:
    """
    Analyze a complex block resource and extract its virtual address, size, and name.

    :param resource: the complex block resource
    :param config:

    :return: the analyzed complex block
    """
    raise NotImplementedError()

ComplexBlockDataReferenceAttributes (ResourceAttributes) dataclass

ComplexBlockDataReferenceAttributes(referenced_data_vm_addresses: Tuple[int, ...])

ComplexBlockUnpacker (Unpacker, ABC)

Unpack a complex block into basic blocks and data words.

unpack(self, resource, config=None) async

Unpack a complex block, identifying all of the basic blocks and data words which are a part of it.

The identified basic blocks and data words must be within the previously identified range of the complex block. If the analysis engine identifies basic blocks outside of this range, those are be ignored - i.e. not unpacked - and the rest of the basic blocks in the function are unpacked as usual.

Source code in ofrak/core/complex_block.py
@abstractmethod
async def unpack(self, resource: Resource, config=None):
    """
    Unpack a complex block, identifying all of the basic blocks and data words which are a part
    of it.

    The identified basic blocks and data words must be within the previously identified range
    of the complex block. If the analysis engine identifies basic blocks outside of this
    range, those are be ignored - i.e. not unpacked - and the rest of the basic blocks in
    the function are unpacked as usual.
    """
    raise NotImplementedError()

DataRefsAnalyzer (Analyzer, ABC)

Analyze the references a complex block makes to data addresses.

analyze(self, resource, config=None) async

Analyze the references a complex block resource makes to data addresses

Parameters:

Name Type Description Default
resource Resource

the complex block resource

required
config None

Returns:

Type Description
Tuple[ofrak.core.complex_block.ComplexBlockDataReferenceAttributes]

The virtual addresses of all the data words referenced by the complex block.

Source code in ofrak/core/complex_block.py
@abstractmethod
async def analyze(
    self, resource: Resource, config=None
) -> Tuple[ComplexBlockDataReferenceAttributes]:
    """
    Analyze the references a complex block resource makes to data addresses

    :param resource: the complex block resource
    :param config:

    :return: The virtual addresses of all the data words referenced by the complex block.
    """
    raise NotImplementedError()