4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-12 19:39:32 +00:00

Parse the PE Load Configuration structure

This commit is contained in:
Romain Thomas 2017-10-06 07:55:58 +02:00
parent e1d2681679
commit 0234e3b8bb
74 changed files with 4518 additions and 98 deletions
Acknowledgements
api/python
doc/sphinx/api
cpp
python
examples/python
include/LIEF
src
tests/pe

@ -13,5 +13,6 @@ LIEF makes use of the following open source projects:
- filesystem - https://github.com/wjakob/filesystem
- utf8-cpp - https://sourceforge.net/projects/utfcpp/
- llvm - http://llvm.org/ - For the formats enums and structures
- virtualbox - https://www.virtualbox.org/ - For the PE 'LoadConfiguration' structures
The logo is designed by Freepik

@ -1,5 +1,6 @@
set(LIEF_PYTHON_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyUtils.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/init_load_configurations.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyResourceNode.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyResourceData.cpp"
@ -20,6 +21,7 @@ set(LIEF_PYTHON_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/signature/pyContentInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/signature/pySignature.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeIntegrity.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDataDirectory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDosHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRichHeader.cpp"
@ -54,4 +56,7 @@ target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_PE_SRC}" "${LIEF_PYTHON_PE_HDR}")
include("${CMAKE_CURRENT_LIST_DIR}/objects/LoadConfigurations/CMakeLists.txt")

@ -0,0 +1,18 @@
set(LIEF_PYTHON_PE_LOAD_CONFIGURE_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfiguration.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV0.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV1.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV2.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV3.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV4.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV5.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV6.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyLoadConfigurationV7.cpp"
)
source_group("Source Files\\PE\\Load Configuration" FILES ${LIEF_PYTHON_PE_LOAD_CONFIGURE_SRC})
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_PE_LOAD_CONFIGURE_SRC}")

