Files
LIEF/doc/code/python/macho.py
T

159 lines
4.3 KiB
Python

import pathlib
import lief
def iterate(fat: lief.MachO.FatBinary) -> lief.MachO.Binary | None:
# lief-doc: iterate-start
fat: lief.MachO.FatBinary
# Iterate
for macho in fat:
print(macho.entrypoint)
print(len(macho.commands))
# Pick one at the specified index
macho = fat.at(0)
# Pick one based on the architecture
macho = fat.take(lief.MachO.Header.CPU_TYPE.ARM64)
# lief-doc: iterate-end
return macho
def write_bytes(macho: lief.MachO.Binary) -> bytes:
# lief-doc: write-bytes-start
macho: lief.MachO.Binary
new_macho: bytes = macho.write_to_bytes()
# lief-doc: write-bytes-end
return new_macho
def parse_from_dump() -> None:
# lief-doc: dump-start
# 0x11e32c000 is the (absolute) address at which the dump was mapped
fat = lief.MachO.parse_from_dump("module.dump", 0x11E32C000)
assert isinstance(fat, lief.MachO.FatBinary)
macho = fat.at(0)
assert isinstance(fat, lief.MachO.Binary)
for segment in macho.segments:
print(segment.name, hex(segment.virtual_address))
# lief-doc: dump-end
def module_dump() -> None:
# lief-doc: dump-runtime-start
# Find the module to dump in the current process
mod = lief.runtime.module_from_name("libsystem_c.dylib")
assert isinstance(mod, lief.runtime.osx.Module)
# Dump the module's memory into a file (the raw bytes are also returned) ...
data: bytes = mod.dump("module.dump")
# ... and parse it back using the same imagebase:
macho = lief.MachO.parse_from_dump(data, mod.imagebase)
# lief-doc: dump-runtime-end
assert isinstance(macho, lief.MachO.FatBinary)
def rpath_atrpath(macho: lief.MachO.Binary) -> None:
# lief-doc: rpath-atrpath-start
macho: lief.MachO.Binary
lib = macho.find_library("libmylib.dylib")
assert isinstance(lib, lief.MachO.DylibCommand)
lib.name = "@rpath/libmylib.dylib"
macho.write("hello_fixed.bin")
# lief-doc: rpath-atrpath-end
def parse_forms() -> lief.MachO.FatBinary | None:
# lief-doc: parse-start
# Using filepath
macho: lief.MachO.FatBinary | None = lief.MachO.parse("/bin/ls")
# Using a Path from pathlib
macho: lief.MachO.FatBinary | None = lief.MachO.parse(
pathlib.Path(r"C:\Users\test.macho")
)
# Using an io object
with open("/bin/ssh", "rb") as f:
macho: lief.MachO.FatBinary | None = lief.MachO.parse(f)
# lief-doc: parse-end
return macho
def write_fat(macho: lief.MachO.FatBinary) -> None:
# lief-doc: write-fat-start
macho: lief.MachO.FatBinary
macho.at(0).write("fit.macho")
macho.write("fat.macho") # write-back the whole FAT binary
# lief-doc: write-fat-end
def advanced_parse_write() -> None:
# lief-doc: advanced-start
parser_config = lief.MachO.ParserConfig()
parser_config.parse_dyld_bindings = False
fat = lief.MachO.parse("my.macho", parser_config)
assert isinstance(fat, lief.MachO.FatBinary)
macho = fat.at(0)
assert isinstance(fat, lief.MachO.Binary)
builder_config = lief.MachO.Builder.config_t()
builder_config.linkedit = False
macho.write("new.macho", builder_config)
# lief-doc: advanced-end
def rpath_change_lib() -> None:
# lief-doc: rpath-change-lib-start
fat = lief.MachO.parse("hello.bin")
assert isinstance(fat, lief.MachO.FatBinary)
macho = fat.at(0)
assert isinstance(fat, lief.MachO.Binary)
lib = macho.find_library("libmylib.dylib")
assert isinstance(lib, lief.MachO.DylibCommand)
lib.name = "/opt/homebrew/my_package/libmylib.dylib"
macho.write("hello_fixed.bin")
# lief-doc: rpath-change-lib-end
def rpath_add() -> None:
# lief-doc: rpath-add-start
fat = lief.MachO.parse("hello.bin")
assert isinstance(fat, lief.MachO.FatBinary)
macho = fat.at(0)
assert isinstance(fat, lief.MachO.Binary)
rpath = lief.MachO.RPathCommand.create("/opt/homebrew/my_package")
assert isinstance(rpath, lief.MachO.RPathCommand)
macho.add(rpath)
# lief-doc: rpath-add-end
def parse_config() -> None:
# lief-doc: parse-config-start
fatbinary_1 = lief.MachO.parse("/usr/bin/ls", config=lief.MachO.ParserConfig.deep)
# or
fatbinary_2 = lief.MachO.parse("/usr/bin/ls", config=lief.MachO.ParserConfig.quick)
# lief-doc: parse-config-end
_ = (fatbinary_1, fatbinary_2)