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:
commit
2c6f052a5f
api/python/ELF/objects
include/LIEF/ELF
src/ELF
tests/elf
@ -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__':
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user