@ -0,0 +1,152 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfiguration::*)(void) const;
template<class T>
using setter_t = void (LoadConfiguration::*)(T);
void init_PE_LoadConfiguration_class(py::module& m) {
py::class_<LoadConfiguration>(m, "LoadConfiguration",
"Class modeling the default PE's ``LoadConfiguration``\n\n"
"It's the base class for any future version of the structure"
)
.def(py::init<>())
.def_property_readonly("version",
&LoadConfiguration::version,
"(SDK) Version of the structure. (" RST_CLASS_REF(lief.PE.WIN_VERSION) ")")
.def_property("characteristics",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::characteristics),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::characteristics),
"Characteristics of the structure.")
.def_property("timedatestamp",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::timedatestamp),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::timedatestamp),
"Date and time stamp value")
.def_property("major_version",
static_cast<getter_t<uint16_t>>(&LoadConfiguration::major_version),
static_cast<setter_t<uint16_t>>(&LoadConfiguration::major_version),
"Major Version")
.def_property("minor_version",
static_cast<getter_t<uint16_t>>(&LoadConfiguration::minor_version),
static_cast<setter_t<uint16_t>>(&LoadConfiguration::minor_version),
"Minor version")
.def_property("global_flags_clear",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::global_flags_clear),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::global_flags_clear),
"The global loader flags to clear for this process as the loader start the process.")
.def_property("global_flags_set",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::global_flags_set),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::global_flags_set),
"The global loader flags to set for this process as the loader starts the process.")
.def_property("critical_section_default_timeout",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::critical_section_default_timeout),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::critical_section_default_timeout),
"The default timeout value to use for is processs critical sections that are abandoned.")
.def_property("decommit_free_block_threshold",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::decommit_free_block_threshold),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::decommit_free_block_threshold),
"Memory that must be freed before it is returned to the system, in bytes.")
.def_property("decommit_total_free_threshold",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::decommit_total_free_threshold),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::decommit_total_free_threshold),
"Total amount of free memory, in bytes")
.def_property("lock_prefix_table",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::lock_prefix_table),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::lock_prefix_table),
"The **VA** of a list of addresses where the ``LOCK`` prefix "
"is used so that they can be replaced with ``NOP`` on single processor machines.")
.def_property("maximum_allocation_size",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::maximum_allocation_size),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::maximum_allocation_size),
"Maximum allocation size, in bytes.")
.def_property("virtual_memory_threshold",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::virtual_memory_threshold),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::virtual_memory_threshold),
"Maximum virtual memory size, in bytes.")
.def_property("process_affinity_mask",
static_cast<getter_t<uint64_t>>(&LoadConfiguration::process_affinity_mask),
static_cast<setter_t<uint64_t>>(&LoadConfiguration::process_affinity_mask),
"Setting this field to a non-zero value is equivalent to calling "
"``SetProcessAffinityMask`` with this value during process startup (.exe only)")
.def_property("process_heap_flags",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::process_heap_flags),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::process_heap_flags),
"Process heap flags that correspond to the first argument of the "
"``HeapCreate`` function. These flags apply to the process heap that is "
"created during process startup.")
.def_property("csd_version",
static_cast<getter_t<uint16_t>>(&LoadConfiguration::csd_version),
static_cast<setter_t<uint16_t>>(&LoadConfiguration::csd_version),
"The service pack version identifier.")
.def_property("reserved1",
static_cast<getter_t<uint16_t>>(&LoadConfiguration::reserved1),
static_cast<setter_t<uint16_t>>(&LoadConfiguration::reserved1),
"Must be zero.")
.def_property("editlist",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::editlist),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::editlist),
"Reserved for use by the system.")
.def_property("security_cookie",
static_cast<getter_t<uint32_t>>(&LoadConfiguration::security_cookie),
static_cast<setter_t<uint32_t>>(&LoadConfiguration::security_cookie),
"A pointer to a cookie that is used by Visual C++ or GS implementation.")
.def("__eq__", &LoadConfiguration::operator==)
.def("__ne__", &LoadConfiguration::operator!=)
.def("__hash__",
[] (const LoadConfiguration& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfiguration& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV0::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV0::*)(T);
void init_PE_LoadConfigurationV0_class(py::module& m) {
py::class_<LoadConfigurationV0, LoadConfiguration>(m, "LoadConfigurationV0",
"" RST_CLASS_REF(lief.PE.LoadConfiguration) " enhanced with SEH. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.SEH`")
.def(py::init<>())
.def_property("se_handler_table",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV0::se_handler_table),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV0::se_handler_table),
"The VA of the sorted table of RVAs of each valid, unique "
"SE handler in the image.")
.def_property("se_handler_count",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV0::se_handler_count),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV0::se_handler_count),
"The count of unique handlers in the table.")
.def("__eq__", &LoadConfigurationV0::operator==)
.def("__ne__", &LoadConfigurationV0::operator!=)
.def("__hash__",
[] (const LoadConfigurationV0& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV0& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,96 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV1::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV1::*)(T);
void init_PE_LoadConfigurationV1_class(py::module& m) {
py::class_<LoadConfigurationV1, LoadConfigurationV0>(m, "LoadConfigurationV1",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV0) " enhanced with *Control Flow Guard*. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN_8_1`"
)
.def(py::init<>())
.def_property("guard_cf_check_function_pointer",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_check_function_pointer),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_check_function_pointer),
"The VA where Control Flow Guard check-function pointer is stored.")
.def_property("guard_cf_dispatch_function_pointer",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_dispatch_function_pointer),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_dispatch_function_pointer),
"The VA where Control Flow Guard dispatch-function pointer is stored.")
.def_property("guard_cf_function_table",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_function_table),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_function_table),
"The VA of the sorted table of RVAs of each Control Flow Guard function in the image.")
.def_property("guard_cf_function_count",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_function_count),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV1::guard_cf_function_count),
"The count of unique RVAs in the :attr:`~lief.PE.LoadConfigurationV1.guard_cf_function_table`")
.def_property("guard_flags",
static_cast<getter_t<uint32_t>>(&LoadConfigurationV1::guard_flags),
static_cast<setter_t<uint32_t>>(&LoadConfigurationV1::guard_flags),
"Control Flow Guard related flags.")
.def("has",
static_cast<bool (LoadConfigurationV1::*)(GUARD_CF_FLAGS) const>(&LoadConfigurationV1::has),
"Check if the given " RST_CLASS_REF(lief.PE.GUARD_CF_FLAGS) " is present in "
":attr:`~lief.PE.LoadConfigurationV1.guard_flags`",
"flag"_a)
.def_property_readonly("guard_cf_flags_list",
&LoadConfigurationV1::guard_cf_flags_list,
"Return list of " RST_CLASS_REF(lief.PE.GUARD_CF_FLAGS) " present in "
":attr:`~lief.PE.LoadConfigurationV1.guard_flags`",
py::return_value_policy::reference_internal)
.def("__eq__", &LoadConfigurationV1::operator==)
.def("__ne__", &LoadConfigurationV1::operator!=)
.def("__hash__",
[] (const LoadConfigurationV1& config) {
return LIEF::Hash::hash(config);
})
.def("__contains__",
static_cast<bool (LoadConfigurationV1::*)(GUARD_CF_FLAGS) const>(&LoadConfigurationV1::has))
.def("__str__", [] (const LoadConfigurationV1& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,60 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV2::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV2::*)(T);
void init_PE_LoadConfigurationV2_class(py::module& m) {
py::class_<LoadConfigurationV2, LoadConfigurationV1>(m, "LoadConfigurationV2",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV1) " enhanced with *code integrity*. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN10_0_9879`")
.def(py::init<>())
.def_property_readonly("code_integrity",
static_cast<CodeIntegrity& (LoadConfigurationV2::*)(void)>(&LoadConfigurationV2::code_integrity),
"" RST_CLASS_REF(lief.PE.CodeIntegrity) " object",
py::return_value_policy::reference)
.def("__eq__", &LoadConfigurationV2::operator==)
.def("__ne__", &LoadConfigurationV2::operator!=)
.def("__hash__",
[] (const LoadConfigurationV2& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV2& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,75 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV3::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV3::*)(T);
void init_PE_LoadConfigurationV3_class(py::module& m) {
py::class_<LoadConfigurationV3, LoadConfigurationV2>(m, "LoadConfigurationV3",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV2) " with Control Flow Guard improved. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN10_0_14286`")
.def(py::init<>())
.def_property("guard_address_taken_iat_entry_table",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV3::guard_address_taken_iat_entry_table),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV3::guard_address_taken_iat_entry_table),
"VA of a table associated with CFG's *IAT* checks")
.def_property("guard_address_taken_iat_entry_count",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV3::guard_address_taken_iat_entry_count),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV3::guard_address_taken_iat_entry_count),
"Number of entries in the :attr:`~lief.PE.guard_address_taken_iat_entry_table`")
.def_property("guard_long_jump_target_table",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV3::guard_long_jump_target_table),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV3::guard_long_jump_target_table),
"VA of a table associated with CFG's *long jump*")
.def_property("guard_long_jump_target_count",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV3::guard_long_jump_target_count),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV3::guard_long_jump_target_count),
"Number of entries in the :attr:`~lief.PE.guard_address_taken_iat_entry_table`")
.def("__eq__", &LoadConfigurationV3::operator==)
.def("__ne__", &LoadConfigurationV3::operator!=)
.def("__hash__",
[] (const LoadConfigurationV3& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV3& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV4::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV4::*)(T);
void init_PE_LoadConfigurationV4_class(py::module& m) {
py::class_<LoadConfigurationV4, LoadConfigurationV3>(m, "LoadConfigurationV4",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV3) " enhanced with:\n\n"
"\t\t * Kind of dynamic relocations\n\n"
"\t\t * *Hybrid Metadata Pointer* \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN10_0_14383`")
.def(py::init<>())
.def_property("dynamic_value_reloc_table",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV4::dynamic_value_reloc_table),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV4::dynamic_value_reloc_table),
"VA of pointing to a ``IMAGE_DYNAMIC_RELOCATION_TABLE``")
.def_property("hybrid_metadata_pointer",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV4::hybrid_metadata_pointer),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV4::hybrid_metadata_pointer),
"")
.def("__eq__", &LoadConfigurationV4::operator==)
.def("__ne__", &LoadConfigurationV4::operator!=)
.def("__hash__",
[] (const LoadConfigurationV4& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV4& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,81 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV5::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV5::*)(T);
void init_PE_LoadConfigurationV5_class(py::module& m) {
py::class_<LoadConfigurationV5, LoadConfigurationV4>(m, "LoadConfigurationV5",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV4) " enhanced with Return Flow Guard. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN10_0_14901`")
.def(py::init<>())
.def_property("guard_rf_failure_routine",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV5::guard_rf_failure_routine),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV5::guard_rf_failure_routine),
"VA of the failure routine")
.def_property("guard_rf_failure_routine_function_pointer",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV5::guard_rf_failure_routine_function_pointer),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV5::guard_rf_failure_routine_function_pointer),
"VA of the failure routine ``fptr``")
.def_property("dynamic_value_reloctable_offset",
static_cast<getter_t<uint32_t>>(&LoadConfigurationV5::dynamic_value_reloctable_offset),
static_cast<setter_t<uint32_t>>(&LoadConfigurationV5::dynamic_value_reloctable_offset),
"Offset of dynamic relocation table relative to the relocation table")
.def_property("dynamic_value_reloctable_section",
static_cast<getter_t<uint16_t>>(&LoadConfigurationV5::dynamic_value_reloctable_section),
static_cast<setter_t<uint16_t>>(&LoadConfigurationV5::dynamic_value_reloctable_section),
"The section index of the dynamic value relocation table")
.def_property("reserved2",
static_cast<getter_t<uint16_t>>(&LoadConfigurationV5::reserved2),
static_cast<setter_t<uint16_t>>(&LoadConfigurationV5::reserved2),
"Must be zero")
.def("__eq__", &LoadConfigurationV5::operator==)
.def("__ne__", &LoadConfigurationV5::operator!=)
.def("__hash__",
[] (const LoadConfigurationV5& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV5& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -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/visitors/Hash.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV6::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV6::*)(T);
void init_PE_LoadConfigurationV6_class(py::module& m) {
py::class_<LoadConfigurationV6, LoadConfigurationV5>(m, "LoadConfigurationV6",
"" RST_CLASS_REF(lief.PE.LoadConfigurationV5) " enhanced with Hotpatch and improved RFG. \n\n"
"It is associated with the " RST_CLASS_REF(lief.PE.WIN_VERSION) ": "
":attr:`~lief.PE.WIN_VERSION.WIN10_0_15002`")
.def(py::init<>())
.def_property("guard_rf_verify_stackpointer_function_pointer",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV6::guard_rf_verify_stackpointer_function_pointer),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV6::guard_rf_verify_stackpointer_function_pointer),
"VA of the Function verifying the stack pointer")
.def_property("hotpatch_table_offset",
static_cast<getter_t<uint32_t>>(&LoadConfigurationV6::hotpatch_table_offset),
static_cast<setter_t<uint32_t>>(&LoadConfigurationV6::hotpatch_table_offset),
"Offset to the *hotpatch* table")
.def("__eq__", &LoadConfigurationV6::operator==)
.def("__ne__", &LoadConfigurationV6::operator!=)
.def("__hash__",
[] (const LoadConfigurationV6& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV6& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,62 @@
/* 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/LoadConfigurations.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (LoadConfigurationV7::*)(void) const;
template<class T>
using setter_t = void (LoadConfigurationV7::*)(T);
void init_PE_LoadConfigurationV7_class(py::module& m) {
py::class_<LoadConfigurationV7, LoadConfigurationV6>(m, "LoadConfigurationV7")
.def(py::init<>())
.def_property("reserved3",
static_cast<getter_t<uint32_t>>(&LoadConfigurationV7::reserved3),
static_cast<setter_t<uint32_t>>(&LoadConfigurationV7::reserved3),
"")
.def_property("addressof_unicode_string",
static_cast<getter_t<uint64_t>>(&LoadConfigurationV7::addressof_unicode_string),
static_cast<setter_t<uint64_t>>(&LoadConfigurationV7::addressof_unicode_string),
"")
.def("__eq__", &LoadConfigurationV7::operator==)
.def("__ne__", &LoadConfigurationV7::operator!=)
.def("__hash__",
[] (const LoadConfigurationV7& config) {
return LIEF::Hash::hash(config);
})
.def("__str__", [] (const LoadConfigurationV7& config)
{
std::ostringstream stream;
stream << config;
std::string str = stream.str();
return str;
});
}

@ -0,0 +1,27 @@
/* 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"
void init_PE_load_configurations(py::module& m) {
init_PE_LoadConfiguration_class(m);
init_PE_LoadConfigurationV0_class(m);
init_PE_LoadConfigurationV1_class(m);
init_PE_LoadConfigurationV2_class(m);
init_PE_LoadConfigurationV3_class(m);
init_PE_LoadConfigurationV4_class(m);
init_PE_LoadConfigurationV5_class(m);
init_PE_LoadConfigurationV6_class(m);
init_PE_LoadConfigurationV7_class(m);
}

@ -124,8 +124,8 @@ void init_PE_Binary_class(py::module& m) {
.def_property_readonly("has_relocations", &Binary::has_relocations,
"``True`` if the current binary use " RST_CLASS_REF(lief.PE.Relocation) "")
.def_property_readonly("has_configurations", &Binary::has_configuration,
"``True`` if the current binary has " RST_CLASS_REF(lief.PE.Configuration) "")
.def_property_readonly("has_configuration", &Binary::has_configuration,
"``True`` if the current binary has " RST_CLASS_REF(lief.PE.LoadConfiguration) "")
.def_property_readonly("has_signature", &Binary::has_signature,
"``True`` if the binary is signed (" RST_CLASS_REF(lief.PE.Signature) ")")
@ -145,6 +145,11 @@ void init_PE_Binary_class(py::module& m) {
"Return the " RST_CLASS_REF(lief.PE.Debug) " object",
py::return_value_policy::reference)
.def_property_readonly("load_configuration",
static_cast<LoadConfiguration& (Binary::*)(void)>(&Binary::load_configuration),
"Return the " RST_CLASS_REF(lief.PE.LoadConfiguration) " object",
py::return_value_policy::reference)
.def("get_export",
static_cast<Export& (Binary::*)(void)>(&Binary::get_export),
"Return a " RST_CLASS_REF(lief.PE.Export) " object",

@ -0,0 +1,72 @@
/* 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/CodeIntegrity.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (CodeIntegrity::*)(void) const;
template<class T>
using setter_t = void (CodeIntegrity::*)(T);
void init_PE_CodeIntegrity_class(py::module& m) {
py::class_<CodeIntegrity>(m, "CodeIntegrity")
.def(py::init<>())
.def_property("flags",
static_cast<getter_t<uint16_t>>(&CodeIntegrity::flags),
static_cast<setter_t<uint16_t>>(&CodeIntegrity::flags),
"Flags to indicate if CI information is available, etc.")
.def_property("catalog",
static_cast<getter_t<uint16_t>>(&CodeIntegrity::catalog),
static_cast<setter_t<uint16_t>>(&CodeIntegrity::catalog),
"``0xFFFF`` means not available")
.def_property("catalog_offset",
static_cast<getter_t<uint32_t>>(&CodeIntegrity::catalog_offset),
static_cast<setter_t<uint32_t>>(&CodeIntegrity::catalog_offset),
"")
.def_property("reserved",
static_cast<getter_t<uint32_t>>(&CodeIntegrity::reserved),
static_cast<setter_t<uint32_t>>(&CodeIntegrity::reserved),
"Additional bitmask to be defined later")
.def("__eq__", &CodeIntegrity::operator==)
.def("__ne__", &CodeIntegrity::operator!=)
.def("__hash__",
[] (const CodeIntegrity& code) {
return LIEF::Hash::hash(code);
})
.def("__str__", [] (const CodeIntegrity& code)
{
std::ostringstream stream;
stream << code;
std::string str = stream.str();
return str;
});
}

@ -54,6 +54,8 @@ void init_PE_module(py::module& m) {
init_PE_ExportEntry_class(LIEF_PE_module);
init_PE_Builder_class(LIEF_PE_module);
init_PE_Debug_class(LIEF_PE_module);
init_PE_CodeIntegrity_class(LIEF_PE_module);
init_PE_load_configurations(LIEF_PE_module);
init_PE_Signature_class(LIEF_PE_module);
init_PE_ContentInfo_class(LIEF_PE_module);

@ -48,6 +48,8 @@ void init_PE_Export_class(py::module&);
void init_PE_ExportEntry_class(py::module&);
void init_PE_Builder_class(py::module&);
void init_PE_Debug_class(py::module&);
void init_PE_CodeIntegrity_class(py::module&);
void init_PE_load_configurations(py::module&);
void init_PE_Signature_class(py::module&);
void init_PE_ContentInfo_class(py::module&);
@ -76,6 +78,18 @@ void init_PE_ResourcesManager_class(py::module&);
void init_PE_Structures_enum(py::module&);
// Load Configurations
void init_PE_LoadConfiguration_class(py::module&);
void init_PE_LoadConfigurationV0_class(py::module&);
void init_PE_LoadConfigurationV1_class(py::module&);
void init_PE_LoadConfigurationV2_class(py::module&);
void init_PE_LoadConfigurationV3_class(py::module&);
void init_PE_LoadConfigurationV4_class(py::module&);
void init_PE_LoadConfigurationV5_class(py::module&);
void init_PE_LoadConfigurationV6_class(py::module&);
void init_PE_LoadConfigurationV7_class(py::module&);
// Opaque containers
PYBIND11_MAKE_OPAQUE(std::vector<LangCodeItem>)
using dict_langcode_item = std::map<std::u16string, std::u16string>;

@ -759,4 +759,31 @@ void init_PE_Structures_enum(py::module& m) {
.value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_7))
.value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_8))
.export_values();
py::enum_<LIEF::PE::WIN_VERSION>(m, "WIN_VERSION")
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN_UNKNOWN))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN_SEH))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN8_1))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_9879))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_14286))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_14383))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_14901))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_15002))
.value(PY_ENUM(LIEF::PE::WIN_VERSION::WIN10_0_16237))
.export_values();
py::enum_<LIEF::PE::GUARD_CF_FLAGS>(m, "GUARD_CF_FLAGS")
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_INSTRUMENTED))
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_W_INSTRUMENTED))
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_FUNCTION_TABLE_PRESENT))
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_EXPORT_SUPPRESSION_INFO_PRESENT))
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_ENABLE_EXPORT_SUPPRESSION))
.value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_LONGJUMP_TABLE_PRESENT))
.export_values();
py::enum_<LIEF::PE::GUARD_RF_FLAGS>(m, "GUARD_RF_FLAGS")
.value(PY_ENUM(LIEF::PE::GUARD_RF_FLAGS::GRF_INSTRUMENTED))
.value(PY_ENUM(LIEF::PE::GUARD_RF_FLAGS::GRF_ENABLE))
.value(PY_ENUM(LIEF::PE::GUARD_RF_FLAGS::GRF_STRICT))
.export_values();
}

@ -79,6 +79,18 @@ void init_json_functions(py::module& m) {
m.def("to_json", &LIEF::to_json_str<LIEF::PE::SignerInfo, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::ContentInfo, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::AuthenticatedAttributes, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::AuthenticatedAttributes, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::CodeIntegrity, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfiguration, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV0, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV1, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV2, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV3, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV4, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV5, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV6, LIEF::PE::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::PE::LoadConfigurationV7, LIEF::PE::JsonVisitor>);
#endif
m.def("to_json", &LIEF::to_json_str<LIEF::Binary>);

@ -304,6 +304,72 @@ Rich Entry
----------
Code Integrity
**************
.. doxygenclass:: LIEF::PE::CodeIntegrity
:project: lief
----------
Load Configuration
******************
.. doxygenclass:: LIEF::PE::LoadConfiguration
:project: lief
Load Configuration V0
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV0
:project: lief
Load Configuration V1
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV1
:project: lief
Load Configuration V2
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV2
:project: lief
Load Configuration V3
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV3
:project: lief
Load Configuration V4
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV4
:project: lief
Load Configuration V5
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV5
:project: lief
Load Configuration V6
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV6
:project: lief
Load Configuration V7
~~~~~~~~~~~~~~~~~~~~~
.. doxygenclass:: LIEF::PE::LoadConfigurationV7
:project: lief
-------------------
Utilities
*********
@ -410,3 +476,12 @@ Enums
.. doxygenenum:: LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES
:project: lief
.. doxygenenum:: LIEF::PE::WIN_VERSION
:project: lief
.. doxygenenum:: LIEF::PE::GUARD_CF_FLAGS
:project: lief
.. doxygenenum:: LIEF::PE::GUARD_RF_FLAGS
:project: lief

@ -369,6 +369,91 @@ Debug
----------
Code Integrity
**************
.. autoclass:: lief.PE.CodeIntegrity
:members:
:inherited-members:
:undoc-members:
----------
Load Configuration
******************
.. autoclass:: lief.PE.LoadConfiguration
:members:
:inherited-members:
:undoc-members:
Load Configuration V0
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV0
:members:
:show-inheritance:
:undoc-members:
Load Configuration V1
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV1
:members:
:show-inheritance:
:undoc-members:
Load Configuration V2
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV2
:members:
:show-inheritance:
:undoc-members:
Load Configuration V3
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV3
:members:
:show-inheritance:
:undoc-members:
Load Configuration V4
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV4
:members:
:show-inheritance:
:undoc-members:
Load Configuration V5
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV4
:members:
:show-inheritance:
:undoc-members:
Load Configuration V6
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV6
:members:
:show-inheritance:
:undoc-members:
Load Configuration V7
~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: lief.PE.LoadConfigurationV7
:members:
:show-inheritance:
:undoc-members:
Utilities
*********
@ -638,3 +723,36 @@ FIXED_VERSION_FILE_SUB_TYPES
:members:
:inherited-members:
:undoc-members:
----------
WIN_VERSION
~~~~~~~~~~~
.. autoclass:: lief.PE.WIN_VERSION
:members:
:inherited-members:
:undoc-members:
----------
GUARD_CF_FLAGS
~~~~~~~~~~~~~~
.. autoclass:: lief.PE.GUARD_CF_FLAGS
:members:
:inherited-members:
:undoc-members:
----------
GUARD_RF_FLAGS
~~~~~~~~~~~~~~
.. autoclass:: lief.PE.GUARD_RF_FLAGS
:members:
:inherited-members:
:undoc-members:

@ -9,7 +9,7 @@ from lief import PE
from lief.PE import oid_to_string
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.GLOBAL)
Logger.set_level(lief.LOGGING_LEVEL.INFO)
from optparse import OptionParser
import sys
@ -342,7 +342,84 @@ def print_resources(binary):
print("")
@exceptions_handler(Exception)
def print_load_configuration(binary):
format_str = "{:<45} {:<30}"
format_hex = "{:<45} 0x{:<28x}"
format_dec = "{:<45} {:<30d}"
print("== Load Configuration ==")
config = binary.load_configuration
print(format_str.format("Version:", str(config.version).split(".")[-1]))
print(format_dec.format("Characteristics:", config.characteristics))
print(format_dec.format("Timedatestamp:", config.timedatestamp))
print(format_dec.format("Major version:", config.major_version))
print(format_dec.format("Minor version:", config.minor_version))
print(format_hex.format("Global flags clear:", config.global_flags_clear))
print(format_hex.format("Global flags set:", config.global_flags_set))
print(format_dec.format("Critical section default timeout:", config.critical_section_default_timeout))
print(format_hex.format("Decommit free block threshold:", config.decommit_free_block_threshold))
print(format_hex.format("Decommit total free threshold:", config.decommit_total_free_threshold))
print(format_hex.format("Lock prefix table:", config.lock_prefix_table))
print(format_hex.format("Maximum allocation size:", config.maximum_allocation_size))
print(format_hex.format("Virtual memory threshold:", config.virtual_memory_threshold))
print(format_hex.format("Process affinity mask:", config.process_affinity_mask))
print(format_hex.format("Process heap flags:", config.process_heap_flags))
print(format_hex.format("CSD Version:", config.csd_version))
print(format_hex.format("Reserved 1:", config.reserved1))
print(format_hex.format("Edit list:", config.editlist))
print(format_hex.format("Security cookie:", config.security_cookie))
if isinstance(config, lief.PE.LoadConfigurationV0):
print(format_hex.format("SE handler table:", config.se_handler_table))
print(format_dec.format("SE handler count:", config.se_handler_count))
if isinstance(config, lief.PE.LoadConfigurationV1):
flags_str = " - ".join(map(lambda e : str(e).split(".")[-1], config.guard_cf_flags_list))
print(format_hex.format("GCF check function pointer:", config.guard_cf_check_function_pointer))
print(format_hex.format("GCF dispatch function pointer:", config.guard_cf_dispatch_function_pointer))
print(format_hex.format("GCF function table :", config.guard_cf_function_table))
print(format_dec.format("GCF Function count :", config.guard_cf_function_count))
print("{:<45} {} (0x{:x})".format("Guard flags:", flags_str, config.guard_flags))
if isinstance(config, lief.PE.LoadConfigurationV2):
code_integrity = config.code_integrity
print("Code Integrity:")
print(format_dec.format(" " * 3 + "Flags:", code_integrity.flags))
print(format_dec.format(" " * 3 + "Catalog:", code_integrity.catalog))
print(format_hex.format(" " * 3 + "Catalog offset:", code_integrity.catalog_offset))
print(format_dec.format(" " * 3 + "Reserved:", code_integrity.reserved))
if isinstance(config, lief.PE.LoadConfigurationV3):
print(format_hex.format("Guard address taken iat entry table:", config.guard_address_taken_iat_entry_table))
print(format_hex.format("Guard address taken iat entry count:", config.guard_address_taken_iat_entry_count))
print(format_hex.format("Guard long jump target table:", config.guard_long_jump_target_table))
print(format_hex.format("Guard long jump target count:", config.guard_long_jump_target_count))
if isinstance(config, lief.PE.LoadConfigurationV4):
print(format_hex.format("Dynamic value relocation table:", config.dynamic_value_reloc_table))
print(format_hex.format("Hybrid metadata pointer:", config.hybrid_metadata_pointer))
if isinstance(config, lief.PE.LoadConfigurationV5):
print(format_hex.format("GRF failure routine:", config.guard_rf_failure_routine))
print(format_hex.format("GRF failure routine function pointer:", config.guard_rf_failure_routine_function_pointer))
print(format_hex.format("Dynamic value reloctable offset:", config.dynamic_value_reloctable_offset))
print(format_hex.format("Dynamic value reloctable section:", config.dynamic_value_reloctable_section))
if isinstance(config, lief.PE.LoadConfigurationV6):
print(format_hex.format("GRF verify stackpointer function pointer:", config.guard_rf_verify_stackpointer_function_pointer))
print(format_hex.format("Hotpatch table offset:", config.hotpatch_table_offset))
if isinstance(config, lief.PE.LoadConfigurationV7):
print(format_hex.format("Reserved 3:", config.reserved3))
print("")
def main():
optparser = OptionParser(
@ -407,6 +484,11 @@ def main():
help='Display exported functions/libraries')
optparser.add_option('--load-config',
action='store_true', dest='show_loadconfig',
help='Display load configuration')
options, args = optparser.parse_args()
@ -460,5 +542,8 @@ def main():
if (options.show_resources or options.show_all) and binary.has_resources:
print_resources(binary)
if (options.show_loadconfig or options.show_all) and binary.has_configuration:
print_load_configuration(binary)
if __name__ == "__main__":
main()

@ -35,6 +35,7 @@
#include "LIEF/PE/Debug.hpp"
#include "LIEF/PE/ResourcesManager.hpp"
#include "LIEF/PE/signature/Signature.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
#include "LIEF/Abstract/Binary.hpp"
@ -140,7 +141,7 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
//! @brief Check if the current binary has debugs
bool has_debug(void) const;
//! @brief Check if the current binary has configuration
//! @brief Check if the current binary has a load configuration
bool has_configuration(void) const;
//! @brief Return the Signature object if the bianry is signed
@ -235,6 +236,10 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
Debug& debug(void);
const Debug& debug(void) const;
//! @brief Retrun the LoadConfiguration object
const LoadConfiguration& load_configuration(void) const;
LoadConfiguration& load_configuration(void);
// =======
// Overlay
// =======
@ -415,6 +420,8 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
std::vector<uint8_t> overlay_;
std::vector<uint8_t> dos_stub_;
LoadConfiguration* load_configuration_;
std::map<std::string, std::map<std::string, uint64_t>> hooks_;
};

@ -0,0 +1,74 @@
/* 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.
*/
#ifndef LIEF_PE_CODE_INTEGRITY_H_
#define LIEF_PE_CODE_INTEGRITY_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/Visitable.hpp"
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
namespace LIEF {
namespace PE {
class DLL_PUBLIC CodeIntegrity : public Visitable {
public:
static constexpr size_t PRINT_WIDTH = 20;
CodeIntegrity(void);
CodeIntegrity(const pe_code_integrity *header);
virtual ~CodeIntegrity(void);
CodeIntegrity& operator=(const CodeIntegrity&);
CodeIntegrity(const CodeIntegrity&);
//! @brief Flags to indicate if CI information is available, etc.
uint16_t flags(void) const;
//! @brief 0xFFFF means not available
uint16_t catalog(void) const;
uint32_t catalog_offset(void) const;
//! @brief Additional bitmask to be defined later
uint32_t reserved(void) const;
void flags(uint16_t flags);
void catalog(uint16_t catalog);
void catalog_offset(uint32_t catalog_offset);
void reserved(uint32_t reserved);
virtual void accept(Visitor& visitor) const override;
bool operator==(const CodeIntegrity& rhs) const;
bool operator!=(const CodeIntegrity& rhs) const;
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const CodeIntegrity& entry);
private:
uint16_t flags_;
uint16_t catalog_;
uint32_t catalog_offset_;
uint32_t reserved_;
};
}
}
#endif

@ -58,6 +58,11 @@ DLL_PUBLIC const char* to_string(FIXED_VERSION_FILE_FLAGS e);
DLL_PUBLIC const char* to_string(FIXED_VERSION_FILE_TYPES e);
DLL_PUBLIC const char* to_string(FIXED_VERSION_FILE_SUB_TYPES e);
DLL_PUBLIC const char* to_string(WIN_VERSION e);
DLL_PUBLIC const char* to_string(GUARD_CF_FLAGS e);
DLL_PUBLIC const char* to_string(GUARD_RF_FLAGS e);
} // namespace PE
} // namespace LIEF
#endif

