Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12cf390bc8 | ||
|
|
764a40f9f4 | ||
|
|
337f9bf585 |
@@ -137,6 +137,8 @@ endif()
|
||||
|
||||
|
||||
ADD_FLAG_IF_SUPPORTED("-Wno-macro-redefined" NO_MACRO_REDEFINED)
|
||||
ADD_FLAG_IF_SUPPORTED("-fdiagnostics-color=always" DIAGNOSTICS_COLOR)
|
||||
ADD_FLAG_IF_SUPPORTED("-fcolor-diagnostics" COLOR_DIAGNOSTICS)
|
||||
ADD_FLAG_IF_SUPPORTED("-Wno-deprecated-declarations" NO_DEPRECATED_DECLARATIONS)
|
||||
|
||||
set_target_properties(pyLIEF PROPERTIES PREFIX "" OUTPUT_NAME "lief")
|
||||
@@ -144,7 +146,7 @@ add_dependencies(pyLIEF lief_pybind11)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(pyLIEF PROPERTIES MACOSX_RPATH ".")
|
||||
set_target_properties(pyLIEF PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ")
|
||||
set_target_properties(pyLIEF PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
set_target_properties(pyLIEF PROPERTIES PREFIX "")
|
||||
|
||||
@@ -42,7 +42,15 @@ void create<Binary>(py::module& m) {
|
||||
|
||||
// Binary object
|
||||
py::class_<Binary, LIEF::Binary>(m, "Binary", "ELF binary representation")
|
||||
.def(py::init<const std::string&, ELF_CLASS>())
|
||||
//.def(py::init<const std::string&, ELF_CLASS>())
|
||||
.def("create_lief_core",
|
||||
&Binary::create_lief_core,
|
||||
py::return_value_policy::take_ownership)
|
||||
|
||||
.def("create_lief_dyn",
|
||||
&Binary::create_lief_dyn,
|
||||
py::return_value_policy::take_ownership)
|
||||
|
||||
|
||||
.def_property_readonly("type",
|
||||
&Binary::type,
|
||||
|
||||
@@ -69,6 +69,13 @@ void init_enums(py::module& m) {
|
||||
.value(PY_ENUM(E_TYPE::ET_EXEC))
|
||||
.value(PY_ENUM(E_TYPE::ET_DYN))
|
||||
.value(PY_ENUM(E_TYPE::ET_CORE))
|
||||
|
||||
.value(PY_ENUM(E_TYPE::ET_PSPEXEC))
|
||||
|
||||
.value(PY_ENUM(E_TYPE::ET_LIEF))
|
||||
.value(PY_ENUM(E_TYPE::ET_LIEF_CORE))
|
||||
|
||||
.value(PY_ENUM(E_TYPE::ET_HIOS))
|
||||
.value(PY_ENUM(E_TYPE::ET_LOPROC))
|
||||
.value(PY_ENUM(E_TYPE::ET_HIPROC));
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import lief
|
||||
|
||||
from lief import Logger
|
||||
Logger.set_level(lief.LOGGING_LEVEL.DEBUG)
|
||||
|
||||
b = lief.ELF.Binary.create_lief_dyn(lief.ELF.ARCH.x86_64)
|
||||
print(b)
|
||||
|
||||
for i in range(3):
|
||||
s = lief.ELF.Section(f".foo{i}")
|
||||
s.content = [i & 0xFF for x in range(0x1000)]
|
||||
b.add(s, True)
|
||||
|
||||
print(b)
|
||||
b.write("/tmp/out")
|
||||
|
||||
|
||||
b = lief.ELF.Binary.create_lief_dyn(lief.ELF.ARCH.x86_64)
|
||||
print(b)
|
||||
|
||||
|
||||
for i in range(3):
|
||||
s = lief.ELF.Segment()
|
||||
s.type = lief.ELF.SEGMENT_TYPES.LOAD
|
||||
s.content = [i & 0xFF for x in range(0x1000)]
|
||||
b.add(s)
|
||||
|
||||
for i in range(10):
|
||||
s = lief.ELF.Section(f".foo{i}")
|
||||
b.add(s, False)
|
||||
|
||||
print(b)
|
||||
b.write("/tmp/out2")
|
||||
@@ -5,6 +5,7 @@ set(LIEF_ELF_CPP_EXAMPLES
|
||||
elf_section_rename.cpp
|
||||
elf_strip.cpp
|
||||
elf_symbols.cpp
|
||||
coredump.cpp
|
||||
)
|
||||
|
||||
set(LIEF_PE_CPP_EXAMPLES
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <link.h>
|
||||
#include <LIEF/ELF.hpp>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace LIEF::ELF;
|
||||
|
||||
void dump(void) {
|
||||
|
||||
std::unique_ptr<Binary> core = Binary::create_lief_core(LIEF::ELF::ARCH::EM_X86_64);
|
||||
|
||||
dl_iterate_phdr([] (dl_phdr_info* info, size_t size, void* data) {
|
||||
Binary* core = reinterpret_cast<Binary*>(data);
|
||||
|
||||
if (info->dlpi_name == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < info->dlpi_phnum; ++i) {
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "." << info->dlpi_name << "." << std::dec << i;
|
||||
Section section{oss.str()};
|
||||
const uint8_t* start = reinterpret_cast<uint8_t*>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
|
||||
const uint8_t* stop = start + info->dlpi_phdr[i].p_memsz;
|
||||
//std::cout << std::showbase << std::hex << info->dlpi_addr + info->dlpi_phdr[i].p_vaddr << std::endl;
|
||||
section.content({start, stop});
|
||||
|
||||
Section& added = core->add(section, true);
|
||||
|
||||
added.virtual_address(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
|
||||
}
|
||||
|
||||
std::cout << info->dlpi_name << std::endl;
|
||||
return 0;
|
||||
}, core.get());
|
||||
core->write("/tmp/bar");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
dump();
|
||||
return 0;
|
||||
}
|
||||
@@ -62,8 +62,11 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
using string_list_t = std::vector<std::string>;
|
||||
using overlay_t = std::vector<uint8_t>;
|
||||
|
||||
static std::unique_ptr<Binary> create_lief_core(ARCH arch);
|
||||
static std::unique_ptr<Binary> create_lief_dyn(ARCH arch);
|
||||
|
||||
public:
|
||||
Binary(const std::string& name, ELF_CLASS type);
|
||||
//Binary(const std::string& name, ELF_CLASS type);
|
||||
|
||||
Binary& operator=(const Binary& ) = delete;
|
||||
Binary(const Binary& copy) = delete;
|
||||
@@ -566,6 +569,12 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
Section& add_section(const Section& section);
|
||||
symbols_t static_dyn_symbols(void) const;
|
||||
|
||||
template<class T>
|
||||
LIEF_LOCAL static std::unique_ptr<Binary> create_lief_core_impl(ARCH arch, ELF_CLASS clazz);
|
||||
|
||||
template<class T>
|
||||
LIEF_LOCAL static std::unique_ptr<Binary> create_lief_dyn_impl(ARCH arch, ELF_CLASS clazz);
|
||||
|
||||
std::string shstrtab_name(void) const;
|
||||
|
||||
LIEF::Binary::functions_t tor_functions(DYNAMIC_TAGS tag) const;
|
||||
|
||||
@@ -22,8 +22,17 @@ enum _LIEF_EN(E_TYPE) {
|
||||
_LIEF_EI(ET_EXEC) = 2, /**< Executable file */
|
||||
_LIEF_EI(ET_DYN) = 3, /**< Shared object file */
|
||||
_LIEF_EI(ET_CORE) = 4, /**< Core file */
|
||||
_LIEF_EI(ET_LOPROC) = 0xff00, /**< Beginning of processor-specific codes */
|
||||
_LIEF_EI(ET_HIPROC) = 0xffff /**< Processor-specific */
|
||||
|
||||
_LIEF_EI(ET_PSPEXEC) = 0xFFA0, /**< Sony PSP executable file */
|
||||
|
||||
_LIEF_EI(ET_LIEF) = 0xFF10, /**< Custom LIEF format */
|
||||
_LIEF_EI(ET_LIEF_CORE) = 0xFF11, /**< Custom LIEF Core file */
|
||||
_LIEF_EI(ET_LIEF_EXEC) = 0xFF12, /**< Custom LIEF Executable file */
|
||||
_LIEF_EI(ET_LIEF_DYN) = 0xFF13, /**< Custom LIEF Dynamic file */
|
||||
|
||||
_LIEF_EI(ET_HIOS) = 0xFEFF, /**< Operating system-specific */
|
||||
_LIEF_EI(ET_LOPROC) = 0xFF00, /**< Beginning of processor-specific codes */
|
||||
_LIEF_EI(ET_HIPROC) = 0xFFFF, /**< Processor-specific */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#undef ET_CORE
|
||||
#undef ET_LOPROC
|
||||
#undef ET_HIPROC
|
||||
#undef ET_HIOS
|
||||
|
||||
|
||||
#undef EV_NONE
|
||||
@@ -674,6 +675,15 @@
|
||||
#undef NT_SIGINFO
|
||||
#undef NT_FILE
|
||||
#undef NT_PRXFPREG
|
||||
#undef NT_ARM_VFP
|
||||
#undef NT_ARM_TLS
|
||||
#undef NT_ARM_HW_BREAK
|
||||
#undef NT_ARM_HW_WATCH
|
||||
#undef NT_ARM_SYSTEM_CALL
|
||||
#undef NT_ARM_SVE
|
||||
#undef NT_386_TLS
|
||||
#undef NT_386_IOPERM
|
||||
#undef NT_386_XSTATE
|
||||
|
||||
#undef ELF_NOTE_UNKNOWN
|
||||
#undef ELF_NOTE_OS_LINUX
|
||||
|
||||
+71
-5
@@ -41,21 +41,75 @@
|
||||
#include "LIEF/ELF/hash.hpp"
|
||||
|
||||
#include "Binary.tcc"
|
||||
#include "BinaryDyn.tcc"
|
||||
#include "Object.tcc"
|
||||
|
||||
namespace LIEF {
|
||||
namespace ELF {
|
||||
Binary::Binary(void) = default;
|
||||
|
||||
Binary::Binary(const std::string& name, ELF_CLASS type) : type_{type} {
|
||||
this->name_ = name;
|
||||
if (type_ == ELF_CLASS::ELFCLASS32) {
|
||||
}
|
||||
else if (type_ == ELF_CLASS::ELFCLASS32) {
|
||||
|
||||
std::unique_ptr<Binary> Binary::create_lief_core(ARCH arch) {
|
||||
|
||||
switch (arch) {
|
||||
case ARCH::EM_X86_64:
|
||||
{
|
||||
return create_lief_core_impl<ELF64>(arch, ELF_CLASS::ELFCLASS64);
|
||||
}
|
||||
|
||||
case ARCH::EM_386:
|
||||
{
|
||||
return create_lief_core_impl<ELF32>(arch, ELF_CLASS::ELFCLASS32);
|
||||
}
|
||||
|
||||
case ARCH::EM_ARM:
|
||||
{
|
||||
return create_lief_core_impl<ELF32>(arch, ELF_CLASS::ELFCLASS32);
|
||||
}
|
||||
|
||||
case ARCH::EM_AARCH64:
|
||||
{
|
||||
return create_lief_core_impl<ELF64>(arch, ELF_CLASS::ELFCLASS64);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Binary> Binary::create_lief_dyn(ARCH arch) {
|
||||
|
||||
switch (arch) {
|
||||
case ARCH::EM_X86_64:
|
||||
{
|
||||
return create_lief_dyn_impl<ELF64>(arch, ELF_CLASS::ELFCLASS64);
|
||||
}
|
||||
|
||||
case ARCH::EM_386:
|
||||
{
|
||||
return create_lief_dyn_impl<ELF32>(arch, ELF_CLASS::ELFCLASS32);
|
||||
}
|
||||
|
||||
case ARCH::EM_ARM:
|
||||
{
|
||||
return create_lief_dyn_impl<ELF32>(arch, ELF_CLASS::ELFCLASS32);
|
||||
}
|
||||
|
||||
case ARCH::EM_AARCH64:
|
||||
{
|
||||
return create_lief_dyn_impl<ELF64>(arch, ELF_CLASS::ELFCLASS64);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Header& Binary::header(void) {
|
||||
return const_cast<Header&>(static_cast<const Binary*>(this)->header());
|
||||
}
|
||||
@@ -1187,6 +1241,18 @@ Segment& Binary::add(const Segment& segment, uint64_t base) {
|
||||
break;
|
||||
}
|
||||
|
||||
case E_TYPE::ET_LIEF_CORE:
|
||||
{
|
||||
return this->add_segment<E_TYPE::ET_LIEF_CORE>(segment, new_base);
|
||||
break;
|
||||
}
|
||||
|
||||
case E_TYPE::ET_LIEF_DYN:
|
||||
{
|
||||
return this->add_segment<E_TYPE::ET_LIEF_DYN>(segment, new_base);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw not_implemented(std::string("Adding segment for ") + to_string(this->header().file_type()) + " is not implemented");
|
||||
|
||||
+177
-11
@@ -268,7 +268,6 @@ Segment& Binary::add_segment<E_TYPE::ET_EXEC>(const Segment& segment, uint64_t b
|
||||
// ------------------------------------------
|
||||
// Part 1: Move PHDR at the end of the binary
|
||||
// ------------------------------------------
|
||||
|
||||
header.numberof_segments(header.numberof_segments() + 1);
|
||||
|
||||
auto&& it_text_segment = std::find_if(
|
||||
@@ -279,11 +278,12 @@ Segment& Binary::add_segment<E_TYPE::ET_EXEC>(const Segment& segment, uint64_t b
|
||||
s->has(ELF_SEGMENT_FLAGS::PF_X) and s->has(ELF_SEGMENT_FLAGS::PF_R);
|
||||
});
|
||||
|
||||
if (it_text_segment == std::end(this->segments_)) {
|
||||
throw not_found("Unable to find a LOAD segment with 'r-x' permissions");
|
||||
Segment* text_segment = nullptr;
|
||||
if (it_text_segment != std::end(this->segments_)) {
|
||||
//throw not_found("Unable to find a LOAD segment with 'r-x' permissions");
|
||||
text_segment = *it_text_segment;
|
||||
}
|
||||
|
||||
Segment* text_segment = *it_text_segment;
|
||||
|
||||
uint64_t last_offset_sections = std::accumulate(
|
||||
std::begin(this->sections_),
|
||||
@@ -329,19 +329,19 @@ Segment& Binary::add_segment<E_TYPE::ET_EXEC>(const Segment& segment, uint64_t b
|
||||
|
||||
VLOG(VDEBUG) << "New PHDR size 0x" << std::hex << new_phdr_size;
|
||||
|
||||
phdr_segment->file_offset(new_phdr_offset);
|
||||
phdr_segment->virtual_address(text_segment->virtual_address() - text_segment->file_offset() + phdr_segment->file_offset());
|
||||
//phdr_segment->file_offset(new_phdr_offset);
|
||||
//phdr_segment->virtual_address(text_segment->virtual_address() - text_segment->file_offset() + phdr_segment->file_offset());
|
||||
|
||||
phdr_segment->physical_address(phdr_segment->virtual_address());
|
||||
//phdr_segment->physical_address(phdr_segment->virtual_address());
|
||||
|
||||
phdr_segment->physical_size(new_phdr_size);
|
||||
phdr_segment->virtual_size(phdr_segment->virtual_size() + phdr_size);
|
||||
|
||||
uint64_t gap = phdr_segment->file_offset() + phdr_segment->physical_size();
|
||||
gap -= text_segment->file_offset() + text_segment->physical_size();
|
||||
//uint64_t gap = phdr_segment->file_offset() + phdr_segment->physical_size();
|
||||
// gap -= text_segment->file_offset() + text_segment->physical_size();
|
||||
|
||||
text_segment->physical_size(text_segment->physical_size() + gap);
|
||||
text_segment->virtual_size(text_segment->virtual_size() + gap);
|
||||
//text_segment->physical_size(text_segment->physical_size() + gap);
|
||||
//text_segment->virtual_size(text_segment->virtual_size() + gap);
|
||||
|
||||
// Clear PHDR segment
|
||||
phdr_segment->content(std::vector<uint8_t>(phdr_segment->physical_size(), 0));
|
||||
@@ -644,6 +644,7 @@ Section& Binary::add_section<true>(const Section& section) {
|
||||
new_section->size(segment_added.physical_size());
|
||||
new_section->offset(segment_added.file_offset());
|
||||
new_section->original_size_ = segment_added.physical_size();
|
||||
new_section->segments_.push_back(&segment_added);
|
||||
|
||||
this->header().numberof_sections(this->header().numberof_sections() + 1);
|
||||
|
||||
@@ -686,5 +687,170 @@ Section& Binary::add_section<false>(const Section& section) {
|
||||
return *(this->sections_.back());
|
||||
}
|
||||
|
||||
|
||||
// ============
|
||||
// ET_LIEF_CORE
|
||||
// ============
|
||||
template<>
|
||||
Segment& Binary::add_segment<E_TYPE::ET_LIEF_CORE>(const Segment& segment, uint64_t base) {
|
||||
Header& header = this->header();
|
||||
|
||||
uint64_t last_offset_sections = std::accumulate(
|
||||
std::begin(this->sections_),
|
||||
std::end(this->sections_), 0,
|
||||
[] (uint64_t offset, const Section* section) {
|
||||
return std::max<uint64_t>(section->file_offset() + section->size(), offset);
|
||||
});
|
||||
|
||||
uint64_t last_offset_segments = std::accumulate(
|
||||
std::begin(this->segments_),
|
||||
std::end(this->segments_), 0,
|
||||
[] (uint64_t offset, const Segment* segment) {
|
||||
return std::max<uint64_t>(segment->file_offset() + segment->physical_size(), offset);
|
||||
});
|
||||
|
||||
uint64_t last_offset = std::max<uint64_t>(last_offset_sections, last_offset_segments);
|
||||
uint64_t new_phdr_offset = last_offset;
|
||||
|
||||
header.numberof_segments(header.numberof_segments() + 1);
|
||||
|
||||
uint64_t phdr_size = 0;
|
||||
if (this->type() == ELF_CLASS::ELFCLASS32) {
|
||||
phdr_size = sizeof(ELF32::Elf_Phdr);
|
||||
}
|
||||
|
||||
if (this->type() == ELF_CLASS::ELFCLASS64) {
|
||||
phdr_size = sizeof(ELF64::Elf_Phdr);
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> content = segment.content();
|
||||
Segment* new_segment = new Segment{segment};
|
||||
new_segment->datahandler_ = this->datahandler_;
|
||||
|
||||
DataHandler::Node new_node{
|
||||
new_segment->file_offset(),
|
||||
new_segment->physical_size(),
|
||||
DataHandler::Node::SEGMENT};
|
||||
this->datahandler_->add(new_node);
|
||||
|
||||
const uint64_t psize = static_cast<uint64_t>(getpagesize());
|
||||
const uint64_t last_offset_aligned = align(last_offset, psize);
|
||||
|
||||
new_segment->file_offset(last_offset_aligned);
|
||||
if (segment.virtual_address() == 0) {
|
||||
new_segment->virtual_address(base + last_offset_aligned);
|
||||
}
|
||||
|
||||
new_segment->physical_address(new_segment->virtual_address());
|
||||
|
||||
uint64_t segmentsize = align(content.size(), psize);
|
||||
content.resize(segmentsize, 0);
|
||||
|
||||
new_segment->physical_size(segmentsize);
|
||||
new_segment->virtual_size(segmentsize);
|
||||
|
||||
if (new_segment->alignment() == 0) {
|
||||
new_segment->alignment(psize);
|
||||
}
|
||||
|
||||
this->datahandler_->make_hole(last_offset_aligned, new_segment->physical_size());
|
||||
new_segment->content(content);
|
||||
|
||||
//if (header.section_headers_offset() <= new_segment->file_offset() + new_segment->physical_size()) {
|
||||
//
|
||||
//header.section_headers_offset(header.section_headers_offset() + new_phdr_offset + phdr_size * header.numberof_segments());
|
||||
header.section_headers_offset(header.section_headers_offset() + new_segment->file_offset() + new_segment->physical_size() + phdr_size);
|
||||
|
||||
//}
|
||||
|
||||
//if (header.program_headers_offset() <= new_segment->file_offset() + new_segment->physical_size()) {
|
||||
header.program_headers_offset(header.program_headers_offset() + new_segment->file_offset() + new_segment->physical_size());
|
||||
//}
|
||||
|
||||
auto&& it_new_segment_place = std::find_if(
|
||||
this->segments_.rbegin(),
|
||||
this->segments_.rend(),
|
||||
[&new_segment] (const Segment* s) {
|
||||
return s->type() == new_segment->type();
|
||||
});
|
||||
|
||||
if (it_new_segment_place == this->segments_.rend()) {
|
||||
this->segments_.push_back(new_segment);
|
||||
} else {
|
||||
const size_t idx = std::distance(std::begin(this->segments_), it_new_segment_place.base());
|
||||
this->segments_.insert(std::begin(this->segments_) + idx, new_segment);
|
||||
}
|
||||
|
||||
return *new_segment;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
std::unique_ptr<Binary> Binary::create_lief_core_impl(ARCH arch, ELF_CLASS clazz) {
|
||||
using Elf_Phdr = typename T::Elf_Phdr;
|
||||
using Elf_Ehdr = typename T::Elf_Ehdr;
|
||||
using Elf_Shdr = typename T::Elf_Shdr;
|
||||
|
||||
std::unique_ptr<Binary> new_binary{new Binary{}};
|
||||
new_binary->type_ = clazz;
|
||||
|
||||
// Set header
|
||||
new_binary->header_.file_type(E_TYPE::ET_LIEF_CORE);
|
||||
new_binary->header_.machine_type(arch);
|
||||
new_binary->header_.object_file_version(VERSION::EV_CURRENT);
|
||||
new_binary->header_.entrypoint(0);
|
||||
|
||||
|
||||
new_binary->header_.processor_flag(0);
|
||||
|
||||
new_binary->header_.header_size(sizeof(Elf_Ehdr));
|
||||
new_binary->header_.program_header_size(sizeof(Elf_Phdr));
|
||||
new_binary->header_.section_header_size(sizeof(Elf_Shdr));
|
||||
|
||||
std::string ident = "\x7F";
|
||||
new_binary->header_.identity(ident + "ELF");
|
||||
new_binary->header_.identity_class(clazz);
|
||||
new_binary->header_.identity_data(ELF_DATA::ELFDATA2LSB);
|
||||
new_binary->header_.identity_version(VERSION::EV_CURRENT);
|
||||
new_binary->header_.identity_os_abi(OS_ABI::ELFOSABI_SYSTEMV);
|
||||
|
||||
|
||||
new_binary->datahandler_ = new DataHandler::Handler{std::vector<uint8_t>{}};
|
||||
|
||||
size_t cursor = sizeof(Elf_Ehdr);
|
||||
// Add new null entry section
|
||||
|
||||
Section* null = new Section{"", ELF_SECTION_TYPES::SHT_NULL};
|
||||
null->datahandler_ = new_binary->datahandler_;
|
||||
new_binary->datahandler_->add({null->file_offset(), null->size(), DataHandler::Node::SECTION});
|
||||
|
||||
new_binary->sections_.push_back(null);
|
||||
|
||||
Section* shstrtab = new Section{".shstrtab", ELF_SECTION_TYPES::SHT_STRTAB};
|
||||
shstrtab->offset(cursor);
|
||||
|
||||
shstrtab->datahandler_ = new_binary->datahandler_;
|
||||
new_binary->datahandler_->add({shstrtab->file_offset(), 0, DataHandler::Node::SECTION});
|
||||
shstrtab->size(100);
|
||||
cursor += shstrtab->size();
|
||||
new_binary->sections_.push_back(shstrtab);
|
||||
new_binary->datahandler_->make_hole(shstrtab->file_offset(), shstrtab->size());
|
||||
|
||||
new_binary->header_.program_headers_offset(cursor);
|
||||
cursor += 1;
|
||||
|
||||
new_binary->header_.section_headers_offset(cursor);
|
||||
new_binary->header_.section_name_table_idx(new_binary->sections_.size() - 1);
|
||||
|
||||
const size_t shdr_sizes = (new_binary->sections_.size() + 1) * sizeof(Elf_Shdr);
|
||||
cursor += shdr_sizes;
|
||||
|
||||
new_binary->header().numberof_sections(new_binary->sections_.size());
|
||||
new_binary->header().numberof_segments(new_binary->segments_.size());
|
||||
return new_binary;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/* Copyright 2017 R. Thomas
|
||||
* Copyright 2017 Quarkslab
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "LIEF/logging++.hpp"
|
||||
#include "LIEF/ELF/enums.hpp"
|
||||
namespace LIEF {
|
||||
namespace ELF {
|
||||
|
||||
// ============
|
||||
// ET_LIEF_DYN
|
||||
// ============
|
||||
template<>
|
||||
Segment& Binary::add_segment<E_TYPE::ET_LIEF_DYN>(const Segment& segment, uint64_t base) {
|
||||
Header& header = this->header();
|
||||
|
||||
uint64_t last_offset_sections = std::accumulate(
|
||||
std::begin(this->sections_),
|
||||
std::end(this->sections_), 0,
|
||||
[] (uint64_t offset, const Section* section) {
|
||||
return std::max<uint64_t>(section->file_offset() + section->size(), offset);
|
||||
});
|
||||
|
||||
uint64_t last_offset_segments = std::accumulate(
|
||||
std::begin(this->segments_),
|
||||
std::end(this->segments_), 0,
|
||||
[] (uint64_t offset, const Segment* segment) {
|
||||
return std::max<uint64_t>(segment->file_offset() + segment->physical_size(), offset);
|
||||
});
|
||||
|
||||
uint64_t last_offset = std::max<uint64_t>(last_offset_sections, last_offset_segments);
|
||||
uint64_t new_phdr_offset = last_offset;
|
||||
|
||||
header.numberof_segments(header.numberof_segments() + 1);
|
||||
|
||||
uint64_t phdr_size = 0;
|
||||
if (this->type() == ELF_CLASS::ELFCLASS32) {
|
||||
phdr_size = sizeof(ELF32::Elf_Phdr);
|
||||
}
|
||||
|
||||
if (this->type() == ELF_CLASS::ELFCLASS64) {
|
||||
phdr_size = sizeof(ELF64::Elf_Phdr);
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> content = segment.content();
|
||||
Segment* new_segment = new Segment{segment};
|
||||
new_segment->datahandler_ = this->datahandler_;
|
||||
|
||||
DataHandler::Node new_node{
|
||||
new_segment->file_offset(),
|
||||
new_segment->physical_size(),
|
||||
DataHandler::Node::SEGMENT};
|
||||
this->datahandler_->add(new_node);
|
||||
|
||||
const uint64_t psize = static_cast<uint64_t>(getpagesize());
|
||||
const uint64_t last_offset_aligned = align(last_offset, psize);
|
||||
|
||||
new_segment->file_offset(last_offset_aligned);
|
||||
if (segment.virtual_address() == 0) {
|
||||
new_segment->virtual_address(base + last_offset_aligned);
|
||||
}
|
||||
|
||||
new_segment->physical_address(new_segment->virtual_address());
|
||||
|
||||
uint64_t segmentsize = align(content.size(), psize);
|
||||
content.resize(segmentsize, 0);
|
||||
|
||||
new_segment->physical_size(segmentsize);
|
||||
new_segment->virtual_size(segmentsize);
|
||||
|
||||
if (new_segment->alignment() == 0) {
|
||||
new_segment->alignment(psize);
|
||||
}
|
||||
|
||||
this->datahandler_->make_hole(last_offset_aligned, new_segment->physical_size());
|
||||
new_segment->content(content);
|
||||
|
||||
//if (header.section_headers_offset() <= new_segment->file_offset() + new_segment->physical_size()) {
|
||||
//
|
||||
//header.section_headers_offset(header.section_headers_offset() + new_phdr_offset + phdr_size * header.numberof_segments());
|
||||
header.section_headers_offset(header.section_headers_offset() + new_segment->file_offset() + new_segment->physical_size() + phdr_size);
|
||||
|
||||
//}
|
||||
|
||||
//if (header.program_headers_offset() <= new_segment->file_offset() + new_segment->physical_size()) {
|
||||
header.program_headers_offset(header.program_headers_offset() + new_segment->file_offset() + new_segment->physical_size());
|
||||
//}
|
||||
|
||||
auto&& it_new_segment_place = std::find_if(
|
||||
this->segments_.rbegin(),
|
||||
this->segments_.rend(),
|
||||
[&new_segment] (const Segment* s) {
|
||||
return s->type() == new_segment->type();
|
||||
});
|
||||
|
||||
if (it_new_segment_place == this->segments_.rend()) {
|
||||
this->segments_.push_back(new_segment);
|
||||
} else {
|
||||
const size_t idx = std::distance(std::begin(this->segments_), it_new_segment_place.base());
|
||||
this->segments_.insert(std::begin(this->segments_) + idx, new_segment);
|
||||
}
|
||||
|
||||
return *new_segment;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
std::unique_ptr<Binary> Binary::create_lief_dyn_impl(ARCH arch, ELF_CLASS clazz) {
|
||||
using Elf_Phdr = typename T::Elf_Phdr;
|
||||
using Elf_Ehdr = typename T::Elf_Ehdr;
|
||||
using Elf_Shdr = typename T::Elf_Shdr;
|
||||
|
||||
std::unique_ptr<Binary> new_binary{new Binary{}};
|
||||
new_binary->type_ = clazz;
|
||||
|
||||
// Set header
|
||||
new_binary->header_.file_type(E_TYPE::ET_LIEF_DYN);
|
||||
new_binary->header_.machine_type(arch);
|
||||
new_binary->header_.object_file_version(VERSION::EV_CURRENT);
|
||||
new_binary->header_.entrypoint(0);
|
||||
|
||||
|
||||
new_binary->header_.processor_flag(0);
|
||||
|
||||
new_binary->header_.header_size(sizeof(Elf_Ehdr));
|
||||
new_binary->header_.program_header_size(sizeof(Elf_Phdr));
|
||||
new_binary->header_.section_header_size(sizeof(Elf_Shdr));
|
||||
|
||||
std::string ident = "\x7F";
|
||||
new_binary->header_.identity(ident + "ELF");
|
||||
new_binary->header_.identity_class(clazz);
|
||||
new_binary->header_.identity_data(ELF_DATA::ELFDATA2LSB);
|
||||
new_binary->header_.identity_version(VERSION::EV_CURRENT);
|
||||
new_binary->header_.identity_os_abi(OS_ABI::ELFOSABI_SYSTEMV);
|
||||
|
||||
|
||||
new_binary->datahandler_ = new DataHandler::Handler{std::vector<uint8_t>{}};
|
||||
|
||||
size_t cursor = sizeof(Elf_Ehdr);
|
||||
// Add new null entry section
|
||||
|
||||
Section* null = new Section{"", ELF_SECTION_TYPES::SHT_NULL};
|
||||
null->datahandler_ = new_binary->datahandler_;
|
||||
new_binary->datahandler_->add({null->file_offset(), null->size(), DataHandler::Node::SECTION});
|
||||
|
||||
new_binary->sections_.push_back(null);
|
||||
|
||||
Section* shstrtab = new Section{".shstrtab", ELF_SECTION_TYPES::SHT_STRTAB};
|
||||
shstrtab->offset(cursor);
|
||||
|
||||
shstrtab->datahandler_ = new_binary->datahandler_;
|
||||
new_binary->datahandler_->add({shstrtab->file_offset(), 0, DataHandler::Node::SECTION});
|
||||
shstrtab->size(100);
|
||||
cursor += shstrtab->size();
|
||||
new_binary->sections_.push_back(shstrtab);
|
||||
new_binary->datahandler_->make_hole(shstrtab->file_offset(), shstrtab->size());
|
||||
|
||||
new_binary->header_.program_headers_offset(cursor);
|
||||
cursor += 1;
|
||||
|
||||
new_binary->header_.section_headers_offset(cursor);
|
||||
new_binary->header_.section_name_table_idx(new_binary->sections_.size() - 1);
|
||||
|
||||
const size_t shdr_sizes = (new_binary->sections_.size() + 1) * sizeof(Elf_Shdr);
|
||||
cursor += shdr_sizes;
|
||||
|
||||
new_binary->header().numberof_sections(new_binary->sections_.size());
|
||||
new_binary->header().numberof_segments(new_binary->segments_.size());
|
||||
return new_binary;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -198,9 +198,20 @@ void Builder::build(const Header& header) {;
|
||||
|
||||
using Elf_Ehdr = typename ELF_T::Elf_Ehdr;
|
||||
|
||||
Elf_Ehdr ehdr;
|
||||
static const std::map<E_TYPE, E_TYPE> lief_type2elf_type = {
|
||||
{ E_TYPE::ET_LIEF_EXEC, E_TYPE::ET_EXEC },
|
||||
{ E_TYPE::ET_LIEF_DYN , E_TYPE::ET_DYN },
|
||||
};
|
||||
|
||||
ehdr.e_type = static_cast<Elf_Half>(header.file_type());
|
||||
Elf_Ehdr ehdr;
|
||||
E_TYPE ftype = header.file_type();
|
||||
|
||||
auto&& it_translate = lief_type2elf_type.find(ftype);
|
||||
if (it_translate != std::end(lief_type2elf_type)) {
|
||||
ftype = it_translate->second;
|
||||
}
|
||||
|
||||
ehdr.e_type = static_cast<Elf_Half>(ftype);
|
||||
ehdr.e_machine = static_cast<Elf_Half>(header.machine_type());
|
||||
ehdr.e_version = static_cast<Elf_Word>(header.object_file_version());
|
||||
ehdr.e_entry = static_cast<Elf_Addr>(header.entrypoint());
|
||||
|
||||
@@ -45,6 +45,7 @@ set(LIEF_ELF_SRC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Builder.tcc"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Parser.tcc"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Binary.tcc"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/BinaryDyn.tcc"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hash.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Note.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/NoteDetails.cpp"
|
||||
|
||||
@@ -39,14 +39,23 @@ const char* to_string(SYMBOL_BINDINGS e) {
|
||||
|
||||
|
||||
const char* to_string(E_TYPE e) {
|
||||
CONST_MAP(E_TYPE, const char*, 7) enumStrings {
|
||||
CONST_MAP(E_TYPE, const char*, 13) enumStrings {
|
||||
{ E_TYPE::ET_NONE, "NONE" },
|
||||
{ E_TYPE::ET_REL, "RELOCATABLE" },
|
||||
{ E_TYPE::ET_EXEC, "EXECUTABLE" },
|
||||
{ E_TYPE::ET_DYN, "DYNAMIC" },
|
||||
{ E_TYPE::ET_CORE, "CORE" },
|
||||
{ E_TYPE::ET_LOPROC, "LOPROC" },
|
||||
{ E_TYPE::ET_HIPROC, "HIPROC" }
|
||||
{ E_TYPE::ET_REL, "RELOCATABLE" },
|
||||
{ E_TYPE::ET_EXEC, "EXECUTABLE" },
|
||||
{ E_TYPE::ET_DYN, "DYNAMIC" },
|
||||
{ E_TYPE::ET_CORE, "CORE" },
|
||||
|
||||
{ E_TYPE::ET_PSPEXEC, "PSPEXEC" },
|
||||
|
||||
{ E_TYPE::ET_LIEF, "LIEF" },
|
||||
{ E_TYPE::ET_LIEF_CORE, "LIEF_CORE" },
|
||||
{ E_TYPE::ET_LIEF_EXEC, "LIEF_EXEC" },
|
||||
{ E_TYPE::ET_LIEF_DYN, "LIEF_DYN" },
|
||||
|
||||
{ E_TYPE::ET_HIOS, "HIOS" },
|
||||
{ E_TYPE::ET_LOPROC, "LOPROC" },
|
||||
{ E_TYPE::ET_HIPROC, "HIPROC" }
|
||||
};
|
||||
auto it = enumStrings.find(e);
|
||||
return it == enumStrings.end() ? "UNDEFINED" : it->second;
|
||||
|
||||
Reference in New Issue
Block a user