def test_bin2lib(tmp_path): file_path = "MachO/mbedtls_selftest_arm64.bin" if is_aarch64( ) else "MachO/mbedtls_selftest_x86_64.bin" bin_path = pathlib.Path(get_sample(file_path)) original = lief.parse(bin_path.as_posix()) output = f"{tmp_path}/libtest.dylib" header: lief.MachO.Header = original.header header.file_type = lief.MachO.FILE_TYPES.DYLIB # Create LC_ID_DYLIB command original.add(lief.MachO.DylibCommand.id_dylib(output, 0, 1, 2)) # Create a new export :) ADDR = 0x10000D782 if header.cpu_type == lief.MachO.CPU_TYPES.x86_64 else 0x10004F3F4 assert original.add_exported_function(ADDR, "_lief_test_export") original.write(output) new = lief.parse(output) checked, err = lief.MachO.check_layout(new) assert checked, err if is_osx(): sign(output) print(f"Loading {output}") lib = ctypes.cdll.LoadLibrary(output) assert lib assert lib.lief_test_export
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) # Extend __LINKEDIT (last one) original_linkedit_size = original.get_segment("__LINKEDIT").file_size original.extend_segment(original.get_segment("__LINKEDIT"), 0x30000) original.remove_signature() original.write(output) new = lief.parse(output) self.assertEqual( new.get_segment("__LINKEDIT").file_size, original_linkedit_size + 0x30000) self.assertEqual(new[lief.MachO.LOAD_COMMAND_TYPES.UUID].size, original_size + 0x100) if is_osx() and not is_aarch64(): stdout = run_program(output) self.logger.debug(stdout) self.assertIsNotNone(re.search(r'uid=', stdout))
def test_libadd_api2(self): _, binaddc = tempfile.mkstemp(prefix="binadd_", suffix=".c") _, libaddc = tempfile.mkstemp(prefix="libadd_", suffix=".c") self._logger.debug(binaddc) self._logger.debug(libaddc) fd, binadd = tempfile.mkstemp(prefix="binadd_", suffix=".bin") _, libadd = tempfile.mkstemp(prefix="libadd_", suffix=".so") _, libadd2 = tempfile.mkstemp(prefix="libadd2_", suffix=".so") self._logger.debug(binadd) self._logger.debug(libadd) self._logger.debug(libadd2) with open(binaddc, 'w') as f: f.write(BINADD) with open(libaddc, 'w') as f: f.write(LIBADD) compiler = get_compiler() fmt = "" if is_x86_64(): fmt = "{compiler} -Wl,--export-dynamic -mcmodel=large -fPIE -pie -o {output} {input}" if is_aarch64(): fmt = "{compiler} -Wl,--export-dynamic -fPIE -pie -o {output} {input}" # Compile libadd r = self.run_cmd( fmt.format(compiler=compiler, output=libadd, input=libaddc)) self.assertTrue(r, msg="Unable to compile libadd") libadd = lief.parse(libadd) add_hidden_static = libadd.get_static_symbol("add_hidden") libadd.add_exported_function(add_hidden_static.value, add_hidden_static.name) libadd.write(libadd2) lib_directory = os.path.dirname(libadd2) libname = os.path.basename(libadd2)[3:-3] # libadd.so ---> add r = self.run_cmd( "{compiler} -Wl,--export-dynamic -mcmodel=large -fPIE -pie -Wl,-rpath={libdir} -L{libdir} -o {output} {input} -l{libadd2}" .format(compiler=compiler, libdir=lib_directory, libadd2=libname, output=binadd, input=binaddc)) self.assertTrue(r, msg="Unable to compile binadd") os.close(fd) st = os.stat(binadd) os.chmod(binadd, st.st_mode | stat.S_IEXEC) r = self.run_cmd(binadd + " 1 2") self.assertTrue(r) self.assertIn("From [email protected] a + b = 3", r.output)
def test_ssh(self): stub = None if is_x86_64(): stub = lief.parse(os.path.join(CURRENT_DIRECTORY, "hello_lief.bin")) elif is_aarch64(): stub = lief.parse( os.path.join(CURRENT_DIRECTORY, "hello_lief_aarch64.bin")) output = os.path.join(self.tmp_dir, "ssh.replace_segment") target = lief.parse("/usr/bin/ssh") if not lief.ELF.SEGMENT_TYPES.NOTE in target: self.logger.error("Note not found!") return segment = stub.segments[0] original_va = segment.virtual_address segment.virtual_address = 0 segment = target.replace(segment, target[lief.ELF.SEGMENT_TYPES.NOTE]) new_ep = (stub.header.entrypoint - original_va) + segment.virtual_address target.header.entrypoint = new_ep target.write(output) st = os.stat(output) os.chmod(output, st.st_mode | stat.S_IEXEC) p = Popen(output, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate() self.logger.debug(stdout.decode("utf8")) self.assertIsNotNone( re.search(r'LIEF is Working', stdout.decode("utf8")))
def run_add_segment(self, target): if not os.path.isfile(target): self.logger.debug("%s does not exists. Skip!", target) return stub = None if is_x86_64(): stub = lief.parse(os.path.join(CURRENT_DIRECTORY, "hello_lief.bin")) elif is_aarch64(): stub = lief.parse( os.path.join(CURRENT_DIRECTORY, "hello_lief_aarch64.bin")) name = os.path.basename(target) target = lief.parse(target) output = os.path.join(self.tmp_dir, "{}.segment".format(name)) for i in range(6): stub_segment = stub.segments[0] segment = lief.ELF.Segment() segment.content = stub.segments[0].content segment.type = stub_segment.type segment.alignment = stub_segment.alignment segment.flags = stub_segment.flags new_segment = target.add(segment) new_ep = (stub.header.entrypoint - stub.imagebase - stub_segment.file_offset) + new_segment.virtual_address target.header.entrypoint = new_ep target.write(output) st = os.stat(output) os.chmod(output, st.st_mode | stat.S_IEXEC) p = Popen(output, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate() self.logger.debug(stdout.decode("utf8")) self.assertIsNotNone( re.search(r'LIEF is Working', stdout.decode("utf8")))
import tempfile import shutil from subprocess import Popen import lief from lief.ELF import Section from unittest import TestCase from utils import get_sample, has_recent_glibc, is_linux, is_x86_64, is_aarch64 CURRENT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) STUB_FILE = None if is_x86_64(): STUB_FILE = "hello_lief.bin" elif is_aarch64(): STUB_FILE = "hello_lief_aarch64.bin" STUB = lief.parse(os.path.join(CURRENT_DIRECTORY, STUB_FILE)) class TestAddSection(TestCase): def setUp(self): self.logger = logging.getLogger(__name__) self.tmp_dir = tempfile.mkdtemp(suffix='_lief_test_section') self.logger.debug("temp dir: {}".format(self.tmp_dir)) @unittest.skipUnless(is_linux() and is_x86_64(), "requires Linux x86-64") @unittest.skipUnless(has_recent_glibc(), "Need a recent GLIBC version") def test_simple(self): sample_path = get_sample('ELF/ELF64_x86-64_binary_ls.bin')
def test_libadd(self): _, binaddc = tempfile.mkstemp(prefix="binadd_", suffix=".c") _, libaddc = tempfile.mkstemp(prefix="libadd_", suffix=".c") self._logger.debug(binaddc) self._logger.debug(libaddc) fd, binadd = tempfile.mkstemp(prefix="binadd_", suffix=".bin") _, libadd = tempfile.mkstemp(prefix="libadd_", suffix=".so") _, libadd2 = tempfile.mkstemp(prefix="libadd2_", suffix=".so") self._logger.debug(binadd) self._logger.debug(libadd) self._logger.debug(libadd2) with open(binaddc, 'w') as f: f.write(BINADD) with open(libaddc, 'w') as f: f.write(LIBADD) compiler = get_compiler() fmt = "" if is_x86_64(): fmt = "{compiler} -Wl,--export-dynamic -mcmodel=large -fPIE -pie -o {output} {input}" if is_aarch64(): fmt = "{compiler} -Wl,--export-dynamic -fPIE -pie -o {output} {input}" # Compile libadd r = self.run_cmd( fmt.format(compiler=compiler, output=libadd, input=libaddc)) self.assertTrue(r, msg="Unable to compile libadd") libadd = lief.parse(libadd) libadd_hidden = libadd.get_symbol("add_hidden") libadd_hidden.binding = lief.ELF.SYMBOL_BINDINGS.GLOBAL libadd_hidden.visibility = lief.ELF.SYMBOL_VISIBILITY.DEFAULT libadd_hidden = libadd.add_dynamic_symbol( libadd_hidden, lief.ELF.SymbolVersion.global_) if libadd.has(lief.ELF.DYNAMIC_TAGS.FLAGS_1): libadd[lief.ELF.DYNAMIC_TAGS.FLAGS_1].remove( lief.ELF.DYNAMIC_FLAGS_1.PIE) self._logger.debug(libadd_hidden) libadd.add(lief.ELF.DynamicSharedObject(os.path.basename(libadd2))) libadd.write(libadd2) lib_directory = os.path.dirname(libadd2) libname = os.path.basename(libadd2)[3:-3] # libadd.so ---> add fmt = "" if is_x86_64(): fmt = "{compiler} -Wl,--export-dynamic -mcmodel=large -fPIE -pie -Wl,-rpath={libdir} -L{libdir} -o {output} {input} -l{libadd2}" if is_aarch64(): fmt = "{compiler} -Wl,--export-dynamic -fPIE -pie -Wl,-rpath={libdir} -L{libdir} -o {output} {input} -l{libadd2}" r = self.run_cmd( fmt.format(compiler=compiler, libdir=lib_directory, libadd2=libname, output=binadd, input=binaddc)) self.assertTrue(r, msg="Unable to compile binadd") os.close(fd) st = os.stat(binadd) os.chmod(binadd, st.st_mode | stat.S_IEXEC) r = self.run_cmd(binadd + " 1 2") self.assertTrue(r) self.assertIn("From [email protected] a + b = 3", r.output)