4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-10 18:59:33 +00:00

Add function to apply a permutation on the dynamic symbols

This commit is contained in:
Romain Thomas 2017-04-05 08:25:22 +02:00
parent 95affa6490
commit 99042451d8
4 changed files with 86 additions and 2 deletions
api/python/ELF/objects
include/LIEF/ELF
src/ELF
tests/elf

@ -198,6 +198,10 @@ void init_ELF_Binary_class(py::module& m) {
&Binary::strip,
"Strip the binary")
.def("permute_dynamic_symbols",
&Binary::permute_dynamic_symbols,
"Apply the given permutation on the dynamic symbols table")
.def("write",
&Binary::write,
"Rebuild the binary and write it in a file",

@ -97,7 +97,6 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
it_symbols get_dynamic_symbols(void);
it_const_symbols get_dynamic_symbols(void) const;
//! @brief Return symbols which are exported by the binary
it_exported_symbols get_exported_symbols(void);
it_const_exported_symbols get_exported_symbols(void) const;
@ -346,6 +345,12 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
//! @brief Method so that the ``visitor`` can visit us
virtual void accept(LIEF::Visitor& visitor) const override;
//! @brief Apply the given permutation on the dynamic symbols table
//!
//! To avoid override by the ELF::Builder, one should set ELF::Builder::empties_gnuhash
//! to ``true``
void permute_dynamic_symbols(const std::vector<size_t>& permutation);
size_t hash(const std::string& name);
virtual ~Binary(void);

@ -1391,6 +1391,23 @@ bool Binary::has_dynamic_entry(DYNAMIC_TAGS tag) const {
return true;
}
void Binary::permute_dynamic_symbols(const std::vector<size_t>& permutation) {
for (size_t i = 0; i < permutation.size(); ++i) {
if (this->dynamic_symbols_[i]->has_version() and this->dynamic_symbols_[permutation[i]]->has_version()) {
std::swap(this->symbol_version_table_[i], this->symbol_version_table_[permutation[i]]);
std::swap(this->dynamic_symbols_[i], this->dynamic_symbols_[permutation[i]]);
} else if (not this->dynamic_symbols_[i]->has_version() and not this->dynamic_symbols_[permutation[i]]->has_version()) {
std::swap(this->dynamic_symbols_[i], this->dynamic_symbols_[permutation[i]]);
} else if (permutation[i] == i) {
continue;
} else {
LOG(ERROR) << "Can't apply permutation at index " << std::dec << i;
}
}
}
LIEF::Header Binary::get_abstract_header(void) const {
LIEF::Header header;
const std::pair<ARCHITECTURES, std::set<MODES>>& am = this->get_header().abstract_architecture();
@ -1403,6 +1420,8 @@ LIEF::Header Binary::get_abstract_header(void) const {
}
void Binary::accept(LIEF::Visitor&) const {
}

@ -1,12 +1,25 @@
#!/usr/bin/env python
import unittest
import lief
import tempfile
import sys
import subprocess
import stat
import os
import logging
import random
from subprocess import Popen
from unittest import TestCase
from utils import get_sample
class TestELF(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
def test_rpath(self):
etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_etterlog.bin'))
@ -59,6 +72,41 @@ class TestELF(TestCase):
0x12F7C433, 0xEB01FAB6, 0xECD54543, 0xAD3C9892, 0x72632CCF, 0x12F7A2B3, 0x7C92E3BB, 0x7C96F087]
self.assertEqual(hash_values, hash_values_test)
def test_permutation(self):
samples = [
"ELF/ELF64_x86-64_binary_ls.bin",
"ELF/ELF64_x86-64_binary_gcc.bin",
"ELF/ELF64_x86-64_binary_openssl.bin",
]
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
builder = lief.ELF.Builder(binary)
builder.empties_gnuhash(True)
builder.build()
output = os.path.join(tmp_dir, "{}.permutated".format(binary.name))
binary.write(output)
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)
@ -68,5 +116,13 @@ class TestELF(TestCase):
if __name__ == '__main__':
unittest.main(verbosity = 2)
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)