@ -0,0 +1,29 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATIONS_H_
#define LIEF_PE_LOAD_CONFIGURATIONS_H_
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV7.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV6.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV5.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV4.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV3.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV2.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV1.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV0.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfiguration.hpp"
#endif

@ -0,0 +1,187 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_H_
#define LIEF_PE_LOAD_CONFIGURATION_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/Visitable.hpp"
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
namespace LIEF {
namespace PE {
//! @brief Class modeling the default PE's ``LoadConfiguration``
//!
//! It's the base class for any future version of the structure
class DLL_PUBLIC LoadConfiguration : public Visitable {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN_UNKNOWN;
static constexpr size_t PRINT_WIDTH = 45;
LoadConfiguration(void);
template<class T>
LoadConfiguration(const load_configuration<T>* header);
LoadConfiguration& operator=(const LoadConfiguration&);
LoadConfiguration(const LoadConfiguration&);
//! @brief (SDK) Version of the structure
virtual WIN_VERSION version(void) const;
//! @brief Characteristics of the structure
//! It usually holds its size
//!
//! @see @link version LoadConfiguration::version@endlink
uint32_t characteristics(void) const;
//! @brief Date and time stamp value
uint32_t timedatestamp(void) const;
//! @brief Major Version
uint16_t major_version(void) const;
//! @brief Minor version
uint16_t minor_version(void) const;
//! @brief The global loader flags to clear for
//! this process as the loader start the process.
uint32_t global_flags_clear(void) const;
//! @brief The global loader flags to set for
//! this process as the loader starts the process.
uint32_t global_flags_set(void) const;
//! @brief The default timeout value to use for
//! this processs critical sections that are abandoned.
uint32_t critical_section_default_timeout(void) const;
//! @brief Memory that must be freed before
//! it is returned to the system, in bytes.
uint64_t decommit_free_block_threshold(void) const;
//! @brief Total amount of free memory, in
//! bytes.
uint64_t decommit_total_free_threshold(void) const;
//! @brief The VA of a list of
//! addresses where the LOCK prefix
//! is used so that they can be replaced with NOP on single
//! processor machines.
//!
//! @warning For ``x86`` only
uint64_t lock_prefix_table(void) const;
//! @brief Maximum allocation size, in bytes.
uint64_t maximum_allocation_size(void) const;
//! @brief Maximum virtual memory size, in bytes.
uint64_t virtual_memory_threshold(void) const;
//! @brief Setting this field to a non-zero value is equivalent to calling
//! ``SetProcessAffinityMask`` with this value during process startup (.exe only)
uint64_t process_affinity_mask(void) const;
//! @brief Process heap flags that correspond to the first argument of the
//! ``HeapCreate`` function. These flags apply to the process heap that is
//! created during process startup.
uint32_t process_heap_flags(void) const;
//! @brief The service pack version identifier.
uint16_t csd_version(void) const;
//! @brief Must be zero.
uint16_t reserved1(void) const;
//! @brief Reserved for use by the system.
uint32_t editlist(void) const;
//! @brief A pointer to a cookie that is used by Visual C++ or GS
//! implementation.
uint32_t security_cookie(void) const;
void characteristics(uint32_t characteristics);
void timedatestamp(uint32_t timedatestamp);
void major_version(uint16_t major_version);
void minor_version(uint16_t minor_version);
void global_flags_clear(uint32_t global_flags_clear);
void global_flags_set(uint32_t global_flags_set);
void critical_section_default_timeout(uint32_t critical_section_default_timeout);
void decommit_free_block_threshold(uint64_t decommit_free_block_threshold);
void decommit_total_free_threshold(uint64_t decommit_total_free_threshold);
void lock_prefix_table(uint64_t lock_prefix_table);
void maximum_allocation_size(uint64_t maximum_allocation_size);
void virtual_memory_threshold(uint64_t virtual_memory_threshold);
void process_affinity_mask(uint64_t process_affinity_mask);
void process_heap_flags(uint32_t process_heap_flagsid);
void csd_version(uint16_t csd_version);
void reserved1(uint16_t reserved1);
void editlist(uint32_t editlist);
void security_cookie(uint32_t security_cookie);
virtual ~LoadConfiguration(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfiguration& rhs) const;
bool operator!=(const LoadConfiguration& rhs) const;
virtual std::ostream& print(std::ostream& os) const;
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const LoadConfiguration& config);
protected:
uint32_t characteristics_;
uint32_t timedatestamp_;
uint16_t major_version_;
uint16_t minor_version_;
uint32_t global_flags_clear_;
uint32_t global_flags_set_;
uint32_t critical_section_default_timeout_;
uint64_t decommit_free_block_threshold_;
uint64_t decommit_total_free_threshold_;
uint64_t lock_prefix_table_;
uint64_t maximum_allocation_size_;
uint64_t virtual_memory_threshold_;
uint64_t process_affinity_mask_;
uint32_t process_heap_flags_;
uint16_t csd_version_;
uint16_t reserved1_;
uint64_t editlist_;
uint64_t security_cookie_;
};
}
}
#endif

@ -0,0 +1,73 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V0_H_
#define LIEF_PE_LOAD_CONFIGURATION_V0_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfiguration.hpp"
namespace LIEF {
namespace PE {
//! @brief LoadConfiguration enhanced with SEH
class DLL_PUBLIC LoadConfigurationV0 : public LoadConfiguration {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN_SEH;
LoadConfigurationV0(void);
LoadConfigurationV0& operator=(const LoadConfigurationV0&);
LoadConfigurationV0(const LoadConfigurationV0&);
template<class T>
DLL_LOCAL LoadConfigurationV0(const load_configuration_v0<T>* header);
virtual WIN_VERSION version(void) const override;
//! @brief The VA of the sorted table of RVAs of each valid, unique
//! SE handler in the image.
uint64_t se_handler_table(void) const;
//! @brief The count of unique handlers in the table.
uint64_t se_handler_count(void) const;
void se_handler_table(uint64_t se_handler_table);
void se_handler_count(uint64_t se_handler_count);
virtual ~LoadConfigurationV0(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV0& rhs) const;
bool operator!=(const LoadConfigurationV0& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t se_handler_table_;
uint64_t se_handler_count_;
};
}
}
#endif

@ -0,0 +1,98 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V1_H_
#define LIEF_PE_LOAD_CONFIGURATION_V1_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/type_traits.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV0.hpp"
namespace LIEF {
namespace PE {
//! @brief LoadConfiguration enhanced with Control Flow Guard
//!
//! This structure is available from Windows 8.1
class DLL_PUBLIC LoadConfigurationV1 : public LoadConfigurationV0 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN8_1;
LoadConfigurationV1(void);
template<class T>
DLL_LOCAL LoadConfigurationV1(const load_configuration_v1<T>* header);
LoadConfigurationV1& operator=(const LoadConfigurationV1&);
LoadConfigurationV1(const LoadConfigurationV1&);
virtual WIN_VERSION version(void) const override;
//! @brief The VA where Control Flow Guard check-function pointer is stored.
uint64_t guard_cf_check_function_pointer(void) const;
//! @brief The VA where Control Flow Guard dispatch-function pointer is stored.
uint64_t guard_cf_dispatch_function_pointer(void) const;
//! @brief The VA of the sorted table of RVAs of each Control Flow Guard
//! function in the image.
uint64_t guard_cf_function_table(void) const;
//! @brief The count of unique RVAs in the
//! LoadConfigurationV1::guard_cf_function_table.
uint64_t guard_cf_function_count(void) const;
//! @brief Control Flow Guard related flags.
uint32_t guard_flags(void) const;
//! @brief Check if the given flag is present in LoadConfigurationV1::guard_flags
bool has(GUARD_CF_FLAGS flag) const;
//! @brief LoadConfigurationV1::guard_flags as a list of LIEF::PE::GUARD_CF_FLAGS
guard_cf_flags_list_t guard_cf_flags_list(void) const;
void guard_cf_check_function_pointer(uint64_t guard_cf_check_function_pointer);
void guard_cf_dispatch_function_pointer(uint64_t guard_cf_dispatch_function_pointer);
void guard_cf_function_table(uint64_t guard_cf_function_table);
void guard_cf_function_count(uint64_t guard_cf_function_count);
void guard_flags(uint32_t guard_flags);
virtual ~LoadConfigurationV1(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV1& rhs) const;
bool operator!=(const LoadConfigurationV1& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t guard_cf_check_function_pointer_;
uint64_t guard_cf_dispatch_function_pointer_;
uint64_t guard_cf_function_table_;
uint64_t guard_cf_function_count_;
uint32_t guard_flags_;
};
}
}
#endif

@ -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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V2_H_
#define LIEF_PE_LOAD_CONFIGURATION_V2_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/CodeIntegrity.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV1.hpp"
namespace LIEF {
namespace PE {
//! @brief LoadConfiguration enhanced with code integrity
class DLL_PUBLIC LoadConfigurationV2 : public LoadConfigurationV1 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_9879;
LoadConfigurationV2(void);
LoadConfigurationV2& operator=(const LoadConfigurationV2&);
LoadConfigurationV2(const LoadConfigurationV2&);
template<class T>
DLL_LOCAL LoadConfigurationV2(const load_configuration_v2<T>* header);
virtual WIN_VERSION version(void) const override;
//! @brief CodeIntegrity associated with
const CodeIntegrity& code_integrity(void) const;
CodeIntegrity& code_integrity(void);
virtual ~LoadConfigurationV2(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV2& rhs) const;
bool operator!=(const LoadConfigurationV2& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
CodeIntegrity code_integrity_;
};
}
}
#endif

@ -0,0 +1,83 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V3_H_
#define LIEF_PE_LOAD_CONFIGURATION_V3_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV2.hpp"
namespace LIEF {
namespace PE {
//! @brief LoadConfiguration with Control Flow Guard improved
class DLL_PUBLIC LoadConfigurationV3 : public LoadConfigurationV2 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_14286;
LoadConfigurationV3(void);
template<class T>
DLL_LOCAL LoadConfigurationV3(const load_configuration_v3<T>* header);
LoadConfigurationV3& operator=(const LoadConfigurationV3&);
LoadConfigurationV3(const LoadConfigurationV3&);
virtual WIN_VERSION version(void) const override;
//! @brief VA of a table associated with CFG's *IAT* checks
uint64_t guard_address_taken_iat_entry_table(void) const;
//! @brief Number of entries in the LoadConfigurationV3::guard_address_taken_iat_entry_table
uint64_t guard_address_taken_iat_entry_count(void) const;
//! @brief VA of a table associated with CFG's *long jump*
uint64_t guard_long_jump_target_table(void) const;
//! @brief Number of entries in the LoadConfigurationV3::guard_long_jump_target_table
uint64_t guard_long_jump_target_count(void) const;
void guard_address_taken_iat_entry_table(uint64_t value);
void guard_address_taken_iat_entry_count(uint64_t value);
void guard_long_jump_target_table(uint64_t value);
void guard_long_jump_target_count(uint64_t value);
virtual ~LoadConfigurationV3(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV3& rhs) const;
bool operator!=(const LoadConfigurationV3& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t guard_address_taken_iat_entry_table_;
uint64_t guard_address_taken_iat_entry_count_;
uint64_t guard_long_jump_target_table_;
uint64_t guard_long_jump_target_count_;
};
}
}
#endif

@ -0,0 +1,73 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V4_H_
#define LIEF_PE_LOAD_CONFIGURATION_V4_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV3.hpp"
namespace LIEF {
namespace PE {
//! @brief Load Configuration enhanced with
//! * Kind of dynamic relocations
//! * *Hybrid Metadata Pointer*
class DLL_PUBLIC LoadConfigurationV4 : public LoadConfigurationV3 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_14383;
LoadConfigurationV4(void);
template<class T>
DLL_LOCAL LoadConfigurationV4(const load_configuration_v4<T>* header);
LoadConfigurationV4& operator=(const LoadConfigurationV4&);
LoadConfigurationV4(const LoadConfigurationV4&);
virtual WIN_VERSION version(void) const override;
//! @brief VA of pointing to a ``IMAGE_DYNAMIC_RELOCATION_TABLE``
uint64_t dynamic_value_reloc_table(void) const;
uint64_t hybrid_metadata_pointer(void) const;
void dynamic_value_reloc_table(uint64_t value);
void hybrid_metadata_pointer(uint64_t value);
virtual ~LoadConfigurationV4(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV4& rhs) const;
bool operator!=(const LoadConfigurationV4& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t dynamic_value_reloc_table_;
uint64_t hybrid_metadata_pointer_;
};
}
}
#endif

@ -0,0 +1,86 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V5_H_
#define LIEF_PE_LOAD_CONFIGURATION_V5_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV4.hpp"
namespace LIEF {
namespace PE {
//! @brief Load Configuration enhanced with Return Flow Guard
class DLL_PUBLIC LoadConfigurationV5 : public LoadConfigurationV4 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_14901;
LoadConfigurationV5(void);
template<class T>
DLL_LOCAL LoadConfigurationV5(const load_configuration_v5<T>* header);
LoadConfigurationV5& operator=(const LoadConfigurationV5&);
LoadConfigurationV5(const LoadConfigurationV5&);
virtual WIN_VERSION version(void) const override;
//! @brief VA of the failure routine
uint64_t guard_rf_failure_routine(void) const;
//! @brief VA of the failure routine ``fptr``.
uint64_t guard_rf_failure_routine_function_pointer(void) const;
//! @brief Offset of dynamic relocation table relative to the relocation table
uint32_t dynamic_value_reloctable_offset(void) const;
//! The section index of the dynamic value relocation table
uint16_t dynamic_value_reloctable_section(void) const;
//! @brief Must be zero
uint16_t reserved2(void) const;
void guard_rf_failure_routine(uint64_t value);
void guard_rf_failure_routine_function_pointer(uint64_t value);
void dynamic_value_reloctable_offset(uint32_t value);
void dynamic_value_reloctable_section(uint16_t value);
void reserved2(uint16_t value);
virtual ~LoadConfigurationV5(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV5& rhs) const;
bool operator!=(const LoadConfigurationV5& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t guard_rf_failure_routine_;
uint64_t guard_rf_failure_routine_function_pointer_;
uint32_t dynamic_value_reloctable_offset_;
uint16_t dynamic_value_reloctable_section_;
uint16_t reserved2_;
};
}
}
#endif

@ -0,0 +1,72 @@
/* 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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V6_H_
#define LIEF_PE_LOAD_CONFIGURATION_V6_H_
#include <array>
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV5.hpp"
namespace LIEF {
namespace PE {
//! @brief Load Configuration enhanced with Hotpatch and improved RFG
class DLL_PUBLIC LoadConfigurationV6 : public LoadConfigurationV5 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_15002;
LoadConfigurationV6(void);
template<class T>
DLL_LOCAL LoadConfigurationV6(const load_configuration_v6<T>* header);
LoadConfigurationV6& operator=(const LoadConfigurationV6&);
LoadConfigurationV6(const LoadConfigurationV6&);
virtual WIN_VERSION version(void) const override;
//! @brief VA of the Function verifying the stack pointer
uint64_t guard_rf_verify_stackpointer_function_pointer(void) const;
//! @brief Offset to the *hotpatch* table
uint32_t hotpatch_table_offset(void) const;
void guard_rf_verify_stackpointer_function_pointer(uint64_t value);
void hotpatch_table_offset(uint32_t value);
virtual ~LoadConfigurationV6(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV6& rhs) const;
bool operator!=(const LoadConfigurationV6& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint64_t guardrf_verify_stackpointer_function_pointer_;
uint32_t hotpatch_table_offset_;
};
}
}
#endif

@ -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.
*/
#ifndef LIEF_PE_LOAD_CONFIGURATION_V7_H_
#define LIEF_PE_LOAD_CONFIGURATION_V7_H_
#include <array>
#include <functional>
#include <algorithm>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/PE/Structures.hpp"
#include "LIEF/PE/LoadConfigurations/LoadConfigurationV6.hpp"
namespace LIEF {
namespace PE {
class DLL_PUBLIC LoadConfigurationV7 : public LoadConfigurationV6 {
public:
static constexpr WIN_VERSION VERSION = WIN_VERSION::WIN10_0_16237;
LoadConfigurationV7(void);
template<class T>
DLL_LOCAL LoadConfigurationV7(const load_configuration_v7<T>* header);
LoadConfigurationV7& operator=(const LoadConfigurationV7&);
LoadConfigurationV7(const LoadConfigurationV7&);
virtual WIN_VERSION version(void) const override;
uint32_t reserved3(void) const;
uint64_t addressof_unicode_string(void) const;
void reserved3(uint32_t value);
void addressof_unicode_string(uint64_t value);
virtual ~LoadConfigurationV7(void);
virtual void accept(Visitor& visitor) const override;
bool operator==(const LoadConfigurationV7& rhs) const;
bool operator!=(const LoadConfigurationV7& rhs) const;
virtual std::ostream& print(std::ostream& os) const override;
protected:
uint32_t reserved3_;
uint64_t addressof_unicode_string_;
};
}
}
#endif

@ -67,38 +67,41 @@ class DLL_PUBLIC Parser : public LIEF::Parser {
void init(const std::string& name = "");
template<typename PE_T>
void build(void);
void parse(void);
void build_exports(void);
void build_sections(void);
void parse_exports(void);
void parse_sections(void);
template<typename PE_T>
void build_headers(void);
void parse_headers(void);
void build_configuration(void);
void parse_configuration(void);
template<typename PE_T>
void build_data_directories(void);
void parse_data_directories(void);
template<typename PE_T>
void build_import_table(void);
void parse_import_table(void);
void build_export_table(void);
void build_debug(void);
void parse_export_table(void);
void parse_debug(void);
template<typename PE_T>
void build_tls(void);
void parse_tls(void);
void build_relocations(void);
void build_resources(void);
void build_string_table(void);
void build_symbols(void);
void build_signature(void);
void build_overlay(void);
void build_dos_stub(void);
void build_rich_header(void);
template<typename PE_T>
void parse_load_config(void);
ResourceNode* build_resource_node(
void parse_relocations(void);
void parse_resources(void);
void parse_string_table(void);
void parse_symbols(void);
void parse_signature(void);
void parse_overlay(void);
void parse_dos_stub(void);
void parse_rich_header(void);
ResourceNode* parse_resource_node(
const pe_resource_directory_table *directory_table,
uint32_t base_offset, uint32_t current_offset, uint32_t depth = 0);

@ -1,6 +1,7 @@
#ifndef LIEF_PE_STRUCTURES_H_
#define LIEF_PE_STRUCTURES_H_
#include <type_traits>
#include <map>
#include "LIEF/types.hpp"
@ -66,7 +67,8 @@ enum class PE_SECTION_TYPES : uint8_t {
RELOCATION = 6,
EXPORT = 7,
DEBUG = 8,
UNKNOWN = 9
LOAD_CONFIG = 9,
UNKNOWN = 10
};
@ -196,9 +198,9 @@ static const DIALOG_BOX_STYLES dialog_box_styles_array[] = {
DS_SHELLFONT,
};
// From Virtualbox - include/iprt/formats/pecoff.h
template <typename T>
struct LoadConfiguration {
struct load_configuration {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
@ -206,28 +208,115 @@ template <typename T>
uint32_t GlobalFlagsClear;
uint32_t GlobalFlagsSet;
uint32_t CriticalSectionDefaultTimeout;
T DeCommitFreeBlockThreshold;
T DeCommitTotalFreeThreshold;
T LockPrefixTable;
T MaximumAllocationSize;
T VirtualMemoryThreshold;
T ProcessAffinityMask;
T DeCommitFreeBlockThreshold;
T DeCommitTotalFreeThreshold;
T LockPrefixTable;
T MaximumAllocationSize;
T VirtualMemoryThreshold;
T ProcessAffinityMask;
uint32_t ProcessHeapFlags;
uint16_t CSDVersion;
uint16_t Reserved1;
T EditList;
T SecurityCookie;
T SEHandlerTable;
T SEHandlerCount;
T EditList;
T SecurityCookie;
};
template <typename T>
struct load_configuration_v0 : load_configuration<T> {
T SEHandlerTable;
T SEHandlerCount;
};
#pragma pack(4)
// Windows 10 - 9879
template <typename T>
struct load_configuration_v1 : load_configuration_v0<T> {
T GuardCFCheckFunctionPointer;
T GuardCFDispatchFunctionPointer;
T GuardCFFunctionTable;
T GuardCFFunctionCount;
uint32_t GuardFlags;
};
#pragma pack()
// Windows 10 - 9879
template <typename T>
struct load_configuration_v2 : load_configuration_v1<T> {
pe_code_integrity CodeIntegrity;
};
template <typename T>
struct load_configuration_v3 : load_configuration_v2<T> {
T GuardAddressTakenIatEntryTable;
T GuardAddressTakenIatEntryCount;
T GuardLongJumpTargetTable;
T GuardLongJumpTargetCount;
};
template <typename T>
struct load_configuration_v4 : load_configuration_v3<T> {
T DynamicValueRelocTable;
T HybridMetadataPointer;
};
template <typename T>
struct load_configuration_v5 : load_configuration_v4<T> {
T GuardRFFailureRoutine;
T GuardRFFailureRoutineFunctionPointer;
uint32_t DynamicValueRelocTableOffset;
uint16_t DynamicValueRelocTableSection;
uint16_t Reserved2;
};
#pragma pack(4)
template <typename T>
struct load_configuration_v6 : load_configuration_v5<T> {
T GuardRFVerifyStackPointerFunctionPointer;
uint32_t HotPatchTableOffset;
};
#pragma pack()
template <typename T>
struct load_configuration_v7 : load_configuration_v6<T> {
uint32_t Reserved3;
T AddressOfSomeUnicodeString;
};
class PE32 {
public:
using pe_optional_header = pe32_optional_header;
using pe_tls = pe32_tls;
using uint = uint32_t;
using load_configuration_t = load_configuration<uint32_t>;
using load_configuration_v0_t = load_configuration_v0<uint32_t>;
using load_configuration_v1_t = load_configuration_v1<uint32_t>;
using load_configuration_v2_t = load_configuration_v2<uint32_t>;
using load_configuration_v3_t = load_configuration_v3<uint32_t>;
using load_configuration_v4_t = load_configuration_v4<uint32_t>;
using load_configuration_v5_t = load_configuration_v5<uint32_t>;
using load_configuration_v6_t = load_configuration_v6<uint32_t>;
using load_configuration_v7_t = load_configuration_v7<uint32_t>;
static_assert(sizeof(load_configuration_t) == 0x40, "");
static_assert(sizeof(load_configuration_v0_t) == 0x48, "");
static_assert(sizeof(load_configuration_v1_t) == 0x5c, "");
static_assert(sizeof(load_configuration_v2_t) == 0x68, "");
static_assert(sizeof(load_configuration_v3_t) == 0x78, "");
static_assert(sizeof(load_configuration_v4_t) == 0x80, "");
static_assert(sizeof(load_configuration_v5_t) == 0x90, "");
static_assert(sizeof(load_configuration_v6_t) == 0x98, "");
//static_assert(sizeof(LoadConfiguration_V7) == 0xA0, "");
static const std::map<WIN_VERSION, size_t> load_configuration_sizes;
};
@ -236,7 +325,31 @@ class PE64 {
using pe_optional_header = pe64_optional_header;
using pe_tls = pe64_tls;
using uint = uint64_t;
};
using load_configuration_t = load_configuration<uint64_t>;
using load_configuration_v0_t = load_configuration_v0<uint64_t>;
using load_configuration_v1_t = load_configuration_v1<uint64_t>;
using load_configuration_v2_t = load_configuration_v2<uint64_t>;
using load_configuration_v3_t = load_configuration_v3<uint64_t>;
using load_configuration_v4_t = load_configuration_v4<uint64_t>;
using load_configuration_v5_t = load_configuration_v5<uint64_t>;
using load_configuration_v6_t = load_configuration_v6<uint64_t>;
using load_configuration_v7_t = load_configuration_v7<uint64_t>;
static_assert(sizeof(load_configuration_t) == 0x60, "");
static_assert(sizeof(load_configuration_v0_t) == 0x70, "");
static_assert(sizeof(load_configuration_v1_t) == 0x94, "");
static_assert(sizeof(load_configuration_v2_t) == 0xA0, "");
static_assert(sizeof(load_configuration_v3_t) == 0xC0, "");
static_assert(sizeof(load_configuration_v4_t) == 0xD0, "");
static_assert(sizeof(load_configuration_v5_t) == 0xE8, "");
static_assert(sizeof(load_configuration_v6_t) == 0xF4, "");
static_assert(sizeof(load_configuration_v7_t) == 0x100, "");
static const std::map<WIN_VERSION, size_t> load_configuration_sizes;
};
} // end namesapce ELF
}

@ -236,6 +236,16 @@ static const RESOURCE_SUBLANGS resource_sublangs_array[] = {
RESOURCE_SUBLANGS::SUBLANG_GAELIC_MANX,
};
static const GUARD_CF_FLAGS guard_cf_flags_array[] = {
GUARD_CF_FLAGS::GCF_INSTRUMENTED,
GUARD_CF_FLAGS::GCF_W_INSTRUMENTED,
GUARD_CF_FLAGS::GCF_FUNCTION_TABLE_PRESENT,
GUARD_CF_FLAGS::GCF_EXPORT_SUPPRESSION_INFO_PRESENT,
GUARD_CF_FLAGS::GCF_ENABLE_EXPORT_SUPPRESSION,
GUARD_CF_FLAGS::GCF_LONGJUMP_TABLE_PRESENT,
};
}
}
#endif

