4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-12 19:39:32 +00:00

Merge branch 'packer/tencent'

This commit is contained in:
Romain Thomas 2018-12-13 09:33:46 +01:00
commit 2c6f052a5f
9 changed files with 148 additions and 29 deletions

@ -489,6 +489,20 @@ void create<Binary>(py::module& m) {
&Binary::dtor_functions,
"Destuctor functions that are called the main execution")
.def_property_readonly("eof_offset",
&Binary::eof_offset,
"Last offset that is used by the ELF format. Data after this offset are "
"considered as overlay data")
.def_property_readonly("has_overlay",
&Binary::has_overlay,
"True if data are appended to the end of the binary")
.def_property("overlay",
static_cast<getter_t<const Binary::overlay_t&>>(&Binary::overlay),
static_cast<setter_t<Binary::overlay_t>>(&Binary::overlay),
"Overlay data that are not a part of the ELF format")
.def(py::self += Segment())

@ -60,6 +60,7 @@ class LIEF_API Binary : public LIEF::Binary {
public:
using string_list_t = std::vector<std::string>;
using overlay_t = std::vector<uint8_t>;
public:
Binary(const std::string& name, ELF_CLASS type);
@ -482,6 +483,17 @@ class LIEF_API Binary : public LIEF::Binary {
it_notes notes(void);
uint64_t eof_offset(void) const;
//! True if data are present at the end of the binary
bool has_overlay(void) const;
//! Overlay data (if any)
const overlay_t& overlay(void) const;
void overlay(overlay_t overlay);
size_t hash(const std::string& name);
virtual ~Binary(void);
@ -602,6 +614,7 @@ class LIEF_API Binary : public LIEF::Binary {
DataHandler::Handler* datahandler_;
std::string interpreter_;
overlay_t overlay_;
};
}

@ -116,6 +116,9 @@ class LIEF_API Builder {
template<typename ELF_T>
void relocate_dynamic_array(DynamicEntryArray& entry_array, DynamicEntry& entry_size);
template<typename ELF_T>
void build_overlay(void);
bool should_swap(void) const;
mutable vector_iostream ios_;

@ -229,6 +229,7 @@ class LIEF_API Parser : public LIEF::Parser {
//! @brief Parse Symbols's SYSV hash
void parse_symbol_sysv_hash(uint64_t offset);
void parse_overlay(void);
template<typename ELF_T, typename REL_T>
uint32_t max_relocation_index(uint64_t relocations_offset, uint64_t size) const;

@ -2562,13 +2562,52 @@ LIEF::Binary::functions_t Binary::functions(void) const {
std::inserter(functions_set, std::end(functions_set)));
return {std::begin(functions_set), std::end(functions_set)};
}
uint64_t Binary::eof_offset(void) const {
uint64_t last_offset_sections = 0;
for (Section* section : this->sections_) {
if (section->type() != LIEF::ELF::ELF_SECTION_TYPES::SHT_NOBITS) {
last_offset_sections = std::max<uint64_t>(section->file_offset() + section->size(), last_offset_sections);
}
}
const uint64_t section_header_size = this->type() == LIEF::ELF::ELF_CLASS::ELFCLASS64 ? sizeof(typename ELF64::Elf_Shdr) : sizeof(typename ELF32::Elf_Shdr);
const uint64_t segment_header_size = this->type() == LIEF::ELF::ELF_CLASS::ELFCLASS64 ? sizeof(typename ELF64::Elf_Phdr) : sizeof(typename ELF32::Elf_Phdr);
const uint64_t end_sht_table =
this->header().section_headers_offset() +
this->sections_.size() * section_header_size;
const uint64_t end_phdr_table =
this->header().program_headers_offset() +
this->segments_.size() * segment_header_size;
last_offset_sections = std::max<uint64_t>({last_offset_sections, end_sht_table, end_phdr_table});
const uint64_t last_offset_segments = this->last_offset_segment();
const uint64_t last_offset = std::max<uint64_t>(last_offset_sections, last_offset_segments);
return last_offset;
}
bool Binary::has_overlay(void) const {
return this->overlay_.size() > 0;
}
const Binary::overlay_t& Binary::overlay(void) const {
return this->overlay_;
}
void Binary::overlay(Binary::overlay_t overlay) {
this->overlay_ = std::move(overlay);
}
// Operator+=
// ==========
Binary& Binary::operator+=(const DynamicEntry& entry) {

@ -140,6 +140,7 @@ void Builder::build(void) {
}
this->build<ELF_T>(this->binary_->header());
this->build_overlay<ELF_T>();
}
@ -299,9 +300,15 @@ void Builder::build_sections(void) {
VLOG(VDEBUG) << "Writing back '" << section->name() << "'";
// Write Section's content
if (section->size() > 0) {
this->ios_.seekp(section->file_offset());
this->ios_.write(section->content());
if (section->size() > 0 and section->file_offset() > 0) {
//const E_TYPE bin_type = this->binary_->header().file_type();
//bool is_object_file = bin_type == E_TYPE::ET_REL; // Object file (.o)
//bool is_final = bin_type == E_TYPE::ET_EXEC or bin_type == E_TYPE::ET_DYN; // Executable or Library
//if (is_object_file or is_final) {
this->ios_.seekp(section->file_offset());
this->ios_.write(section->content());
//}
}
}
@ -616,7 +623,7 @@ void Builder::build_dynamic_section(void) {
const size_t array_size = array.size() * sizeof(Elf_Addr);
if (array_section.original_size() < array_size) {
if (array_section.original_size() < array_size and array_section.original_size() > 0) {
this->relocate_dynamic_array<ELF_T>(*dynamic_cast<DynamicEntryArray*>(entry), *dt_array_size);
return build_dynamic_section<ELF_T>();
}
@ -646,7 +653,7 @@ void Builder::build_dynamic_section(void) {
}
if (dynamic_table_raw.size() > dyn_section.original_size()) {
if (dynamic_table_raw.size() > dyn_section.original_size() and dyn_section.original_size() > 0) {
VLOG(VDEBUG) << "Need to relocate the '.dynamic' section";
VLOG(VDEBUG) << std::dec << dynamic_table_raw.size() << " > " << dyn_section.original_size();
@ -682,7 +689,7 @@ void Builder::build_dynamic_section(void) {
}
if (dynamic_strings_raw.size() > dyn_strtab_section.original_size()) {
if (dynamic_strings_raw.size() > dyn_strtab_section.original_size() and dyn_strtab_section.original_size() > 0) {
VLOG(VDEBUG) << "Need to relocate the '.dynstr' section";
VLOG(VDEBUG) << std::dec << dynamic_strings_raw.size() << " > " << dyn_strtab_section.size();
@ -1085,7 +1092,7 @@ void Builder::build_dynamic_symbols(void) {
VLOG(VDEBUG) << "Set raw string table";
// Relocation .dynstr section
if (string_table_raw.size() > string_table_section.original_size()) {
if (string_table_raw.size() > string_table_section.original_size() and string_table_section.original_size() > 0) {
LOG(INFO) << "Need to relocate the '" << string_table_section.name() << "' section";
VLOG(VDEBUG) << std::dec << string_table_raw.size() << " > " << string_table_section.size();
@ -1109,7 +1116,7 @@ void Builder::build_dynamic_symbols(void) {
}
// Relocation the .dynsym section
if (symbol_table_raw.size() > symbol_table_section.original_size()) {
if (symbol_table_raw.size() > symbol_table_section.original_size() and symbol_table_section.original_size() > 0) {
LOG(INFO) << "Need to relocate the '" << symbol_table_section.name() << "' section";
Segment dynsym_load;
@ -1249,7 +1256,7 @@ void Builder::build_section_relocations(void) {
VLOG(VDEBUG) << "Section associated with object relocations: " << section->name();
VLOG(VDEBUG) << "Is Rela: " << std::boolalpha << isRela;
// Relocation the '.rela.xxxx' section
if (content.size() > section->original_size()) {
if (content.size() > section->original_size() and section->original_size() > 0) {
Section rela_section(section->name(), (isRela)?ELF_SECTION_TYPES::SHT_RELA:ELF_SECTION_TYPES::SHT_REL);
rela_section.content(content);
this->binary_->add(rela_section, false);
@ -1396,7 +1403,8 @@ void Builder::build_dynamic_relocations(void) {
VLOG(VDEBUG) << "Section associated with dynamic relocations: " << relocation_section.name();
VLOG(VDEBUG) << "Is Rela: " << std::boolalpha << isRela;
// Relocation the '.dyn.rel' section
if (content.size() > relocation_section.original_size()) {
if (content.size() > relocation_section.original_size() and relocation_section.original_size() > 0) {
LOG(INFO) << "Need to relocated dynamic relocation section (" << content.size() << " vs " << relocation_section.original_size() << ")" << std::endl;
// Need relocation of the reloc section
Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
@ -1527,7 +1535,7 @@ void Builder::build_pltgot_relocations(void) {
}
if (content.size() > relocation_section.original_size()) {
if (content.size() > relocation_section.original_size() and relocation_section.original_size() > 0) {
// Need relocation of the reloc section
Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
@ -1649,7 +1657,7 @@ void Builder::build_symbol_requirement(void) {
++svr_idx;
}
if (dyn_str_raw.size() > dyn_str_section.original_size()) {
if (dyn_str_raw.size() > dyn_str_section.original_size() and dyn_str_section.original_size() > 0) {
LOG(INFO) << "Need to relocate the '" << dyn_str_section.name() << "' section";
VLOG(VDEBUG) << std::dec << dyn_str_raw.size() << " > " << dyn_str_section.size();
@ -1760,7 +1768,7 @@ void Builder::build_symbol_definition(void) {
++svd_idx;
}
if (dyn_str_raw.size() > dyn_str_section.original_size()) {
if (dyn_str_raw.size() > dyn_str_section.original_size() and dyn_str_section.original_size() > 0) {
LOG(INFO) << "Need to relocate the '" << dyn_str_section.name() << "' section";
VLOG(VDEBUG) << std::dec << dyn_str_raw.size() << " > " << dyn_str_section.size();
@ -1958,7 +1966,7 @@ void Builder::build_interpreter(void) {
}
Segment* interp_segment = *it_pt_interp;
if (inter_str.size() > interp_segment->physical_size()) {
if (inter_str.size() > interp_segment->physical_size() and interp_segment->physical_size() > 0) {
LOG(INFO) << "The 'interpreter' segment needs to be relocated";
// Create a LOAD segment for the new Interpreter:
@ -2033,7 +2041,7 @@ void Builder::build_notes(void) {
}
}
if (segment_note.physical_size() < raw_notes.size()) {
if (segment_note.physical_size() < raw_notes.size() and segment_note.physical_size() > 0) {
LOG(INFO) << "Segment Note needs to be relocated";
Segment note = segment_note;
note.virtual_address(0);
@ -2083,7 +2091,7 @@ void Builder::build_symbol_version(void) {
Section& sv_section = this->binary_->section_from_virtual_address(sv_address);
if (sv_raw.size() > sv_section.original_size()) {
if (sv_raw.size() > sv_section.original_size() and sv_section.original_size() > 0) {
LOG(INFO) << "Need to relocate the '" << sv_section.name() << "' section";
Segment sv_load;
@ -2107,6 +2115,21 @@ void Builder::build_symbol_version(void) {
}
template<class ELF_T>
void Builder::build_overlay(void) {
if (this->binary_->overlay_.size() == 0) {
return;
}
const Binary::overlay_t& overlay = this->binary_->overlay();
const uint64_t last_offset = this->binary_->eof_offset();
if (last_offset > 0 and overlay.size() > 0) {
this->ios_.seekp(last_offset);
this->ios_.write(overlay);
}
}

@ -387,6 +387,31 @@ void Parser::parse_notes(uint64_t offset, uint64_t size) {
}
void Parser::parse_overlay(void) {
const uint64_t last_offset = this->binary_->eof_offset();
if (last_offset > this->stream_->size()) {
return;
}
const uint64_t overlay_size = this->stream_->size() - last_offset;
if (overlay_size == 0) {
return;
}
LOG(INFO) << "Overlay detected at " << std::hex << std::showbase << last_offset << " ("
<< std::dec << overlay_size << " bytes)" << std::endl;
const uint8_t* overlay = this->stream_->peek_array<uint8_t>(last_offset, overlay_size, /* check */ false);
if (overlay == nullptr) {
LOG(WARNING) << "Can't read overlay data";
return;
}
this->binary_->overlay_ = {overlay, overlay + overlay_size};
}
}
}

@ -450,6 +450,7 @@ void Parser::parse_binary(void) {
}
this->link_symbol_version();
this->parse_overlay();
}

@ -33,23 +33,23 @@ class TestEquality64(TestCase):
def test_sections(self):
for l, r in zip(self.input.sections, self.output.sections):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_segments(self):
for l, r in zip(self.input.segments, self.output.segments):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_relocations(self):
for l, r in zip(self.input.relocations, self.output.relocations):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_symbols(self):
for l, r in zip(self.input.symbols, self.output.symbols):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_dynamic_entries(self):
for l, r in zip(self.input.dynamic_entries, self.output.dynamic_entries):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
class TestEquality32(TestCase):
@ -68,23 +68,23 @@ class TestEquality32(TestCase):
def test_sections(self):
for l, r in zip(self.input.sections, self.output.sections):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_segments(self):
for l, r in zip(self.input.segments, self.output.segments):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_relocations(self):
for l, r in zip(self.input.relocations, self.output.relocations):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_symbols(self):
for l, r in zip(self.input.symbols, self.output.symbols):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
def test_dynamic_entries(self):
for l, r in zip(self.input.dynamic_entries, self.output.dynamic_entries):
self.assertEqual(l, r)
self.assertEqual(l, r, "\n{!s}\n{!s}".format(l, r))
if __name__ == '__main__':