2017-03-30 16:56:49 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
import unittest
|
|
|
|
import lief
|
2017-04-05 08:25:22 +02:00
|
|
|
import tempfile
|
|
|
|
import sys
|
|
|
|
import subprocess
|
|
|
|
import stat
|
|
|
|
import os
|
|
|
|
import logging
|
|
|
|
import random
|
2017-06-28 17:45:12 +02:00
|
|
|
import itertools
|
2017-04-05 08:25:22 +02:00
|
|
|
|
Improve the ELF part of LIEF
Major changes (features):
* Enable adding multiple sections/segments - Executable (PIE or not), Library
* Enable adding multiple dynamic entries (DT_NEEDED, DT_INIT etc)
* Enable adding multiple relocations
* Enable adding multiple dynamic symbols
* Enable segment replacement
Major changes (API):
* Getters Binary::get_*name*() has been renamed to "name()"
* Binary::add(const DynamicEntry& entry) - To add an entry in the dynamic table
* Section& Binary::add(const Section& section, bool loaded = true) - To add a section(s)
* Segment& Binary::add(const Segment& segment, uint64_t base = 0) - To add segments
* Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0)
* Binary's last_offset_section(), last_offset_segment(), next_virtual_address()
to have information about offset
* Binary's add_library(), get_library(), has_library() to handle
DT_NEEDED entries
Other changes:
* Binary::insert_content() - Use add(const Section&) or add(const Segment&) instead
* ELF's DataHandler has been cleaned
* Through LIEF::Section one can look for integers, strings, data
within the section (see LIEF::Section::search,
LIEF::Section::search_all)
* Through LIEF::Binary one can get *xref* of a number (or address)
see LIEF::Binary::xref function
* To access to the Abstract binary in Python, one can now use
the 'abstract' attribute. (e.g. binary.abstract.header.is_32)
Resolve: #83
Resolve: #66
Resolve: #48
2017-09-02 08:54:54 +02:00
|
|
|
from lief import Logger
|
|
|
|
Logger.set_level(lief.LOGGING_LEVEL.WARNING)
|
|
|
|
#Logger.set_level(lief.LOGGING_LEVEL.DEBUG)
|
|
|
|
|
2017-04-05 08:25:22 +02:00
|
|
|
from subprocess import Popen
|
2017-03-30 16:56:49 +02:00
|
|
|
|
|
|
|
from unittest import TestCase
|
2019-08-22 22:05:53 +01:00
|
|
|
from utils import get_sample, has_recent_glibc
|
2017-03-30 16:56:49 +02:00
|
|
|
|
|
|
|
class TestELF(TestCase):
|
|
|
|
|
2017-04-05 08:25:22 +02:00
|
|
|
def setUp(self):
|
|
|
|
self.logger = logging.getLogger(__name__)
|
|
|
|
|
2017-03-30 16:56:49 +02:00
|
|
|
def test_rpath(self):
|
|
|
|
etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_etterlog.bin'))
|
|
|
|
|
|
|
|
dynamic_entries = etterlog.dynamic_entries
|
|
|
|
|
|
|
|
rpath = [e for e in dynamic_entries if e.tag == lief.ELF.DYNAMIC_TAGS.RPATH]
|
|
|
|
|
|
|
|
self.assertEqual(len(rpath), 1)
|
|
|
|
rpath = rpath.pop()
|
|
|
|
|
|
|
|
self.assertEqual(rpath.name, "/usr/lib")
|
|
|
|
|
|
|
|
def test_runpath(self):
|
|
|
|
etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_systemd-resolve.bin'))
|
|
|
|
|
|
|
|
dynamic_entries = etterlog.dynamic_entries
|
|
|
|
|
|
|
|
runpath = [e for e in dynamic_entries if e.tag == lief.ELF.DYNAMIC_TAGS.RUNPATH]
|
|
|
|
|
|
|
|
self.assertEqual(len(runpath), 1)
|
|
|
|
runpath = runpath.pop()
|
|
|
|
|
|
|
|
self.assertEqual(runpath.name, "/usr/lib/systemd")
|
|
|
|
|
|
|
|
|
|
|
|
def test_gnuhash(self):
|
|
|
|
ls = lief.parse(get_sample('ELF/ELF64_x86-64_binary_ls.bin'))
|
|
|
|
gnu_hash = ls.gnu_hash
|
|
|
|
|
|
|
|
self.assertEqual(gnu_hash.nb_buckets, 33)
|
|
|
|
self.assertEqual(gnu_hash.symbol_index, 109)
|
|
|
|
self.assertEqual(gnu_hash.shift2, 7)
|
|
|
|
|
|
|
|
bloom_filters = gnu_hash.bloom_filters
|
|
|
|
|
|
|
|
self.assertEqual(len(bloom_filters), 2)
|
|
|
|
self.assertIn(0x3FAE01120C48A1A6, bloom_filters)
|
|
|
|
self.assertIn(0x900004A81310D428, bloom_filters)
|
|
|
|
|
|
|
|
buckets = gnu_hash.buckets
|
|
|
|
self.assertEqual(len(buckets), 33)
|
|
|
|
|
|
|
|
buckets_test = [109, 110, 0, 0, 0, 0, 0, 111, 113, 114, 0, 0, 0, 115, 0, 116, 0, 0, 117, 118, 119, 0, 120, 0, 0, 121, 123, 124, 126, 128, 129, 130, 0]
|
|
|
|
self.assertEqual(buckets_test, buckets)
|
|
|
|
|
|
|
|
|
|
|
|
hash_values = gnu_hash.hash_values
|
|
|
|
hash_values_test = [0x60E0C78D, 0xF54162E5, 0x7FFD8E4E, 0x1C8BF239, 0xEEFD3EB, 0x1C8C1D29, 0x1C5871D9,
|
|
|
|
0x5B7F3E03, 0x759A6A7F, 0xEF18DB9, 0xBA53E4D, 0x9789A097, 0x9E7650BC, 0xD39AD3D,
|
|
|
|
0x12F7C433, 0xEB01FAB6, 0xECD54543, 0xAD3C9892, 0x72632CCF, 0x12F7A2B3, 0x7C92E3BB, 0x7C96F087]
|
|
|
|
self.assertEqual(hash_values, hash_values_test)
|
|
|
|
|
2017-09-22 14:42:39 +02:00
|
|
|
#for s in list(ls.dynamic_symbols)[gnu_hash.symbol_index:]:
|
|
|
|
# print(gnu_hash.check(s.name), s.name)
|
|
|
|
self.assertTrue(all(gnu_hash.check(x.name) for x in list(ls.dynamic_symbols)[gnu_hash.symbol_index:]))
|
|
|
|
|
|
|
|
self.assertFalse(gnu_hash.check("foofdsfdsfds"))
|
|
|
|
self.assertFalse(gnu_hash.check("fazertrvkdfsrezklqpfjeopqdi"))
|
|
|
|
|
2019-08-22 22:05:53 +01:00
|
|
|
@unittest.skipUnless(has_recent_glibc(), "Need a recent GLIBC version")
|
2017-04-05 08:25:22 +02:00
|
|
|
def test_permutation(self):
|
|
|
|
samples = [
|
|
|
|
"ELF/ELF64_x86-64_binary_ls.bin",
|
Improve the ELF part of LIEF
Major changes (features):
* Enable adding multiple sections/segments - Executable (PIE or not), Library
* Enable adding multiple dynamic entries (DT_NEEDED, DT_INIT etc)
* Enable adding multiple relocations
* Enable adding multiple dynamic symbols
* Enable segment replacement
Major changes (API):
* Getters Binary::get_*name*() has been renamed to "name()"
* Binary::add(const DynamicEntry& entry) - To add an entry in the dynamic table
* Section& Binary::add(const Section& section, bool loaded = true) - To add a section(s)
* Segment& Binary::add(const Segment& segment, uint64_t base = 0) - To add segments
* Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0)
* Binary's last_offset_section(), last_offset_segment(), next_virtual_address()
to have information about offset
* Binary's add_library(), get_library(), has_library() to handle
DT_NEEDED entries
Other changes:
* Binary::insert_content() - Use add(const Section&) or add(const Segment&) instead
* ELF's DataHandler has been cleaned
* Through LIEF::Section one can look for integers, strings, data
within the section (see LIEF::Section::search,
LIEF::Section::search_all)
* Through LIEF::Binary one can get *xref* of a number (or address)
see LIEF::Binary::xref function
* To access to the Abstract binary in Python, one can now use
the 'abstract' attribute. (e.g. binary.abstract.header.is_32)
Resolve: #83
Resolve: #66
Resolve: #48
2017-09-02 08:54:54 +02:00
|
|
|
#"ELF/ELF64_x86-64_binary_gcc.bin",
|
|
|
|
#"ELF/ELF64_x86-64_binary_openssl.bin",
|
2017-04-05 08:25:22 +02:00
|
|
|
]
|
|
|
|
tmp_dir = tempfile.mkdtemp(suffix='_lief_test_permutation')
|
|
|
|
for sample in samples:
|
|
|
|
binary = lief.parse(get_sample(sample))
|
|
|
|
dynamic_symbols = binary.dynamic_symbols
|
|
|
|
|
|
|
|
gnu_hash_table = binary.gnu_hash
|
|
|
|
|
|
|
|
idx = gnu_hash_table.symbol_index
|
|
|
|
|
|
|
|
permutation = [i for i in range(1, len(dynamic_symbols))]
|
|
|
|
random.shuffle(permutation)
|
|
|
|
permutation = [0] + permutation
|
Improve the ELF part of LIEF
Major changes (features):
* Enable adding multiple sections/segments - Executable (PIE or not), Library
* Enable adding multiple dynamic entries (DT_NEEDED, DT_INIT etc)
* Enable adding multiple relocations
* Enable adding multiple dynamic symbols
* Enable segment replacement
Major changes (API):
* Getters Binary::get_*name*() has been renamed to "name()"
* Binary::add(const DynamicEntry& entry) - To add an entry in the dynamic table
* Section& Binary::add(const Section& section, bool loaded = true) - To add a section(s)
* Segment& Binary::add(const Segment& segment, uint64_t base = 0) - To add segments
* Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0)
* Binary's last_offset_section(), last_offset_segment(), next_virtual_address()
to have information about offset
* Binary's add_library(), get_library(), has_library() to handle
DT_NEEDED entries
Other changes:
* Binary::insert_content() - Use add(const Section&) or add(const Segment&) instead
* ELF's DataHandler has been cleaned
* Through LIEF::Section one can look for integers, strings, data
within the section (see LIEF::Section::search,
LIEF::Section::search_all)
* Through LIEF::Binary one can get *xref* of a number (or address)
see LIEF::Binary::xref function
* To access to the Abstract binary in Python, one can now use
the 'abstract' attribute. (e.g. binary.abstract.header.is_32)
Resolve: #83
Resolve: #66
Resolve: #48
2017-09-02 08:54:54 +02:00
|
|
|
binary.permute_dynamic_symbols(permutation)
|
2017-04-05 08:25:22 +02:00
|
|
|
|
|
|
|
builder = lief.ELF.Builder(binary)
|
|
|
|
builder.empties_gnuhash(True)
|
|
|
|
builder.build()
|
|
|
|
output = os.path.join(tmp_dir, "{}.permutated".format(binary.name))
|
Improve the ELF part of LIEF
Major changes (features):
* Enable adding multiple sections/segments - Executable (PIE or not), Library
* Enable adding multiple dynamic entries (DT_NEEDED, DT_INIT etc)
* Enable adding multiple relocations
* Enable adding multiple dynamic symbols
* Enable segment replacement
Major changes (API):
* Getters Binary::get_*name*() has been renamed to "name()"
* Binary::add(const DynamicEntry& entry) - To add an entry in the dynamic table
* Section& Binary::add(const Section& section, bool loaded = true) - To add a section(s)
* Segment& Binary::add(const Segment& segment, uint64_t base = 0) - To add segments
* Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0)
* Binary's last_offset_section(), last_offset_segment(), next_virtual_address()
to have information about offset
* Binary's add_library(), get_library(), has_library() to handle
DT_NEEDED entries
Other changes:
* Binary::insert_content() - Use add(const Section&) or add(const Segment&) instead
* ELF's DataHandler has been cleaned
* Through LIEF::Section one can look for integers, strings, data
within the section (see LIEF::Section::search,
LIEF::Section::search_all)
* Through LIEF::Binary one can get *xref* of a number (or address)
see LIEF::Binary::xref function
* To access to the Abstract binary in Python, one can now use
the 'abstract' attribute. (e.g. binary.abstract.header.is_32)
Resolve: #83
Resolve: #66
Resolve: #48
2017-09-02 08:54:54 +02:00
|
|
|
self.logger.debug("Output: {}".format(output))
|
|
|
|
builder.write(output)
|
|
|
|
|
2017-04-05 08:25:22 +02:00
|
|
|
if not sys.platform.startswith("linux"):
|
|
|
|
return
|
|
|
|
|
|
|
|
st = os.stat(output)
|
|
|
|
os.chmod(output, st.st_mode | stat.S_IEXEC)
|
|
|
|
|
|
|
|
p = Popen([output, "--help"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
|
|
stdout, _ = p.communicate()
|
|
|
|
self.logger.debug(stdout.decode("utf8"))
|
|
|
|
self.assertEqual(p.returncode, 0)
|
|
|
|
|
2017-06-11 09:13:52 +02:00
|
|
|
def test_notes(self):
|
|
|
|
systemd_resolve = lief.parse(get_sample('ELF/ELF64_x86-64_binary_systemd-resolve.bin'))
|
|
|
|
notes = systemd_resolve.notes
|
|
|
|
self.assertEqual(len(notes), 3)
|
|
|
|
|
|
|
|
n1 = notes[0]
|
|
|
|
n2 = notes[1]
|
|
|
|
n3 = notes[2]
|
|
|
|
|
|
|
|
self.assertEqual(n1.name, "GNU")
|
|
|
|
self.assertEqual(n2.name, "GNU")
|
|
|
|
self.assertEqual(n3.name, "GNU")
|
|
|
|
|
|
|
|
self.assertEqual(n1.type, lief.ELF.NOTE_TYPES.ABI_TAG)
|
|
|
|
self.assertEqual(n2.type, lief.ELF.NOTE_TYPES.BUILD_ID)
|
|
|
|
self.assertEqual(n3.type, lief.ELF.NOTE_TYPES.GOLD_VERSION)
|
|
|
|
|
2019-04-18 07:15:31 +02:00
|
|
|
self.assertEqual(n1.details.abi, lief.ELF.NOTE_ABIS.LINUX)
|
|
|
|
self.assertEqual(n1.details.version, [2, 6, 32])
|
2017-06-11 09:13:52 +02:00
|
|
|
|
|
|
|
self.assertEqual(list(n2.description), [
|
|
|
|
0x7e, 0x68, 0x6c, 0x7d,
|
|
|
|
0x79, 0x9b, 0xa4, 0xcd,
|
|
|
|
0x32, 0xa2, 0x34, 0xe8,
|
|
|
|
0x4f, 0xd7, 0x45, 0x98,
|
|
|
|
0x21, 0x32, 0x9d, 0xc8
|
|
|
|
])
|
|
|
|
|
|
|
|
self.assertEqual("".join(map(chr, n3.description)), "gold 1.12")
|
|
|
|
|
2017-07-31 14:46:24 +02:00
|
|
|
def test_symbols_access(self):
|
|
|
|
hello = lief.parse(get_sample('ELF/ELF64_x86-64_binary_hello-gdb.bin'))
|
|
|
|
|
|
|
|
symbols = hello.symbols
|
|
|
|
dynamic_symbols = hello.dynamic_symbols
|
|
|
|
static_symbols = hello.static_symbols
|
|
|
|
|
|
|
|
self.assertTrue(all(s in symbols for s in dynamic_symbols))
|
|
|
|
self.assertTrue(all(s in symbols for s in static_symbols))
|
|
|
|
|
2017-06-28 17:45:12 +02:00
|
|
|
def test_relocation_size(self):
|
|
|
|
aarch64_toybox = lief.parse(get_sample('ELF/ELF64_AARCH64_piebinary_toybox.pie'))
|
|
|
|
arm_ls = lief.parse(get_sample('ELF/ELF32_ARM_binary_ls.bin'))
|
|
|
|
x86_ls = lief.parse(get_sample('ELF/ELF32_x86_binary_ls.bin'))
|
|
|
|
x86_64_ls = lief.parse(get_sample('ELF/ELF64_x86-64_binary_ld.bin'))
|
|
|
|
|
|
|
|
for r in itertools.chain(aarch64_toybox.dynamic_relocations, aarch64_toybox.pltgot_relocations):
|
|
|
|
if lief.ELF.RELOCATION_AARCH64(r.type) == lief.ELF.RELOCATION_AARCH64.RELATIVE:
|
|
|
|
self.assertEqual(r.size, 64)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_AARCH64(r.type) == lief.ELF.RELOCATION_AARCH64.GLOB_DAT:
|
|
|
|
self.assertEqual(r.size, 64)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_AARCH64(r.type) == lief.ELF.RELOCATION_AARCH64.JUMP_SLOT:
|
|
|
|
self.assertEqual(r.size, 64)
|
|
|
|
|
|
|
|
for r in itertools.chain(arm_ls.dynamic_relocations, arm_ls.pltgot_relocations):
|
|
|
|
if lief.ELF.RELOCATION_ARM(r.type) == lief.ELF.RELOCATION_ARM.RELATIVE:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_ARM(r.type) == lief.ELF.RELOCATION_ARM.GLOB_DAT:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_ARM(r.type) == lief.ELF.RELOCATION_ARM.ABS32:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_ARM(r.type) == lief.ELF.RELOCATION_ARM.JUMP_SLOT:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
|
|
|
|
for r in itertools.chain(x86_ls.dynamic_relocations, x86_ls.pltgot_relocations):
|
|
|
|
if lief.ELF.RELOCATION_i386(r.type) == lief.ELF.RELOCATION_i386.GLOB_DAT:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_i386(r.type) == lief.ELF.RELOCATION_i386.COPY:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_i386(r.type) == lief.ELF.RELOCATION_i386.JUMP_SLOT:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
|
|
|
|
for r in itertools.chain(x86_64_ls.dynamic_relocations, x86_64_ls.pltgot_relocations):
|
|
|
|
if lief.ELF.RELOCATION_X86_64(r.type) == lief.ELF.RELOCATION_X86_64.GLOB_DAT:
|
|
|
|
self.assertEqual(r.size, 64)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_X86_64(r.type) == lief.ELF.RELOCATION_X86_64.COPY:
|
|
|
|
self.assertEqual(r.size, 32)
|
|
|
|
|
|
|
|
if lief.ELF.RELOCATION_X86_64(r.type) == lief.ELF.RELOCATION_X86_64.JUMP_SLOT:
|
|
|
|
self.assertEqual(r.size, 64)
|
2017-06-11 09:13:52 +02:00
|
|
|
|
2017-04-26 14:51:23 +02:00
|
|
|
def test_sectionless(self):
|
|
|
|
sample = "ELF/ELF64_x86-64_binary_rvs.bin"
|
|
|
|
rvs = lief.parse(get_sample(sample))
|
|
|
|
dynsym = list(rvs.dynamic_symbols)
|
|
|
|
self.assertEqual(len(dynsym), 10)
|
|
|
|
|
2017-08-01 15:22:01 +02:00
|
|
|
def test_dynamic_flags(self):
|
|
|
|
sample = "ELF/ELF32_ARM_binary_ls.bin"
|
|
|
|
ls = lief.parse(get_sample(sample))
|
Improve the ELF part of LIEF
Major changes (features):
* Enable adding multiple sections/segments - Executable (PIE or not), Library
* Enable adding multiple dynamic entries (DT_NEEDED, DT_INIT etc)
* Enable adding multiple relocations
* Enable adding multiple dynamic symbols
* Enable segment replacement
Major changes (API):
* Getters Binary::get_*name*() has been renamed to "name()"
* Binary::add(const DynamicEntry& entry) - To add an entry in the dynamic table
* Section& Binary::add(const Section& section, bool loaded = true) - To add a section(s)
* Segment& Binary::add(const Segment& segment, uint64_t base = 0) - To add segments
* Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0)
* Binary's last_offset_section(), last_offset_segment(), next_virtual_address()
to have information about offset
* Binary's add_library(), get_library(), has_library() to handle
DT_NEEDED entries
Other changes:
* Binary::insert_content() - Use add(const Section&) or add(const Segment&) instead
* ELF's DataHandler has been cleaned
* Through LIEF::Section one can look for integers, strings, data
within the section (see LIEF::Section::search,
LIEF::Section::search_all)
* Through LIEF::Binary one can get *xref* of a number (or address)
see LIEF::Binary::xref function
* To access to the Abstract binary in Python, one can now use
the 'abstract' attribute. (e.g. binary.abstract.header.is_32)
Resolve: #83
Resolve: #66
Resolve: #48
2017-09-02 08:54:54 +02:00
|
|
|
d_flags = ls.get(lief.ELF.DYNAMIC_TAGS.FLAGS)
|
|
|
|
d_flags_1 = ls.get(lief.ELF.DYNAMIC_TAGS.FLAGS_1)
|
2017-08-01 15:22:01 +02:00
|
|
|
|
|
|
|
self.assertIn(lief.ELF.DYNAMIC_FLAGS.BIND_NOW, d_flags)
|
|
|
|
self.assertIn(lief.ELF.DYNAMIC_FLAGS_1.NOW, d_flags_1)
|
2017-03-30 16:56:49 +02:00
|
|
|
|
2018-09-12 14:44:18 +02:00
|
|
|
|
|
|
|
def test_unwind_arm(self):
|
|
|
|
sample = "ELF/ELF32_ARM_binary_ls.bin"
|
|
|
|
ls = lief.parse(get_sample(sample))
|
|
|
|
|
|
|
|
functions = sorted(ls.functions, key=lambda f: f.address)
|
|
|
|
|
|
|
|
self.assertEqual(len(functions), 265)
|
|
|
|
|
|
|
|
self.assertEqual(functions[0].address, 19684)
|
|
|
|
self.assertEqual(functions[0].size, 0)
|
|
|
|
self.assertEqual(functions[0].name, "open")
|
|
|
|
|
|
|
|
self.assertEqual(functions[-1].address, 102372)
|
|
|
|
self.assertEqual(functions[-1].size, 0)
|
|
|
|
self.assertEqual(functions[-1].name, "")
|
|
|
|
|
|
|
|
|
|
|
|
def test_unwind_x86(self):
|
|
|
|
sample = "ELF/ELF64_x86-64_binary_ld.bin"
|
|
|
|
ld = lief.parse(get_sample(sample))
|
|
|
|
|
|
|
|
functions = sorted(ld.functions, key=lambda f: f.address)
|
|
|
|
|
|
|
|
self.assertEqual(len(functions), 503)
|
|
|
|
|
|
|
|
self.assertEqual(functions[0].address, 4209304)
|
|
|
|
self.assertEqual(functions[0].size, 0)
|
|
|
|
self.assertEqual(functions[0].name, "_init")
|
|
|
|
|
|
|
|
self.assertEqual(functions[10].size, 174)
|
|
|
|
self.assertEqual(functions[10].name, "")
|
|
|
|
|
|
|
|
self.assertEqual(functions[-1].address, 4409396)
|
|
|
|
self.assertEqual(functions[-1].size, 0)
|
|
|
|
self.assertEqual(functions[-1].name, "_fini")
|
|
|
|
|
|
|
|
|
2019-05-28 09:47:33 +02:00
|
|
|
def test_misc(self):
|
|
|
|
sample = "ELF/ELF64_x86-64_binary_ld.bin"
|
|
|
|
ld = lief.parse(get_sample(sample))
|
|
|
|
|
|
|
|
text = ld.get_section(".text")
|
|
|
|
|
|
|
|
self.assertFalse(ld.has_section_with_offset(0))
|
|
|
|
self.assertFalse(ld.has_section_with_va(0xFFFFFFFF))
|
|
|
|
|
|
|
|
self.assertTrue(ld.has_section_with_offset(text.offset + 10))
|
|
|
|
self.assertTrue(ld.has_section_with_va(text.virtual_address + 10))
|
|
|
|
|
|
|
|
|
2017-03-30 16:56:49 +02:00
|
|
|
if __name__ == '__main__':
|
2017-04-05 08:25:22 +02:00
|
|
|
|
|
|
|
root_logger = logging.getLogger()
|
|
|
|
root_logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
ch = logging.StreamHandler()
|
|
|
|
ch.setLevel(logging.DEBUG)
|
|
|
|
root_logger.addHandler(ch)
|
|
|
|
|
|
|
|
unittest.main(verbosity=2)
|
2017-03-30 16:56:49 +02:00
|
|
|
|