Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add function to apply a permutation on the dynamic symbols
  • Loading branch information
romainthomas committed Apr 7, 2017
1 parent 2d61e0a commit 2dea7cb
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 2 deletions.
4 changes: 4 additions & 0 deletions api/python/ELF/objects/pyBinary.cpp
Expand Up @@ -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",
Expand Down
7 changes: 6 additions & 1 deletion include/LIEF/ELF/Binary.hpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions src/ELF/Binary.cpp
Expand Up @@ -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();
Expand All @@ -1403,6 +1420,8 @@ LIEF::Header Binary::get_abstract_header(void) const {
}




void Binary::accept(LIEF::Visitor&) const {
}

Expand Down
58 changes: 57 additions & 1 deletion tests/elf/elf_test.py
@@ -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'))

Expand Down Expand Up @@ -59,6 +72,41 @@ def test_gnuhash(self):
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)




Expand All @@ -68,5 +116,13 @@ def test_gnuhash(self):


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)

0 comments on commit 2dea7cb

Please sign in to comment.