@ -847,3 +847,35 @@ enum CODE_PAGES {
CP_UTF_7 = 65000, /**< Unicode (UTF-7) */
CP_UTF_8 = 65001, /**< Unicode (UTF-8) */
};
enum WIN_VERSION {
WIN_UNKNOWN = 0,
WIN_SEH = 1,
WIN8_1 = 2,
WIN10_0_9879 = 3,
WIN10_0_14286 = 4,
WIN10_0_14383 = 5,
WIN10_0_14901 = 6,
WIN10_0_15002 = 7,
WIN10_0_16237 = 8,
};
enum GUARD_CF_FLAGS {
GCF_INSTRUMENTED = 0x00000100, /**< Module performs control flow integrity checks using system-supplied support */
GCF_W_INSTRUMENTED = 0x00000200, /**< Module performs control flow and write integrity checks */
GCF_FUNCTION_TABLE_PRESENT = 0x00000400, /**< Module contains valid control flow target metadata */
GCF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000, /**< Module contains suppressed export information. This also infers that the address taken taken IAT table is also present in the load config. */
GCF_ENABLE_EXPORT_SUPPRESSION = 0x00008000, /**< Module enables suppression of exports */
GCF_LONGJUMP_TABLE_PRESENT = 0x00010000, /**< Module contains longjmp target information */
};
enum GUARD_RF_FLAGS {
GRF_INSTRUMENTED = 0x00020000, /**< Module contains return flow instrumentation and metadata */
GRF_ENABLE = 0x00040000, /**< Module requests that the OS enable return flow protection */
GRF_STRICT = 0x00080000, /**< Module requests that the OS enable return flow protection in strict mode */
};

@ -441,6 +441,13 @@ struct pe_dialog_item_template {
uint16_t id;
};
struct pe_code_integrity {
uint16_t Flags;
uint16_t Catalog;
uint32_t CatalogOffset;
uint32_t Reserved;
};

@ -17,6 +17,7 @@
#define LIEF_PE_TYPE_TRAITS_H_
#include <vector>
#include "LIEF/iterators.hpp"
#include "LIEF/PE/enums.hpp"
namespace LIEF {
namespace PE {
@ -83,6 +84,12 @@ using rich_entries_t = std::vector<RichEntry>;
using it_rich_entries = ref_iterator<rich_entries_t&>;
using it_const_rich_entries = const_ref_iterator<const rich_entries_t&>;
template<class T>
using flags_list_t = std::set<T>;
using guard_cf_flags_list_t = flags_list_t<GUARD_CF_FLAGS>;
}
}

