Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support to parse POGO debug entries
  • Loading branch information
1orenz0 authored and romainthomas committed Dec 16, 2018
1 parent f2b93bf commit 3537440
Show file tree
Hide file tree
Showing 31 changed files with 778 additions and 25 deletions.
2 changes: 2 additions & 0 deletions api/python/PE/CMakeLists.txt
Expand Up @@ -34,6 +34,8 @@ set(LIEF_PYTHON_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDebug.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeView.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeViewPDB.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyPogo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyPogoEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySection.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyExport.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyImport.cpp"
Expand Down
9 changes: 9 additions & 0 deletions api/python/PE/objects/pyDebug.cpp
Expand Up @@ -87,6 +87,15 @@ void create<Debug>(py::module& m) {
" * " RST_CLASS_REF(lief.PE.CodeViewPDB) "\n",
py::return_value_policy::reference)

.def_property_readonly("has_pogo",
&Debug::has_pogo,
"Whether or not a pogo is present")

.def_property_readonly("pogo",
static_cast<Pogo& (Debug::*)(void)>(&Debug::pogo),
"Return an object which subclass " RST_CLASS_REF(lief.PE.Pogo) " representing the pogo entry \n",
py::return_value_policy::reference)

.def("__eq__", &Debug::operator==)
.def("__ne__", &Debug::operator!=)
.def("__hash__",
Expand Down
66 changes: 66 additions & 0 deletions api/python/PE/objects/pyPogo.cpp
@@ -0,0 +1,66 @@
/* 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/PE/hash.hpp"
#include "LIEF/PE/Pogo.hpp"

#include <string>
#include <sstream>

namespace LIEF {
namespace PE {

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

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

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

template<>
void create<Pogo>(py::module& m) {
py::class_<Pogo, LIEF::Object>(m, "Pogo")
.def(py::init<>())

.def_property_readonly("entries",
static_cast<no_const_getter<it_pogo_entries>>(&Pogo::entries),
py::return_value_policy::reference_internal)

.def_property_readonly("signature",
static_cast<getter_t<POGO_SIGNATURES>>(&Pogo::signature),
"Type of the pogo (" RST_CLASS_REF(lief.PE.POGO_SIGNATURES) ")")


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

.def("__str__", [] (const Pogo& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
}
}
}
70 changes: 70 additions & 0 deletions api/python/PE/objects/pyPogoEntry.cpp
@@ -0,0 +1,70 @@
/* 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/PE/hash.hpp"
#include "LIEF/PE/PogoEntry.hpp"

#include <string>
#include <sstream>

namespace LIEF {
namespace PE {

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

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


template<>
void create<PogoEntry>(py::module& m) {
py::class_<PogoEntry, LIEF::Object>(m, "PogoEntry")
.def(py::init<>())

.def_property("name",
[] (const PogoEntry& obj) {
return safe_string_converter(obj.name());
},
static_cast<setter_t<const std::string&>>(&PogoEntry::name))

.def_property("start_rva",
static_cast<getter_t<uint32_t>>(&PogoEntry::start_rva),
static_cast<setter_t<uint32_t>>(&PogoEntry::start_rva))

.def_property("size",
static_cast<getter_t<uint32_t>>(&PogoEntry::size),
static_cast<setter_t<uint32_t>>(&PogoEntry::size))


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

.def("__str__", [] (const PogoEntry& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
}
}
}
4 changes: 4 additions & 0 deletions api/python/PE/pyEnums.cpp
Expand Up @@ -911,6 +911,10 @@ void init_enums(py::module& m) {
.value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_PDB_20))
.value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_CV_50))
.value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_CV_41));

LIEF::enum_<LIEF::PE::POGO_SIGNATURES>(m, "POGO_SIGNATURES")
.value(PY_ENUM(LIEF::PE::POGO_SIGNATURES::POGO_UNKNOWN))
.value(PY_ENUM(LIEF::PE::POGO_SIGNATURES::POGO_LCTG));
}

}
Expand Down
2 changes: 2 additions & 0 deletions api/python/PE/pyPE.cpp
Expand Up @@ -57,6 +57,8 @@ void init_objects(py::module& m) {
CREATE(Debug, m);
CREATE(CodeView, m);
CREATE(CodeViewPDB, m);
CREATE(Pogo, m);
CREATE(PogoEntry, m);
CREATE(Import, m);
CREATE(ImportEntry, m);
CREATE(ResourcesManager, m);
Expand Down
2 changes: 2 additions & 0 deletions api/python/PE/pyPE.hpp
Expand Up @@ -62,6 +62,8 @@ SPECIALIZE_CREATE(Symbol);
SPECIALIZE_CREATE(Debug);
SPECIALIZE_CREATE(CodeView);
SPECIALIZE_CREATE(CodeViewPDB);
SPECIALIZE_CREATE(Pogo);
SPECIALIZE_CREATE(PogoEntry);
SPECIALIZE_CREATE(Import);
SPECIALIZE_CREATE(ImportEntry);
SPECIALIZE_CREATE(ResourceNode);
Expand Down
1 change: 1 addition & 0 deletions api/python/pyIterators.cpp
Expand Up @@ -54,6 +54,7 @@ void init_LIEF_iterators(py::module& m) {
init_ref_iterator<LIEF::PE::it_imports>(m);
init_ref_iterator<LIEF::PE::it_import_entries>(m);
init_ref_iterator<LIEF::PE::it_export_entries>(m);
init_ref_iterator<LIEF::PE::it_pogo_entries>(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);
Expand Down
18 changes: 18 additions & 0 deletions doc/sphinx/api/cpp/pe.rst
Expand Up @@ -337,6 +337,21 @@ Code Integrity

----------

Pogo
****

.. doxygenclass:: LIEF::PE::Pogo
:project: lief

----------

Pogo Entry
**************

.. doxygenclass:: LIEF::PE::PogoEntry
:project: lief

----------

Load Configuration
******************
Expand Down Expand Up @@ -504,3 +519,6 @@ Enums

.. doxygenenum:: LIEF::PE::GUARD_RF_FLAGS
:project: lief

.. doxygenenum:: LIEF::PE::POGO_SIGNATURES
:project: lief
31 changes: 31 additions & 0 deletions doc/sphinx/api/python/pe.rst
Expand Up @@ -414,6 +414,28 @@ Code Integrity
----------


Pogo
****

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

----------


Pogo Entry
**********

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

----------


Load Configuration
******************

Expand Down Expand Up @@ -800,3 +822,12 @@ CODE_VIEW_SIGNATURES
:members:
:inherited-members:
:undoc-members:


POGO_SIGNATURES
~~~~~~~~~~~~~~~

.. autoclass:: lief.PE.POGO_SIGNATURES
:members:
:inherited-members:
:undoc-members:
51 changes: 30 additions & 21 deletions examples/python/pe_reader.py
Expand Up @@ -264,29 +264,38 @@ def print_debug(binary):
format_hex = "{:<33} 0x{:<28x}"
format_dec = "{:<33} {:<30d}"

debug = binary.debug
print("== Debug ==")
print(format_hex.format("Characteristics:", debug.characteristics))
print(format_hex.format("Timestamp:", debug.timestamp))
print(format_dec.format("Major version:", debug.major_version))
print(format_dec.format("Minor version:", debug.minor_version))
print(format_str.format("type:", str(debug.type).split(".")[-1]))
print(format_hex.format("Size of data:", debug.sizeof_data))
print(format_hex.format("Address of raw data:", debug.addressof_rawdata))
print(format_hex.format("Pointer to raw data:", debug.pointerto_rawdata))

if debug.has_code_view:
code_view = debug.code_view
cv_signature = code_view.cv_signature

if cv_signature in (lief.PE.CODE_VIEW_SIGNATURES.PDB_70, lief.PE.CODE_VIEW_SIGNATURES.PDB_70):
sig_str = " ".join(map(lambda e : "{:02x}".format(e), code_view.signature))
print(format_str.format("Code View Signature:", str(cv_signature).split(".")[-1]))
debugs = binary.debug
print("== Debug ({}) ==".format(len(debugs)))
for debug in debugs:
print(format_hex.format("Characteristics:", debug.characteristics))
print(format_hex.format("Timestamp:", debug.timestamp))
print(format_dec.format("Major version:", debug.major_version))
print(format_dec.format("Minor version:", debug.minor_version))
print(format_str.format("type:", str(debug.type).split(".")[-1]))
print(format_hex.format("Size of data:", debug.sizeof_data))
print(format_hex.format("Address of raw data:", debug.addressof_rawdata))
print(format_hex.format("Pointer to raw data:", debug.pointerto_rawdata))

if debug.has_code_view:
code_view = debug.code_view
cv_signature = code_view.cv_signature

if cv_signature in (lief.PE.CODE_VIEW_SIGNATURES.PDB_70, lief.PE.CODE_VIEW_SIGNATURES.PDB_70):
sig_str = " ".join(map(lambda e : "{:02x}".format(e), code_view.signature))
print(format_str.format("Code View Signature:", str(cv_signature).split(".")[-1]))
print(format_str.format("Signature:", sig_str))
print(format_dec.format("Age:", code_view.age))
print(format_str.format("Filename:", code_view.filename))

if debug.has_pogo:
pogo = debug.pogo
sig_str = str(pogo.signature).split(".")[-1]
print(format_str.format("Signature:", sig_str))
print(format_dec.format("Age:", code_view.age))
print(format_str.format("Filename:", code_view.filename))
print("Entries:")
for entry in pogo.entries:
print(" {:<20} 0x{:x} ({:d})".format(entry.name, entry.start_rva, entry.size))

print("")
print("\n")


@exceptions_handler(Exception)
Expand Down
8 changes: 7 additions & 1 deletion include/LIEF/PE/Debug.hpp
Expand Up @@ -24,6 +24,7 @@

#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/CodeView.hpp"
#include "LIEF/PE/Pogo.hpp"

namespace LIEF {
namespace PE {
Expand Down Expand Up @@ -75,6 +76,11 @@ class LIEF_API Debug : public Object {
const CodeView& code_view(void) const;
CodeView& code_view(void);

bool has_pogo(void) const;

const Pogo& pogo(void) const;
Pogo& pogo(void);


void characteristics(uint32_t characteristics);
void timestamp(uint32_t timestamp);
Expand Down Expand Up @@ -105,7 +111,7 @@ class LIEF_API Debug : public Object {
uint32_t pointerto_rawdata_;

CodeView* code_view_;

Pogo* pogo_;


};
Expand Down
1 change: 1 addition & 0 deletions include/LIEF/PE/EnumToString.hpp
Expand Up @@ -44,6 +44,7 @@ LIEF_API const char* to_string(RELOCATIONS_ARM e);

LIEF_API const char* to_string(DEBUG_TYPES e);
LIEF_API const char* to_string(CODE_VIEW_SIGNATURES e);
LIEF_API const char* to_string(POGO_SIGNATURES e);

LIEF_API const char* to_string(RESOURCE_TYPES e);
LIEF_API const char* to_string(RESOURCE_LANGS e);
Expand Down
1 change: 1 addition & 0 deletions include/LIEF/PE/Parser.hpp
Expand Up @@ -86,6 +86,7 @@ class LIEF_API Parser : public LIEF::Parser {
void parse_export_table(void);
void parse_debug(void);
void parse_debug_code_view(Debug& debug_info);
void parse_debug_pogo(Debug& debug_info);

template<typename PE_T>
void parse_tls(void);
Expand Down

0 comments on commit 3537440

Please sign in to comment.