4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-11 11:09:32 +00:00
This commit is contained in:
Romain Thomas 2021-02-24 07:00:17 +01:00
parent 980ed6b3fb
commit 9fb11539da
10 changed files with 42 additions and 15 deletions
api/python/PE/objects
doc/sphinx
include/LIEF
src
tests/pe

@ -105,6 +105,10 @@ void create<Section>(py::module& m) {
&Section::characteristics_list,
":attr:`~lief.PE.Section.characteristics` as a ``list``")
.def_property_readonly("fullname",
&Section::fullname,
"Return the **fullname** of the section including the trailing bytes")
.def("has_characteristic",
&Section::has_characteristic,
"``True`` if the a section has the given " RST_CLASS_REF(lief.PE.SECTION_CHARACTERISTICS) "",

@ -1,6 +1,13 @@
Changelog
=========
0.11.2 - February 24, 2021
--------------------------
:PE:
* Fix regression in the behavior of the PE section's name. One can now access the full
section's name (with trailing bytes) through :attr:`lief.PE.Section.fullname` (see: :issue:`551`)
.. _release-0111:
0.11.1 - February 22, 2021

@ -38,7 +38,7 @@ class LIEF_API Section : public Object {
Section(const Section&);
//! @brief section's name
virtual const std::string& name(void) const;
virtual std::string name(void) const;
//! @brief section's content
virtual std::vector<uint8_t> content(void) const;

@ -20,6 +20,7 @@
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include "LIEF/visibility.h"
#include "LIEF/iostream.hpp"
@ -103,6 +104,7 @@ class LIEF_API Builder {
template<typename T, typename HANDLER>
std::vector<std::string> optimize(const HANDLER& e,
std::function<std::string(const typename HANDLER::value_type)> getter,
std::unordered_map<std::string, size_t> *of_map_p=nullptr);
template<typename ELF_T>

@ -71,6 +71,11 @@ class LIEF_API Section : public LIEF::Section {
uint16_t numberof_line_numbers(void) const;
uint32_t characteristics(void) const;
//! Return the **fullname** of the section including the trailing bytes
inline const std::string& fullname() const {
return this->name_;
}
bool is_type(PE_SECTION_TYPES type) const;
const std::set<PE_SECTION_TYPES>& types(void) const;
bool has_characteristic(SECTION_CHARACTERISTICS c) const;

@ -48,8 +48,8 @@ Section::~Section(void) = default;
Section& Section::operator=(const Section&) = default;
Section::Section(const Section&) = default;
const std::string& Section::name(void) const {
return this->name_;
std::string Section::name(void) const {
return this->name_.c_str();
}

@ -164,6 +164,7 @@ void Builder::build(void) {
template<typename T, typename HANDLER>
std::vector<std::string> Builder::optimize(const HANDLER& container,
std::function<std::string(const typename HANDLER::value_type)> getter,
std::unordered_map<std::string, size_t> *of_map_p) {
std::set<std::string> string_table;
@ -173,12 +174,9 @@ std::vector<std::string> Builder::optimize(const HANDLER& container,
// reverse all symbol names and sort them so we can merge then in the linear time:
// aaa, aadd, aaaa, cca, ca -> aaaa, aaa, acc, ac ddaa
std::transform(
std::begin(container),
std::end(container),
std::inserter(
string_table,
std::end(string_table)),
std::mem_fn(static_cast<const std::string& (T::*)(void) const>(&T::name)));
std::begin(container), std::end(container),
std::inserter(string_table, std::end(string_table)),
getter);
for (auto &val: string_table) {
string_table_optimized.emplace_back(std::move(val));
@ -302,7 +300,8 @@ void Builder::build_sections(void) {
const Elf_Off section_headers_offset = header.section_headers_offset();
std::vector<std::string> shstrtab_opt =
this->optimize<Section, decltype(this->binary_->sections_)>(this->binary_->sections_);
this->optimize<Section, decltype(this->binary_->sections_)>(this->binary_->sections_,
[] (const Section* sec) { return sec->name(); });
// Build section's name
std::vector<uint8_t> section_names;
@ -528,7 +527,8 @@ void Builder::build_static_symbols(void) {
// Container which will hold symbols name (optimized)
std::vector<std::string> string_table_optimize =
this->optimize<Symbol, decltype(this->binary_->static_symbols_)>(this->binary_->static_symbols_,
&offset_name_map);
[] (const Symbol* sym) { return sym->name(); },
&offset_name_map);
// We can't start with a symbol name
string_table_raw.push_back(0);
@ -1131,6 +1131,7 @@ void Builder::build_dynamic_symbols(void) {
std::vector<std::string> string_table_optimized =
this->optimize<Symbol, decltype(this->binary_->dynamic_symbols_)>(this->binary_->dynamic_symbols_,
[] (const Symbol* sym) { return sym->name(); },
&offset_name_map);
for (const std::string& name : string_table_optimized) {

@ -1112,7 +1112,7 @@ std::vector<uint8_t> Binary::authentihash(ALGORITHMS algo) const {
for (const Section* sec : this->sections_) {
std::array<char, 8> name = {0};
const std::string& sec_name = sec->name();
const std::string& sec_name = sec->fullname();
uint32_t name_length = std::min<uint32_t>(sec_name.size() + 1, sizeof(name));
std::copy(sec_name.c_str(), sec_name.c_str() + name_length, std::begin(name));
ios

@ -540,10 +540,12 @@ Builder& Builder::operator<<(const Section& section) {
header.NumberOfRelocations = static_cast<uint16_t>(section.numberof_relocations());
header.NumberOfLineNumbers = static_cast<uint16_t>(section.numberof_line_numbers());
header.Characteristics = static_cast<uint32_t>(section.characteristics());
const char* name = section.name().c_str();
uint32_t name_length = std::min<uint32_t>(section.name().size(), sizeof(header.Name));
std::copy(name, name + name_length, std::begin(header.Name));
std::array<char, 8> name = {0};
const std::string& sec_name = section.fullname();
uint32_t name_length = std::min<uint32_t>(sec_name.size() + 1, sizeof(name));
std::copy(sec_name.c_str(), sec_name.c_str() + name_length, std::begin(header.Name));
this->ios_.write(reinterpret_cast<uint8_t*>(&header), sizeof(pe_section));
size_t pad_length = 0;

@ -129,6 +129,12 @@ class TestPe(TestCase):
self.assertEqual(pogo_entries[23].size, 820)
def test_sections(self):
path = get_sample("PE/PE32_x86_binary_PGO-LTCG.exe")
pe = lief.parse(path)
self.assertIsNotNone(pe.get_section(".text"))
self.assertEqual(pe.sections[0].name, ".text")
self.assertEqual(pe.sections[0].fullname.encode("utf8"), b".text\x00\x00\x00")
def tearDown(self):
# Delete it