@ -110,6 +110,18 @@ class x509;
class SignerInfo;
class ContentInfo;
class AuthenticatedAttributes;
class CodeIntegrity;
class LoadConfiguration;
class LoadConfigurationV0;
class LoadConfigurationV1;
class LoadConfigurationV2;
class LoadConfigurationV3;
class LoadConfigurationV4;
class LoadConfigurationV5;
class LoadConfigurationV6;
class LoadConfigurationV7;
}
namespace MachO {
@ -373,6 +385,36 @@ class DLL_PUBLIC Visitor {
//! @brief Method to visit a LIEF::PE::issuer_t
virtual void visit(const PE::issuer_t& issuer);
//! @brief Method to visit a LIEF::PE::LoadConfiguration
virtual void visit(const PE::LoadConfiguration& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV0
virtual void visit(const PE::LoadConfigurationV0& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV1
virtual void visit(const PE::LoadConfigurationV1& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV2
virtual void visit(const PE::LoadConfigurationV2& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV3
virtual void visit(const PE::LoadConfigurationV3& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV4
virtual void visit(const PE::LoadConfigurationV4& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV5
virtual void visit(const PE::LoadConfigurationV5& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV6
virtual void visit(const PE::LoadConfigurationV6& config);
//! @brief Method to visit a LIEF::PE::LoadConfigurationV7
virtual void visit(const PE::LoadConfigurationV7& config);
//! @brief Method to visit a LIEF::PE::CodeIntegrity
virtual void visit(const PE::CodeIntegrity& code_integrity);
// MachO part
// ==========

@ -50,5 +50,26 @@ class vector_iostream {
pos_type current_pos_;
std::vector<uint8_t> raw_;
};
// From https://stackoverflow.com/questions/27336335/c-cout-with-prefix
class prefixbuf : public std::streambuf {
public:
prefixbuf(std::string const& prefix, std::streambuf* sbuf);
private:
std::string prefix;
std::streambuf* sbuf;
bool need_prefix;
int sync(void);
int overflow(int c);
};
class oprefixstream : private virtual prefixbuf, public std::ostream {
public:
oprefixstream(std::string const& prefix, std::ostream& out);
};
}
#endif

@ -66,6 +66,17 @@ class DLL_PUBLIC JsonVisitor : public LIEF::JsonVisitor {
virtual void visit(const SignerInfo& signerinfo) override;
virtual void visit(const ContentInfo& contentinfo) override;
virtual void visit(const AuthenticatedAttributes& auth) override;
virtual void visit(const CodeIntegrity& code_integrity) override;
virtual void visit(const LoadConfiguration& config) override;
virtual void visit(const LoadConfigurationV0& config) override;
virtual void visit(const LoadConfigurationV1& config) override;
virtual void visit(const LoadConfigurationV2& config) override;
virtual void visit(const LoadConfigurationV3& config) override;
virtual void visit(const LoadConfigurationV4& config) override;
virtual void visit(const LoadConfigurationV5& config) override;
virtual void visit(const LoadConfigurationV6& config) override;
virtual void visit(const LoadConfigurationV7& config) override;
virtual void visit(const LIEF::Binary& binary) override;

@ -100,7 +100,10 @@ Binary::Binary(void) :
resources_{nullptr},
imports_{},
export_{},
debug_{}
debug_{},
overlay_{},
dos_stub_{},
load_configuration_{nullptr}
{}
Binary::~Binary(void) {
@ -119,6 +122,10 @@ Binary::~Binary(void) {
if (this->resources_ != nullptr) {
delete this->resources_;
}
if (this->load_configuration_ != nullptr) {
delete this->load_configuration_;
}
}
PE_TYPE Binary::type(void) const {
@ -340,7 +347,18 @@ bool Binary::has_debug(void) const {
bool Binary::has_configuration(void) const {
return this->has_configuration_;
return this->has_configuration_ and this->load_configuration_ != nullptr;
}
const LoadConfiguration& Binary::load_configuration(void) const {
if (not this->has_configuration()) {
throw not_found("The binary doesn't have load configuration");
}
return *this->load_configuration_;
}
LoadConfiguration& Binary::load_configuration(void) {
return const_cast<LoadConfiguration&>(static_cast<const Binary*>(this)->load_configuration());
}
//
@ -1315,6 +1333,17 @@ std::ostream& Binary::print(std::ostream& os) const {
os << std::endl;
if (this->has_configuration()) {
os << "Load Configuration" << std::endl;
os << "==================" << std::endl;
os << this->load_configuration();
os << std::endl;
}
return os;
}

@ -24,6 +24,7 @@ set(LIEF_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/ResourceData.cpp"
"${CMAKE_CURRENT_LIST_DIR}/RelocationEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/DataDirectory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/CodeIntegrity.cpp"
"${CMAKE_CURRENT_LIST_DIR}/signature/AuthenticatedAttributes.cpp"
"${CMAKE_CURRENT_LIST_DIR}/signature/ContentInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/signature/Signature.cpp"
@ -44,6 +45,37 @@ set(LIEF_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/resources/ResourceIcon.cpp"
)
set(LIEF_PE_LOAD_CONFIGURATION_SRC
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurations.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfiguration.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfiguration.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV0.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV0.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV1.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV1.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV2.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV2.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV3.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV3.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV4.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV4.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV5.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV5.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV6.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV6.tcc"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV7.cpp"
"${CMAKE_CURRENT_LIST_DIR}/LoadConfigurations/LoadConfigurationV7.tcc"
)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/enums.inc" LIEF_PE_ENUMS)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/structures.inc" LIEF_PE_STRUCTURES)
@ -67,6 +99,7 @@ set(LIEF_PE_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/Debug.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/DosHeader.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/RichHeader.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/CodeIntegrity.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/RichEntry.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/EnumToString.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/PE/enums.hpp" # Do we want to do this since it's autogenerated?
@ -92,6 +125,19 @@ set(LIEF_PE_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/utils.hpp"
)
set(LIEF_PE_LOAD_CONFIGURATION_INCLUDE
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfiguration.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV0.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV1.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV2.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV3.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV4.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV5.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV6.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/LoadConfigurations/LoadConfigurationV7.hpp"
)
set(LIEF_PE_SIG_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/AuthenticatedAttributes.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/ContentInfo.hpp"
@ -124,10 +170,29 @@ set(LIEF_PE_UTILS_INCLUDE_FILES
source_group("Source Files\\PE" FILES ${LIEF_PE_SRC})
source_group("Source Files\\PE\\Load Configure" FILES ${LIEF_PE_LOAD_CONFIGURATION_SRC})
source_group("Header Files\\PE" FILES ${LIEF_PE_INCLUDE_FILES})
source_group("Header Files\\PE\\signature" FILES ${LIEF_PE_SIG_INCLUDE_FILES})
source_group("Header Files\\PE\\resources" FILES ${LIEF_PE_RESOURCES_INCLUDE_FILES})
source_group("Header Files\\PE\\Load Configuration" FILES ${LIEF_PE_LOAD_CONFIGURATION_INCLUDE})
source_group("Header Files\\PE\\utils\\Ordinals Lookup Tables" FILES ${LIEF_PE_UTILS_INCLUDE_FILES})
target_sources(LIB_LIEF_STATIC PRIVATE ${LIEF_PE_SRC} ${LIEF_PE_INCLUDE_FILES} ${LIEF_PE_SIG_INCLUDE_FILES} ${LIEF_PE_RESOURCES_INCLUDE_FILES} ${LIEF_PE_UTILS_INCLUDE_FILES})
target_sources(LIB_LIEF_SHARED PRIVATE ${LIEF_PE_SRC} ${LIEF_PE_INCLUDE_FILES} ${LIEF_PE_SIG_INCLUDE_FILES} ${LIEF_PE_RESOURCES_INCLUDE_FILES} ${LIEF_PE_UTILS_INCLUDE_FILES})
target_sources(LIB_LIEF_STATIC PRIVATE
${LIEF_PE_SRC}
${LIEF_PE_INCLUDE_FILES}
${LIEF_PE_SIG_INCLUDE_FILES}
${LIEF_PE_RESOURCES_INCLUDE_FILES}
${LIEF_PE_UTILS_INCLUDE_FILES}
${LIEF_PE_LOAD_CONFIGURATION_SRC}
${LIEF_PE_LOAD_CONFIGURATION_INCLUDE}
)
target_sources(LIB_LIEF_SHARED PRIVATE
${LIEF_PE_SRC}
${LIEF_PE_INCLUDE_FILES}
${LIEF_PE_SIG_INCLUDE_FILES}
${LIEF_PE_RESOURCES_INCLUDE_FILES}
${LIEF_PE_UTILS_INCLUDE_FILES}
${LIEF_PE_LOAD_CONFIGURATION_SRC}
${LIEF_PE_LOAD_CONFIGURATION_INCLUDE}
)

108
src/PE/CodeIntegrity.cpp Normal file

@ -0,0 +1,108 @@
/* 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 <numeric>
#include <iomanip>
#include <sstream>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/PE/EnumToString.hpp"
#include "LIEF/PE/CodeIntegrity.hpp"
namespace LIEF {
namespace PE {
CodeIntegrity::~CodeIntegrity(void) = default;
CodeIntegrity& CodeIntegrity::operator=(const CodeIntegrity&) = default;
CodeIntegrity::CodeIntegrity(const CodeIntegrity&) = default;
CodeIntegrity::CodeIntegrity(void) :
flags_{0},
catalog_{0},
catalog_offset_{0},
reserved_{0}
{}
CodeIntegrity::CodeIntegrity(const pe_code_integrity *header) :
flags_{header->Flags},
catalog_{header->Catalog},
catalog_offset_{header->CatalogOffset},
reserved_{header->Reserved}
{}
uint16_t CodeIntegrity::flags(void) const {
return this->flags_;
}
uint16_t CodeIntegrity::catalog(void) const {
return this->catalog_;
}
uint32_t CodeIntegrity::catalog_offset(void) const {
return this->catalog_offset_;
}
uint32_t CodeIntegrity::reserved(void) const {
return this->reserved_;
}
void CodeIntegrity::flags(uint16_t flags) {
this->flags_ = flags;
}
void CodeIntegrity::catalog(uint16_t catalog) {
this->catalog_ = catalog;
}
void CodeIntegrity::catalog_offset(uint32_t catalog_offset) {
this->catalog_offset_ = catalog_offset;
}
void CodeIntegrity::reserved(uint32_t reserved) {
this->reserved_ = reserved;
}
void CodeIntegrity::accept(LIEF::Visitor& visitor) const {
visitor.visit(this->flags());
visitor.visit(this->catalog());
visitor.visit(this->catalog_offset());
visitor.visit(this->reserved());
}
bool CodeIntegrity::operator==(const CodeIntegrity& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool CodeIntegrity::operator!=(const CodeIntegrity& rhs) const {
return not (*this == rhs);
}
std::ostream& operator<<(std::ostream& os, const CodeIntegrity& entry) {
os << std::hex << std::left << std::showbase;
os << std::setw(CodeIntegrity::PRINT_WIDTH) << std::setfill(' ') << "Flags:" << std::hex << entry.flags() << std::endl;
os << std::setw(CodeIntegrity::PRINT_WIDTH) << std::setfill(' ') << "Catalog:" << std::hex << entry.catalog() << std::endl;
os << std::setw(CodeIntegrity::PRINT_WIDTH) << std::setfill(' ') << "Catalog offset:" << std::hex << entry.catalog_offset() << std::endl;
os << std::setw(CodeIntegrity::PRINT_WIDTH) << std::setfill(' ') << "Reserved:" << std::hex << entry.reserved() << std::endl;
return os;
}
}
}

@ -948,6 +948,48 @@ const char* to_string(CODE_PAGES e) {
const char* to_string(WIN_VERSION e) {
const std::map<WIN_VERSION, const char*> enumStrings {
{ WIN_VERSION::WIN_UNKNOWN, "UNKNOWN" },
{ WIN_VERSION::WIN_SEH, "SEH" },
{ WIN_VERSION::WIN8_1, "WIN_8_1" },
{ WIN_VERSION::WIN10_0_9879, "WIN10_0_9879" },
{ WIN_VERSION::WIN10_0_14286, "WIN10_0_14286" },
{ WIN_VERSION::WIN10_0_14383, "WIN10_0_14383" },
{ WIN_VERSION::WIN10_0_14901, "WIN10_0_14901" },
{ WIN_VERSION::WIN10_0_15002, "WIN10_0_15002" },
{ WIN_VERSION::WIN10_0_16237, "WIN10_0_16237" },
};
auto it = enumStrings.find(e);
return it == enumStrings.end() ? "Out of range" : it->second;
}
const char* to_string(GUARD_CF_FLAGS e) {
const std::map<GUARD_CF_FLAGS, const char*> enumStrings {
{ GUARD_CF_FLAGS::GCF_INSTRUMENTED, "INSTRUMENTED" },
{ GUARD_CF_FLAGS::GCF_W_INSTRUMENTED, "W_INSTRUMENTED" },
{ GUARD_CF_FLAGS::GCF_FUNCTION_TABLE_PRESENT, "FUNCTION_TABLE_PRESENT" },
{ GUARD_CF_FLAGS::GCF_EXPORT_SUPPRESSION_INFO_PRESENT, "EXPORT_SUPPRESSION_INFO_PRESENT" },
{ GUARD_CF_FLAGS::GCF_ENABLE_EXPORT_SUPPRESSION, "ENABLE_EXPORT_SUPPRESSION" },
{ GUARD_CF_FLAGS::GCF_LONGJUMP_TABLE_PRESENT, "LONGJUMP_TABLE_PRESENT" },
};
auto it = enumStrings.find(e);
return it == enumStrings.end() ? "Out of range" : it->second;
}
const char* to_string(GUARD_RF_FLAGS e) {
const std::map<GUARD_RF_FLAGS, const char*> enumStrings {
{ GUARD_RF_FLAGS::GRF_INSTRUMENTED, "INSTRUMENTED" },
{ GUARD_RF_FLAGS::GRF_ENABLE, "ENABLE" },
{ GUARD_RF_FLAGS::GRF_STRICT, "STRICT" },
};
auto it = enumStrings.find(e);
return it == enumStrings.end() ? "Out of range" : it->second;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,296 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
#include "LIEF/PE/EnumToString.hpp"
namespace LIEF {
namespace PE {
LoadConfiguration& LoadConfiguration::operator=(const LoadConfiguration&) = default;
LoadConfiguration::LoadConfiguration(const LoadConfiguration&) = default;
LoadConfiguration::~LoadConfiguration(void) = default;
decltype(PE32::load_configuration_sizes) PE32::load_configuration_sizes = {
{WIN_VERSION::WIN_UNKNOWN, sizeof(PE32::load_configuration_t)},
{WIN_VERSION::WIN_SEH, sizeof(PE32::load_configuration_v0_t)},
{WIN_VERSION::WIN8_1, sizeof(PE32::load_configuration_v1_t)},
{WIN_VERSION::WIN10_0_9879, sizeof(PE32::load_configuration_v2_t)},
{WIN_VERSION::WIN10_0_14286, sizeof(PE32::load_configuration_v3_t)},
{WIN_VERSION::WIN10_0_14383, sizeof(PE32::load_configuration_v4_t)},
{WIN_VERSION::WIN10_0_14901, sizeof(PE32::load_configuration_v5_t)},
{WIN_VERSION::WIN10_0_15002, sizeof(PE32::load_configuration_v6_t)},
{WIN_VERSION::WIN10_0_16237, sizeof(PE32::load_configuration_v7_t)},
};
decltype(PE64::load_configuration_sizes) PE64::load_configuration_sizes = {
{WIN_VERSION::WIN_UNKNOWN, sizeof(PE64::load_configuration_t)},
{WIN_VERSION::WIN_SEH, sizeof(PE64::load_configuration_v0_t)},
{WIN_VERSION::WIN8_1, sizeof(PE64::load_configuration_v1_t)},
{WIN_VERSION::WIN10_0_9879, sizeof(PE64::load_configuration_v2_t)},
{WIN_VERSION::WIN10_0_14286, sizeof(PE64::load_configuration_v3_t)},
{WIN_VERSION::WIN10_0_14383, sizeof(PE64::load_configuration_v4_t)},
{WIN_VERSION::WIN10_0_14901, sizeof(PE64::load_configuration_v5_t)},
{WIN_VERSION::WIN10_0_15002, sizeof(PE64::load_configuration_v6_t)},
{WIN_VERSION::WIN10_0_16237, sizeof(PE64::load_configuration_v7_t)},
};
LoadConfiguration::LoadConfiguration(void) :
characteristics_{0},
timedatestamp_{0},
major_version_{0},
minor_version_{0},
global_flags_clear_{0},
global_flags_set_{0},
critical_section_default_timeout_{0},
decommit_free_block_threshold_{0},
decommit_total_free_threshold_{0},
lock_prefix_table_{0},
maximum_allocation_size_{0},
virtual_memory_threshold_{0},
process_affinity_mask_{0},
process_heap_flags_{0},
csd_version_{0},
reserved1_{0},
editlist_{0},
security_cookie_{0}
{}
WIN_VERSION LoadConfiguration::version(void) const {
return LoadConfiguration::VERSION;
}
uint32_t LoadConfiguration::characteristics(void) const {
return this->characteristics_;
}
uint32_t LoadConfiguration::timedatestamp(void) const {
return this->timedatestamp_;
}
uint16_t LoadConfiguration::major_version(void) const {
return this->major_version_;
}
uint16_t LoadConfiguration::minor_version(void) const {
return this->minor_version_;
}
uint32_t LoadConfiguration::global_flags_clear(void) const {
return this->global_flags_clear_;
}
uint32_t LoadConfiguration::global_flags_set(void) const {
return this->global_flags_set_;
}
uint32_t LoadConfiguration::critical_section_default_timeout(void) const {
return this->critical_section_default_timeout_;
}
uint64_t LoadConfiguration::decommit_free_block_threshold(void) const {
return this->decommit_free_block_threshold_;
}
uint64_t LoadConfiguration::decommit_total_free_threshold(void) const {
return this->decommit_total_free_threshold_;
}
uint64_t LoadConfiguration::lock_prefix_table(void) const {
return this->lock_prefix_table_;
}
uint64_t LoadConfiguration::maximum_allocation_size(void) const {
return this->maximum_allocation_size_;
}
uint64_t LoadConfiguration::virtual_memory_threshold(void) const {
return this->virtual_memory_threshold_;
}
uint64_t LoadConfiguration::process_affinity_mask(void) const {
return this->process_affinity_mask_;
}
uint32_t LoadConfiguration::process_heap_flags(void) const {
return this->process_heap_flags_;
}
uint16_t LoadConfiguration::csd_version(void) const {
return this->csd_version_;
}
uint16_t LoadConfiguration::reserved1(void) const {
return this->reserved1_;
}
uint32_t LoadConfiguration::editlist(void) const {
return this->editlist_;
}
uint32_t LoadConfiguration::security_cookie(void) const {
return this->security_cookie_;
}
void LoadConfiguration::characteristics(uint32_t characteristics) {
this->characteristics_ = characteristics;
}
void LoadConfiguration::timedatestamp(uint32_t timedatestamp) {
this->timedatestamp_ = timedatestamp;
}
void LoadConfiguration::major_version(uint16_t major_version) {
this->major_version_ = major_version;
}
void LoadConfiguration::minor_version(uint16_t minor_version) {
this->minor_version_ = minor_version;
}
void LoadConfiguration::global_flags_clear(uint32_t global_flags_clear) {
this->global_flags_clear_ = global_flags_clear;
}
void LoadConfiguration::global_flags_set(uint32_t global_flags_set) {
this->global_flags_set_ = global_flags_set;
}
void LoadConfiguration::critical_section_default_timeout(uint32_t critical_section_default_timeout) {
this->critical_section_default_timeout_ = critical_section_default_timeout;
}
void LoadConfiguration::decommit_free_block_threshold(uint64_t decommit_free_block_threshold) {
this->decommit_free_block_threshold_ = decommit_free_block_threshold;
}
void LoadConfiguration::decommit_total_free_threshold(uint64_t decommit_total_free_threshold) {
this->decommit_total_free_threshold_ = decommit_total_free_threshold;
}
void LoadConfiguration::lock_prefix_table(uint64_t lock_prefix_table) {
this->lock_prefix_table_ = lock_prefix_table;
}
void LoadConfiguration::maximum_allocation_size(uint64_t maximum_allocation_size) {
this->maximum_allocation_size_ = maximum_allocation_size;
}
void LoadConfiguration::virtual_memory_threshold(uint64_t virtual_memory_threshold) {
this->virtual_memory_threshold_ = virtual_memory_threshold;
}
void LoadConfiguration::process_affinity_mask(uint64_t process_affinity_mask) {
this->process_affinity_mask_ = process_affinity_mask;
}
void LoadConfiguration::process_heap_flags(uint32_t process_heap_flagsid) {
this->process_heap_flags_ = process_heap_flagsid;
}
void LoadConfiguration::csd_version(uint16_t csd_version) {
this->csd_version_ = csd_version;
}
void LoadConfiguration::reserved1(uint16_t reserved1) {
this->reserved1_ = reserved1;
}
void LoadConfiguration::editlist(uint32_t editlist) {
this->editlist_ = editlist;
}
void LoadConfiguration::security_cookie(uint32_t security_cookie) {
this->security_cookie_ = security_cookie;
}
void LoadConfiguration::accept(Visitor& visitor) const {
visitor(*this); // Double dispatch to avoid down-casting
visitor.visit(this->characteristics());
visitor.visit(this->timedatestamp());
visitor.visit(this->major_version());
visitor.visit(this->minor_version());
visitor.visit(this->global_flags_clear());
visitor.visit(this->global_flags_set());
visitor.visit(this->critical_section_default_timeout());
visitor.visit(this->decommit_free_block_threshold());
visitor.visit(this->decommit_total_free_threshold());
visitor.visit(this->lock_prefix_table());
visitor.visit(this->maximum_allocation_size());
visitor.visit(this->virtual_memory_threshold());
visitor.visit(this->process_affinity_mask());
visitor.visit(this->process_heap_flags());
visitor.visit(this->csd_version());
visitor.visit(this->reserved1());
visitor.visit(this->editlist());
visitor.visit(this->security_cookie());
}
bool LoadConfiguration::operator==(const LoadConfiguration& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfiguration::operator!=(const LoadConfiguration& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfiguration::print(std::ostream& os) const {
os << std::hex << std::left << std::showbase;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Version:" << std::hex << to_string(this->version()) << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Characteristics:" << std::hex << this->characteristics() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Timedatestamp:" << std::dec << this->timedatestamp() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Major version:" << std::dec << this->major_version() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Minor version:" << std::dec << this->minor_version() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Global flags clear:" << std::hex << this->global_flags_clear() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Global flags set:" << std::hex << this->global_flags_set() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Critical section default timeout:" << std::dec << this->critical_section_default_timeout() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Decommit free block threshold:" << std::hex << this->decommit_free_block_threshold() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Decommit total free threshold:" << std::hex << this->decommit_total_free_threshold() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Lock prefix table:" << std::hex << this->lock_prefix_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Maximum allocation size:" << std::hex << this->maximum_allocation_size() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Virtual memory threshold:" << std::hex << this->virtual_memory_threshold() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Process affinity mask:" << std::hex << this->process_affinity_mask() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Process heap flags:" << std::hex << this->process_heap_flags() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "CSD Version:" << std::hex << this->csd_version() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Reserved 1:" << std::hex << this->reserved1() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Edit list:" << std::hex << this->editlist() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Security cookie:" << std::hex << this->security_cookie() << std::endl;
return os;
}
std::ostream& operator<<(std::ostream& os, const LoadConfiguration& config) {
return config.print(os);
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,47 @@
/* 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 <iomanip>
namespace LIEF {
namespace PE {
template<class T>
LoadConfiguration::LoadConfiguration(const load_configuration<T>* header) :
characteristics_{header->Characteristics},
timedatestamp_{header->TimeDateStamp},
major_version_{header->MajorVersion},
minor_version_{header->MinorVersion},
global_flags_clear_{header->GlobalFlagsClear},
global_flags_set_{header->GlobalFlagsSet},
critical_section_default_timeout_{header->CriticalSectionDefaultTimeout},
decommit_free_block_threshold_{header->DeCommitFreeBlockThreshold},
decommit_total_free_threshold_{header->DeCommitTotalFreeThreshold},
lock_prefix_table_{header->LockPrefixTable},
maximum_allocation_size_{header->MaximumAllocationSize},
virtual_memory_threshold_{header->VirtualMemoryThreshold},
process_affinity_mask_{header->ProcessAffinityMask},
process_heap_flags_{header->ProcessHeapFlags},
csd_version_{header->CSDVersion},
reserved1_{header->Reserved1},
editlist_{header->EditList},
security_cookie_{header->SecurityCookie}
{}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,84 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV0& LoadConfigurationV0::operator=(const LoadConfigurationV0&) = default;
LoadConfigurationV0::LoadConfigurationV0(const LoadConfigurationV0&) = default;
LoadConfigurationV0::~LoadConfigurationV0(void) = default;
LoadConfigurationV0::LoadConfigurationV0(void) :
LoadConfiguration{},
se_handler_table_{0},
se_handler_count_{0}
{}
WIN_VERSION LoadConfigurationV0::version(void) const {
return LoadConfigurationV0::VERSION;
}
uint64_t LoadConfigurationV0::se_handler_table(void) const {
return this->se_handler_table_;
}
uint64_t LoadConfigurationV0::se_handler_count(void) const {
return this->se_handler_count_;
}
void LoadConfigurationV0::se_handler_table(uint64_t se_handler_table) {
this->se_handler_table_ = se_handler_table;
}
void LoadConfigurationV0::se_handler_count(uint64_t se_handler_count) {
this->se_handler_count_ = se_handler_count;
}
void LoadConfigurationV0::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfiguration*>(this)); // Double dispatch to avoid down-casting
visitor.visit(this->se_handler_table());
visitor.visit(this->se_handler_count());
}
bool LoadConfigurationV0::operator==(const LoadConfigurationV0& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV0::operator!=(const LoadConfigurationV0& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV0::print(std::ostream& os) const {
LoadConfiguration::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "SE handler table:" << std::hex << this->se_handler_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "SE handler count:" << std::dec << this->se_handler_count() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,31 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV0::LoadConfigurationV0(const load_configuration_v0<T>* header) :
LoadConfiguration{reinterpret_cast<const load_configuration<T>*>(header)},
se_handler_table_{header->SEHandlerTable},
se_handler_count_{header->SEHandlerCount}
{
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,146 @@
/* 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 <iomanip>
#include <numeric>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/EnumToString.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV1& LoadConfigurationV1::operator=(const LoadConfigurationV1&) = default;
LoadConfigurationV1::LoadConfigurationV1(const LoadConfigurationV1&) = default;
LoadConfigurationV1::~LoadConfigurationV1(void) = default;
LoadConfigurationV1::LoadConfigurationV1(void) :
LoadConfigurationV0{},
guard_cf_check_function_pointer_{0},
guard_cf_dispatch_function_pointer_{0},
guard_cf_function_table_{0},
guard_cf_function_count_{0},
guard_flags_{0}
{}
WIN_VERSION LoadConfigurationV1::version(void) const {
return LoadConfigurationV1::VERSION;
}
uint64_t LoadConfigurationV1::guard_cf_check_function_pointer(void) const {
return this->guard_cf_check_function_pointer_;
}
uint64_t LoadConfigurationV1::guard_cf_dispatch_function_pointer(void) const {
return this->guard_cf_dispatch_function_pointer_;
}
uint64_t LoadConfigurationV1::guard_cf_function_table(void) const {
return this->guard_cf_function_table_;
}
uint64_t LoadConfigurationV1::guard_cf_function_count(void) const {
return this->guard_cf_function_count_;
}
uint32_t LoadConfigurationV1::guard_flags(void) const {
return this->guard_flags_;
}
bool LoadConfigurationV1::has(GUARD_CF_FLAGS flag) const {
return (this->guard_flags() & flag) > 0;
}
guard_cf_flags_list_t LoadConfigurationV1::guard_cf_flags_list(void) const {
guard_cf_flags_list_t flags;
std::copy_if(
std::begin(guard_cf_flags_array),
std::end(guard_cf_flags_array),
std::inserter(flags, std::begin(flags)),
std::bind(static_cast<bool (LoadConfigurationV1::*)(GUARD_CF_FLAGS) const>(&LoadConfigurationV1::has),
this, std::placeholders::_1));
return flags;
}
void LoadConfigurationV1::guard_cf_check_function_pointer(uint64_t guard_cf_check_function_pointer) {
this->guard_cf_check_function_pointer_ = guard_cf_check_function_pointer;
}
void LoadConfigurationV1::guard_cf_dispatch_function_pointer(uint64_t guard_cf_dispatch_function_pointer) {
this->guard_cf_dispatch_function_pointer_ = guard_cf_dispatch_function_pointer;
}
void LoadConfigurationV1::guard_cf_function_table(uint64_t guard_cf_function_table) {
this->guard_cf_function_table_ = guard_cf_function_table;
}
void LoadConfigurationV1::guard_cf_function_count(uint64_t guard_cf_function_count) {
this->guard_cf_function_count_ = guard_cf_function_count;
}
void LoadConfigurationV1::guard_flags(uint32_t guard_flags) {
this->guard_flags_ = guard_flags;
}
void LoadConfigurationV1::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV0*>(this));
visitor.visit(this->guard_cf_check_function_pointer());
visitor.visit(this->guard_cf_dispatch_function_pointer());
visitor.visit(this->guard_cf_function_table());
visitor.visit(this->guard_cf_function_count());
visitor.visit(this->guard_flags());
}
bool LoadConfigurationV1::operator==(const LoadConfigurationV1& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV1::operator!=(const LoadConfigurationV1& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV1::print(std::ostream& os) const {
LoadConfigurationV0::print(os);
const guard_cf_flags_list_t& flags = this->guard_cf_flags_list();
std::string flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, GUARD_CF_FLAGS b) {
return a.empty() ? to_string(b) : a + " " + to_string(b);
});
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GCF check function pointer:" << std::hex << this->guard_cf_check_function_pointer() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GCF dispatch function pointer:" << std::hex << this->guard_cf_dispatch_function_pointer() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GCF function table :" << std::hex << this->guard_cf_function_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GCF Function count:" << std::dec << this->guard_cf_function_count() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Guard flags:" << std::hex << flags_str << " (" << this->guard_flags() << ")" << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,34 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV1::LoadConfigurationV1(const load_configuration_v1<T>* header) :
LoadConfigurationV0{reinterpret_cast<const load_configuration_v0<T>*>(header)},
guard_cf_check_function_pointer_{header->GuardCFCheckFunctionPointer},
guard_cf_dispatch_function_pointer_{header->GuardCFDispatchFunctionPointer},
guard_cf_function_table_{header->GuardCFFunctionTable},
guard_cf_function_count_{header->GuardCFFunctionCount},
guard_flags_{header->GuardFlags}
{
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,77 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/iostream.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV2& LoadConfigurationV2::operator=(const LoadConfigurationV2&) = default;
LoadConfigurationV2::LoadConfigurationV2(const LoadConfigurationV2&) = default;
LoadConfigurationV2::~LoadConfigurationV2(void) = default;
LoadConfigurationV2::LoadConfigurationV2(void) :
LoadConfigurationV1{},
code_integrity_{}
{}
WIN_VERSION LoadConfigurationV2::version(void) const {
return LoadConfigurationV2::VERSION;
}
const CodeIntegrity& LoadConfigurationV2::code_integrity(void) const {
return this->code_integrity_;
}
CodeIntegrity& LoadConfigurationV2::code_integrity(void) {
return const_cast<CodeIntegrity&>(static_cast<const LoadConfigurationV2*>(this)->code_integrity());
}
void LoadConfigurationV2::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV1*>(this));
visitor.visit(this->code_integrity());
}
bool LoadConfigurationV2::operator==(const LoadConfigurationV2& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV2::operator!=(const LoadConfigurationV2& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV2::print(std::ostream& os) const {
LoadConfigurationV1::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Code Integrity:" << std::endl;
oprefixstream out(" ", os);
out << this->code_integrity();
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,29 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV2::LoadConfigurationV2(const load_configuration_v2<T>* header) :
LoadConfigurationV1{reinterpret_cast<const load_configuration_v1<T>*>(header)},
code_integrity_{&header->CodeIntegrity}
{}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,106 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV3& LoadConfigurationV3::operator=(const LoadConfigurationV3&) = default;
LoadConfigurationV3::LoadConfigurationV3(const LoadConfigurationV3&) = default;
LoadConfigurationV3::~LoadConfigurationV3(void) = default;
LoadConfigurationV3::LoadConfigurationV3(void) :
LoadConfigurationV2{},
guard_address_taken_iat_entry_table_{0},
guard_address_taken_iat_entry_count_{0},
guard_long_jump_target_table_{0},
guard_long_jump_target_count_{0}
{}
WIN_VERSION LoadConfigurationV3::version(void) const {
return LoadConfigurationV3::VERSION;
}
uint64_t LoadConfigurationV3::guard_address_taken_iat_entry_table(void) const {
return this->guard_address_taken_iat_entry_table_;
}
uint64_t LoadConfigurationV3::guard_address_taken_iat_entry_count(void) const {
return this->guard_address_taken_iat_entry_count_;
}
uint64_t LoadConfigurationV3::guard_long_jump_target_table(void) const {
return this->guard_long_jump_target_table_;
}
uint64_t LoadConfigurationV3::guard_long_jump_target_count(void) const {
return this->guard_long_jump_target_count_;
}
void LoadConfigurationV3::guard_address_taken_iat_entry_table(uint64_t value) {
this->guard_address_taken_iat_entry_table_ = value;
}
void LoadConfigurationV3::guard_address_taken_iat_entry_count(uint64_t value) {
this->guard_address_taken_iat_entry_count_ = value;
}
void LoadConfigurationV3::guard_long_jump_target_table(uint64_t value) {
this->guard_long_jump_target_table_ = value;
}
void LoadConfigurationV3::guard_long_jump_target_count(uint64_t value) {
this->guard_long_jump_target_count_ = value;
}
void LoadConfigurationV3::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV2*>(this));
visitor.visit(this->guard_address_taken_iat_entry_table());
visitor.visit(this->guard_address_taken_iat_entry_count());
visitor.visit(this->guard_long_jump_target_table());
visitor.visit(this->guard_long_jump_target_count());
}
bool LoadConfigurationV3::operator==(const LoadConfigurationV3& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV3::operator!=(const LoadConfigurationV3& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV3::print(std::ostream& os) const {
LoadConfigurationV2::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Guard address taken iat entry table:" << std::hex << this->guard_address_taken_iat_entry_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Guard address taken iat entry count:" << std::dec << this->guard_address_taken_iat_entry_count() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Guard long jump target table:" << std::hex << this->guard_long_jump_target_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Guard long jump target count:" << std::dec << this->guard_long_jump_target_count() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,33 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV3::LoadConfigurationV3(const load_configuration_v3<T>* header) :
LoadConfigurationV2{reinterpret_cast<const load_configuration_v2<T>*>(header)},
guard_address_taken_iat_entry_table_{header->GuardAddressTakenIatEntryTable},
guard_address_taken_iat_entry_count_{header->GuardAddressTakenIatEntryCount},
guard_long_jump_target_table_{header->GuardLongJumpTargetTable},
guard_long_jump_target_count_{header->GuardLongJumpTargetCount}
{
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,84 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV4& LoadConfigurationV4::operator=(const LoadConfigurationV4&) = default;
LoadConfigurationV4::LoadConfigurationV4(const LoadConfigurationV4&) = default;
LoadConfigurationV4::~LoadConfigurationV4(void) = default;
LoadConfigurationV4::LoadConfigurationV4(void) :
LoadConfigurationV3{},
dynamic_value_reloc_table_{0},
hybrid_metadata_pointer_{0}
{}
WIN_VERSION LoadConfigurationV4::version(void) const {
return LoadConfigurationV4::VERSION;
}
uint64_t LoadConfigurationV4::dynamic_value_reloc_table(void) const {
return this->dynamic_value_reloc_table_;
}
uint64_t LoadConfigurationV4::hybrid_metadata_pointer(void) const {
return this->hybrid_metadata_pointer_;
}
void LoadConfigurationV4::dynamic_value_reloc_table(uint64_t value) {
this->dynamic_value_reloc_table_ = value;
}
void LoadConfigurationV4::hybrid_metadata_pointer(uint64_t value) {
this->hybrid_metadata_pointer_ = value;
}
void LoadConfigurationV4::accept(Visitor& visitor) const {
visitor(*static_cast<const LoadConfigurationV3*>(this));
visitor.visit(this->dynamic_value_reloc_table());
visitor.visit(this->hybrid_metadata_pointer());
}
bool LoadConfigurationV4::operator==(const LoadConfigurationV4& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV4::operator!=(const LoadConfigurationV4& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV4::print(std::ostream& os) const {
LoadConfigurationV3::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Dynamic value relocation table:" << std::hex << this->dynamic_value_reloc_table() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Hybrid metadata pointer:" << std::hex << this->hybrid_metadata_pointer() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,31 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV4::LoadConfigurationV4(const load_configuration_v4<T>* header) :
LoadConfigurationV3{reinterpret_cast<const load_configuration_v3<T>*>(header)},
dynamic_value_reloc_table_{header->DynamicValueRelocTable},
hybrid_metadata_pointer_{header->HybridMetadataPointer}
{
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,117 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV5& LoadConfigurationV5::operator=(const LoadConfigurationV5&) = default;
LoadConfigurationV5::LoadConfigurationV5(const LoadConfigurationV5&) = default;
LoadConfigurationV5::~LoadConfigurationV5(void) = default;
LoadConfigurationV5::LoadConfigurationV5(void) :
LoadConfigurationV4{},
guard_rf_failure_routine_{0},
guard_rf_failure_routine_function_pointer_{0},
dynamic_value_reloctable_offset_{0},
dynamic_value_reloctable_section_{0},
reserved2_{0}
{}
WIN_VERSION LoadConfigurationV5::version(void) const {
return LoadConfigurationV5::VERSION;
}
uint64_t LoadConfigurationV5::guard_rf_failure_routine(void) const {
return this->guard_rf_failure_routine_;
}
uint64_t LoadConfigurationV5::guard_rf_failure_routine_function_pointer(void) const {
return this->guard_rf_failure_routine_function_pointer_;
}
uint32_t LoadConfigurationV5::dynamic_value_reloctable_offset(void) const {
return this->dynamic_value_reloctable_offset_;
}
uint16_t LoadConfigurationV5::dynamic_value_reloctable_section(void) const {
return this->dynamic_value_reloctable_section_;
}
uint16_t LoadConfigurationV5::reserved2(void) const {
return this->reserved2_;
}
void LoadConfigurationV5::guard_rf_failure_routine(uint64_t value) {
this->guard_rf_failure_routine_ = value;
}
void LoadConfigurationV5::guard_rf_failure_routine_function_pointer(uint64_t value) {
this->guard_rf_failure_routine_function_pointer_ = value;
}
void LoadConfigurationV5::dynamic_value_reloctable_offset(uint32_t value) {
this->dynamic_value_reloctable_offset_ = value;
}
void LoadConfigurationV5::dynamic_value_reloctable_section(uint16_t value) {
this->dynamic_value_reloctable_section_ = value;
}
void LoadConfigurationV5::reserved2(uint16_t value) {
this->reserved2_ = value;
}
void LoadConfigurationV5::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV4*>(this));
visitor.visit(this->guard_rf_failure_routine());
visitor.visit(this->guard_rf_failure_routine_function_pointer());
visitor.visit(this->dynamic_value_reloctable_offset());
visitor.visit(this->dynamic_value_reloctable_section());
}
bool LoadConfigurationV5::operator==(const LoadConfigurationV5& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV5::operator!=(const LoadConfigurationV5& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV5::print(std::ostream& os) const {
LoadConfigurationV4::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GRF failure routine:" << std::hex << this->guard_rf_failure_routine() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GRF failure routine function pointer:" << std::hex << this->guard_rf_failure_routine_function_pointer() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Dynamic value reloctable offset:" << std::hex << this->dynamic_value_reloctable_offset() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Dynamic value reloctable section:" << std::dec << this->dynamic_value_reloctable_section() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,33 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV5::LoadConfigurationV5(const load_configuration_v5<T>* header) :
LoadConfigurationV4{reinterpret_cast<const load_configuration_v4<T>*>(header)},
guard_rf_failure_routine_{header->GuardRFFailureRoutine},
guard_rf_failure_routine_function_pointer_{header->GuardRFFailureRoutineFunctionPointer},
dynamic_value_reloctable_offset_{header->DynamicValueRelocTableOffset},
dynamic_value_reloctable_section_{header->DynamicValueRelocTableSection},
reserved2_{header->Reserved2}
{}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,85 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV6& LoadConfigurationV6::operator=(const LoadConfigurationV6&) = default;
LoadConfigurationV6::LoadConfigurationV6(const LoadConfigurationV6&) = default;
LoadConfigurationV6::~LoadConfigurationV6(void) = default;
LoadConfigurationV6::LoadConfigurationV6(void) :
LoadConfigurationV5{},
guardrf_verify_stackpointer_function_pointer_{0},
hotpatch_table_offset_{0}
{}
WIN_VERSION LoadConfigurationV6::version(void) const {
return LoadConfigurationV6::VERSION;
}
uint64_t LoadConfigurationV6::guard_rf_verify_stackpointer_function_pointer(void) const {
return this->guardrf_verify_stackpointer_function_pointer_;
}
uint32_t LoadConfigurationV6::hotpatch_table_offset(void) const {
return this->hotpatch_table_offset_;
}
void LoadConfigurationV6::guard_rf_verify_stackpointer_function_pointer(uint64_t value) {
this->guardrf_verify_stackpointer_function_pointer_ = value;
}
void LoadConfigurationV6::hotpatch_table_offset(uint32_t value) {
this->hotpatch_table_offset_ = value;
}
void LoadConfigurationV6::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV5*>(this));
visitor.visit(this->guard_rf_verify_stackpointer_function_pointer());
visitor.visit(this->hotpatch_table_offset());
}
bool LoadConfigurationV6::operator==(const LoadConfigurationV6& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV6::operator!=(const LoadConfigurationV6& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV6::print(std::ostream& os) const {
LoadConfigurationV5::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "GRF verify stackpointer function pointer:" << std::hex << this->guard_rf_verify_stackpointer_function_pointer() << std::endl;
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Hotpatch table offset:" << std::hex << this->hotpatch_table_offset() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,30 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV6::LoadConfigurationV6(const load_configuration_v6<T>* header) :
LoadConfigurationV5{reinterpret_cast<const load_configuration_v5<T>*>(header)},
guardrf_verify_stackpointer_function_pointer_{header->GuardRFVerifyStackPointerFunctionPointer},
hotpatch_table_offset_{header->HotPatchTableOffset}
{}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,82 @@
/* 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 <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/exception.hpp"
#include "LIEF/PE/LoadConfigurations.hpp"
namespace LIEF {
namespace PE {
LoadConfigurationV7& LoadConfigurationV7::operator=(const LoadConfigurationV7&) = default;
LoadConfigurationV7::LoadConfigurationV7(const LoadConfigurationV7&) = default;
LoadConfigurationV7::~LoadConfigurationV7(void) = default;
LoadConfigurationV7::LoadConfigurationV7(void) :
LoadConfigurationV6{},
reserved3_{0},
addressof_unicode_string_{0}
{}
WIN_VERSION LoadConfigurationV7::version(void) const {
return LoadConfigurationV7::VERSION;
}
uint32_t LoadConfigurationV7::reserved3(void) const {
return this->reserved3_;
}
uint64_t LoadConfigurationV7::addressof_unicode_string(void) const {
return this->addressof_unicode_string_;
}
void LoadConfigurationV7::reserved3(uint32_t value) {
this->reserved3_ = value;
}
void LoadConfigurationV7::addressof_unicode_string(uint64_t value) {
this->addressof_unicode_string_ = value;
}
void LoadConfigurationV7::accept(Visitor& visitor) const {
visitor.visit(*static_cast<const LoadConfigurationV7*>(this));
visitor.visit(this->reserved3());
visitor.visit(this->addressof_unicode_string());
}
bool LoadConfigurationV7::operator==(const LoadConfigurationV7& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool LoadConfigurationV7::operator!=(const LoadConfigurationV7& rhs) const {
return not (*this == rhs);
}
std::ostream& LoadConfigurationV7::print(std::ostream& os) const {
LoadConfigurationV6::print(os);
os << std::setw(LoadConfiguration::PRINT_WIDTH) << std::setfill(' ') << "Reserved 3:" << std::hex << this->reserved3() << std::endl;
return os;
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,31 @@
/* 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.
*/
namespace LIEF {
namespace PE {
template<class T>
LoadConfigurationV7::LoadConfigurationV7(const load_configuration_v7<T>* header) :
LoadConfigurationV6{reinterpret_cast<const load_configuration_v6<T>*>(header)},
reserved3_{header->Reserved3},
addressof_unicode_string_{header->AddressOfSomeUnicodeString}
{
}
} // namespace PE
} // namespace LIEF

@ -0,0 +1,24 @@
/* 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 "LoadConfiguration.tcc"
#include "LoadConfigurationV0.tcc"
#include "LoadConfigurationV1.tcc"
#include "LoadConfigurationV2.tcc"
#include "LoadConfigurationV3.tcc"
#include "LoadConfigurationV4.tcc"
#include "LoadConfigurationV5.tcc"
#include "LoadConfigurationV6.tcc"
#include "LoadConfigurationV7.tcc"

@ -78,14 +78,14 @@ void Parser::init(const std::string& name) {
this->binary_->type_ = this->type_;
if (this->type_ == PE_TYPE::PE32) {
this->build<PE32>();
this->parse<PE32>();
} else {
this->build<PE64>();
this->parse<PE64>();
}
}
void Parser::build_dos_stub(void) {
void Parser::parse_dos_stub(void) {
const DosHeader& dos_header = this->binary_->dos_header();
if (dos_header.addressof_new_exeheader() < sizeof(pe_dos_header)) {
@ -102,7 +102,7 @@ void Parser::build_dos_stub(void) {
}
void Parser::build_rich_header(void) {
void Parser::parse_rich_header(void) {
VLOG(VDEBUG) << "Parsing Rich Header";
const std::vector<uint8_t>& dos_stub = this->binary_->dos_stub();
VectorStream stream{dos_stub};
@ -169,10 +169,10 @@ void Parser::build_rich_header(void) {
//
// Build PE sections
// parse PE sections
//
// TODO: Check offset etc
void Parser::build_sections(void) {
void Parser::parse_sections(void) {
VLOG(VDEBUG) << "[+] Parsing sections";
@ -234,9 +234,9 @@ void Parser::build_sections(void) {
//
// Build relocations
// parse relocations
//
void Parser::build_relocations(void) {
void Parser::parse_relocations(void) {
VLOG(VDEBUG) << "[+] Parsing relocations";
this->binary_->has_relocations_ = true;
@ -281,9 +281,9 @@ void Parser::build_relocations(void) {
//
// Build ressources
// parse ressources
//
void Parser::build_resources(void) {
void Parser::parse_resources(void) {
VLOG(VDEBUG) << "[+] Parsing resources";
this->binary_->has_resources_ = true;
@ -297,14 +297,14 @@ void Parser::build_resources(void) {
const pe_resource_directory_table* directory_table = reinterpret_cast<const pe_resource_directory_table*>(
this->stream_->read(offset, sizeof(pe_resource_directory_table)));
this->binary_->resources_ = this->build_resource_node(directory_table, offset, offset);
this->binary_->resources_ = this->parse_resource_node(directory_table, offset, offset);
}
//
// Build the resources tree
// parse the resources tree
//
ResourceNode* Parser::build_resource_node(
ResourceNode* Parser::parse_resource_node(
const pe_resource_directory_table *directory_table,
uint32_t base_offset,
uint32_t current_offset,
@ -399,7 +399,7 @@ ResourceNode* Parser::build_resource_node(
}
this->resource_visited_.insert(offset);
std::unique_ptr<ResourceNode> node{this->build_resource_node(nextDirectoryTable, base_offset, offset, depth + 1)};
std::unique_ptr<ResourceNode> node{this->parse_resource_node(nextDirectoryTable, base_offset, offset, depth + 1)};
node->id(id);
node->name(name);
directory->childs_.push_back(node.release());
@ -416,9 +416,9 @@ ResourceNode* Parser::build_resource_node(
}
//
// Build string table
// parse string table
//
void Parser::build_string_table(void) {
void Parser::parse_string_table(void) {
VLOG(VDEBUG) << "[+] Parsing string table";
uint32_t stringTableOffset =
this->binary_->header().pointerto_symbol_table() +
@ -440,9 +440,9 @@ void Parser::build_string_table(void) {
//
// Build Symbols
// parse Symbols
//
void Parser::build_symbols(void) {
void Parser::parse_symbols(void) {
VLOG(VDEBUG) << "[+] Parsing symbols";
uint32_t symbolTableOffset = this->binary_->header().pointerto_symbol_table();
uint32_t numberOfSymbols = this->binary_->header().numberof_symbols();
@ -451,7 +451,7 @@ void Parser::build_symbols(void) {
uint32_t idx = 0;
while (idx < numberOfSymbols) {
//if (offsetToNextSymbol >= this->rawBinary_.size()) {
// throw LIEF::exception("Parser::build_symbols(): Symbol offset corrupted",
// throw LIEF::exception("Parser::parse_symbols(): Symbol offset corrupted",
// LIEF::EXCEPTION_TYPES::CORRUPTED_OFFSET);
//}
//TODO: try catch
@ -542,10 +542,10 @@ void Parser::build_symbols(void) {
//
// Build Debug
// parse Debug
//
void Parser::build_debug(void) {
void Parser::parse_debug(void) {
VLOG(VDEBUG) << "[+] Parsing Debug";
this->binary_->has_debug_ = true;
@ -560,21 +560,11 @@ void Parser::build_debug(void) {
this->binary_->debug_ = {debug_struct};
}
//
// Build configuration
//
void Parser::build_configuration(void) {
VLOG(VDEBUG) << "[+] Parsing Load config";
this->binary_->has_configuration_ = true;
//uint32_t offset = rva_to_offset(this->binary_->sectionsList_, this->binary_->dataDirList_[LOAD_CONFIG_TABLE].getRVA());
//this->binary_->loadConfigure_ = *(reinterpret_cast<LoadConfiguration<uint32_t>*>(this->rawBinary_.data() + offset));
}
//
// Build Export
// parse Export
//
void Parser::build_exports(void) {
void Parser::parse_exports(void) {
VLOG(VDEBUG) << "[+] Parsing exports";
this->binary_->has_exports_ = true;
@ -670,7 +660,7 @@ void Parser::build_exports(void) {
}
void Parser::build_signature(void) {
void Parser::parse_signature(void) {
VLOG(VDEBUG) << "[+] Parsing signature";
/*** /!\ In this data directory, RVA is used as an **OFFSET** /!\ ****/
@ -1174,7 +1164,7 @@ void Parser::build_signature(void) {
}
void Parser::build_overlay(void) {
void Parser::parse_overlay(void) {
VLOG(VDEBUG) << "Parsing Overlay";
const uint64_t last_section_offset = std::accumulate(
std::begin(this->binary_->sections_),

@ -14,25 +14,28 @@
* limitations under the License.
*/
#include "easylogging++.h"
#include "LIEF/PE/LoadConfigurations.hpp"
#include "LoadConfigurations/LoadConfigurations.tcc"
namespace LIEF {
namespace PE {
template<typename PE_T>
void Parser::build(void) {
void Parser::parse(void) {
try {
this->build_headers<PE_T>();
this->parse_headers<PE_T>();
} catch (const corrupted& e) {
LOG(WARNING) << e.what();
}
VLOG(VDEBUG) << "[+] Retreive Dos stub";
this->build_dos_stub();
this->parse_dos_stub();
try {
this->build_rich_header();
this->parse_rich_header();
} catch (const corrupted& e) {
LOG(WARNING) << e.what();
}
@ -40,29 +43,29 @@ void Parser::build(void) {
VLOG(VDEBUG) << "[+] Decomposing Sections";
try {
this->build_sections();
this->parse_sections();
} catch (const corrupted& e) {
LOG(WARNING) << e.what();
}
VLOG(VDEBUG) << "[+] Decomposing Data directories";
try {
this->build_data_directories<PE_T>();
this->parse_data_directories<PE_T>();
} catch (const exception& e) {
LOG(WARNING) << e.what();
}
try {
this->build_symbols();
this->parse_symbols();
} catch (const corrupted& e) {
LOG(WARNING) << e.what();
}
this->build_overlay();
this->parse_overlay();
}
template<typename PE_T>
void Parser::build_headers(void) {
void Parser::parse_headers(void) {
using pe_optional_header = typename PE_T::pe_optional_header;
//DOS Header
@ -97,7 +100,7 @@ void Parser::build_headers(void) {
}
template<typename PE_T>
void Parser::build_data_directories(void) {
void Parser::parse_data_directories(void) {
using pe_optional_header = typename PE_T::pe_optional_header;
VLOG(VDEBUG) << "[+] Parsing data directories";
@ -150,7 +153,7 @@ void Parser::build_data_directories(void) {
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with Import Table";
}
this->build_import_table<PE_T>();
this->parse_import_table<PE_T>();
}
} catch (const exception& e) {
LOG(WARNING) << e.what();
@ -161,7 +164,7 @@ void Parser::build_data_directories(void) {
VLOG(VDEBUG) << "[+] Decomposing Exports";
try {
this->build_exports();
this->parse_exports();
} catch (const exception& e) {
LOG(WARNING) << e.what();
}
@ -170,7 +173,7 @@ void Parser::build_data_directories(void) {
// Signature
if (this->binary_->data_directory(DATA_DIRECTORY::CERTIFICATE_TABLE).RVA() > 0) {
try {
this->build_signature();
this->parse_signature();
} catch (const exception& e) {
LOG(WARNING) << e.what();
}
@ -181,12 +184,12 @@ void Parser::build_data_directories(void) {
if (this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE).RVA() > 0) {
VLOG(VDEBUG) << "[+] Decomposing TLS";
const uint32_t import_rva = this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE).RVA();
const uint64_t offset = this->binary_->rva_to_offset(import_rva);
const uint32_t tls_rva = this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE).RVA();
const uint64_t offset = this->binary_->rva_to_offset(tls_rva);
try {
Section& section = this->binary_->section_from_offset(offset);
section.add_type(PE_SECTION_TYPES::TLS);
this->build_tls<PE_T>();
this->parse_tls<PE_T>();
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with TLS";
} catch (const exception& e) {
@ -194,6 +197,23 @@ void Parser::build_data_directories(void) {
}
}
// Load Config
if (this->binary_->data_directory(DATA_DIRECTORY::LOAD_CONFIG_TABLE).RVA() > 0) {
const uint32_t load_config_rva = this->binary_->data_directory(DATA_DIRECTORY::LOAD_CONFIG_TABLE).RVA();
const uint64_t offset = this->binary_->rva_to_offset(load_config_rva);
try {
Section& section = this->binary_->section_from_offset(offset);
section.add_type(PE_SECTION_TYPES::LOAD_CONFIG);
this->parse_load_config<PE_T>();
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with Load Config";
} catch (const exception& e) {
LOG(WARNING) << e.what();
}
}
// Relocations
if (this->binary_->data_directory(DATA_DIRECTORY::BASE_RELOCATION_TABLE).RVA() > 0) {
@ -203,7 +223,7 @@ void Parser::build_data_directories(void) {
try {
Section& section = this->binary_->section_from_offset(offset);
section.add_type(PE_SECTION_TYPES::RELOCATION);
this->build_relocations();
this->parse_relocations();
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with relocations";
} catch (const exception& e) {
@ -221,7 +241,7 @@ void Parser::build_data_directories(void) {
try {
Section& section = this->binary_->section_from_offset(offset);
section.add_type(PE_SECTION_TYPES::DEBUG);
this->build_debug();
this->parse_debug();
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with debug";
} catch (const exception& e) {
@ -239,7 +259,7 @@ void Parser::build_data_directories(void) {
try {
Section& section = this->binary_->section_from_offset(offset);
section.add_type(PE_SECTION_TYPES::RESOURCE);
this->build_resources();
this->parse_resources();
} catch (const not_found&) {
LOG(WARNING) << "Unable to find the section associated with resources";
} catch (const exception& e) {
@ -250,7 +270,7 @@ void Parser::build_data_directories(void) {
}
template<typename PE_T>
void Parser::build_import_table(void) {
void Parser::parse_import_table(void) {
using uint__ = typename PE_T::uint;
this->binary_->has_imports_ = true;
@ -349,7 +369,7 @@ void Parser::build_import_table(void) {
}
template<typename PE_T>
void Parser::build_tls(void) {
void Parser::parse_tls(void) {
using pe_tls = typename PE_T::pe_tls;
using uint__ = typename PE_T::uint;
@ -414,7 +434,142 @@ void Parser::build_tls(void) {
} catch (const not_found&) {
LOG(WARNING) << "No section associated with TLS";
}
}
template<typename PE_T>
void Parser::parse_load_config(void) {
using load_configuration_t = typename PE_T::load_configuration_t;
using load_configuration_v0_t = typename PE_T::load_configuration_v0_t;
using load_configuration_v1_t = typename PE_T::load_configuration_v1_t;
using load_configuration_v2_t = typename PE_T::load_configuration_v2_t;
using load_configuration_v3_t = typename PE_T::load_configuration_v3_t;
using load_configuration_v4_t = typename PE_T::load_configuration_v4_t;
using load_configuration_v5_t = typename PE_T::load_configuration_v5_t;
using load_configuration_v6_t = typename PE_T::load_configuration_v6_t;
using load_configuration_v7_t = typename PE_T::load_configuration_v7_t;
VLOG(VDEBUG) << "[+] Parsing Load Config";
const uint32_t directory_size = this->binary_->data_directory(DATA_DIRECTORY::LOAD_CONFIG_TABLE).size();
const uint32_t ldc_rva = this->binary_->data_directory(DATA_DIRECTORY::LOAD_CONFIG_TABLE).RVA();
const uint64_t offset = this->binary_->rva_to_offset(ldc_rva);
const uint32_t size_from_header = this->stream_->read_integer<uint32_t>(offset);
if (directory_size != size_from_header) {
LOG(WARNING) << "The size of directory '" << to_string(DATA_DIRECTORY::LOAD_CONFIG_TABLE)
<< "' is different from the size in the load configuration header";
}
const uint32_t size = std::min<uint32_t>(directory_size, size_from_header);
size_t current_size = 0;
WIN_VERSION version_found = WIN_VERSION::WIN_UNKNOWN;
for (auto&& p : PE_T::load_configuration_sizes) {
if (p.second > current_size and p.second <= size) {
std::tie(version_found, current_size) = p;
}
}
VLOG(VDEBUG) << "Version found: " << std::dec << to_string(version_found) << "(Size: 0x" << std::hex << size << ")";
std::unique_ptr<LoadConfiguration> ld_conf;
switch (version_found) {
case WIN_VERSION::WIN_SEH:
{
const load_configuration_v0_t* header = reinterpret_cast<const load_configuration_v0_t*>(
this->stream_->read(offset, sizeof(load_configuration_v0_t)));
ld_conf = std::unique_ptr<LoadConfigurationV0>{new LoadConfigurationV0{header}};
break;
}
case WIN_VERSION::WIN8_1:
{
const load_configuration_v1_t* header = reinterpret_cast<const load_configuration_v1_t*>(
this->stream_->read(offset, sizeof(load_configuration_v1_t)));
ld_conf = std::unique_ptr<LoadConfigurationV1>{new LoadConfigurationV1{header}};
break;
}
case WIN_VERSION::WIN10_0_9879:
{
const load_configuration_v2_t* header = reinterpret_cast<const load_configuration_v2_t*>(
this->stream_->read(offset, sizeof(load_configuration_v2_t)));
ld_conf = std::unique_ptr<LoadConfigurationV2>{new LoadConfigurationV2{header}};
break;
}
case WIN_VERSION::WIN10_0_14286:
{
const load_configuration_v3_t* header = reinterpret_cast<const load_configuration_v3_t*>(
this->stream_->read(offset, sizeof(load_configuration_v3_t)));
ld_conf = std::unique_ptr<LoadConfigurationV3>{new LoadConfigurationV3{header}};
break;
}
case WIN_VERSION::WIN10_0_14383:
{
const load_configuration_v4_t* header = reinterpret_cast<const load_configuration_v4_t*>(
this->stream_->read(offset, sizeof(load_configuration_v4_t)));
ld_conf = std::unique_ptr<LoadConfigurationV4>{new LoadConfigurationV4{header}};
break;
}
case WIN_VERSION::WIN10_0_14901:
{
const load_configuration_v5_t* header = reinterpret_cast<const load_configuration_v5_t*>(
this->stream_->read(offset, sizeof(load_configuration_v5_t)));
ld_conf = std::unique_ptr<LoadConfigurationV5>{new LoadConfigurationV5{header}};
break;
}
case WIN_VERSION::WIN10_0_15002:
{
const load_configuration_v6_t* header = reinterpret_cast<const load_configuration_v6_t*>(
this->stream_->read(offset, sizeof(load_configuration_v6_t)));
ld_conf = std::unique_ptr<LoadConfigurationV6>{new LoadConfigurationV6{header}};
break;
}
case WIN_VERSION::WIN10_0_16237:
{
const load_configuration_v7_t* header = reinterpret_cast<const load_configuration_v7_t*>(
this->stream_->read(offset, sizeof(load_configuration_v7_t)));
ld_conf = std::unique_ptr<LoadConfigurationV7>{new LoadConfigurationV7{header}};
break;
}
case WIN_VERSION::WIN_UNKNOWN:
default:
{
const load_configuration_t* header = reinterpret_cast<const load_configuration_t*>(
this->stream_->read(offset, sizeof(load_configuration_t)));
ld_conf = std::unique_ptr<LoadConfiguration>{new LoadConfiguration{header}};
}
}
this->binary_->load_configuration_ = ld_conf.release();
this->binary_->has_configuration_ = true;
}
}
}
}

@ -286,18 +286,22 @@ void Visitor::visit(const PE::Signature& signature) {
signature.accept(*this);
}
void Visitor::visit(const PE::x509& x509) {
x509.accept(*this);
}
void Visitor::visit(const PE::SignerInfo& signer_info) {
signer_info.accept(*this);
}
void Visitor::visit(const PE::ContentInfo& content_info) {
content_info.accept(*this);
}
void Visitor::visit(const PE::AuthenticatedAttributes& authenticated_attributes) {
authenticated_attributes.accept(*this);
}
@ -305,6 +309,47 @@ void Visitor::visit(const PE::AuthenticatedAttributes& authenticated_attributes)
void Visitor::visit(const PE::issuer_t&) {
}
void Visitor::visit(const PE::LoadConfiguration& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV0& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV1& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV2& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV3& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV4& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV5& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV6& config) {
config.accept(*this);
}
void Visitor::visit(const PE::LoadConfigurationV7& config) {
config.accept(*this);
}
void Visitor::visit(const PE::CodeIntegrity& code_integrity) {
code_integrity.accept(*this);
}
// MachO part
// ----------

@ -123,5 +123,40 @@ vector_iostream& vector_iostream::seekp(vector_iostream::off_type p, std::ios_ba
return *this;
}
// Prefixbuf
prefixbuf::prefixbuf(std::string const& prefix, std::streambuf* sbuf) :
prefix{prefix},
sbuf{sbuf},
need_prefix{true}
{}
int prefixbuf::sync() {
return this->sbuf->pubsync();
}
int prefixbuf::overflow(int c) {
if (c != std::char_traits<char>::eof()) {
if (this->need_prefix and not this->prefix.empty() and
this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
return std::char_traits<char>::eof();
}
this->need_prefix = c == '\n';
}
return this->sbuf->sputc(c);
}
oprefixstream::oprefixstream(std::string const& prefix, std::ostream& out) :
prefixbuf(prefix, out.rdbuf()),
std::ios(static_cast<std::streambuf*>(this)),
std::ostream(static_cast<std::streambuf*>(this))
{}
}

@ -137,6 +137,15 @@ void JsonVisitor::visit(const Binary& binary) {
this->node_["signature"] = visitor.get();
}
// Load Configuration
if (binary.has_configuration()) {
JsonVisitor visitor;
const LoadConfiguration& config = binary.load_configuration();
config.accept(visitor);
visitor.visit(config);
this->node_["load_configuration"] = visitor.get();
}
}
@ -645,6 +654,93 @@ void JsonVisitor::visit(const AuthenticatedAttributes& auth) {
this->node_["message_digest"] = auth.message_digest();
}
void JsonVisitor::visit(const CodeIntegrity& code_integrity) {
this->node_["flags"] = code_integrity.flags();
this->node_["catalog"] = code_integrity.catalog();
this->node_["catalog_offset"] = code_integrity.catalog_offset();
this->node_["reserved"] = code_integrity.reserved();
}
void JsonVisitor::visit(const LoadConfiguration& config) {
this->node_["version"] = to_string(config.version());
this->node_["characteristics"] = config.characteristics();
this->node_["timedatestamp"] = config.timedatestamp();
this->node_["major_version"] = config.major_version();
this->node_["minor_version"] = config.minor_version();
this->node_["global_flags_clear"] = config.global_flags_clear();
this->node_["global_flags_set"] = config.global_flags_set();
this->node_["critical_section_default_timeout"] = config.critical_section_default_timeout();
this->node_["decommit_free_block_threshold"] = config.decommit_free_block_threshold();
this->node_["decommit_total_free_threshold"] = config.decommit_total_free_threshold();
this->node_["lock_prefix_table"] = config.lock_prefix_table();
this->node_["maximum_allocation_size"] = config.maximum_allocation_size();
this->node_["virtual_memory_threshold"] = config.virtual_memory_threshold();
this->node_["process_affinity_mask"] = config.process_affinity_mask();
this->node_["process_heap_flags"] = config.process_heap_flags();
this->node_["csd_version"] = config.csd_version();
this->node_["reserved1"] = config.reserved1();
this->node_["editlist"] = config.editlist();
this->node_["security_cookie"] = config.security_cookie();
config.accept(*this);
}
void JsonVisitor::visit(const LoadConfigurationV0& config) {
this->node_["se_handler_table"] = config.se_handler_table();
this->node_["se_handler_count"] = config.se_handler_count();
}
void JsonVisitor::visit(const LoadConfigurationV1& config) {
this->node_["guard_cf_check_function_pointer"] = config.guard_cf_check_function_pointer();
this->node_["guard_cf_dispatch_function_pointer"] = config.guard_cf_dispatch_function_pointer();
this->node_["guard_cf_function_table"] = config.guard_cf_function_table();
this->node_["guard_cf_function_count"] = config.guard_cf_function_count();
this->node_["guard_flags"] = config.guard_flags();
this->visit(static_cast<const LoadConfigurationV0&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV2& config) {
JsonVisitor code_integrity_visitor;
code_integrity_visitor(config.code_integrity());
this->node_["code_integrity"] = code_integrity_visitor.get();
this->visit(static_cast<const LoadConfigurationV1&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV3& config) {
this->node_["guard_address_taken_iat_entry_table"] = config.guard_address_taken_iat_entry_table();
this->node_["guard_address_taken_iat_entry_count"] = config.guard_address_taken_iat_entry_count();
this->node_["guard_long_jump_target_table"] = config.guard_long_jump_target_table();
this->node_["guard_long_jump_target_count"] = config.guard_long_jump_target_count();
this->visit(static_cast<const LoadConfigurationV2&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV4& config) {
this->node_["dynamic_value_reloc_table"] = config.dynamic_value_reloc_table();
this->node_["hybrid_metadata_pointer"] = config.hybrid_metadata_pointer();
this->visit(static_cast<const LoadConfigurationV3&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV5& config) {
this->node_["guard_rf_failure_routine"] = config.guard_rf_failure_routine();
this->node_["guard_rf_failure_routine_function_pointer"] = config.guard_rf_failure_routine_function_pointer();
this->node_["dynamic_value_reloctable_offset"] = config.dynamic_value_reloctable_offset();
this->node_["dynamic_value_reloctable_section"] = config.dynamic_value_reloctable_section();
this->node_["reserved2"] = config.guard_rf_failure_routine();
this->visit(static_cast<const LoadConfigurationV4&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV6& config) {
this->node_["guard_rf_verify_stackpointer_function_pointer"] = config.guard_rf_verify_stackpointer_function_pointer();
this->node_["hotpatch_table_offset"] = config.hotpatch_table_offset();
this->visit(static_cast<const LoadConfigurationV5&>(config));
}
void JsonVisitor::visit(const LoadConfigurationV7& config) {
this->node_["reserved3"] = config.reserved3();
this->node_["addressof_unicode_string"] = config.addressof_unicode_string();
this->visit(static_cast<const LoadConfigurationV6&>(config));
}
// LIEF Abstract
void JsonVisitor::visit(const LIEF::Binary& binary) {

@ -139,6 +139,10 @@ if (PYTHON_TESTS_ENABLED)
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_builder.py")
ADD_PYTHON_TEST(PE_PYTHON_load_configuration
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_loadconfig.py")
endif()

@ -0,0 +1,99 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import lief
import unittest
import logging
import os
import sys
import random
from unittest import TestCase
from utils import get_sample
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.INFO)
class TestLoadConfig(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
def test_winapp(self):
winapp = lief.parse(get_sample('PE/PE64_x86-64_binary_WinApp.exe'))
self.assertTrue(winapp.has_configuration)
lconf = winapp.load_configuration
self.assertEqual(lconf.version, lief.PE.WIN_VERSION.WIN10_0_15002)
self.assertEqual(lconf.characteristics, 0xF8)
self.assertEqual(lconf.timedatestamp, 0)
self.assertEqual(lconf.major_version, 0)
self.assertEqual(lconf.minor_version, 0)
self.assertEqual(lconf.global_flags_clear, 0)
self.assertEqual(lconf.global_flags_set, 0)
self.assertEqual(lconf.critical_section_default_timeout, 0)
self.assertEqual(lconf.decommit_free_block_threshold, 0)
self.assertEqual(lconf.decommit_total_free_threshold, 0)
self.assertEqual(lconf.lock_prefix_table, 0)
self.assertEqual(lconf.maximum_allocation_size, 0)
self.assertEqual(lconf.virtual_memory_threshold, 0)
self.assertEqual(lconf.process_affinity_mask, 0)
self.assertEqual(lconf.process_heap_flags, 0)
self.assertEqual(lconf.csd_version, 0)
self.assertEqual(lconf.reserved1, 0)
self.assertEqual(lconf.editlist, 0)
self.assertEqual(lconf.security_cookie, 0x4000d008)
# V0
self.assertEqual(lconf.se_handler_table, 0)
self.assertEqual(lconf.se_handler_count, 0)
# V1
self.assertEqual(lconf.guard_cf_check_function_pointer, 0x140012000)
self.assertEqual(lconf.guard_cf_dispatch_function_pointer, 0x140012010)
self.assertEqual(lconf.guard_cf_function_table, 0x140011000)
self.assertEqual(lconf.guard_cf_function_count, 15)
self.assertEqual(lconf.guard_flags, 0x10500)
# V2
code_integrity = lconf.code_integrity
self.assertEqual(code_integrity.flags, 0)
self.assertEqual(code_integrity.catalog, 0)
self.assertEqual(code_integrity.catalog_offset, 0)
self.assertEqual(code_integrity.reserved, 0)
# V3
self.assertEqual(lconf.guard_address_taken_iat_entry_table, 0)
self.assertEqual(lconf.guard_address_taken_iat_entry_count, 0)
self.assertEqual(lconf.guard_long_jump_target_table, 0)
self.assertEqual(lconf.guard_long_jump_target_count, 0)
# V4
self.assertEqual(lconf.dynamic_value_reloc_table, 0)
self.assertEqual(lconf.hybrid_metadata_pointer, 0)
# V5
self.assertEqual(lconf.guard_rf_failure_routine, 0x140001040)
self.assertEqual(lconf.guard_rf_failure_routine_function_pointer, 0x140012020)
self.assertEqual(lconf.dynamic_value_reloctable_offset, 0)
self.assertEqual(lconf.dynamic_value_reloctable_section, 0)
self.assertEqual(lconf.reserved2, 0)
# V6
self.assertEqual(lconf.guard_rf_verify_stackpointer_function_pointer, 0x140012030)
self.assertEqual(lconf.hotpatch_table_offset, 0)
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)