Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_lazy_bind(self):
target = lief.parse(get_sample('MachO/MachO64_x86-64_binary_lazy-bind-LLVM.bin'))
self.assertTrue(target.has_dyld_info)
bindings = list(target.dyld_info.bindings)[1:] # Skip the 1st one (Standard one)
self.assertEqual(len(bindings), 3)
self.assertEqual(bindings[0].binding_class, lief.MachO.BINDING_CLASS.LAZY)
self.assertEqual(bindings[0].binding_type, lief.MachO.BIND_TYPES.POINTER)
self.assertEqual(bindings[0].address, 0x100001010)
self.assertEqual(bindings[0].symbol.name, "_foo")
self.assertEqual(bindings[0].segment.name, "__DATA")
self.assertEqual(bindings[0].library.name, "libfoo.dylib")
self.assertEqual(bindings[1].binding_class, lief.MachO.BINDING_CLASS.LAZY)
self.assertEqual(bindings[1].binding_type, lief.MachO.BIND_TYPES.POINTER)
self.assertEqual(bindings[1].address, 0x100001018)
self.assertEqual(bindings[1].symbol.name, "_bar")
self.assertEqual(bindings[1].segment.name, "__DATA")
self.assertEqual(bindings[1].library.name, "libbar.dylib")
self.assertEqual(bindings[2].binding_class, lief.MachO.BINDING_CLASS.LAZY)
self.assertEqual(bindings[2].binding_type, lief.MachO.BIND_TYPES.POINTER)
self.assertEqual(bindings[2].address, 0x100001020)
def test_build_version(self):
binary = lief.MachO.parse(get_sample('MachO/FAT_MachO_arm-arm64-binary-helloworld.bin'))
target = binary[1]
self.assertTrue(target.has_build_version)
build_version = target.build_version
self.assertEqual(build_version.minos, [12, 1, 0])
self.assertEqual(build_version.sdk, [12, 1, 0])
self.assertEqual(build_version.platform, lief.MachO.BuildVersion.PLATFORMS.IOS)
tools = build_version.tools
self.assertEqual(len(tools), 1)
self.assertEqual(tools[0].version, [409, 12, 0])
self.assertEqual(tools[0].tool, lief.MachO.BuildToolVersion.TOOLS.LD)
def test_build_version(self):
binary = lief.MachO.parse(get_sample('MachO/FAT_MachO_arm-arm64-binary-helloworld.bin'))
target = binary[1]
self.assertTrue(target.has_build_version)
build_version = target.build_version
self.assertEqual(build_version.minos, [12, 1, 0])
self.assertEqual(build_version.sdk, [12, 1, 0])
self.assertEqual(build_version.platform, lief.MachO.BuildVersion.PLATFORMS.IOS)
tools = build_version.tools
self.assertEqual(len(tools), 1)
self.assertEqual(tools[0].version, [409, 12, 0])
self.assertEqual(tools[0].tool, lief.MachO.BuildToolVersion.TOOLS.LD)
def test_id(self):
original = lief.parse(get_sample('MachO/MachO64_x86-64_binary_id.bin'))
_, output = tempfile.mkstemp(prefix="lief_id_remove_cmd")
# Extend UUID
uuid_cmd = original[lief.MachO.LOAD_COMMAND_TYPES.UUID]
original_size = uuid_cmd.size
original.extend(uuid_cmd, 0x100)
uuid_cmd = original[lief.MachO.LOAD_COMMAND_TYPES.UUID]
# Extend __LINKEDIT (last one)
original.extend_segment(original.get_segment("__LINKEDIT"), 0x30000)
original.remove_signature()
original.write(output)
new = lief.parse(output)
self.assertEqual(new[lief.MachO.LOAD_COMMAND_TYPES.UUID].size, original_size + 0x100)
if sys.platform.startswith("darwin"):
stdout = run_program(output)
self.logger.debug(stdout)
self.assertIsNotNone(re.search(r'uid=', stdout))
for reloc in binary.relocations:
type_str = ""
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.DYLDINFO:
type_str = str(lief.MachO.REBASE_TYPES(reloc.type)).split(".")[-1]
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.RELOC_TABLE:
if reloc.architecture == MachO.CPU_TYPES.x86:
type_str = str(MachO.X86_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.x86_64:
type_str = str(MachO.X86_64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM:
type_str = str(MachO.ARM_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM64:
type_str = str(MachO.ARM64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.POWERPC:
type_str = str(MachO.PPC_RELOCATION(reloc.type))
type_str = type_str.split(".")[-1]
symbol_name = ""
if reloc.has_symbol:
symbol_name = reloc.symbol.name
secseg_name = ""
if reloc.has_segment and reloc.has_section:
secseg_name = "{}.{}".format(reloc.segment.name, reloc.section.name)
else:
if reloc.has_segment:
address="Address",
size="Size",
type="Type",
pcrel="PC Relative",
secseg="Section/Section",
symbol="Symbol"))
for reloc in binary.relocations:
type_str = ""
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.DYLDINFO:
type_str = str(lief.MachO.REBASE_TYPES(reloc.type)).split(".")[-1]
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.RELOC_TABLE:
if reloc.architecture == MachO.CPU_TYPES.x86:
type_str = str(MachO.X86_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.x86_64:
type_str = str(MachO.X86_64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM:
type_str = str(MachO.ARM_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM64:
type_str = str(MachO.ARM64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.POWERPC:
type_str = str(MachO.PPC_RELOCATION(reloc.type))
type_str = type_str.split(".")[-1]
symbol_name = ""
f_value = "|0x{address:<10x} | {size:<4d} | {type:<15} | {pcrel:<11} | {secseg:<23} | {symbol}"
f_title = "|{address:<12} | {size:<4} | {type:<15} | {pcrel:<11} | {secseg:<23} | {symbol}"
print(f_title.format(
address="Address",
size="Size",
type="Type",
pcrel="PC Relative",
secseg="Section/Section",
symbol="Symbol"))
for reloc in binary.relocations:
type_str = ""
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.DYLDINFO:
type_str = str(lief.MachO.REBASE_TYPES(reloc.type)).split(".")[-1]
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.RELOC_TABLE:
if reloc.architecture == MachO.CPU_TYPES.x86:
type_str = str(MachO.X86_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.x86_64:
type_str = str(MachO.X86_64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM:
type_str = str(MachO.ARM_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM64:
type_str = str(MachO.ARM64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.POWERPC:
type_str = str(MachO.PPC_RELOCATION(reloc.type))
def scan(self, data, file, options, expire_at):
tmp_directory = options.get('tmp_directory', '/tmp/')
macho = MachO.parse(raw=data, config=MachO.ParserConfig.deep)
self.event['total'] = {
'binaries': macho.size,
}
if macho.size > 1:
for r in range(0, macho.size):
b = macho.at(r)
with tempfile.NamedTemporaryFile(dir=tmp_directory) as tmp_data:
b.write(tmp_data.name)
tmp_data.flush()
with open(tmp_data.name, 'rb') as f:
extract_file = strelka.File(
name=f'binary_{r}',
source=self.name,
if len(binary.exported_functions):
syms = binary.exported_functions
elif len(binary.symbols):
syms = binary.symbols
elif len(binary.static_symbols):
syms = binary.static_symbols
else:
syms = []
for index, s in enumerate(syms):
if debug_static_archives > 1:
print(s)
# if s.type&16:
# continue
is_notexported = True
is_undefined = index >= first_undefined_symbol and index <= last_undefined_symbol
if binary.__class__ != lief.MachO.Binary:
if isinstance(s, str):
s_name = '%s' % s
else:
s_name = '%s' % s.name
if s.exported and s.imported:
print("Weird, symbol {} is both imported and exported".format(s.name))
if s.exported:
is_undefined = True
is_notexported = False
elif s.imported:
is_undefined = False
else:
s_name = '%s' % s.name
is_notexported = False if s.type & 1 else True
# print("{:32s} : s.type 0b{:020b}, s.value 0b{:020b}".format(s.name, s.type, s.value))
def get_libraries(file):
result = []
binary = ensure_binary(file)
if binary:
if binary.format == lief.EXE_FORMATS.PE:
result = binary.libraries
else:
result = [lib if is_string(lib) else lib.name for lib in binary.libraries]
# LIEF returns LC_ID_DYLIB name @rpath/libbz2.dylib in binary.libraries. Strip that.
binary_name = None
if binary.format == lief.EXE_FORMATS.MACHO:
binary_name = [command.name for command in binary.commands
if command.command == lief.MachO.LOAD_COMMAND_TYPES.ID_DYLIB]
binary_name = binary_name[0] if len(binary_name) else None
result = [from_os_varnames(binary.format, None, lib) for lib in result
if not binary_name or lib != binary_name]
return result