Beispiel #1
0
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
Beispiel #2
0
    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))
Beispiel #3
0
    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)
Beispiel #4
0
    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")))
Beispiel #5
0
    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")))
Beispiel #6
0
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')
Beispiel #7
0
    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)