mirror of
https://github.com/lief-project/LIEF
synced 2026-06-08 15:30:44 +00:00
108 lines
3.8 KiB
Python
108 lines
3.8 KiB
Python
#!/usr/bin/env python
|
|
import os
|
|
import re
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import pytest
|
|
from subprocess import Popen
|
|
from pathlib import Path
|
|
|
|
import lief
|
|
from utils import get_sample, has_recent_glibc, is_linux, is_x86_64, is_aarch64
|
|
is_updated_linux = is_linux() and is_x86_64() and has_recent_glibc()
|
|
is_linux_x64 = is_linux() and is_x86_64()
|
|
|
|
CWD = Path(__file__).parent
|
|
|
|
def test_simple(tmp_path: Path):
|
|
sample_path = get_sample('ELF/ELF64_x86-64_binary_ls.bin')
|
|
stub = lief.ELF.parse(CWD / "hello_lief.bin")
|
|
output = tmp_path / "ls.replace_segment"
|
|
target = lief.ELF.parse(sample_path)
|
|
|
|
|
|
if lief.ELF.Segment.TYPE.NOTE not in target:
|
|
lief.logging.err("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.TYPE.NOTE])
|
|
new_ep = (stub.header.entrypoint - original_va) + segment.virtual_address
|
|
|
|
target.header.entrypoint = new_ep
|
|
target.write(output)
|
|
|
|
if is_updated_linux:
|
|
st = os.stat(output)
|
|
os.chmod(output, st.st_mode | stat.S_IEXEC)
|
|
|
|
with Popen(output.as_posix(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as P:
|
|
stdout = P.stdout.read().decode("utf8")
|
|
lief.logging.info(stdout)
|
|
assert re.search(r'LIEF is Working', stdout) is not None
|
|
|
|
def test_gcc(tmp_path: Path):
|
|
sample_path = get_sample('ELF/ELF64_x86-64_binary_gcc.bin')
|
|
stub = lief.ELF.parse(CWD / "hello_lief.bin")
|
|
output = tmp_path / "gcc.replace_segment"
|
|
target = lief.ELF.parse(sample_path)
|
|
|
|
if lief.ELF.Segment.TYPE.NOTE not in target:
|
|
lief.logging.err("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.TYPE.NOTE])
|
|
new_ep = (stub.header.entrypoint - original_va) + segment.virtual_address
|
|
|
|
target.header.entrypoint = new_ep
|
|
target.write(output)
|
|
|
|
if is_updated_linux:
|
|
st = os.stat(output)
|
|
os.chmod(output, st.st_mode | stat.S_IEXEC)
|
|
|
|
with Popen(output.as_posix(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as P:
|
|
stdout = P.stdout.read().decode("utf8")
|
|
lief.logging.info(stdout)
|
|
assert re.search(r'LIEF is Working', stdout) is not None
|
|
|
|
@pytest.mark.skipif(not is_linux(), reason="requires Linux")
|
|
@pytest.mark.skipif(not Path('/usr/bin/ssh').is_file(), reason="missing '/usr/bin/ssh'")
|
|
def test_ssh(tmp_path: Path):
|
|
stub = None
|
|
if is_x86_64():
|
|
stub = lief.ELF.parse(CWD / "hello_lief.bin")
|
|
elif is_aarch64():
|
|
stub = lief.ELF.parse(CWD / "hello_lief_aarch64.bin")
|
|
|
|
output = tmp_path / "ssh.replace_segment"
|
|
target = lief.ELF.parse("/usr/bin/ssh")
|
|
|
|
if lief.ELF.Segment.TYPE.NOTE not in target:
|
|
lief.logging.warn("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.TYPE.NOTE])
|
|
new_ep = (stub.header.entrypoint - original_va) + segment.virtual_address
|
|
|
|
target.header.entrypoint = new_ep
|
|
target.write(output)
|
|
|
|
if is_linux() and has_recent_glibc():
|
|
st = os.stat(output)
|
|
os.chmod(output, st.st_mode | stat.S_IEXEC)
|
|
|
|
with Popen(output.as_posix(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as P:
|
|
stdout = P.stdout.read().decode("utf8")
|
|
lief.logging.info(stdout)
|
|
assert re.search(r'LIEF is Working', stdout) is not None
|