instruction.py
ofrak.core.instruction
Instruction (MemoryRegion)
dataclass
A single ISA instruction.
Attributes:
| Name | Type | Description |
|---|---|---|
virtual_address |
int |
the virtual address of the start of the instruction |
size |
int |
the size of the instruction |
mnemonic |
str |
the instruction's mnemonic |
operands |
str |
the instruction's operands |
mode |
InstructionSetMode |
the instruction set mode of the instruction |
get_assembly(self)
Get the instruction as an assembly string.
Returns:
| Type | Description |
|---|---|
str |
the instruction as an assembly string |
Source code in ofrak/core/instruction.py
def get_assembly(self) -> str:
"""
Get the instruction as an assembly string.
:return: the instruction as an assembly string
"""
return f"{self.mnemonic} {self.operands}"
modify_assembly(self, mnemonic=None, operands=None, mode=None)
async
Modify the instruction, changing it to an instruction of equal size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mnemonic |
Optional[str] |
the modified instruction mnemonic |
None |
operands |
Optional[str] |
the modified instruction operands |
None |
mode |
Optional[ofrak_type.architecture.InstructionSetMode] |
the modified instruction's instruction set mode |
None |
Returns:
| Type | Description |
|---|---|
bytes |
the instruction's machine code after modification |
Source code in ofrak/core/instruction.py
async def modify_assembly(
self,
mnemonic: Optional[str] = None,
operands: Optional[str] = None,
mode: Optional[InstructionSetMode] = None,
) -> bytes:
"""
Modify the instruction, changing it to an instruction of equal size.
:param mnemonic: the modified instruction mnemonic
:param operands: the modified instruction operands
:param mode: the modified instruction's instruction set mode
:return: the instruction's machine code after modification
"""
modification_config = InstructionModifierConfig(
mnemonic or self.mnemonic,
operands or self.operands,
mode or self.mode,
)
await self.resource.run(InstructionModifier, modification_config)
data_after_modification = await self.resource.get_data()
return data_after_modification
InstructionAnalyzer (Analyzer, ABC)
Analyze an instruction and extract its attributes.
InstructionModifier (Modifier)
Modifies individual assembly instructions by changing their mnemonic (operation) and/or operands (arguments), enabling instruction-level binary patching. The replacement instruction must be the same size as the original to prevent corruption. Use for changing specific instructions, redirecting branches or calls, modifying instruction operands, implementing instruction-level patches, NOP-ing operations, or fine-tuning code behavior. Powerful but requires understanding of instruction encoding and size constraints.
modify(self, resource, config)
async
Modify an instruction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
resource |
Resource |
the instruction resource to modify |
required |
config |
InstructionModifierConfig |
required |
Exceptions:
| Type | Description |
|---|---|
AssertionError |
if the modified instruction length does not match the length of the original instruction |
Source code in ofrak/core/instruction.py
async def modify(self, resource: Resource, config: InstructionModifierConfig):
"""
Modify an instruction.
:param resource: the instruction resource to modify
:param config:
:raises AssertionError: if the modified instruction length does not match the length of
the original instruction
"""
resource_memory_region = await resource.view_as(MemoryRegion)
modified_assembly = f"{config.mnemonic} {config.operands}"
asm = await self._assembler_service.assemble(
modified_assembly,
resource_memory_region.virtual_address,
await resource.analyze(ProgramAttributes),
config.mode,
)
assert (
len(asm) == resource_memory_region.size
), "The modified instruction length does not match the original instruction length"
new_attributes = AttributesType[Instruction](
mnemonic=config.mnemonic,
operands=config.operands,
mode=config.mode,
)
resource.queue_patch(Range.from_size(0, len(asm)), asm)
resource.add_attributes(new_attributes)
InstructionModifierConfig (ComponentConfig)
dataclass
Config for the InstructionModifier.
Attributes:
| Name | Type | Description |
|---|---|---|
mnemonic |
str |
the modified instruction's mnemonic |
operands |
str |
the modified instruction's operands |
mode |
InstructionSetMode |
the modified instruction's instruction set mode |
InstructionRegisterUsageAnalyzer (Analyzer, ABC)
Analyze an instruction and extract the list of registers read and written.
RegisterUsage (ResourceAttributes)
dataclass
Information about the register usage in a Resource containing some assembly, such as an Instruction.
Attributes:
| Name | Type | Description |
|---|---|---|
registers_read |
Tuple[str, ...] |
registers read from when the assembly executes |
registers_written |
Tuple[str, ...] |
registers written to when the assembly executes |
_KeystoneExternalTool (ComponentExternalTool)
private
Keystone (keystone-engine) installs from PyPI do not work on MacOS.
To use keystone with OFRAK, do a "no-binary" install from PyPI (and make sure cmake is installed):
pip install --no-binary keystone-engine
__init__(self)
special
Initialize self. See help(type(self)) for accurate signature.
Source code in ofrak/core/instruction.py
def __init__(self):
super().__init__(
"kstool",
"https://www.keystone-engine.org/",
install_check_arg="",
)
is_tool_installed(self)
async
Check if a tool is installed by running it with the install_check_arg.
This method runs <tool> <install_check_arg>.
Returns:
| Type | Description |
|---|---|
bool |
True if the |
Source code in ofrak/core/instruction.py
async def is_tool_installed(self) -> bool:
return KEYSTONE_INSTALL_WORKS