Skip to content

Commit

Permalink
Parse PE Rich Header (resolve #15)
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Jun 27, 2017
1 parent 8bf1eb9 commit 0893bd9
Show file tree
Hide file tree
Showing 28 changed files with 751 additions and 56 deletions.
2 changes: 2 additions & 0 deletions api/python/PE/CMakeLists.txt
Expand Up @@ -20,6 +20,8 @@ set(LIEF_PYTHON_PE_SRC

"${CMAKE_CURRENT_LIST_DIR}/objects/pyDataDirectory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDosHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRichHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRichEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBuilder.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyOptionalHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocationEntry.cpp"
Expand Down
9 changes: 9 additions & 0 deletions api/python/PE/objects/pyBinary.cpp
Expand Up @@ -93,6 +93,15 @@ void init_PE_Binary_class(py::module& m) {
"" RST_CLASS_REF(lief.PE.TLS) " object (if present)",
py::return_value_policy::reference)

.def_property("rich_header",
static_cast<RichHeader& (Binary::*)(void)>(&Binary::rich_header),
static_cast<void (Binary::*)(const RichHeader&)>(&Binary::rich_header),
"" RST_CLASS_REF(lief.PE.RichHeader) " object (if present)",
py::return_value_policy::reference)

.def_property_readonly("has_rich_header", &Binary::has_rich_header,
"``True`` if the current binary has a " RST_CLASS_REF(lief.PE.RichHeader) " object")

.def_property_readonly("has_debug", &Binary::has_debug,
"``True`` if the current binary has a " RST_CLASS_REF(lief.PE.Debug) " object")

Expand Down
67 changes: 67 additions & 0 deletions api/python/PE/objects/pyRichEntry.cpp
@@ -0,0 +1,67 @@
/* 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 "pyPE.hpp"

#include "LIEF/visitors/Hash.hpp"
#include "LIEF/PE/RichEntry.hpp"

#include <string>
#include <sstream>

template<class T>
using getter_t = T (RichEntry::*)(void) const;

template<class T>
using setter_t = void (RichEntry::*)(T);

void init_PE_RichEntry_class(py::module& m) {
py::class_<RichEntry>(m, "RichEntry")
.def(py::init<>())
.def(py::init<uint16_t, uint16_t, uint32_t>())

.def_property("id",
static_cast<getter_t<uint16_t>>(&RichEntry::id),
static_cast<setter_t<uint16_t>>(&RichEntry::id),
"Type of the entry")

.def_property("build_id",
static_cast<getter_t<uint16_t>>(&RichEntry::build_id),
static_cast<setter_t<uint16_t>>(&RichEntry::build_id),
"Builder number of the tool (if any)")

.def_property("count",
static_cast<getter_t<uint32_t>>(&RichEntry::count),
static_cast<setter_t<uint32_t>>(&RichEntry::count),
"*Occurrence* count")

.def("__eq__", &RichEntry::operator==)
.def("__ne__", &RichEntry::operator!=)
.def("__hash__",
[] (const RichEntry& entry) {
return LIEF::Hash::hash(entry);
})

.def("__str__", [] (const RichEntry& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});



}
76 changes: 76 additions & 0 deletions api/python/PE/objects/pyRichHeader.cpp
@@ -0,0 +1,76 @@
/* 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 "pyPE.hpp"

#include "LIEF/visitors/Hash.hpp"
#include "LIEF/PE/RichHeader.hpp"

#include <string>
#include <sstream>

template<class T>
using getter_t = T (RichHeader::*)(void) const;

template<class T>
using setter_t = void (RichHeader::*)(T);

template<class T>
using no_const_getter = T (RichHeader::*)(void);

void init_PE_RichHeader_class(py::module& m) {
py::class_<RichHeader>(m, "RichHeader")
.def(py::init<>())
.def_property("key",
static_cast<getter_t<uint32_t>>(&RichHeader::key),
static_cast<setter_t<uint32_t>>(&RichHeader::key),
"Key used to encode the header (xor operation)")

.def_property_readonly("entries",
static_cast<no_const_getter<it_rich_entries>>(&RichHeader::entries),
"Return binary's " RST_CLASS_REF(lief.PE.RichEntry) " within the header",
py::return_value_policy::reference)

.def("add_entry",
static_cast<void (RichHeader::*)(const RichEntry&)>(&RichHeader::add_entry),
"Add a new " RST_CLASS_REF(lief.PE.RichEntry) "",
"entry"_a)

.def("add_entry",
static_cast<void (RichHeader::*)(uint16_t, uint16_t, uint32_t)>(&RichHeader::add_entry),
"Add a new " RST_CLASS_REF(lief.PE.RichEntry) " given its "
":attr:`~lief.PE.RichEntry.id`, "
":attr:`~lief.PE.RichEntry.build_id`, "
":attr:`~lief.PE.RichEntry.count`",
"id"_a, "build_id"_a, "count"_a)

.def("__eq__", &RichHeader::operator==)
.def("__ne__", &RichHeader::operator!=)
.def("__hash__",
[] (const RichHeader& rich_header) {
return LIEF::Hash::hash(rich_header);
})

.def("__str__", [] (const RichHeader& rich_header)
{
std::ostringstream stream;
stream << rich_header;
std::string str = stream.str();
return str;
});



}
2 changes: 2 additions & 0 deletions api/python/PE/pyPE.cpp
Expand Up @@ -37,6 +37,8 @@ void init_PE_module(py::module& m) {
init_PE_DataDirectory_class(LIEF_PE_module);
init_PE_Header_class(LIEF_PE_module);
init_PE_DosHeader_class(LIEF_PE_module);
init_PE_RichHeader_class(LIEF_PE_module);
init_PE_RichEntry_class(LIEF_PE_module);
init_PE_OptionalHeader_class(LIEF_PE_module);
init_PE_Section_class(LIEF_PE_module);
init_PE_Import_class(LIEF_PE_module);
Expand Down
2 changes: 2 additions & 0 deletions api/python/PE/pyPE.hpp
Expand Up @@ -31,6 +31,8 @@ void init_PE_Binary_class(py::module&);
void init_PE_DataDirectory_class(py::module&);
void init_PE_Header_class(py::module&);
void init_PE_DosHeader_class(py::module&);
void init_PE_RichHeader_class(py::module&);
void init_PE_RichEntry_class(py::module&);
void init_PE_Section_class(py::module&);
void init_PE_OptionalHeader_class(py::module&);
void init_PE_Import_class(py::module&);
Expand Down
1 change: 1 addition & 0 deletions api/python/pyIterators.cpp
Expand Up @@ -53,6 +53,7 @@ void init_LIEF_iterators(py::module& m) {
init_ref_iterator<LIEF::PE::it_symbols>(m);
init_ref_iterator<LIEF::PE::it_const_crt>(m);
init_ref_iterator<LIEF::PE::it_childs>(m);
init_ref_iterator<LIEF::PE::it_rich_entries>(m);
#endif


Expand Down
2 changes: 2 additions & 0 deletions api/python/pyJson.cpp
Expand Up @@ -46,6 +46,8 @@ void init_json_functions(py::module& m) {
#if defined(LIEF_PE_MODULE)
m.def("to_json", &LIEF::to_json_str<LIEF::PE::Binary, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::DosHeader, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::RichHeader, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::RichEntry, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::Header, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::OptionalHeader, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::DataDirectory, LIEF::PE::JsonVisitor>);
Expand Down
15 changes: 15 additions & 0 deletions doc/sphinx/api/cpp/pe.rst
Expand Up @@ -288,6 +288,21 @@ Lang code item

----------

Rich Header
***********

.. doxygenclass:: LIEF::PE::RichHeader
:project: lief

----------

Rich Entry
**********

.. doxygenclass:: LIEF::PE::RichEntry
:project: lief

----------

Enums
*****
Expand Down
20 changes: 20 additions & 0 deletions doc/sphinx/api/python/pe.rst
Expand Up @@ -341,6 +341,26 @@ Lang code item

----------

Rich Header
***********

.. autoclass:: lief.PE.RichHeader
:members:
:inherited-members:
:undoc-members:

----------

Rich Entry
**********

.. autoclass:: lief.PE.RichEntry
:members:
:inherited-members:
:undoc-members:

----------

Enums
*****

Expand Down
4 changes: 4 additions & 0 deletions examples/cpp/pe_reader.cpp
Expand Up @@ -38,6 +38,10 @@ int main(int argc, char **argv) {
std::cout << "== Optional Header ==" << std::endl;
std::cout << binary->optional_header() << std::endl;

if (binary->has_rich_header()) {
std::cout << "== Rich Header ==" << std::endl;
std::cout << binary->rich_header() << std::endl;
}

std::cout << "== Data Directories ==" << std::endl;
for (const DataDirectory& directory : binary->data_directories()) {
Expand Down

0 comments on commit 0893bd9

Please sign in to comment.