lief_modifier.py
ofrak.core.elf.lief_modifier
LiefAddSectionModifer (Modifier)
modify(self, resource, config)
async
Modify the given resource.
Users should not call this method directly; rather, they should run Resource.run.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
required | |
config |
LiefAddSectionModifierConfig |
Optional config for modification. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run. |
required |
Source code in ofrak/core/elf/lief_modifier.py
async def modify(self, resource: Resource, config: LiefAddSectionModifierConfig):
binary: Optional[lief.Binary] = lief.parse(await resource.get_data())
if not binary or not isinstance(binary, lief.ELF.Binary):
raise ValueError("Lief failed parsing binary.")
section: lief.ELF.Section = lief.ELF.Section()
section.name = config.name
section.content = memoryview(bytearray(config.content))
section.flags = config.flags
binary.add(section)
with tempfile.NamedTemporaryFile(delete_on_close=False) as temp_file:
temp_file.close()
binary.write(temp_file.name)
with open(temp_file.name, "rb") as f_handle:
new_data = f_handle.read()
# replace all old content (old range) with new content from Lief
resource.queue_patch(Range(0, await resource.get_data_length()), new_data)
LiefAddSectionModifierConfig (ComponentConfig)
dataclass
LiefAddSectionModifierConfig(name: str, content: bytes, flags: int)
LiefAddSegmentConfig (ComponentConfig)
dataclass
Config for the LiefAddSegmentModifier.
Attributes:
Name | Type | Description |
---|---|---|
virtual_address |
int |
virtual address of the new segment |
alignment |
int |
alignment of the new segment |
content |
List[int] |
list of integers representing the raw bytes of the new segment |
rwx_flags |
str |
string representation of the new segment's R/W/X permissions |
replace_note |
bool |
replace the unused NOTE segment with the new segment, rather than adding a new segment. defaults to |
physical_address |
Optional[int] |
overwrite the default physical address (defaults to the virtual address) |
LiefAddSegmentModifier (Modifier)
modify(self, resource, config)
async
Modify the given resource.
Users should not call this method directly; rather, they should run Resource.run.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
required | |
config |
LiefAddSegmentConfig |
Optional config for modification. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run. |
required |
Source code in ofrak/core/elf/lief_modifier.py
async def modify(self, resource: Resource, config: LiefAddSegmentConfig) -> None:
binary: Optional[lief.Binary] = lief.parse(await resource.get_data())
if not binary or not isinstance(binary, lief.ELF.Binary):
raise ValueError("Lief failed parsing binary.")
segment = lief.ELF.Segment()
segment.type = lief.ELF.Segment.TYPE.LOAD
segment.content = memoryview(bytearray(config.content))
segment.alignment = config.alignment
segment.virtual_address = config.virtual_address
if config.physical_address is not None:
segment.physical_address = config.physical_address
if "r" in config.rwx_flags:
segment.add(lief.ELF.Segment.FLAGS.R)
if "w" in config.rwx_flags:
segment.add(lief.ELF.Segment.FLAGS.W)
if "x" in config.rwx_flags:
segment.add(lief.ELF.Segment.FLAGS.X)
if config.replace_note:
# instead of adding a segment to the binary, replace a useless NOTE segment
# see https://github.com/lief-project/LIEF/issues/98
# and https://github.com/lief-project/LIEF/issues/143
if not binary.has(lief.ELF.Segment.TYPE.NOTE):
raise ValueError("Binary must have a NOTE section to add a new section")
segment = binary.replace(segment, binary[lief.ELF.Segment.TYPE.NOTE])
if config.physical_address is not None:
segment.physical_address = config.physical_address
else:
_ = binary.add(segment)
with tempfile.NamedTemporaryFile(delete_on_close=False) as temp_file:
temp_file.close()
binary.write(temp_file.name)
with open(temp_file.name, "rb") as f_handle:
new_data = f_handle.read()
# replace all old content (old range) with new content from Lief
resource.queue_patch(Range(0, await resource.get_data_length()), new_data)
LiefRemoveSectionModifier (Modifier)
modify(self, resource, config)
async
Modify the given resource.
Users should not call this method directly; rather, they should run Resource.run.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource |
Resource |
required | |
config |
LiefRemoveSectionModifierConfig |
Optional config for modification. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run. |
required |
Source code in ofrak/core/elf/lief_modifier.py
async def modify(self, resource: Resource, config: LiefRemoveSectionModifierConfig):
binary: Optional[lief.Binary] = lief.parse(await resource.get_data())
if not binary or not isinstance(binary, lief.ELF.Binary):
raise ValueError("Lief failed parsing binary.")
section: lief.ELF.Section = binary.get_section(config.name)
if section is None:
raise AttributeError(f"No section with name {config.name}")
binary.remove(section)
with tempfile.NamedTemporaryFile(delete_on_close=False) as temp_file:
temp_file.close()
binary.write(temp_file.name)
with open(temp_file.name, "rb") as f_handle:
new_data = f_handle.read()
# replace all old content (old range) with new content from Lief
resource.queue_patch(Range(0, await resource.get_data_length()), new_data)
LiefRemoveSectionModifierConfig (ComponentConfig)
dataclass
LiefRemoveSectionModifierConfig(name: str)