Skip to content

Modifiers

Overview

Modifiers operate on the current state of the binary, directly manipulating the underlying binary data. When they do this, they invalidate the data and attribute dependencies for the modified resource.

The most basic modifier, outlined below, performs simple offset and content patching:

@dataclass
class BinaryPatchConfig(ComponentConfig):
    offset: int  # Physical offset from beginning of resource
    bytes: bytes  # Raw bytes to patch


class BinaryPatchModifier(Modifier[BinaryPatchConfig]):
    """
    Patch the binary at the target offset with raw bytes.
    """

    targets = (ResourceTag,)

    async def modify(self, resource: Resource, config: BinaryPatchConfig) -> None:
        resource_size = await resource.get_data_length()
        if len(config.patch_bytes) > resource_size - config.offset:
            raise ModifierError(
                f"The binary patch, {config}, overflows the original size of the resource "
                f"{resource.get_id().hex()}."
            )
        return resource.queue_patch(config.get_range(), config.patch_bytes)

Usage

Modifiers should be run directly against a resource. For example:

patch_config = BinaryPatchConfig(100, b"Meow!")
await resource.run(BinaryPatchModifier, patch_config)