diff --git a/.github/deploy.py b/.github/deploy.py index 0628274..4851b91 100644 --- a/.github/deploy.py +++ b/.github/deploy.py @@ -105,7 +105,7 @@ else: CI_PRETTY_NAME = pretty_ci_name(CURRENT_CI) logger.info("CI: %s", CI_PRETTY_NAME) -ALLOWED_BRANCHES = {"master", "deploy", "devel"} +ALLOWED_BRANCHES = {"master", "deploy", "devel", "enhancement/pe-authenticode"} BRANCH_NAME = get_branch(CURRENT_CI) logger.info("Branch: %s", BRANCH_NAME) if BRANCH_NAME not in ALLOWED_BRANCHES: @@ -175,13 +175,29 @@ if DEPLOY_IV is None: # Clone package repo ##################### target_branch = "gh-pages" if BRANCH_NAME == "master" else "packages-{}".format(BRANCH_NAME) +new_branch = False if not LIEF_PACKAGE_DIR.is_dir(): cmd = "{} clone --branch={} -j8 --single-branch {} {}".format(GIT, target_branch, LIEF_PACKAGE_REPO, LIEF_PACKAGE_DIR) p = subprocess.Popen(cmd, shell=True, cwd=REPODIR, stderr=subprocess.STDOUT) p.wait() if p.returncode: - sys.exit(1) + cmd = "{} clone --branch=master -j8 --single-branch {} {}".format(GIT, LIEF_PACKAGE_REPO, LIEF_PACKAGE_DIR) + pmaster = subprocess.Popen(cmd, shell=True, cwd=REPODIR, stderr=subprocess.STDOUT) + pmaster.wait() + if pmaster.returncode: + sys.exit(1) + new_branch = True + + cmd = "{} checkout --orphan {}".format(GIT, target_branch) + pmaster = subprocess.Popen(cmd, shell=True, cwd=LIEF_PACKAGE_DIR, stderr=subprocess.STDOUT) + pmaster.wait() + if pmaster.returncode: + sys.exit(1) + + cmd = "{} reset --hard".format(GIT) + pmaster = subprocess.Popen(cmd, shell=True, cwd=LIEF_PACKAGE_DIR, stderr=subprocess.STDOUT) + pmaster.wait() SDK_PACKAGE_DIR.mkdir(exist_ok=True) PYPI_PACKAGE_DIR.mkdir(exist_ok=True) @@ -261,10 +277,6 @@ html = Template(INDEX_TEMPLATE).render(names=fnames, base_url=BASE_URL, base="pa with open((SDK_PACKAGE_DIR / "index.html").as_posix(), "w") as f: f.write(html) - - - - if not SSH_DIR.is_dir(): SSH_DIR.mkdir(mode=0o700) diff --git a/CMakeLists.txt b/CMakeLists.txt index f55ebee..dce1bde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,8 @@ set(LIBLIEF_SOURCE_FILES "${mbedtls_src_x509}" "${mbedtls_src_tls}" "${LIBFUZZER_SRC_FILES}" + "${CMAKE_CURRENT_SOURCE_DIR}/src/errors.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/hash_stream.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/logging.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/exception.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/iostream.cpp" @@ -121,6 +123,7 @@ set(LIBLIEF_SOURCE_FILES # Grouping basic headers together # =============================== set(LIEF_INC_FILES + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/errors.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/Abstract.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/exception.hpp" @@ -139,6 +142,7 @@ set(LIEF_INC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/BinaryStream.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/VectorStream.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/Convert.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/hash_stream.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/frozen.hpp") set(LIEF_VISITOR_INCLUDE_FILES @@ -284,10 +288,9 @@ list(APPEND LIEF_PUBLIC_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/" "${CMAKE_CURRENT_BINARY_DIR}/include/") list(APPEND LIEF_PRIVATE_INCLUDE_DIR "${LIEF_PUBLIC_INCLUDE_DIR}" - "${LIBRANG_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" - "${CMAKE_BINARY_DIR}") + "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_BINARY_DIR}") -configure_file(${PROJECT_SOURCE_DIR}/LIEF.pc.in ${PROJECT_BINARY_DIR}/LIEF.pc +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/LIEF.pc.in ${CMAKE_CURRENT_BINARY_DIR}/LIEF.pc @ONLY) # Grouping external projects @@ -322,6 +325,15 @@ if(LIEF_FROZEN_ENABLED) add_dependencies(LIB_LIEF lief_frozen) endif() +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/boost/leaf/all.hpp + COMMAND + ${CMAKE_COMMAND} -E copy_directory ${LEAF_INCLUDE_DIR}/ + ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/ + DEPENDS lief_leaf) + +target_sources(LIB_LIEF PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/boost/leaf/all.hpp) + add_dependencies(LIB_LIEF lief_spdlog lief_mbed_tls) # Flags definition @@ -351,7 +363,8 @@ target_compile_definitions(LIB_LIEF PUBLIC -D_GLIBCXX_USE_CXX11_ABI=1) # SpcSpAgencyInfo Critical Extension, which mbed TLS doesn't support, so set # MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this # extension. -add_definitions(-DMBEDTLS_MD2_C -DMBEDTLS_MD4_C +add_definitions(-DMBEDTLS_MD2_C -DMBEDTLS_MD4_C -DMBEDTLS_PEM_PARSE_C + -DMBEDTLS_X509_CRT_PARSE_C -DMBEDTLS_PEM_WRITE_C -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) # ASAN - LSAN - TSAN - USAN @@ -496,6 +509,7 @@ endif() # Tests # ====================== + if(LIEF_TESTS) enable_testing() add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests") @@ -584,7 +598,7 @@ install( COMPONENT config) install( - FILES ${PROJECT_BINARY_DIR}/LIEF.pc + FILES ${CMAKE_BINARY_DIR}/LIEF.pc DESTINATION lib/pkgconfig COMPONENT libraries) diff --git a/api/python/Abstract/objects/pyBinary.cpp b/api/python/Abstract/objects/pyBinary.cpp index 68ec32a..e690924 100644 --- a/api/python/Abstract/objects/pyBinary.cpp +++ b/api/python/Abstract/objects/pyBinary.cpp @@ -181,8 +181,8 @@ void create(py::module& m) { .def("xref", &Binary::xref, - "Return all **virtual address** that *use* the ``address`` given in parameter" - "virtual_address"_a) + "Return all **virtual addresses** that *use* the ``address`` given in parameter", + "virtual_address"_a) .def("__str__", [] (const Binary& binary) diff --git a/api/python/PE/CMakeLists.txt b/api/python/PE/CMakeLists.txt index a853a79..e553f4d 100644 --- a/api/python/PE/CMakeLists.txt +++ b/api/python/PE/CMakeLists.txt @@ -16,12 +16,6 @@ set(LIEF_PYTHON_PE_SRC "${CMAKE_CURRENT_LIST_DIR}/objects/resources/pyResourceStringTable.cpp" "${CMAKE_CURRENT_LIST_DIR}/objects/resources/pyResourceAccelerator.cpp" - "${CMAKE_CURRENT_LIST_DIR}/objects/signature/pySignerInfo.cpp" - "${CMAKE_CURRENT_LIST_DIR}/objects/signature/pyAuthenticatedAttributes.cpp" - "${CMAKE_CURRENT_LIST_DIR}/objects/signature/pyx509.cpp" - "${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" @@ -62,6 +56,6 @@ target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_PE_SRC}" "${LIEF_PYTHON_PE_HDR}") include("${CMAKE_CURRENT_LIST_DIR}/objects/LoadConfigurations/CMakeLists.txt") - +include("${CMAKE_CURRENT_LIST_DIR}/objects/signature/CMakeLists.txt") diff --git a/api/python/PE/objects/pyBinary.cpp b/api/python/PE/objects/pyBinary.cpp index 5a7e543..e13d92c 100644 --- a/api/python/PE/objects/pyBinary.cpp +++ b/api/python/PE/objects/pyBinary.cpp @@ -132,8 +132,8 @@ void create(py::module& m) { .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) ")") + .def_property_readonly("has_signatures", &Binary::has_signatures, + "``True`` if the binary has signatures (" RST_CLASS_REF(lief.PE.Signature) ")") .def_property_readonly("is_reproducible_build", &Binary::is_reproducible_build, "``True`` if the binary was compiled with a reproducible build directive (" RST_CLASS_REF(lief.PE.Debug) ")") @@ -151,11 +151,69 @@ void create(py::module& m) { "Try to predict the RVA of the given function name in the given import library name", "library"_a, "function"_a) - .def_property_readonly("signature", - static_cast(&Binary::signature), - "Return the " RST_CLASS_REF(lief.PE.Signature) " object", + .def_property_readonly("signatures", + static_cast(&Binary::signatures), + "Return an iterator over the " RST_CLASS_REF(lief.PE.Signature) " objects", py::return_value_policy::reference) + .def("authentihash", + [] (const Binary& bin, ALGORITHMS algo) { + const std::vector& data = bin.authentihash(algo); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "Compute the authentihash according to the " RST_CLASS_REF(lief.PE.ALGORITHMS) " " + "given in the first parameter", + "algorithm"_a) + + .def("verify_signature", + static_cast(&Binary::verify_signature), + R"delim( + Verify the binary against the embedded signature(s) (if any) + Firstly, it checks that the embedded signatures are correct (c.f. :meth:`lief.PE.Signature.check`) + and then it checks that the authentihash matches :attr:`lief.PE.ContentInfo.digest` + )delim") + + .def("verify_signature", + static_cast(&Binary::verify_signature), + R"delim( + Verify the binary with the Signature object provided in the first parameter + It can be used to verify a detached signature: + + .. code-block:: python + + detached = lief.PE.Signature.parse("sig.pkcs7") + binary.verify_signature(detached) + )delim", + "signature"_a) + + .def_property_readonly("authentihash_md5", + [] (const Binary& bin) { + const std::vector& data = bin.authentihash(ALGORITHMS::MD5); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "Authentihash **MD5** value") + + .def_property_readonly("authentihash_sha1", + [] (const Binary& bin) { + const std::vector& data = bin.authentihash(ALGORITHMS::SHA_1); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "Authentihash **SHA1** value") + + .def_property_readonly("authentihash_sha256", + [] (const Binary& bin) { + const std::vector& data = bin.authentihash(ALGORITHMS::SHA_256); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "Authentihash **SHA-256** value") + + .def_property_readonly("authentihash_sha512", + [] (const Binary& bin) { + const std::vector& data = bin.authentihash(ALGORITHMS::SHA_512); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "Authentihash **SHA-512** value") + .def_property_readonly("debug", static_cast(&Binary::debug), "Return the " RST_CLASS_REF(lief.PE.Debug) "", diff --git a/api/python/PE/objects/signature/CMakeLists.txt b/api/python/PE/objects/signature/CMakeLists.txt new file mode 100644 index 0000000..48c5923 --- /dev/null +++ b/api/python/PE/objects/signature/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LIEF_PYTHON_PE_SIG_SRC + "${CMAKE_CURRENT_LIST_DIR}/pySignerInfo.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyAttribute.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyx509.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyContentInfo.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pySignature.cpp" +) + +source_group("Header Files\\PE\\signature" FILES ${LIEF_PYTHON_PE_SIG_SRC}) + +target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}") +target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_PE_SIG_SRC}) + +include("${CMAKE_CURRENT_LIST_DIR}/attributes/CMakeLists.txt") diff --git a/api/python/PE/objects/signature/attributes/CMakeLists.txt b/api/python/PE/objects/signature/attributes/CMakeLists.txt new file mode 100644 index 0000000..e917910 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/CMakeLists.txt @@ -0,0 +1,19 @@ +set(LIEF_PYTHON_PE_SIG_ATTR_SRC + "${CMAKE_CURRENT_LIST_DIR}/pyMsCounterSign.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyContentType.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyGenericType.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pySpcSpOpusInfo.cpp" + + "${CMAKE_CURRENT_LIST_DIR}/pyMsSpcStatementType.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyMsSpcNestedSignature.cpp" + + "${CMAKE_CURRENT_LIST_DIR}/pyPKCS9SigningTime.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyPKCS9MessageDigest.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyPKCS9AtSequenceNumber.cpp" + "${CMAKE_CURRENT_LIST_DIR}/pyPKCS9CounterSignature.cpp" +) + +source_group("Header Files\\PE\\signature\\attributes" FILES ${LIEF_PYTHON_PE_SIG_ATTR_SRC}) + +target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}") +target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_PE_SIG_ATTR_SRC}) diff --git a/api/python/PE/objects/signature/attributes/pyContentType.cpp b/api/python/PE/objects/signature/attributes/pyContentType.cpp new file mode 100644 index 0000000..6937768 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyContentType.cpp @@ -0,0 +1,50 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/ContentType.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (ContentType::*)(void) const; + +template +using setter_t = void (ContentType::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "ContentType") + .def_property_readonly("oid", + &ContentType::oid) + + .def("__hash__", + [] (const ContentType& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &ContentType::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyGenericType.cpp b/api/python/PE/objects/signature/attributes/pyGenericType.cpp new file mode 100644 index 0000000..5d10570 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyGenericType.cpp @@ -0,0 +1,53 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/GenericType.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (GenericType::*)(void) const; + +template +using setter_t = void (GenericType::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "GenericType") + .def_property_readonly("oid", + &GenericType::oid) + + .def_property_readonly("raw_content", + &GenericType::raw_content) + + .def("__hash__", + [] (const GenericType& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &GenericType::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyMsCounterSign.cpp b/api/python/PE/objects/signature/attributes/pyMsCounterSign.cpp new file mode 100644 index 0000000..680a8b6 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyMsCounterSign.cpp @@ -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. + */ +#include +#include + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/MsCounterSign.hpp" + +#include "pyPE.hpp" + +namespace LIEF { +namespace PE { + +} +} + diff --git a/api/python/PE/objects/signature/attributes/pyMsSpcNestedSignature.cpp b/api/python/PE/objects/signature/attributes/pyMsSpcNestedSignature.cpp new file mode 100644 index 0000000..17acd53 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyMsSpcNestedSignature.cpp @@ -0,0 +1,51 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (MsSpcNestedSignature::*)(void) const; + +template +using setter_t = void (MsSpcNestedSignature::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "MsSpcNestedSignature") + .def_property_readonly("signature", + &MsSpcNestedSignature::sig, + py::return_value_policy::reference) + + .def("__hash__", + [] (const MsSpcNestedSignature& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &MsSpcNestedSignature::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyMsSpcStatementType.cpp b/api/python/PE/objects/signature/attributes/pyMsSpcStatementType.cpp new file mode 100644 index 0000000..1602f14 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyMsSpcStatementType.cpp @@ -0,0 +1,50 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/MsSpcStatementType.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (MsSpcStatementType::*)(void) const; + +template +using setter_t = void (MsSpcStatementType::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "MsSpcStatementType") + .def_property_readonly("oid", + &MsSpcStatementType::oid) + + .def("__hash__", + [] (const MsSpcStatementType& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &MsSpcStatementType::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyPKCS9AtSequenceNumber.cpp b/api/python/PE/objects/signature/attributes/pyPKCS9AtSequenceNumber.cpp new file mode 100644 index 0000000..059d939 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyPKCS9AtSequenceNumber.cpp @@ -0,0 +1,50 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (PKCS9AtSequenceNumber::*)(void) const; + +template +using setter_t = void (PKCS9AtSequenceNumber::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "PKCS9AtSequenceNumber") + .def_property_readonly("number", + &PKCS9AtSequenceNumber::number) + + .def("__hash__", + [] (const PKCS9AtSequenceNumber& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &PKCS9AtSequenceNumber::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyPKCS9CounterSignature.cpp b/api/python/PE/objects/signature/attributes/pyPKCS9CounterSignature.cpp new file mode 100644 index 0000000..fe9a2db --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyPKCS9CounterSignature.cpp @@ -0,0 +1,50 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (PKCS9CounterSignature::*)(void) const; + +template +using setter_t = void (PKCS9CounterSignature::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "PKCS9CounterSignature") + .def_property_readonly("signers", + &PKCS9CounterSignature::signers) + + .def("__hash__", + [] (const PKCS9CounterSignature& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &PKCS9CounterSignature::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyPKCS9MessageDigest.cpp b/api/python/PE/objects/signature/attributes/pyPKCS9MessageDigest.cpp new file mode 100644 index 0000000..2afdbb5 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyPKCS9MessageDigest.cpp @@ -0,0 +1,54 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (PKCS9MessageDigest::*)(void) const; + +template +using setter_t = void (PKCS9MessageDigest::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "PKCS9MessageDigest") + .def_property_readonly("digest", + [] (const PKCS9MessageDigest& digest) -> py::object { + const std::vector& data = digest.digest(); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }) + + .def("__hash__", + [] (const PKCS9MessageDigest& obj) { + return Hash::hash(obj); + }) + + + .def("__str__", &PKCS9MessageDigest::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pyPKCS9SigningTime.cpp b/api/python/PE/objects/signature/attributes/pyPKCS9SigningTime.cpp new file mode 100644 index 0000000..c8e7c06 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pyPKCS9SigningTime.cpp @@ -0,0 +1,50 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/PKCS9SigningTime.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (PKCS9SigningTime::*)(void) const; + +template +using setter_t = void (PKCS9SigningTime::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "PKCS9SigningTime") + .def_property_readonly("time", + &PKCS9SigningTime::time) + + .def("__hash__", + [] (const PKCS9SigningTime& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &PKCS9SigningTime::print); +} + +} +} diff --git a/api/python/PE/objects/signature/attributes/pySpcSpOpusInfo.cpp b/api/python/PE/objects/signature/attributes/pySpcSpOpusInfo.cpp new file mode 100644 index 0000000..2c3b8b8 --- /dev/null +++ b/api/python/PE/objects/signature/attributes/pySpcSpOpusInfo.cpp @@ -0,0 +1,57 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (SpcSpOpusInfo::*)(void) const; + +template +using setter_t = void (SpcSpOpusInfo::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "SpcSpOpusInfo") + .def_property_readonly("program_name", + [] (const SpcSpOpusInfo& info) { + return safe_string_converter(info.program_name()); + }) + + .def_property_readonly("more_info", + [] (const SpcSpOpusInfo& info) { + return safe_string_converter(info.more_info()); + }) + + .def("__hash__", + [] (const SpcSpOpusInfo& obj) { + return Hash::hash(obj); + }) + + .def("__str__", &SpcSpOpusInfo::print); +} + +} +} diff --git a/api/python/PE/objects/signature/pyAttribute.cpp b/api/python/PE/objects/signature/pyAttribute.cpp new file mode 100644 index 0000000..033b219 --- /dev/null +++ b/api/python/PE/objects/signature/pyAttribute.cpp @@ -0,0 +1,51 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pyPE.hpp" + +#include "LIEF/PE/hash.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +#include +#include + +namespace LIEF { +namespace PE { + +template +using getter_t = T (Attribute::*)(void) const; + +template +using setter_t = void (Attribute::*)(T); + + +template<> +void create(py::module& m) { + py::class_(m, "Attribute") + .def_property_readonly("type", + &Attribute::type) + + + .def("__str__", [] (const Attribute& attr) + { + std::ostringstream stream; + //stream << config; + //std::string str = stream.str(); + return stream.str(); + }); +} + +} +} diff --git a/api/python/PE/objects/signature/pyAuthenticatedAttributes.cpp b/api/python/PE/objects/signature/pyAuthenticatedAttributes.cpp deleted file mode 100644 index 67a3d8d..0000000 --- a/api/python/PE/objects/signature/pyAuthenticatedAttributes.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* 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 -#include - -#include "LIEF/PE/hash.hpp" -#include "LIEF/utils.hpp" -#include "LIEF/PE/signature/AuthenticatedAttributes.hpp" - -#include "pyPE.hpp" - -namespace LIEF { -namespace PE { - -template -using getter_t = T (AuthenticatedAttributes::*)(void) const; - -template -using setter_t = void (AuthenticatedAttributes::*)(T); - - -template<> -void create(py::module& m) { - - py::class_(m, "AuthenticatedAttributes") - - .def_property_readonly("content_type", - &AuthenticatedAttributes::content_type, - "Should return the ``messageDigest`` OID") - - .def_property_readonly("message_digest", - &AuthenticatedAttributes::message_digest, - "Return an hash of the signed attributes") - - .def_property_readonly("program_name", - [] (const AuthenticatedAttributes& authenticated_attributes) { - return safe_string_converter(LIEF::u16tou8(authenticated_attributes.program_name())); - }, - "Return the program description (if any)") - - .def_property_readonly("more_info", - [] (const AuthenticatedAttributes& obj) { - return safe_string_converter(obj.more_info()); - }, - "Return an URL to website with more information about the signer") - - .def_property_readonly("raw", - &AuthenticatedAttributes::raw, - "Return the raw bytes associated with the AuthenticatedAttributes") - - .def("__str__", - [] (const AuthenticatedAttributes& authenticated_attributes) - { - std::ostringstream stream; - stream << authenticated_attributes; - std::string str = stream.str(); - return str; - }); -} - -} -} - diff --git a/api/python/PE/objects/signature/pyContentInfo.cpp b/api/python/PE/objects/signature/pyContentInfo.cpp index 058c48e..451c854 100644 --- a/api/python/PE/objects/signature/pyContentInfo.cpp +++ b/api/python/PE/objects/signature/pyContentInfo.cpp @@ -40,21 +40,23 @@ void create(py::module& m) { &ContentInfo::content_type, "OID of the content type. This value should match ``SPC_INDIRECT_DATA_OBJID``") - .def_property_readonly("type", - &ContentInfo::type) - - .def_property_readonly("digest_algorithm", + .def_property_readonly("digest_algorithm", &ContentInfo::digest_algorithm, - "Algorithm (OID) used to hash the file. This value should match SignerInfo.digest_algorithm and Signature.digest_algorithm") - + "Algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to hash the file. " + "This value should match " RST_ATTR_REF_FULL(SignerInfo.digest_algorithm) " and " + "" RST_ATTR_REF_FULL(Signature.digest_algorithm) "") .def_property_readonly("digest", - &ContentInfo::digest, - "The digest") + [] (const ContentInfo& info) -> py::bytes { + const std::vector& dg = info.digest(); + return py::bytes(reinterpret_cast(dg.data()), dg.size()); + }, + "The digest as ``bytes`` ") - .def_property_readonly("raw", - &ContentInfo::raw, - "Return the raw bytes associated with the ContentInfo") + .def("__hash__", + [] (const ContentInfo& info) { + return Hash::hash(info); + }) .def("__str__", [] (const ContentInfo& content_info) diff --git a/api/python/PE/objects/signature/pySignature.cpp b/api/python/PE/objects/signature/pySignature.cpp index 9023ae9..066880b 100644 --- a/api/python/PE/objects/signature/pySignature.cpp +++ b/api/python/PE/objects/signature/pySignature.cpp @@ -16,8 +16,11 @@ #include #include +#include "enums_wrapper.hpp" + #include "LIEF/PE/hash.hpp" #include "LIEF/PE/signature/Signature.hpp" +#include "LIEF/PE/signature/SignatureParser.hpp" #include "pyPE.hpp" @@ -34,7 +37,42 @@ using setter_t = void (Signature::*)(T); template<> void create(py::module& m) { - py::class_(m, "Signature") + py::class_ signature(m, "Signature"); + LIEF::enum_(signature, "VERIFICATION_FLAGS", py::arithmetic()) + .value("OK", Signature::VERIFICATION_FLAGS::OK) + .value("INVALID_SIGNER", Signature::VERIFICATION_FLAGS::INVALID_SIGNER) + .value("UNSUPPORTED_ALGORITHM", Signature::VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM) + .value("INCONSISTENT_DIGEST_ALGORITHM", Signature::VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM) + .value("CERT_NOT_FOUND", Signature::VERIFICATION_FLAGS::CERT_NOT_FOUND) + .value("CORRUPTED_CONTENT_INFO", Signature::VERIFICATION_FLAGS::CORRUPTED_CONTENT_INFO) + .value("CORRUPTED_AUTH_DATA", Signature::VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA) + .value("MISSING_PKCS9_MESSAGE_DIGEST", Signature::VERIFICATION_FLAGS::MISSING_PKCS9_MESSAGE_DIGEST) + .value("BAD_DIGEST", Signature::VERIFICATION_FLAGS::BAD_DIGEST) + .value("BAD_SIGNATURE", Signature::VERIFICATION_FLAGS::BAD_SIGNATURE) + .value("NO_SIGNATURE", Signature::VERIFICATION_FLAGS::NO_SIGNATURE); + + signature + .def_static("parse", + [] (const std::string& path) -> py::object { + auto sig = SignatureParser::parse(path); + if (not sig) { + return py::none(); + } + return py::cast(sig.value()); + }, + "Parse the DER PKCS #7 signature from the file path given in the first parameter", + "path"_a) + + .def_static("parse", + [] (const std::vector& raw, bool skip_header) -> py::object { + auto sig = SignatureParser::parse(raw, skip_header); + if (not sig) { + return py::none(); + } + return py::cast(sig.value()); + }, + "Parse the raw (DER) PKCS #7 signature given in the first parameter", + "raw"_a, "skip_header"_a = false) .def_property_readonly("version", &Signature::version, @@ -42,7 +80,8 @@ void create(py::module& m) { .def_property_readonly("digest_algorithm", &Signature::digest_algorithm, - "Return the algorithm (OID) used to sign the content of " RST_CLASS_REF(lief.PE.ContentInfo) "") + "Return the algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") \ + used to sign the content of " RST_CLASS_REF(lief.PE.ContentInfo) "") .def_property_readonly("content_info", @@ -57,24 +96,34 @@ void create(py::module& m) { py::return_value_policy::reference) - .def_property_readonly("signer_info", - &Signature::signer_info, - "Return the " RST_CLASS_REF(lief.PE.SignerInfo) "", + .def_property_readonly("signers", + &Signature::signers, + "Return an iterator over the signers: " RST_CLASS_REF(lief.PE.SignerInfo) "", py::return_value_policy::reference) + .def("check", + &Signature::check, + "Check the integrity of the signature and return a " RST_CLASS_REF(lief.PE.Signature.VERIFICATION_FLAGS) "") - .def_property_readonly("original_signature", - &Signature::original_signature, - "Return the raw original signature") + .def_property_readonly("raw_der", + [] (const Signature& sig) { + const std::vector& raw = sig.raw_der(); + return py::bytes(reinterpret_cast(raw.data()), raw.size()); + }, + "Return the raw original signature", + py::return_value_policy::reference_internal) + .def("__hash__", + [] (const Signature& obj) { + return Hash::hash(obj); + }) .def("__str__", [] (const Signature& signature) { std::ostringstream stream; stream << signature; - std::string str = stream.str(); - return str; + return stream.str(); }); } diff --git a/api/python/PE/objects/signature/pySignerInfo.cpp b/api/python/PE/objects/signature/pySignerInfo.cpp index 737fbeb..b247e3f 100644 --- a/api/python/PE/objects/signature/pySignerInfo.cpp +++ b/api/python/PE/objects/signature/pySignerInfo.cpp @@ -40,31 +40,68 @@ void create(py::module& m) { &SignerInfo::version, "Should be 1") + .def_property_readonly("serial_number", + [] (const SignerInfo& info) -> py::bytes { + const std::vector& data = info.serial_number(); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, + "The X509 serial number used to sign the signed-data") + .def_property_readonly("issuer", [] (const SignerInfo& object) { - const issuer_t& issuer = object.issuer(); - return std::pair>{safe_string_converter(std::get<0>(issuer)), std::get<1>(issuer)}; + return safe_string_converter(object.issuer()); }, "Issuer and serial number", py::return_value_policy::copy) .def_property_readonly("digest_algorithm", &SignerInfo::digest_algorithm, - "Algorithm (OID) used to hash the file. This value should match ContentInfo.digest_algorithm and Signature.digest_algorithm") + "Algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to hash the file. " + "This value should match " RST_ATTR_REF_FULL(ContentInfo.digest_algorithm) " " + "and " RST_ATTR_REF_FULL(Signature.digest_algorithm) "") - .def_property_readonly("signature_algorithm", - &SignerInfo::signature_algorithm, - "Return the signature algorithm (OID)") + .def_property_readonly("encryption_algorithm", + &SignerInfo::encryption_algorithm, + "Return algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to encrypt the digest") .def_property_readonly("encrypted_digest", - &SignerInfo::encrypted_digest, + [] (const SignerInfo& info) { + const std::vector& data = info.encrypted_digest(); + return py::bytes(reinterpret_cast(data.data()), data.size()); + }, "Return the signature created by the signing certificate's private key") .def_property_readonly("authenticated_attributes", &SignerInfo::authenticated_attributes, - "Return the " RST_CLASS_REF(lief.PE.AuthenticatedAttributes) " object", + "Return an iterator over the authenticated attributes (" + "" RST_CLASS_REF(lief.PE.Attribute) ")", py::return_value_policy::reference) + .def_property_readonly("unauthenticated_attributes", + &SignerInfo::unauthenticated_attributes, + "Return an iterator over the unauthenticated attributes (" + "" RST_CLASS_REF(lief.PE.Attribute) ")", + py::return_value_policy::reference) + + .def("get_attribute", + &SignerInfo::get_attribute, + "Return the authenticated or un-authenticated attribute matching the " + "given " RST_CLASS_REF(lief.PE.SIG_ATTRIBUTE_TYPES) " \n\n" + "It returns **the first** entry that matches the given type. If it can't be " + "found, it returns a nullptr", + "type"_a, + py::return_value_policy::reference) + + .def_property_readonly("cert", + static_cast(&SignerInfo::cert), + "" RST_CLASS_REF(lief.PE.x509) " certificate used by this signer. If it can't be found, it returns None", + py::return_value_policy::reference) + + .def("__hash__", + [] (const SignerInfo& obj) { + return Hash::hash(obj); + }) + .def("__str__", [] (const SignerInfo& signer_info) { diff --git a/api/python/PE/objects/signature/pyx509.cpp b/api/python/PE/objects/signature/pyx509.cpp index 646bea3..2ca5e66 100644 --- a/api/python/PE/objects/signature/pyx509.cpp +++ b/api/python/PE/objects/signature/pyx509.cpp @@ -16,6 +16,8 @@ #include #include +#include "enums_wrapper.hpp" + #include "LIEF/PE/hash.hpp" #include "LIEF/PE/signature/x509.hpp" @@ -34,14 +36,54 @@ using setter_t = void (x509::*)(T); template<> void create(py::module& m) { - py::class_(m, "x509") + py::class_ cls_x509(m, "x509"); + + LIEF::enum_(cls_x509, "VERIFICATION_FLAGS", py::arithmetic(), + "Verification flags associated with " RST_METH_REF(lief.PE.x509.verify) "") + .value("OK", x509::VERIFICATION_FLAGS::OK, "The verification succeed") + .value("BADCERT_EXPIRED", x509::VERIFICATION_FLAGS::BADCERT_EXPIRED, "The certificate validity has expired") + .value("BADCERT_REVOKED", x509::VERIFICATION_FLAGS::BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)") + .value("BADCERT_CN_MISMATCH", x509::VERIFICATION_FLAGS::BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN.") + .value("BADCERT_NOT_TRUSTED", x509::VERIFICATION_FLAGS::BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA.") + .value("BADCRL_NOT_TRUSTED", x509::VERIFICATION_FLAGS::BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA.") + .value("BADCRL_EXPIRED", x509::VERIFICATION_FLAGS::BADCRL_EXPIRED, "The CRL is expired.") + .value("BADCERT_MISSING", x509::VERIFICATION_FLAGS::BADCERT_MISSING, "Certificate was missing.") + .value("BADCERT_SKIP_VERIFY", x509::VERIFICATION_FLAGS::BADCERT_SKIP_VERIFY, "Certificate verification was skipped.") + .value("BADCERT_OTHERNATURE", x509::VERIFICATION_FLAGS::BADCERT_OTHER, "Other reason") + .value("BADCERT_FUTURE", x509::VERIFICATION_FLAGS::BADCERT_FUTURE, "The certificate validity starts in the future.") + .value("BADCRL_FUTURE", x509::VERIFICATION_FLAGS::BADCRL_FUTURE, "The CRL is from the future") + .value("BADCERT_KEY_USAGE", x509::VERIFICATION_FLAGS::BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension.") + .value("BADCERT_EXT_KEY_USAGE", x509::VERIFICATION_FLAGS::BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension.") + .value("BADCERT_NS_CERT_TYPE", x509::VERIFICATION_FLAGS::BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension.") + .value("BADCERT_BAD_MD", x509::VERIFICATION_FLAGS::BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash.") + .value("BADCERT_BAD_PK", x509::VERIFICATION_FLAGS::BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).") + .value("BADCERT_BAD_KEY", x509::VERIFICATION_FLAGS::BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short).") + .value("BADCRL_BAD_MD", x509::VERIFICATION_FLAGS::BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash.") + .value("BADCRL_BAD_PK", x509::VERIFICATION_FLAGS::BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).") + .value("BADCRL_BAD_KEY", x509::VERIFICATION_FLAGS::BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)."); + + cls_x509 + .def_static("parse", + static_cast(&x509::parse), + "Parse " RST_CLASS_REF(lief.PE.x509) " certificate(s) from a file path given in the first parameter.\n" + "It returns a **list** of " RST_CLASS_REF(lief.PE.x509) " objects", + "path"_a) + + .def_static("parse", + static_cast&)>(&x509::parse), + "Parse " RST_CLASS_REF(lief.PE.x509) " certificate(s) from a raw blob given in the first parameter.\n" + "It returns a **list** of " RST_CLASS_REF(lief.PE.x509) " objects", + "raw"_a) .def_property_readonly("version", &x509::version, "X.509 version. (1=v1, 2=v2, 3=v3)") .def_property_readonly("serial_number", - &x509::serial_number, + [] (const x509& crt) -> py::bytes { + const std::vector& sn = crt.serial_number(); + return py::bytes(reinterpret_cast(sn.data()), sn.size()); + }, "Unique id for certificate issued by a specific CA.") .def_property_readonly("signature_algorithm", @@ -58,14 +100,12 @@ void create(py::module& m) { &x509::valid_to, "End time of certificate validity") - .def_property_readonly("issuer", [] (const x509& object) { return safe_string_converter(object.issuer()); }, "Issuer informations") - .def_property_readonly("subject", [] (const x509& object) { return safe_string_converter(object.subject()); @@ -73,16 +113,35 @@ void create(py::module& m) { "Subject informations") .def_property_readonly("raw", - &x509::raw, + [] (const x509& crt) -> py::bytes { + const std::vector& raw = crt.raw(); + return py::bytes(reinterpret_cast(raw.data()), raw.size()); + }, "The raw bytes associated with this x509 cert (DER encoded)") + .def("verify", + static_cast(&x509::verify), + "Verify that this certificate has been used **to trust** the given certificate (" RST_CLASS_REF(lief.PE.x509) " object) " + "It returns a set of flags defined by " RST_CLASS_REF(lief.PE.x509.VERIFICATION_FLAGS) "", + "ca"_a) + + .def("is_trusted_by", + &x509::is_trusted_by, + "Verify this certificate against a list of root CA (list of " RST_CLASS_REF(lief.PE.x509) " object) " + "It returns a set of flags defined by " RST_CLASS_REF(lief.PE.x509.VERIFICATION_FLAGS) "", + "ca_list"_a) + + .def("__hash__", + [] (const x509& obj) { + return Hash::hash(obj); + }) + .def("__str__", [] (const x509& x509_crt) { std::ostringstream stream; stream << x509_crt; - std::string str = stream.str(); - return str; + return safe_string_converter(stream.str()); }); } diff --git a/api/python/PE/pyEnums.cpp b/api/python/PE/pyEnums.cpp index 694bfa6..8323240 100644 --- a/api/python/PE/pyEnums.cpp +++ b/api/python/PE/pyEnums.cpp @@ -26,1088 +26,1127 @@ namespace PE { void init_enums(py::module& m) { - LIEF::enum_(m, "PE_TYPE") - .value(PY_ENUM(LIEF::PE::PE_TYPE::PE32)) - .value(PY_ENUM(LIEF::PE::PE_TYPE::PE32_PLUS)); + LIEF::enum_(m, "PE_TYPE") + .value(PY_ENUM(PE_TYPE::PE32)) + .value(PY_ENUM(PE_TYPE::PE32_PLUS)); - LIEF::enum_(m, "MACHINE_TYPES") - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::MT_Invalid)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_AM33)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_AMD64)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_ARMNT)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM64)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_EBC)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_I386)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_IA64)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_M32R)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPS16)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPSFPU)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPSFPU16)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_POWERPC)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_POWERPCFP)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_R4000)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_SH3)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_SH3DSP)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_SH4)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_SH5)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_THUMB)) - .value(PY_ENUM(LIEF::PE::MACHINE_TYPES::IMAGE_FILE_MACHINE_WCEMIPSV2)); + LIEF::enum_(m, "MACHINE_TYPES") + .value(PY_ENUM(MACHINE_TYPES::MT_Invalid)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_UNKNOWN)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_AM33)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_AMD64)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_ARMNT)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM64)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_EBC)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_I386)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_IA64)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_M32R)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPS16)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPSFPU)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_MIPSFPU16)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_POWERPC)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_POWERPCFP)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_R4000)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_SH3)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_SH3DSP)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_SH4)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_SH5)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_THUMB)) + .value(PY_ENUM(MACHINE_TYPES::IMAGE_FILE_MACHINE_WCEMIPSV2)); - LIEF::enum_(m, "HEADER_CHARACTERISTICS", py::arithmetic()) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_RELOCS_STRIPPED)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_EXECUTABLE_IMAGE)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_LINE_NUMS_STRIPPED)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_LOCAL_SYMS_STRIPPED)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_AGGRESSIVE_WS_TRIM)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_LARGE_ADDRESS_AWARE)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_BYTES_REVERSED_LO)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_32BIT_MACHINE)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_DEBUG_STRIPPED)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_NET_RUN_FROM_SWAP)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_SYSTEM)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_DLL)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_UP_SYSTEM_ONLY)) - .value(PY_ENUM(LIEF::PE::HEADER_CHARACTERISTICS::IMAGE_FILE_BYTES_REVERSED_HI)); + LIEF::enum_(m, "HEADER_CHARACTERISTICS", py::arithmetic()) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_RELOCS_STRIPPED)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_EXECUTABLE_IMAGE)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_LINE_NUMS_STRIPPED)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_LOCAL_SYMS_STRIPPED)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_AGGRESSIVE_WS_TRIM)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_LARGE_ADDRESS_AWARE)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_BYTES_REVERSED_LO)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_32BIT_MACHINE)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_DEBUG_STRIPPED)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_NET_RUN_FROM_SWAP)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_SYSTEM)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_DLL)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_UP_SYSTEM_ONLY)) + .value(PY_ENUM(HEADER_CHARACTERISTICS::IMAGE_FILE_BYTES_REVERSED_HI)); - LIEF::enum_(m, "SUBSYSTEM") - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_NATIVE)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_GUI)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_CUI)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_OS2_CUI)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_POSIX_CUI)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_NATIVE_WINDOWS)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_APPLICATION)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_ROM)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_XBOX)) - .value(PY_ENUM(LIEF::PE::SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)); + LIEF::enum_(m, "SUBSYSTEM") + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_UNKNOWN)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_NATIVE)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_GUI)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_CUI)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_OS2_CUI)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_POSIX_CUI)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_NATIVE_WINDOWS)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_APPLICATION)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_EFI_ROM)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_XBOX)) + .value(PY_ENUM(SUBSYSTEM::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)); - LIEF::enum_(m, "DATA_DIRECTORY") - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::EXPORT_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::IMPORT_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::RESOURCE_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::EXCEPTION_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::CERTIFICATE_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::BASE_RELOCATION_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::DEBUG)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::ARCHITECTURE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::GLOBAL_PTR)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::TLS_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::LOAD_CONFIG_TABLE)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::BOUND_IMPORT)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::IAT)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::DELAY_IMPORT_DESCRIPTOR)) - .value(PY_ENUM(LIEF::PE::DATA_DIRECTORY::CLR_RUNTIME_HEADER)); + LIEF::enum_(m, "DATA_DIRECTORY") + .value(PY_ENUM(DATA_DIRECTORY::EXPORT_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::IMPORT_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::RESOURCE_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::EXCEPTION_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::CERTIFICATE_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::BASE_RELOCATION_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::DEBUG)) + .value(PY_ENUM(DATA_DIRECTORY::ARCHITECTURE)) + .value(PY_ENUM(DATA_DIRECTORY::GLOBAL_PTR)) + .value(PY_ENUM(DATA_DIRECTORY::TLS_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::LOAD_CONFIG_TABLE)) + .value(PY_ENUM(DATA_DIRECTORY::BOUND_IMPORT)) + .value(PY_ENUM(DATA_DIRECTORY::IAT)) + .value(PY_ENUM(DATA_DIRECTORY::DELAY_IMPORT_DESCRIPTOR)) + .value(PY_ENUM(DATA_DIRECTORY::CLR_RUNTIME_HEADER)); - LIEF::enum_(m, "DLL_CHARACTERISTICS", py::arithmetic()) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_SEH)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_BIND)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_APPCONTAINER)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_GUARD_CF)) - .value(PY_ENUM(LIEF::PE::DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE)); + LIEF::enum_(m, "DLL_CHARACTERISTICS", py::arithmetic()) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_SEH)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_NO_BIND)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_APPCONTAINER)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_GUARD_CF)) + .value(PY_ENUM(DLL_CHARACTERISTICS::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE)); - LIEF::enum_(m, "SECTION_CHARACTERISTICS", py::arithmetic()) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_TYPE_NO_PAD)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_CODE)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_INITIALIZED_DATA)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_OTHER)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_INFO)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_REMOVE)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_COMDAT)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_GPREL)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_PURGEABLE)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_16BIT)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_LOCKED)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_PRELOAD)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_1BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_2BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_4BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_8BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_16BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_32BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_64BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_128BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_256BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_512BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_1024BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_2048BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_4096BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_8192BYTES)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_NRELOC_OVFL)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_DISCARDABLE)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_NOT_CACHED)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_NOT_PAGED)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_SHARED)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_EXECUTE)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_READ)) - .value(PY_ENUM(LIEF::PE::SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_WRITE)); + LIEF::enum_(m, "SECTION_CHARACTERISTICS", py::arithmetic()) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_TYPE_NO_PAD)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_CODE)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_INITIALIZED_DATA)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_OTHER)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_INFO)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_REMOVE)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_COMDAT)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_GPREL)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_PURGEABLE)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_16BIT)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_LOCKED)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_PRELOAD)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_1BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_2BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_4BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_8BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_16BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_32BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_64BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_128BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_256BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_512BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_1024BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_2048BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_4096BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_ALIGN_8192BYTES)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_LNK_NRELOC_OVFL)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_DISCARDABLE)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_NOT_CACHED)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_NOT_PAGED)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_SHARED)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_EXECUTE)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_READ)) + .value(PY_ENUM(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_WRITE)); - LIEF::enum_(m, "SECTION_TYPES") - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::TEXT)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::TLS)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::IMPORT)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::DATA)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::BSS)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::RESOURCE)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::RELOCATION)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::EXPORT)) - .value(PY_ENUM(LIEF::PE::PE_SECTION_TYPES::UNKNOWN)); + LIEF::enum_(m, "SECTION_TYPES") + .value(PY_ENUM(PE_SECTION_TYPES::TEXT)) + .value(PY_ENUM(PE_SECTION_TYPES::TLS)) + .value(PY_ENUM(PE_SECTION_TYPES::IMPORT)) + .value(PY_ENUM(PE_SECTION_TYPES::DATA)) + .value(PY_ENUM(PE_SECTION_TYPES::BSS)) + .value(PY_ENUM(PE_SECTION_TYPES::RESOURCE)) + .value(PY_ENUM(PE_SECTION_TYPES::RELOCATION)) + .value(PY_ENUM(PE_SECTION_TYPES::EXPORT)) + .value(PY_ENUM(PE_SECTION_TYPES::UNKNOWN)); - LIEF::enum_(m, "SYMBOL_BASE_TYPES") - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_NULL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_VOID)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_CHAR)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_SHORT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_INT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_LONG)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_FLOAT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_DOUBLE)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_STRUCT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_UNION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_ENUM)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_MOE)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_BYTE)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_WORD)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_UINT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_DWORD)); + LIEF::enum_(m, "SYMBOL_BASE_TYPES") + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_NULL)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_VOID)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_CHAR)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_SHORT)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_INT)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_LONG)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_FLOAT)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_DOUBLE)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_STRUCT)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_UNION)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_ENUM)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_MOE)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_BYTE)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_WORD)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_UINT)) + .value(PY_ENUM(SYMBOL_BASE_TYPES::IMAGE_SYM_TYPE_DWORD)); - LIEF::enum_(m, "SYMBOL_COMPLEX_TYPES") - .value(PY_ENUM(LIEF::PE::SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_NULL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_POINTER)) - .value(PY_ENUM(LIEF::PE::SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_FUNCTION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_ARRAY)) - .value(PY_ENUM(LIEF::PE::SYMBOL_COMPLEX_TYPES::SCT_COMPLEX_TYPE_SHIFT)); + LIEF::enum_(m, "SYMBOL_COMPLEX_TYPES") + .value(PY_ENUM(SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_NULL)) + .value(PY_ENUM(SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_POINTER)) + .value(PY_ENUM(SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_FUNCTION)) + .value(PY_ENUM(SYMBOL_COMPLEX_TYPES::IMAGE_SYM_DTYPE_ARRAY)) + .value(PY_ENUM(SYMBOL_COMPLEX_TYPES::SCT_COMPLEX_TYPE_SHIFT)); - LIEF::enum_(m, "SYMBOL_SECTION_NUMBER") - .value(PY_ENUM(LIEF::PE::SYMBOL_SECTION_NUMBER::IMAGE_SYM_DEBUG)) - .value(PY_ENUM(LIEF::PE::SYMBOL_SECTION_NUMBER::IMAGE_SYM_ABSOLUTE)) - .value(PY_ENUM(LIEF::PE::SYMBOL_SECTION_NUMBER::IMAGE_SYM_UNDEFINED)); + LIEF::enum_(m, "SYMBOL_SECTION_NUMBER") + .value(PY_ENUM(SYMBOL_SECTION_NUMBER::IMAGE_SYM_DEBUG)) + .value(PY_ENUM(SYMBOL_SECTION_NUMBER::IMAGE_SYM_ABSOLUTE)) + .value(PY_ENUM(SYMBOL_SECTION_NUMBER::IMAGE_SYM_UNDEFINED)); - LIEF::enum_(m, "SYMBOL_STORAGE_CLASS") - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_END_OF_FUNCTION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_NULL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_AUTOMATIC)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_EXTERNAL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_STATIC)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_REGISTER)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_EXTERNAL_DEF)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_LABEL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNDEFINED_LABEL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNION_TAG)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_TYPE_DEFINITION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNDEFINED_STATIC)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_ENUM_TAG)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_MEMBER_OF_ENUM)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_REGISTER_PARAM)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_BIT_FIELD)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_BLOCK)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_FUNCTION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_END_OF_STRUCT)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_FILE)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_SECTION)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_WEAK_EXTERNAL)) - .value(PY_ENUM(LIEF::PE::SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_CLR_TOKEN)); + LIEF::enum_(m, "SYMBOL_STORAGE_CLASS") + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_END_OF_FUNCTION)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_NULL)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_AUTOMATIC)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_EXTERNAL)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_STATIC)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_REGISTER)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_EXTERNAL_DEF)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_LABEL)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNDEFINED_LABEL)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNION_TAG)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_TYPE_DEFINITION)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_UNDEFINED_STATIC)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_ENUM_TAG)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_MEMBER_OF_ENUM)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_REGISTER_PARAM)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_BIT_FIELD)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_BLOCK)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_FUNCTION)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_END_OF_STRUCT)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_FILE)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_SECTION)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_WEAK_EXTERNAL)) + .value(PY_ENUM(SYMBOL_STORAGE_CLASS::IMAGE_SYM_CLASS_CLR_TOKEN)); - LIEF::enum_(m, "RELOCATIONS_BASE_TYPES") - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ABSOLUTE)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGH)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_LOW)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGHLOW)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGHADJ)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_MIPS_JMPADDR)) - .value("ARM_MOV32A", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32A) - .value("ARM_MOV32", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32) - .value("RISCV_HI20", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_HI20) - .value("ARM_MOV32T", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32T) - .value("THUMB_MOV32", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_THUMB_MOV32) - .value("RISCV_LOW12I", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_LOW12I) - .value("RISCV_LOW12S", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_LOW12S) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_SECTION)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_REL)) - .value("MIPS_JMPADDR16", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_MIPS_JMPADDR16) - .value("IA64_IMM64", LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_IA64_IMM64) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_DIR64)) - .value(PY_ENUM(LIEF::PE::RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGH3ADJ)); + LIEF::enum_(m, "RELOCATIONS_BASE_TYPES") + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ABSOLUTE)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGH)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_LOW)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGHLOW)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGHADJ)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_MIPS_JMPADDR)) + .value("ARM_MOV32A", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32A) + .value("ARM_MOV32", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32) + .value("RISCV_HI20", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_HI20) + .value("ARM_MOV32T", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_ARM_MOV32T) + .value("THUMB_MOV32", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_THUMB_MOV32) + .value("RISCV_LOW12I", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_LOW12I) + .value("RISCV_LOW12S", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_RISCV_LOW12S) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_SECTION)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_REL)) + .value("MIPS_JMPADDR16", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_MIPS_JMPADDR16) + .value("IA64_IMM64", RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_IA64_IMM64) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_DIR64)) + .value(PY_ENUM(RELOCATIONS_BASE_TYPES::IMAGE_REL_BASED_HIGH3ADJ)); - LIEF::enum_(m, "DEBUG_TYPES") - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_COFF)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_CODEVIEW)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_FPO)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_MISC)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_EXCEPTION)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_FIXUP)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_OMAP_TO_SRC)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_BORLAND)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_CLSID)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_VC_FEATURE)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_POGO)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_ILTCG)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_MPX)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_REPRO)) - .value(PY_ENUM(LIEF::PE::DEBUG_TYPES::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS)); + LIEF::enum_(m, "DEBUG_TYPES") + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_UNKNOWN)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_COFF)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_CODEVIEW)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_FPO)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_MISC)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_EXCEPTION)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_FIXUP)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_OMAP_TO_SRC)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_BORLAND)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_CLSID)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_VC_FEATURE)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_POGO)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_ILTCG)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_MPX)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_REPRO)) + .value(PY_ENUM(DEBUG_TYPES::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS)); - LIEF::enum_(m, "RESOURCE_TYPES") - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::CURSOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::BITMAP)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::ICON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::MENU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::DIALOG)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::STRING)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::FONTDIR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::FONT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::ACCELERATOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::RCDATA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::MESSAGETABLE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::GROUP_CURSOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::GROUP_ICON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::VERSION)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::DLGINCLUDE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::PLUGPLAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::VXD)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::ANICURSOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::ANIICON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::HTML)) - .value(PY_ENUM(LIEF::PE::RESOURCE_TYPES::MANIFEST)); + LIEF::enum_(m, "RESOURCE_TYPES") + .value(PY_ENUM(RESOURCE_TYPES::CURSOR)) + .value(PY_ENUM(RESOURCE_TYPES::BITMAP)) + .value(PY_ENUM(RESOURCE_TYPES::ICON)) + .value(PY_ENUM(RESOURCE_TYPES::MENU)) + .value(PY_ENUM(RESOURCE_TYPES::DIALOG)) + .value(PY_ENUM(RESOURCE_TYPES::STRING)) + .value(PY_ENUM(RESOURCE_TYPES::FONTDIR)) + .value(PY_ENUM(RESOURCE_TYPES::FONT)) + .value(PY_ENUM(RESOURCE_TYPES::ACCELERATOR)) + .value(PY_ENUM(RESOURCE_TYPES::RCDATA)) + .value(PY_ENUM(RESOURCE_TYPES::MESSAGETABLE)) + .value(PY_ENUM(RESOURCE_TYPES::GROUP_CURSOR)) + .value(PY_ENUM(RESOURCE_TYPES::GROUP_ICON)) + .value(PY_ENUM(RESOURCE_TYPES::VERSION)) + .value(PY_ENUM(RESOURCE_TYPES::DLGINCLUDE)) + .value(PY_ENUM(RESOURCE_TYPES::PLUGPLAY)) + .value(PY_ENUM(RESOURCE_TYPES::VXD)) + .value(PY_ENUM(RESOURCE_TYPES::ANICURSOR)) + .value(PY_ENUM(RESOURCE_TYPES::ANIICON)) + .value(PY_ENUM(RESOURCE_TYPES::HTML)) + .value(PY_ENUM(RESOURCE_TYPES::MANIFEST)); - LIEF::enum_(m, "RESOURCE_LANGS") - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_NEUTRAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_INVARIANT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_AFRIKAANS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ALBANIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ARABIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ARMENIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ASSAMESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_AZERI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_BASQUE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_BELARUSIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_BANGLA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_BULGARIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_CATALAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_CHINESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_CROATIAN)) - .value("BOSNIAN", LIEF::PE::RESOURCE_LANGS::LANG_BOSNIAN) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_CZECH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_DANISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_DIVEHI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_DUTCH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ENGLISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ESTONIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_FAEROESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_FARSI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_FINNISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_FRENCH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_GALICIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_GEORGIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_GERMAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_GREEK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_GUJARATI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_HEBREW)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_HINDI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_HUNGARIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ICELANDIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_INDONESIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ITALIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_JAPANESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KANNADA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KASHMIRI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KAZAK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KONKANI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KOREAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_KYRGYZ)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_LATVIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_LITHUANIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MACEDONIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MALAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MALAYALAM)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MANIPURI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MARATHI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MONGOLIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_NEPALI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_NORWEGIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ORIYA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_POLISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_PORTUGUESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_PUNJABI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ROMANIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_RUSSIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SANSKRIT)) - .value("SERBIAN", LIEF::PE::RESOURCE_LANGS::LANG_SERBIAN) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SINDHI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SLOVAK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SLOVENIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SPANISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SWAHILI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SWEDISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SYRIAC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TAMIL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TATAR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TELUGU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_THAI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TURKISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_UKRAINIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_URDU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_UZBEK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_VIETNAMESE)) - .value("GAELIC", LIEF::PE::RESOURCE_LANGS::LANG_GAELIC) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MALTESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_MAORI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_RHAETO_ROMANCE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SAMI)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SORBIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_SUTU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TSONGA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TSWANA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_VENDA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_XHOSA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ZULU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_ESPERANTO)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_WALON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_CORNISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_WELSH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_BRETON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_INUKTITUT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_IRISH)) - .value("LOWER_SORBIAN", LIEF::PE::RESOURCE_LANGS::LANG_LOWER_SORBIAN) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_PULAR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_QUECHUA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TAMAZIGHT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_LANGS::LANG_TIGRINYA)) - .value("VALENCIAN", LIEF::PE::RESOURCE_LANGS::LANG_VALENCIAN); + LIEF::enum_(m, "RESOURCE_LANGS") + .value(PY_ENUM(RESOURCE_LANGS::LANG_NEUTRAL)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_INVARIANT)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_AFRIKAANS)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ALBANIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ARABIC)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ARMENIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ASSAMESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_AZERI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_BASQUE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_BELARUSIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_BANGLA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_BULGARIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_CATALAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_CHINESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_CROATIAN)) + .value("BOSNIAN", RESOURCE_LANGS::LANG_BOSNIAN) + .value(PY_ENUM(RESOURCE_LANGS::LANG_CZECH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_DANISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_DIVEHI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_DUTCH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ENGLISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ESTONIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_FAEROESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_FARSI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_FINNISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_FRENCH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_GALICIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_GEORGIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_GERMAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_GREEK)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_GUJARATI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_HEBREW)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_HINDI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_HUNGARIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ICELANDIC)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_INDONESIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ITALIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_JAPANESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KANNADA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KASHMIRI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KAZAK)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KONKANI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KOREAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_KYRGYZ)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_LATVIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_LITHUANIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MACEDONIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MALAY)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MALAYALAM)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MANIPURI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MARATHI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MONGOLIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_NEPALI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_NORWEGIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ORIYA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_POLISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_PORTUGUESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_PUNJABI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ROMANIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_RUSSIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SANSKRIT)) + .value("SERBIAN", RESOURCE_LANGS::LANG_SERBIAN) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SINDHI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SLOVAK)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SLOVENIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SPANISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SWAHILI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SWEDISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SYRIAC)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TAMIL)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TATAR)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TELUGU)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_THAI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TURKISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_UKRAINIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_URDU)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_UZBEK)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_VIETNAMESE)) + .value("GAELIC", RESOURCE_LANGS::LANG_GAELIC) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MALTESE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_MAORI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_RHAETO_ROMANCE)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SAMI)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SORBIAN)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_SUTU)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TSONGA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TSWANA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_VENDA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_XHOSA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ZULU)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_ESPERANTO)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_WALON)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_CORNISH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_WELSH)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_BRETON)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_INUKTITUT)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_IRISH)) + .value("LOWER_SORBIAN", RESOURCE_LANGS::LANG_LOWER_SORBIAN) + .value(PY_ENUM(RESOURCE_LANGS::LANG_PULAR)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_QUECHUA)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TAMAZIGHT)) + .value(PY_ENUM(RESOURCE_LANGS::LANG_TIGRINYA)) + .value("VALENCIAN", RESOURCE_LANGS::LANG_VALENCIAN); - LIEF::enum_(m, "RESOURCE_SUBLANGS") - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_AFRIKAANS_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ALBANIAN_ALBANIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ALSATIAN_FRANCE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_AMHARIC_ETHIOPIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_ALGERIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_BAHRAIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_EGYPT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_IRAQ)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_JORDAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_KUWAIT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_LEBANON)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_LIBYA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_MOROCCO)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_OMAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_QATAR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_SAUDI_ARABIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_SYRIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_TUNISIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_UAE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARABIC_YEMEN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ARMENIAN_ARMENIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ASSAMESE_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_AZERI_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_AZERI_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BASHKIR_RUSSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BASQUE_BASQUE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BELARUSIAN_BELARUS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BANGLA_BANGLADESH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BANGLA_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BRETON_FRANCE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_BULGARIAN_BULGARIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CATALAN_CATALAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CHINESE_HONGKONG)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CHINESE_MACAU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CHINESE_SIMPLIFIED)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CHINESE_SINGAPORE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CHINESE_TRADITIONAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CORSICAN_FRANCE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CROATIAN_CROATIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CUSTOM_DEFAULT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CUSTOM_UNSPECIFIED)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_CZECH_CZECH_REPUBLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DANISH_DENMARK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DARI_AFGHANISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DEFAULT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DIVEHI_MALDIVES)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DUTCH_BELGIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_DUTCH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_AUS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_BELIZE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_CAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_CARIBBEAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_EIRE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_JAMAICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_MALAYSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_NZ)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_PHILIPPINES)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_SINGAPORE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_TRINIDAD)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_UK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_US)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_ZIMBABWE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ENGLISH_IRELAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ESTONIAN_ESTONIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FAEROESE_FAROE_ISLANDS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FILIPINO_PHILIPPINES)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FINNISH_FINLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH_BELGIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH_CANADIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH_LUXEMBOURG)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH_MONACO)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH_SWISS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRENCH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_FRISIAN_NETHERLANDS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GALICIAN_GALICIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GEORGIAN_GEORGIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GERMAN_AUSTRIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GERMAN_LIECHTENSTEIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GERMAN_LUXEMBOURG)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GERMAN_SWISS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GERMAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GREEK_GREECE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GREENLANDIC_GREENLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_GUJARATI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_HAUSA_NIGERIA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_HEBREW_ISRAEL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_HINDI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_HUNGARIAN_HUNGARY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ICELANDIC_ICELAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_IGBO_NIGERIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_INDONESIAN_INDONESIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_INUKTITUT_CANADA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_INUKTITUT_CANADA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_IRISH_IRELAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ITALIAN_SWISS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ITALIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_JAPANESE_JAPAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KANNADA_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KASHMIRI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KASHMIRI_SASIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KAZAK_KAZAKHSTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KHMER_CAMBODIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KICHE_GUATEMALA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KINYARWANDA_RWANDA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KONKANI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KOREAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_KYRGYZ_KYRGYZSTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LAO_LAO)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LATVIAN_LATVIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LITHUANIAN_CLASSIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LITHUANIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LOWER_SORBIAN_GERMANY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_LUXEMBOURGISH_LUXEMBOURG)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MACEDONIAN_MACEDONIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MALAY_BRUNEI_DARUSSALAM)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MALAY_MALAYSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MALAYALAM_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MALTESE_MALTA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MAORI_NEW_ZEALAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MAPUDUNGUN_CHILE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MARATHI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MOHAWK_MOHAWK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_MONGOLIAN_PRC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_NEPALI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_NEPALI_NEPAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_NEUTRAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_NORWEGIAN_BOKMAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_NORWEGIAN_NYNORSK)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_OCCITAN_FRANCE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ORIYA_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PASHTO_AFGHANISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PERSIAN_IRAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_POLISH_POLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PORTUGUESE_BRAZILIAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PORTUGUESE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PUNJABI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_QUECHUA_BOLIVIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_QUECHUA_ECUADOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_QUECHUA_PERU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ROMANIAN_ROMANIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ROMANSH_SWITZERLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_RUSSIAN_RUSSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_INARI_FINLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_LULE_NORWAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_LULE_SWEDEN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_FINLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_NORWAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_SWEDEN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_SKOLT_FINLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_SOUTHERN_NORWAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SAMI_SOUTHERN_SWEDEN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SANSKRIT_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SERBIAN_CROATIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SERBIAN_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SERBIAN_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SINDHI_AFGHANISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SINDHI_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SINDHI_PAKISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SINHALESE_SRI_LANKA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SLOVAK_SLOVAKIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SLOVENIAN_SLOVENIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_ARGENTINA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_BOLIVIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_CHILE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_COLOMBIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_COSTA_RICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_DOMINICAN_REPUBLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_ECUADOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_EL_SALVADOR)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_GUATEMALA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_HONDURAS)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_MEXICAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_MODERN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_NICARAGUA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_PANAMA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_PARAGUAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_PERU)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_PUERTO_RICO)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_URUGUAY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_US)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH_VENEZUELA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SPANISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SWAHILI_KENYA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SWEDISH_FINLAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SWEDISH)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SYRIAC_SYRIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_SYS_DEFAULT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TAJIK_TAJIKISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TAMAZIGHT_ALGERIA_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TAMIL_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TATAR_RUSSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TELUGU_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_THAI_THAILAND)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TIBETAN_PRC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TIGRIGNA_ERITREA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TSWANA_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TURKISH_TURKEY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TURKMEN_TURKMENISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UI_CUSTOM_DEFAULT)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UIGHUR_PRC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UKRAINIAN_UKRAINE)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UPPER_SORBIAN_GERMANY)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_URDU_INDIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_URDU_PAKISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UZBEK_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_UZBEK_LATIN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_VIETNAMESE_VIETNAM)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_WELSH_UNITED_KINGDOM)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_WOLOF_SENEGAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_XHOSA_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_YAKUT_RUSSIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_YI_PRC)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_YORUBA_NIGERIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_ZULU_SOUTH_AFRICA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PULAR_SENEGAL)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_PUNJABI_PAKISTAN)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TSWANA_BOTSWANA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TAMIL_SRI_LANKA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TIGRINYA_ETHIOPIA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_TIGRINYA_ERITREA)) - .value(PY_ENUM(LIEF::PE::RESOURCE_SUBLANGS::SUBLANG_VALENCIAN_VALENCIA)); + LIEF::enum_(m, "RESOURCE_SUBLANGS") + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_AFRIKAANS_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ALBANIAN_ALBANIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ALSATIAN_FRANCE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_AMHARIC_ETHIOPIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_ALGERIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_BAHRAIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_EGYPT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_IRAQ)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_JORDAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_KUWAIT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_LEBANON)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_LIBYA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_MOROCCO)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_OMAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_QATAR)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_SAUDI_ARABIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_SYRIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_TUNISIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_UAE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARABIC_YEMEN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ARMENIAN_ARMENIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ASSAMESE_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_AZERI_CYRILLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_AZERI_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BASHKIR_RUSSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BASQUE_BASQUE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BELARUSIAN_BELARUS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BANGLA_BANGLADESH)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BANGLA_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BRETON_FRANCE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_BULGARIAN_BULGARIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CATALAN_CATALAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CHINESE_HONGKONG)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CHINESE_MACAU)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CHINESE_SIMPLIFIED)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CHINESE_SINGAPORE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CHINESE_TRADITIONAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CORSICAN_FRANCE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CROATIAN_CROATIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CUSTOM_DEFAULT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CUSTOM_UNSPECIFIED)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_CZECH_CZECH_REPUBLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DANISH_DENMARK)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DARI_AFGHANISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DEFAULT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DIVEHI_MALDIVES)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DUTCH_BELGIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_DUTCH)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_AUS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_BELIZE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_CAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_CARIBBEAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_EIRE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_JAMAICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_MALAYSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_NZ)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_PHILIPPINES)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_SINGAPORE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_TRINIDAD)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_UK)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_US)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_ZIMBABWE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ENGLISH_IRELAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ESTONIAN_ESTONIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FAEROESE_FAROE_ISLANDS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FILIPINO_PHILIPPINES)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FINNISH_FINLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH_BELGIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH_CANADIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH_LUXEMBOURG)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH_MONACO)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH_SWISS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRENCH)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_FRISIAN_NETHERLANDS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GALICIAN_GALICIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GEORGIAN_GEORGIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GERMAN_AUSTRIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GERMAN_LIECHTENSTEIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GERMAN_LUXEMBOURG)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GERMAN_SWISS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GERMAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GREEK_GREECE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GREENLANDIC_GREENLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_GUJARATI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_HAUSA_NIGERIA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_HEBREW_ISRAEL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_HINDI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_HUNGARIAN_HUNGARY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ICELANDIC_ICELAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_IGBO_NIGERIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_INDONESIAN_INDONESIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_INUKTITUT_CANADA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_INUKTITUT_CANADA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_IRISH_IRELAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ITALIAN_SWISS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ITALIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_JAPANESE_JAPAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KANNADA_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KASHMIRI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KASHMIRI_SASIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KAZAK_KAZAKHSTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KHMER_CAMBODIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KICHE_GUATEMALA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KINYARWANDA_RWANDA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KONKANI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KOREAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_KYRGYZ_KYRGYZSTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LAO_LAO)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LATVIAN_LATVIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LITHUANIAN_CLASSIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LITHUANIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LOWER_SORBIAN_GERMANY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_LUXEMBOURGISH_LUXEMBOURG)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MACEDONIAN_MACEDONIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MALAY_BRUNEI_DARUSSALAM)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MALAY_MALAYSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MALAYALAM_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MALTESE_MALTA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MAORI_NEW_ZEALAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MAPUDUNGUN_CHILE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MARATHI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MOHAWK_MOHAWK)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_MONGOLIAN_PRC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_NEPALI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_NEPALI_NEPAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_NEUTRAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_NORWEGIAN_BOKMAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_NORWEGIAN_NYNORSK)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_OCCITAN_FRANCE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ORIYA_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PASHTO_AFGHANISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PERSIAN_IRAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_POLISH_POLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PORTUGUESE_BRAZILIAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PORTUGUESE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PUNJABI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_QUECHUA_BOLIVIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_QUECHUA_ECUADOR)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_QUECHUA_PERU)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ROMANIAN_ROMANIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ROMANSH_SWITZERLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_RUSSIAN_RUSSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_INARI_FINLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_LULE_NORWAY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_LULE_SWEDEN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_FINLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_NORWAY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_NORTHERN_SWEDEN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_SKOLT_FINLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_SOUTHERN_NORWAY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SAMI_SOUTHERN_SWEDEN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SANSKRIT_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SERBIAN_CROATIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SERBIAN_CYRILLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SERBIAN_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SINDHI_AFGHANISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SINDHI_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SINDHI_PAKISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SINHALESE_SRI_LANKA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SLOVAK_SLOVAKIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SLOVENIAN_SLOVENIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_ARGENTINA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_BOLIVIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_CHILE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_COLOMBIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_COSTA_RICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_DOMINICAN_REPUBLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_ECUADOR)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_EL_SALVADOR)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_GUATEMALA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_HONDURAS)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_MEXICAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_MODERN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_NICARAGUA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_PANAMA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_PARAGUAY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_PERU)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_PUERTO_RICO)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_URUGUAY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_US)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH_VENEZUELA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SPANISH)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SWAHILI_KENYA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SWEDISH_FINLAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SWEDISH)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SYRIAC_SYRIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_SYS_DEFAULT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TAJIK_TAJIKISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TAMAZIGHT_ALGERIA_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TAMIL_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TATAR_RUSSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TELUGU_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_THAI_THAILAND)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TIBETAN_PRC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TIGRIGNA_ERITREA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TSWANA_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TURKISH_TURKEY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TURKMEN_TURKMENISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UI_CUSTOM_DEFAULT)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UIGHUR_PRC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UKRAINIAN_UKRAINE)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UPPER_SORBIAN_GERMANY)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_URDU_INDIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_URDU_PAKISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UZBEK_CYRILLIC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_UZBEK_LATIN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_VIETNAMESE_VIETNAM)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_WELSH_UNITED_KINGDOM)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_WOLOF_SENEGAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_XHOSA_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_YAKUT_RUSSIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_YI_PRC)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_YORUBA_NIGERIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_ZULU_SOUTH_AFRICA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PULAR_SENEGAL)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_PUNJABI_PAKISTAN)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TSWANA_BOTSWANA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TAMIL_SRI_LANKA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TIGRINYA_ETHIOPIA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_TIGRINYA_ERITREA)) + .value(PY_ENUM(RESOURCE_SUBLANGS::SUBLANG_VALENCIAN_VALENCIA)); - LIEF::enum_(m, "EXTENDED_WINDOW_STYLES") - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_DLGMODALFRAME)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_NOPARENTNOTIFY)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_TOPMOST)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_ACCEPTFILES)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_TRANSPARENT)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_MDICHILD)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_TOOLWINDOW)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_WINDOWEDGE)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_CLIENTEDGE)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_CONTEXTHELP)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_RIGHT)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_LEFT)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_RTLREADING)) - .value("LTRREADING", LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_LTRREADING) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_LEFTSCROLLBAR)) - .value("RIGHTSCROLLBAR", LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_RIGHTSCROLLBAR) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_CONTROLPARENT)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_STATICEDGE)) - .value(PY_ENUM(LIEF::PE::EXTENDED_WINDOW_STYLES::WS_EX_APPWINDOW)); + LIEF::enum_(m, "EXTENDED_WINDOW_STYLES") + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_DLGMODALFRAME)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_NOPARENTNOTIFY)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_TOPMOST)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_ACCEPTFILES)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_TRANSPARENT)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_MDICHILD)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_TOOLWINDOW)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_WINDOWEDGE)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_CLIENTEDGE)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_CONTEXTHELP)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_RIGHT)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_LEFT)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_RTLREADING)) + .value("LTRREADING", EXTENDED_WINDOW_STYLES::WS_EX_LTRREADING) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_LEFTSCROLLBAR)) + .value("RIGHTSCROLLBAR", EXTENDED_WINDOW_STYLES::WS_EX_RIGHTSCROLLBAR) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_CONTROLPARENT)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_STATICEDGE)) + .value(PY_ENUM(EXTENDED_WINDOW_STYLES::WS_EX_APPWINDOW)); - LIEF::enum_(m, "WINDOW_STYLES") - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_OVERLAPPED)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_POPUP)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_CHILD)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_MINIMIZE)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_VISIBLE)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_DISABLED)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_CLIPSIBLINGS)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_CLIPCHILDREN)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_MAXIMIZE)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_CAPTION)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_BORDER)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_DLGFRAME)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_VSCROLL)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_HSCROLL)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_SYSMENU)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_THICKFRAME)) - .value("GROUP", LIEF::PE::WINDOW_STYLES::WS_GROUP) - .value("TABSTOP", LIEF::PE::WINDOW_STYLES::WS_TABSTOP) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_MINIMIZEBOX)) - .value(PY_ENUM(LIEF::PE::WINDOW_STYLES::WS_MAXIMIZEBOX)); + LIEF::enum_(m, "WINDOW_STYLES") + .value(PY_ENUM(WINDOW_STYLES::WS_OVERLAPPED)) + .value(PY_ENUM(WINDOW_STYLES::WS_POPUP)) + .value(PY_ENUM(WINDOW_STYLES::WS_CHILD)) + .value(PY_ENUM(WINDOW_STYLES::WS_MINIMIZE)) + .value(PY_ENUM(WINDOW_STYLES::WS_VISIBLE)) + .value(PY_ENUM(WINDOW_STYLES::WS_DISABLED)) + .value(PY_ENUM(WINDOW_STYLES::WS_CLIPSIBLINGS)) + .value(PY_ENUM(WINDOW_STYLES::WS_CLIPCHILDREN)) + .value(PY_ENUM(WINDOW_STYLES::WS_MAXIMIZE)) + .value(PY_ENUM(WINDOW_STYLES::WS_CAPTION)) + .value(PY_ENUM(WINDOW_STYLES::WS_BORDER)) + .value(PY_ENUM(WINDOW_STYLES::WS_DLGFRAME)) + .value(PY_ENUM(WINDOW_STYLES::WS_VSCROLL)) + .value(PY_ENUM(WINDOW_STYLES::WS_HSCROLL)) + .value(PY_ENUM(WINDOW_STYLES::WS_SYSMENU)) + .value(PY_ENUM(WINDOW_STYLES::WS_THICKFRAME)) + .value("GROUP", WINDOW_STYLES::WS_GROUP) + .value("TABSTOP", WINDOW_STYLES::WS_TABSTOP) + .value(PY_ENUM(WINDOW_STYLES::WS_MINIMIZEBOX)) + .value(PY_ENUM(WINDOW_STYLES::WS_MAXIMIZEBOX)); - LIEF::enum_(m, "DIALOG_BOX_STYLES") - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_ABSALIGN)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_SYSMODAL)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_LOCALEDIT)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_SETFONT)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_MODALFRAME)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_NOIDLEMSG)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_SETFOREGROUND)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_3DLOOK)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_FIXEDSYS)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_NOFAILCREATE)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_CONTROL)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_CENTER)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_CENTERMOUSE)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_CONTEXTHELP)) - .value(PY_ENUM(LIEF::PE::DIALOG_BOX_STYLES::DS_SHELLFONT)); + LIEF::enum_(m, "DIALOG_BOX_STYLES") + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_ABSALIGN)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_SYSMODAL)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_LOCALEDIT)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_SETFONT)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_MODALFRAME)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_NOIDLEMSG)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_SETFOREGROUND)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_3DLOOK)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_FIXEDSYS)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_NOFAILCREATE)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_CONTROL)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_CENTER)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_CENTERMOUSE)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_CONTEXTHELP)) + .value(PY_ENUM(DIALOG_BOX_STYLES::DS_SHELLFONT)); - LIEF::enum_(m, "FIXED_VERSION_OS") - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_DOS)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_NT)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS__WINDOWS16)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS__WINDOWS32)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_OS216)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_OS232)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS__PM16)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS__PM32)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_DOS_WINDOWS16)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_DOS_WINDOWS32)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_NT_WINDOWS32)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_OS216_PM16)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_OS::VOS_OS232_PM32)); + LIEF::enum_(m, "FIXED_VERSION_OS") + .value(PY_ENUM(FIXED_VERSION_OS::VOS_UNKNOWN)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_DOS)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_NT)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS__WINDOWS16)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS__WINDOWS32)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_OS216)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_OS232)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS__PM16)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS__PM32)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_DOS_WINDOWS16)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_DOS_WINDOWS32)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_NT_WINDOWS32)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_OS216_PM16)) + .value(PY_ENUM(FIXED_VERSION_OS::VOS_OS232_PM32)); - LIEF::enum_(m, "FIXED_VERSION_FILE_FLAGS") - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_DEBUG)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_INFOINFERRED)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_PATCHED)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_PRERELEASE)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_PRIVATEBUILD)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_FLAGS::VS_FF_SPECIALBUILD)); + LIEF::enum_(m, "FIXED_VERSION_FILE_FLAGS") + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_DEBUG)) + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_INFOINFERRED)) + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_PATCHED)) + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_PRERELEASE)) + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_PRIVATEBUILD)) + .value(PY_ENUM(FIXED_VERSION_FILE_FLAGS::VS_FF_SPECIALBUILD)); - LIEF::enum_(m, "FIXED_VERSION_FILE_TYPES") - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_APP)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_DLL)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_DRV)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_FONT)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_STATIC_LIB)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_TYPES::VFT_VXD)); + LIEF::enum_(m, "FIXED_VERSION_FILE_TYPES") + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_APP)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_DLL)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_DRV)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_FONT)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_STATIC_LIB)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_UNKNOWN)) + .value(PY_ENUM(FIXED_VERSION_FILE_TYPES::VFT_VXD)); - LIEF::enum_(m, "FIXED_VERSION_FILE_SUB_TYPES") - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_COMM)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_DISPLAY)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_INSTALLABLE)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_KEYBOARD)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_LANGUAGE)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_MOUSE)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_NETWORK)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_PRINTER)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_SOUND)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_SYSTEM)) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_VERSIONED_PRINTER)) - .value("FONT_RASTER", LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_RASTER) - .value("FONT_TRUETYPE", LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_TRUETYPE) - .value("FONT_VECTOR", LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_VECTOR) - .value(PY_ENUM(LIEF::PE::FIXED_VERSION_FILE_SUB_TYPES::VFT2_UNKNOWN)); + LIEF::enum_(m, "FIXED_VERSION_FILE_SUB_TYPES") + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_COMM)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_DISPLAY)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_INSTALLABLE)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_KEYBOARD)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_LANGUAGE)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_MOUSE)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_NETWORK)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_PRINTER)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_SOUND)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_SYSTEM)) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_DRV_VERSIONED_PRINTER)) + .value("FONT_RASTER", FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_RASTER) + .value("FONT_TRUETYPE", FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_TRUETYPE) + .value("FONT_VECTOR", FIXED_VERSION_FILE_SUB_TYPES::VFT2_FONT_VECTOR) + .value(PY_ENUM(FIXED_VERSION_FILE_SUB_TYPES::VFT2_UNKNOWN)); - LIEF::enum_(m, "CODE_PAGES") - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM037)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM437)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM500)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ASMO_708)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_DOS_720)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM737)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM775)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM850)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM852)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM855)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM857)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM00858)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM860)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM861)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_DOS_862)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM863)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM864)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM865)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_CP866)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM869)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM870)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_874)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_CP875)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_SHIFT_JIS)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_GB2312)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_KS_C_5601_1987)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_BIG5)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM1026)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01047)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01140)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01141)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01142)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01143)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01144)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01145)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01146)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01147)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01148)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM01149)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_16)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UNICODEFFFE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1250)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1251)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1252)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1253)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1254)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1255)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1256)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1257)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_WINDOWS_1258)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_JOHAB)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_MACINTOSH)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_JAPANESE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_CHINESETRAD)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_KOREAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_ARABIC)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_HEBREW)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_GREEK)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_CYRILLIC)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_CHINESESIMP)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_ROMANIAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_UKRAINIAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_THAI)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_CE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_ICELANDIC)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_TURKISH)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_MAC_CROATIAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_32)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_32BE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CHINESE_CNS)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20001)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CHINESE_ETEN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20003)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20004)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20005)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_IA5)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_IA5_GERMAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_IA5_SWEDISH)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_IA5_NORWEGIAN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_US_ASCII)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20261)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20269)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM273)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM277)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM278)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM280)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM284)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM285)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM290)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM297)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM420)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM423)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM424)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_EBCDIC_KOREANEXTENDED)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM_THAI)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_KOI8_R)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM871)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM880)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM905)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_IBM00924)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_EUC_JP_JIS)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20936)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP20949)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_CP1025)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_KOI8_U)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_1)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_2)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_3)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_4)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_5)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_6)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_7)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_8)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_9)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_13)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_15)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_EUROPA)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_8859_8_I)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_2022_JP)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_CSISO2022JP)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_2022_JP_JIS)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_ISO_2022_KR)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_CP50227)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_EUC_JP)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_EUC_CN)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_EUC_KR)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_HZ_GB_2312)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_GB18030)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_DE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_BE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_TA)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_TE)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_AS)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_OR)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_KA)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_MA)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_GU)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_X_ISCII_PA)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_7)) - .value(PY_ENUM(LIEF::PE::CODE_PAGES::CP_UTF_8)); + LIEF::enum_(m, "CODE_PAGES") + .value(PY_ENUM(CODE_PAGES::CP_IBM037)) + .value(PY_ENUM(CODE_PAGES::CP_IBM437)) + .value(PY_ENUM(CODE_PAGES::CP_IBM500)) + .value(PY_ENUM(CODE_PAGES::CP_ASMO_708)) + .value(PY_ENUM(CODE_PAGES::CP_DOS_720)) + .value(PY_ENUM(CODE_PAGES::CP_IBM737)) + .value(PY_ENUM(CODE_PAGES::CP_IBM775)) + .value(PY_ENUM(CODE_PAGES::CP_IBM850)) + .value(PY_ENUM(CODE_PAGES::CP_IBM852)) + .value(PY_ENUM(CODE_PAGES::CP_IBM855)) + .value(PY_ENUM(CODE_PAGES::CP_IBM857)) + .value(PY_ENUM(CODE_PAGES::CP_IBM00858)) + .value(PY_ENUM(CODE_PAGES::CP_IBM860)) + .value(PY_ENUM(CODE_PAGES::CP_IBM861)) + .value(PY_ENUM(CODE_PAGES::CP_DOS_862)) + .value(PY_ENUM(CODE_PAGES::CP_IBM863)) + .value(PY_ENUM(CODE_PAGES::CP_IBM864)) + .value(PY_ENUM(CODE_PAGES::CP_IBM865)) + .value(PY_ENUM(CODE_PAGES::CP_CP866)) + .value(PY_ENUM(CODE_PAGES::CP_IBM869)) + .value(PY_ENUM(CODE_PAGES::CP_IBM870)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_874)) + .value(PY_ENUM(CODE_PAGES::CP_CP875)) + .value(PY_ENUM(CODE_PAGES::CP_SHIFT_JIS)) + .value(PY_ENUM(CODE_PAGES::CP_GB2312)) + .value(PY_ENUM(CODE_PAGES::CP_KS_C_5601_1987)) + .value(PY_ENUM(CODE_PAGES::CP_BIG5)) + .value(PY_ENUM(CODE_PAGES::CP_IBM1026)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01047)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01140)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01141)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01142)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01143)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01144)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01145)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01146)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01147)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01148)) + .value(PY_ENUM(CODE_PAGES::CP_IBM01149)) + .value(PY_ENUM(CODE_PAGES::CP_UTF_16)) + .value(PY_ENUM(CODE_PAGES::CP_UNICODEFFFE)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1250)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1251)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1252)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1253)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1254)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1255)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1256)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1257)) + .value(PY_ENUM(CODE_PAGES::CP_WINDOWS_1258)) + .value(PY_ENUM(CODE_PAGES::CP_JOHAB)) + .value(PY_ENUM(CODE_PAGES::CP_MACINTOSH)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_JAPANESE)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_CHINESETRAD)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_KOREAN)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_ARABIC)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_HEBREW)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_GREEK)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_CYRILLIC)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_CHINESESIMP)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_ROMANIAN)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_UKRAINIAN)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_THAI)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_CE)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_ICELANDIC)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_TURKISH)) + .value(PY_ENUM(CODE_PAGES::CP_X_MAC_CROATIAN)) + .value(PY_ENUM(CODE_PAGES::CP_UTF_32)) + .value(PY_ENUM(CODE_PAGES::CP_UTF_32BE)) + .value(PY_ENUM(CODE_PAGES::CP_X_CHINESE_CNS)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20001)) + .value(PY_ENUM(CODE_PAGES::CP_X_CHINESE_ETEN)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20003)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20004)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20005)) + .value(PY_ENUM(CODE_PAGES::CP_X_IA5)) + .value(PY_ENUM(CODE_PAGES::CP_X_IA5_GERMAN)) + .value(PY_ENUM(CODE_PAGES::CP_X_IA5_SWEDISH)) + .value(PY_ENUM(CODE_PAGES::CP_X_IA5_NORWEGIAN)) + .value(PY_ENUM(CODE_PAGES::CP_US_ASCII)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20261)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20269)) + .value(PY_ENUM(CODE_PAGES::CP_IBM273)) + .value(PY_ENUM(CODE_PAGES::CP_IBM277)) + .value(PY_ENUM(CODE_PAGES::CP_IBM278)) + .value(PY_ENUM(CODE_PAGES::CP_IBM280)) + .value(PY_ENUM(CODE_PAGES::CP_IBM284)) + .value(PY_ENUM(CODE_PAGES::CP_IBM285)) + .value(PY_ENUM(CODE_PAGES::CP_IBM290)) + .value(PY_ENUM(CODE_PAGES::CP_IBM297)) + .value(PY_ENUM(CODE_PAGES::CP_IBM420)) + .value(PY_ENUM(CODE_PAGES::CP_IBM423)) + .value(PY_ENUM(CODE_PAGES::CP_IBM424)) + .value(PY_ENUM(CODE_PAGES::CP_X_EBCDIC_KOREANEXTENDED)) + .value(PY_ENUM(CODE_PAGES::CP_IBM_THAI)) + .value(PY_ENUM(CODE_PAGES::CP_KOI8_R)) + .value(PY_ENUM(CODE_PAGES::CP_IBM871)) + .value(PY_ENUM(CODE_PAGES::CP_IBM880)) + .value(PY_ENUM(CODE_PAGES::CP_IBM905)) + .value(PY_ENUM(CODE_PAGES::CP_IBM00924)) + .value(PY_ENUM(CODE_PAGES::CP_EUC_JP_JIS)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20936)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP20949)) + .value(PY_ENUM(CODE_PAGES::CP_CP1025)) + .value(PY_ENUM(CODE_PAGES::CP_KOI8_U)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_1)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_2)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_3)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_4)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_5)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_6)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_7)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_8)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_9)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_13)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_15)) + .value(PY_ENUM(CODE_PAGES::CP_X_EUROPA)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_8859_8_I)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_2022_JP)) + .value(PY_ENUM(CODE_PAGES::CP_CSISO2022JP)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_2022_JP_JIS)) + .value(PY_ENUM(CODE_PAGES::CP_ISO_2022_KR)) + .value(PY_ENUM(CODE_PAGES::CP_X_CP50227)) + .value(PY_ENUM(CODE_PAGES::CP_EUC_JP)) + .value(PY_ENUM(CODE_PAGES::CP_EUC_CN)) + .value(PY_ENUM(CODE_PAGES::CP_EUC_KR)) + .value(PY_ENUM(CODE_PAGES::CP_HZ_GB_2312)) + .value(PY_ENUM(CODE_PAGES::CP_GB18030)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_DE)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_BE)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_TA)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_TE)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_AS)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_OR)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_KA)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_MA)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_GU)) + .value(PY_ENUM(CODE_PAGES::CP_X_ISCII_PA)) + .value(PY_ENUM(CODE_PAGES::CP_UTF_7)) + .value(PY_ENUM(CODE_PAGES::CP_UTF_8)); - LIEF::enum_(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)); + LIEF::enum_(m, "WIN_VERSION") + .value(PY_ENUM(WIN_VERSION::WIN_UNKNOWN)) + .value(PY_ENUM(WIN_VERSION::WIN_SEH)) + .value(PY_ENUM(WIN_VERSION::WIN8_1)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_9879)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_14286)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_14383)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_14901)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_15002)) + .value(PY_ENUM(WIN_VERSION::WIN10_0_16237)); - LIEF::enum_(m, "GUARD_CF_FLAGS", py::arithmetic()) - .value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GCF_NONE)) - .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)) - .value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GRF_INSTRUMENTED)) - .value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GRF_ENABLE)) - .value(PY_ENUM(LIEF::PE::GUARD_CF_FLAGS::GRF_STRICT)); + LIEF::enum_(m, "GUARD_CF_FLAGS", py::arithmetic()) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_NONE)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_INSTRUMENTED)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_W_INSTRUMENTED)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_FUNCTION_TABLE_PRESENT)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_EXPORT_SUPPRESSION_INFO_PRESENT)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_ENABLE_EXPORT_SUPPRESSION)) + .value(PY_ENUM(GUARD_CF_FLAGS::GCF_LONGJUMP_TABLE_PRESENT)) + .value(PY_ENUM(GUARD_CF_FLAGS::GRF_INSTRUMENTED)) + .value(PY_ENUM(GUARD_CF_FLAGS::GRF_ENABLE)) + .value(PY_ENUM(GUARD_CF_FLAGS::GRF_STRICT)); - LIEF::enum_(m, "CODE_VIEW_SIGNATURES") - .value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_PDB_70)) - .value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_PDB_20)) - .value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_CV_50)) - .value(PY_ENUM(LIEF::PE::CODE_VIEW_SIGNATURES::CVS_CV_41)); + LIEF::enum_(m, "CODE_VIEW_SIGNATURES") + .value(PY_ENUM(CODE_VIEW_SIGNATURES::CVS_UNKNOWN)) + .value(PY_ENUM(CODE_VIEW_SIGNATURES::CVS_PDB_70)) + .value(PY_ENUM(CODE_VIEW_SIGNATURES::CVS_PDB_20)) + .value(PY_ENUM(CODE_VIEW_SIGNATURES::CVS_CV_50)) + .value(PY_ENUM(CODE_VIEW_SIGNATURES::CVS_CV_41)); - LIEF::enum_(m, "POGO_SIGNATURES") - .value(PY_ENUM(LIEF::PE::POGO_SIGNATURES::POGO_UNKNOWN)) - .value(PY_ENUM(LIEF::PE::POGO_SIGNATURES::POGO_LCTG)) - .value(PY_ENUM(LIEF::PE::POGO_SIGNATURES::POGO_PGI)); + LIEF::enum_(m, "POGO_SIGNATURES") + .value(PY_ENUM(POGO_SIGNATURES::POGO_UNKNOWN)) + .value(PY_ENUM(POGO_SIGNATURES::POGO_LCTG)) + .value(PY_ENUM(POGO_SIGNATURES::POGO_PGI)); - LIEF::enum_(m, "ACCELERATOR_FLAGS", py::arithmetic()) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::FVIRTKEY)) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::FNOINVERT)) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::FSHIFT)) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::FCONTROL)) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::FALT)) - .value(PY_ENUM(LIEF::PE::ACCELERATOR_FLAGS::END)); + LIEF::enum_(m, "ACCELERATOR_FLAGS", py::arithmetic()) + .value(PY_ENUM(ACCELERATOR_FLAGS::FVIRTKEY)) + .value(PY_ENUM(ACCELERATOR_FLAGS::FNOINVERT)) + .value(PY_ENUM(ACCELERATOR_FLAGS::FSHIFT)) + .value(PY_ENUM(ACCELERATOR_FLAGS::FCONTROL)) + .value(PY_ENUM(ACCELERATOR_FLAGS::FALT)) + .value(PY_ENUM(ACCELERATOR_FLAGS::END)); - LIEF::enum_(m, "ACCELERATOR_VK_CODES") - .value("VK_LBUTTON" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LBUTTON) - .value("VK_RBUTTON" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RBUTTON) - .value("VK_CANCEL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CANCEL) - .value("VK_MBUTTON" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MBUTTON) - .value("VK_XBUTTON1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_XBUTTON1) - .value("VK_XBUTTON2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_XBUTTON2) - .value("VK_BACK" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BACK) - .value("VK_TAB" , LIEF::PE::ACCELERATOR_VK_CODES::VK_TAB) - .value("VK_CLEAR" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CLEAR) - .value("VK_RETURN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RETURN) - .value("VK_SHIFT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SHIFT) - .value("VK_CONTROL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CONTROL) - .value("VK_MENU" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MENU) - .value("VK_PAUSE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PAUSE) - .value("VK_CAPITAL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CAPITAL) - .value("VK_KANA" , LIEF::PE::ACCELERATOR_VK_CODES::VK_KANA) - .value("VK_HANGUEL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_HANGUEL) - .value("VK_HANGUL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_HANGUL) - .value("VK_IME_ON" , LIEF::PE::ACCELERATOR_VK_CODES::VK_IME_ON) - .value("VK_JUNJA" , LIEF::PE::ACCELERATOR_VK_CODES::VK_JUNJA) - .value("VK_FINAL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_FINAL) - .value("VK_HANJA" , LIEF::PE::ACCELERATOR_VK_CODES::VK_HANJA) - .value("VK_KANJI" , LIEF::PE::ACCELERATOR_VK_CODES::VK_KANJI) - .value("VK_IME_OFF" , LIEF::PE::ACCELERATOR_VK_CODES::VK_IME_OFF) - .value("VK_ESCAPE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_ESCAPE) - .value("VK_CONVERT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CONVERT) - .value("VK_NONCONVERT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NONCONVERT) - .value("VK_ACCEPT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_ACCEPT) - .value("VK_MODECHANGE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MODECHANGE) - .value("VK_SPACE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SPACE) - .value("VK_PRIOR" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PRIOR) - .value("VK_NEXT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NEXT) - .value("VK_END" , LIEF::PE::ACCELERATOR_VK_CODES::VK_END) - .value("VK_HOME" , LIEF::PE::ACCELERATOR_VK_CODES::VK_HOME) - .value("VK_LEFT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LEFT) - .value("VK_UP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_UP) - .value("VK_RIGHT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RIGHT) - .value("VK_DOWN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_DOWN) - .value("VK_SELECT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SELECT) - .value("VK_PRINT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PRINT) - .value("VK_EXECUTE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_EXECUTE) - .value("VK_SNAPSHOT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SNAPSHOT) - .value("VK_INSERT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_INSERT) - .value("VK_DELETE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_DELETE) - .value("VK_HELP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_HELP) - .value("VK_0" , LIEF::PE::ACCELERATOR_VK_CODES::VK_0) - .value("VK_1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_1) - .value("VK_2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_2) - .value("VK_3" , LIEF::PE::ACCELERATOR_VK_CODES::VK_3) - .value("VK_4" , LIEF::PE::ACCELERATOR_VK_CODES::VK_4) - .value("VK_5" , LIEF::PE::ACCELERATOR_VK_CODES::VK_5) - .value("VK_6" , LIEF::PE::ACCELERATOR_VK_CODES::VK_6) - .value("VK_7" , LIEF::PE::ACCELERATOR_VK_CODES::VK_7) - .value("VK_8" , LIEF::PE::ACCELERATOR_VK_CODES::VK_8) - .value("VK_9" , LIEF::PE::ACCELERATOR_VK_CODES::VK_9) - .value("VK_A" , LIEF::PE::ACCELERATOR_VK_CODES::VK_A) - .value("VK_B" , LIEF::PE::ACCELERATOR_VK_CODES::VK_B) - .value("VK_C" , LIEF::PE::ACCELERATOR_VK_CODES::VK_C) - .value("VK_D" , LIEF::PE::ACCELERATOR_VK_CODES::VK_D) - .value("VK_E" , LIEF::PE::ACCELERATOR_VK_CODES::VK_E) - .value("VK_F" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F) - .value("VK_G" , LIEF::PE::ACCELERATOR_VK_CODES::VK_G) - .value("VK_H" , LIEF::PE::ACCELERATOR_VK_CODES::VK_H) - .value("VK_I" , LIEF::PE::ACCELERATOR_VK_CODES::VK_I) - .value("VK_J" , LIEF::PE::ACCELERATOR_VK_CODES::VK_J) - .value("VK_K" , LIEF::PE::ACCELERATOR_VK_CODES::VK_K) - .value("VK_L" , LIEF::PE::ACCELERATOR_VK_CODES::VK_L) - .value("VK_M" , LIEF::PE::ACCELERATOR_VK_CODES::VK_M) - .value("VK_N" , LIEF::PE::ACCELERATOR_VK_CODES::VK_N) - .value("VK_O" , LIEF::PE::ACCELERATOR_VK_CODES::VK_O) - .value("VK_P" , LIEF::PE::ACCELERATOR_VK_CODES::VK_P) - .value("VK_Q" , LIEF::PE::ACCELERATOR_VK_CODES::VK_Q) - .value("VK_R" , LIEF::PE::ACCELERATOR_VK_CODES::VK_R) - .value("VK_S" , LIEF::PE::ACCELERATOR_VK_CODES::VK_S) - .value("VK_T" , LIEF::PE::ACCELERATOR_VK_CODES::VK_T) - .value("VK_U" , LIEF::PE::ACCELERATOR_VK_CODES::VK_U) - .value("VK_V" , LIEF::PE::ACCELERATOR_VK_CODES::VK_V) - .value("VK_W" , LIEF::PE::ACCELERATOR_VK_CODES::VK_W) - .value("VK_X" , LIEF::PE::ACCELERATOR_VK_CODES::VK_X) - .value("VK_Y" , LIEF::PE::ACCELERATOR_VK_CODES::VK_Y) - .value("VK_Z" , LIEF::PE::ACCELERATOR_VK_CODES::VK_Z) - .value("VK_LWIN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LWIN) - .value("VK_RWIN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RWIN) - .value("VK_APPS" , LIEF::PE::ACCELERATOR_VK_CODES::VK_APPS) - .value("VK_SLEEP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SLEEP) - .value("VK_NUMPAD0" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD0) - .value("VK_NUMPAD1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD1) - .value("VK_NUMPAD2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD2) - .value("VK_NUMPAD3" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD3) - .value("VK_NUMPAD4" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD4) - .value("VK_NUMPAD5" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD5) - .value("VK_NUMPAD6" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD6) - .value("VK_NUMPAD7" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD7) - .value("VK_NUMPAD8" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD8) - .value("VK_NUMPAD9" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMPAD9) - .value("VK_MULTIPLY" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MULTIPLY) - .value("VK_ADD" , LIEF::PE::ACCELERATOR_VK_CODES::VK_ADD) - .value("VK_SEPARATOR" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SEPARATOR) - .value("VK_SUBTRACT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SUBTRACT) - .value("VK_DECIMAL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_DECIMAL) - .value("VK_DIVIDE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_DIVIDE) - .value("VK_F1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F1) - .value("VK_F2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F2) - .value("VK_F3" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F3) - .value("VK_F4" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F4) - .value("VK_F5" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F5) - .value("VK_F6" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F6) - .value("VK_F7" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F7) - .value("VK_F8" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F8) - .value("VK_F9" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F9) - .value("VK_F10" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F10) - .value("VK_F11" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F11) - .value("VK_F12" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F12) - .value("VK_F13" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F13) - .value("VK_F14" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F14) - .value("VK_F15" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F15) - .value("VK_F16" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F16) - .value("VK_F17" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F17) - .value("VK_F18" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F18) - .value("VK_F19" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F19) - .value("VK_F20" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F20) - .value("VK_F21" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F21) - .value("VK_F22" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F22) - .value("VK_F23" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F23) - .value("VK_F24" , LIEF::PE::ACCELERATOR_VK_CODES::VK_F24) - .value("VK_NUMLOCK" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NUMLOCK) - .value("VK_SCROLL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_SCROLL) - .value("VK_LSHIFT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LSHIFT) - .value("VK_RSHIFT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RSHIFT) - .value("VK_LCONTROL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LCONTROL) - .value("VK_RCONTROL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RCONTROL) - .value("VK_LMENU" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LMENU) - .value("VK_RMENU" , LIEF::PE::ACCELERATOR_VK_CODES::VK_RMENU) - .value("VK_BROWSER_BACK" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_BACK) - .value("VK_BROWSER_FORWARD" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_FORWARD) - .value("VK_BROWSER_REFRESH" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_REFRESH) - .value("VK_BROWSER_STOP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_STOP) - .value("VK_BROWSER_SEARCH" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_SEARCH) - .value("VK_BROWSER_FAVORITES" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_FAVORITES) - .value("VK_BROWSER_HOME" , LIEF::PE::ACCELERATOR_VK_CODES::VK_BROWSER_HOME) - .value("VK_VOLUME_MUTE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_VOLUME_MUTE) - .value("VK_VOLUME_DOWN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_VOLUME_DOWN) - .value("VK_VOLUME_UP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_VOLUME_UP) - .value("VK_MEDIA_NEXT_TRACK" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MEDIA_NEXT_TRACK) - .value("VK_MEDIA_PREV_TRACK" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MEDIA_PREV_TRACK) - .value("VK_MEDIA_STOP" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MEDIA_STOP) - .value("VK_MEDIA_PLAY_PAUSE" , LIEF::PE::ACCELERATOR_VK_CODES::VK_MEDIA_PLAY_PAUSE) - .value("VK_LAUNCH_MAIL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LAUNCH_MAIL) - .value("VK_LAUNCH_MEDIA_SELECT" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LAUNCH_MEDIA_SELECT) - .value("VK_LAUNCH_APP1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LAUNCH_APP1) - .value("VK_LAUNCH_APP2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_LAUNCH_APP2) - .value("VK_OEM_1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_1) - .value("VK_OEM_PLUS" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_PLUS) - .value("VK_OEM_COMMA" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_COMMA) - .value("VK_OEM_MINUS" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_MINUS) - .value("VK_OEM_PERIOD" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_PERIOD) - .value("VK_OEM_2" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_2) - .value("VK_OEM_4" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_4) - .value("VK_OEM_5" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_5) - .value("VK_OEM_6" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_6) - .value("VK_OEM_7" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_7) - .value("VK_OEM_8" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_8) - .value("VK_OEM_102" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_102) - .value("VK_PROCESSKEY" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PROCESSKEY) - .value("VK_PACKET" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PACKET) - .value("VK_ATTN" , LIEF::PE::ACCELERATOR_VK_CODES::VK_ATTN) - .value("VK_CRSEL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_CRSEL) - .value("VK_EXSEL" , LIEF::PE::ACCELERATOR_VK_CODES::VK_EXSEL) - .value("VK_EREOF" , LIEF::PE::ACCELERATOR_VK_CODES::VK_EREOF) - .value("VK_PLAY" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PLAY) - .value("VK_ZOOM" , LIEF::PE::ACCELERATOR_VK_CODES::VK_ZOOM) - .value("VK_NONAME" , LIEF::PE::ACCELERATOR_VK_CODES::VK_NONAME) - .value("VK_PA1" , LIEF::PE::ACCELERATOR_VK_CODES::VK_PA1) - .value("VK_OEM_CLEAR" , LIEF::PE::ACCELERATOR_VK_CODES::VK_OEM_CLEAR); + LIEF::enum_(m, "ACCELERATOR_VK_CODES") + .value("VK_LBUTTON" , ACCELERATOR_VK_CODES::VK_LBUTTON) + .value("VK_RBUTTON" , ACCELERATOR_VK_CODES::VK_RBUTTON) + .value("VK_CANCEL" , ACCELERATOR_VK_CODES::VK_CANCEL) + .value("VK_MBUTTON" , ACCELERATOR_VK_CODES::VK_MBUTTON) + .value("VK_XBUTTON1" , ACCELERATOR_VK_CODES::VK_XBUTTON1) + .value("VK_XBUTTON2" , ACCELERATOR_VK_CODES::VK_XBUTTON2) + .value("VK_BACK" , ACCELERATOR_VK_CODES::VK_BACK) + .value("VK_TAB" , ACCELERATOR_VK_CODES::VK_TAB) + .value("VK_CLEAR" , ACCELERATOR_VK_CODES::VK_CLEAR) + .value("VK_RETURN" , ACCELERATOR_VK_CODES::VK_RETURN) + .value("VK_SHIFT" , ACCELERATOR_VK_CODES::VK_SHIFT) + .value("VK_CONTROL" , ACCELERATOR_VK_CODES::VK_CONTROL) + .value("VK_MENU" , ACCELERATOR_VK_CODES::VK_MENU) + .value("VK_PAUSE" , ACCELERATOR_VK_CODES::VK_PAUSE) + .value("VK_CAPITAL" , ACCELERATOR_VK_CODES::VK_CAPITAL) + .value("VK_KANA" , ACCELERATOR_VK_CODES::VK_KANA) + .value("VK_HANGUEL" , ACCELERATOR_VK_CODES::VK_HANGUEL) + .value("VK_HANGUL" , ACCELERATOR_VK_CODES::VK_HANGUL) + .value("VK_IME_ON" , ACCELERATOR_VK_CODES::VK_IME_ON) + .value("VK_JUNJA" , ACCELERATOR_VK_CODES::VK_JUNJA) + .value("VK_FINAL" , ACCELERATOR_VK_CODES::VK_FINAL) + .value("VK_HANJA" , ACCELERATOR_VK_CODES::VK_HANJA) + .value("VK_KANJI" , ACCELERATOR_VK_CODES::VK_KANJI) + .value("VK_IME_OFF" , ACCELERATOR_VK_CODES::VK_IME_OFF) + .value("VK_ESCAPE" , ACCELERATOR_VK_CODES::VK_ESCAPE) + .value("VK_CONVERT" , ACCELERATOR_VK_CODES::VK_CONVERT) + .value("VK_NONCONVERT" , ACCELERATOR_VK_CODES::VK_NONCONVERT) + .value("VK_ACCEPT" , ACCELERATOR_VK_CODES::VK_ACCEPT) + .value("VK_MODECHANGE" , ACCELERATOR_VK_CODES::VK_MODECHANGE) + .value("VK_SPACE" , ACCELERATOR_VK_CODES::VK_SPACE) + .value("VK_PRIOR" , ACCELERATOR_VK_CODES::VK_PRIOR) + .value("VK_NEXT" , ACCELERATOR_VK_CODES::VK_NEXT) + .value("VK_END" , ACCELERATOR_VK_CODES::VK_END) + .value("VK_HOME" , ACCELERATOR_VK_CODES::VK_HOME) + .value("VK_LEFT" , ACCELERATOR_VK_CODES::VK_LEFT) + .value("VK_UP" , ACCELERATOR_VK_CODES::VK_UP) + .value("VK_RIGHT" , ACCELERATOR_VK_CODES::VK_RIGHT) + .value("VK_DOWN" , ACCELERATOR_VK_CODES::VK_DOWN) + .value("VK_SELECT" , ACCELERATOR_VK_CODES::VK_SELECT) + .value("VK_PRINT" , ACCELERATOR_VK_CODES::VK_PRINT) + .value("VK_EXECUTE" , ACCELERATOR_VK_CODES::VK_EXECUTE) + .value("VK_SNAPSHOT" , ACCELERATOR_VK_CODES::VK_SNAPSHOT) + .value("VK_INSERT" , ACCELERATOR_VK_CODES::VK_INSERT) + .value("VK_DELETE" , ACCELERATOR_VK_CODES::VK_DELETE) + .value("VK_HELP" , ACCELERATOR_VK_CODES::VK_HELP) + .value("VK_0" , ACCELERATOR_VK_CODES::VK_0) + .value("VK_1" , ACCELERATOR_VK_CODES::VK_1) + .value("VK_2" , ACCELERATOR_VK_CODES::VK_2) + .value("VK_3" , ACCELERATOR_VK_CODES::VK_3) + .value("VK_4" , ACCELERATOR_VK_CODES::VK_4) + .value("VK_5" , ACCELERATOR_VK_CODES::VK_5) + .value("VK_6" , ACCELERATOR_VK_CODES::VK_6) + .value("VK_7" , ACCELERATOR_VK_CODES::VK_7) + .value("VK_8" , ACCELERATOR_VK_CODES::VK_8) + .value("VK_9" , ACCELERATOR_VK_CODES::VK_9) + .value("VK_A" , ACCELERATOR_VK_CODES::VK_A) + .value("VK_B" , ACCELERATOR_VK_CODES::VK_B) + .value("VK_C" , ACCELERATOR_VK_CODES::VK_C) + .value("VK_D" , ACCELERATOR_VK_CODES::VK_D) + .value("VK_E" , ACCELERATOR_VK_CODES::VK_E) + .value("VK_F" , ACCELERATOR_VK_CODES::VK_F) + .value("VK_G" , ACCELERATOR_VK_CODES::VK_G) + .value("VK_H" , ACCELERATOR_VK_CODES::VK_H) + .value("VK_I" , ACCELERATOR_VK_CODES::VK_I) + .value("VK_J" , ACCELERATOR_VK_CODES::VK_J) + .value("VK_K" , ACCELERATOR_VK_CODES::VK_K) + .value("VK_L" , ACCELERATOR_VK_CODES::VK_L) + .value("VK_M" , ACCELERATOR_VK_CODES::VK_M) + .value("VK_N" , ACCELERATOR_VK_CODES::VK_N) + .value("VK_O" , ACCELERATOR_VK_CODES::VK_O) + .value("VK_P" , ACCELERATOR_VK_CODES::VK_P) + .value("VK_Q" , ACCELERATOR_VK_CODES::VK_Q) + .value("VK_R" , ACCELERATOR_VK_CODES::VK_R) + .value("VK_S" , ACCELERATOR_VK_CODES::VK_S) + .value("VK_T" , ACCELERATOR_VK_CODES::VK_T) + .value("VK_U" , ACCELERATOR_VK_CODES::VK_U) + .value("VK_V" , ACCELERATOR_VK_CODES::VK_V) + .value("VK_W" , ACCELERATOR_VK_CODES::VK_W) + .value("VK_X" , ACCELERATOR_VK_CODES::VK_X) + .value("VK_Y" , ACCELERATOR_VK_CODES::VK_Y) + .value("VK_Z" , ACCELERATOR_VK_CODES::VK_Z) + .value("VK_LWIN" , ACCELERATOR_VK_CODES::VK_LWIN) + .value("VK_RWIN" , ACCELERATOR_VK_CODES::VK_RWIN) + .value("VK_APPS" , ACCELERATOR_VK_CODES::VK_APPS) + .value("VK_SLEEP" , ACCELERATOR_VK_CODES::VK_SLEEP) + .value("VK_NUMPAD0" , ACCELERATOR_VK_CODES::VK_NUMPAD0) + .value("VK_NUMPAD1" , ACCELERATOR_VK_CODES::VK_NUMPAD1) + .value("VK_NUMPAD2" , ACCELERATOR_VK_CODES::VK_NUMPAD2) + .value("VK_NUMPAD3" , ACCELERATOR_VK_CODES::VK_NUMPAD3) + .value("VK_NUMPAD4" , ACCELERATOR_VK_CODES::VK_NUMPAD4) + .value("VK_NUMPAD5" , ACCELERATOR_VK_CODES::VK_NUMPAD5) + .value("VK_NUMPAD6" , ACCELERATOR_VK_CODES::VK_NUMPAD6) + .value("VK_NUMPAD7" , ACCELERATOR_VK_CODES::VK_NUMPAD7) + .value("VK_NUMPAD8" , ACCELERATOR_VK_CODES::VK_NUMPAD8) + .value("VK_NUMPAD9" , ACCELERATOR_VK_CODES::VK_NUMPAD9) + .value("VK_MULTIPLY" , ACCELERATOR_VK_CODES::VK_MULTIPLY) + .value("VK_ADD" , ACCELERATOR_VK_CODES::VK_ADD) + .value("VK_SEPARATOR" , ACCELERATOR_VK_CODES::VK_SEPARATOR) + .value("VK_SUBTRACT" , ACCELERATOR_VK_CODES::VK_SUBTRACT) + .value("VK_DECIMAL" , ACCELERATOR_VK_CODES::VK_DECIMAL) + .value("VK_DIVIDE" , ACCELERATOR_VK_CODES::VK_DIVIDE) + .value("VK_F1" , ACCELERATOR_VK_CODES::VK_F1) + .value("VK_F2" , ACCELERATOR_VK_CODES::VK_F2) + .value("VK_F3" , ACCELERATOR_VK_CODES::VK_F3) + .value("VK_F4" , ACCELERATOR_VK_CODES::VK_F4) + .value("VK_F5" , ACCELERATOR_VK_CODES::VK_F5) + .value("VK_F6" , ACCELERATOR_VK_CODES::VK_F6) + .value("VK_F7" , ACCELERATOR_VK_CODES::VK_F7) + .value("VK_F8" , ACCELERATOR_VK_CODES::VK_F8) + .value("VK_F9" , ACCELERATOR_VK_CODES::VK_F9) + .value("VK_F10" , ACCELERATOR_VK_CODES::VK_F10) + .value("VK_F11" , ACCELERATOR_VK_CODES::VK_F11) + .value("VK_F12" , ACCELERATOR_VK_CODES::VK_F12) + .value("VK_F13" , ACCELERATOR_VK_CODES::VK_F13) + .value("VK_F14" , ACCELERATOR_VK_CODES::VK_F14) + .value("VK_F15" , ACCELERATOR_VK_CODES::VK_F15) + .value("VK_F16" , ACCELERATOR_VK_CODES::VK_F16) + .value("VK_F17" , ACCELERATOR_VK_CODES::VK_F17) + .value("VK_F18" , ACCELERATOR_VK_CODES::VK_F18) + .value("VK_F19" , ACCELERATOR_VK_CODES::VK_F19) + .value("VK_F20" , ACCELERATOR_VK_CODES::VK_F20) + .value("VK_F21" , ACCELERATOR_VK_CODES::VK_F21) + .value("VK_F22" , ACCELERATOR_VK_CODES::VK_F22) + .value("VK_F23" , ACCELERATOR_VK_CODES::VK_F23) + .value("VK_F24" , ACCELERATOR_VK_CODES::VK_F24) + .value("VK_NUMLOCK" , ACCELERATOR_VK_CODES::VK_NUMLOCK) + .value("VK_SCROLL" , ACCELERATOR_VK_CODES::VK_SCROLL) + .value("VK_LSHIFT" , ACCELERATOR_VK_CODES::VK_LSHIFT) + .value("VK_RSHIFT" , ACCELERATOR_VK_CODES::VK_RSHIFT) + .value("VK_LCONTROL" , ACCELERATOR_VK_CODES::VK_LCONTROL) + .value("VK_RCONTROL" , ACCELERATOR_VK_CODES::VK_RCONTROL) + .value("VK_LMENU" , ACCELERATOR_VK_CODES::VK_LMENU) + .value("VK_RMENU" , ACCELERATOR_VK_CODES::VK_RMENU) + .value("VK_BROWSER_BACK" , ACCELERATOR_VK_CODES::VK_BROWSER_BACK) + .value("VK_BROWSER_FORWARD" , ACCELERATOR_VK_CODES::VK_BROWSER_FORWARD) + .value("VK_BROWSER_REFRESH" , ACCELERATOR_VK_CODES::VK_BROWSER_REFRESH) + .value("VK_BROWSER_STOP" , ACCELERATOR_VK_CODES::VK_BROWSER_STOP) + .value("VK_BROWSER_SEARCH" , ACCELERATOR_VK_CODES::VK_BROWSER_SEARCH) + .value("VK_BROWSER_FAVORITES" , ACCELERATOR_VK_CODES::VK_BROWSER_FAVORITES) + .value("VK_BROWSER_HOME" , ACCELERATOR_VK_CODES::VK_BROWSER_HOME) + .value("VK_VOLUME_MUTE" , ACCELERATOR_VK_CODES::VK_VOLUME_MUTE) + .value("VK_VOLUME_DOWN" , ACCELERATOR_VK_CODES::VK_VOLUME_DOWN) + .value("VK_VOLUME_UP" , ACCELERATOR_VK_CODES::VK_VOLUME_UP) + .value("VK_MEDIA_NEXT_TRACK" , ACCELERATOR_VK_CODES::VK_MEDIA_NEXT_TRACK) + .value("VK_MEDIA_PREV_TRACK" , ACCELERATOR_VK_CODES::VK_MEDIA_PREV_TRACK) + .value("VK_MEDIA_STOP" , ACCELERATOR_VK_CODES::VK_MEDIA_STOP) + .value("VK_MEDIA_PLAY_PAUSE" , ACCELERATOR_VK_CODES::VK_MEDIA_PLAY_PAUSE) + .value("VK_LAUNCH_MAIL" , ACCELERATOR_VK_CODES::VK_LAUNCH_MAIL) + .value("VK_LAUNCH_MEDIA_SELECT" , ACCELERATOR_VK_CODES::VK_LAUNCH_MEDIA_SELECT) + .value("VK_LAUNCH_APP1" , ACCELERATOR_VK_CODES::VK_LAUNCH_APP1) + .value("VK_LAUNCH_APP2" , ACCELERATOR_VK_CODES::VK_LAUNCH_APP2) + .value("VK_OEM_1" , ACCELERATOR_VK_CODES::VK_OEM_1) + .value("VK_OEM_PLUS" , ACCELERATOR_VK_CODES::VK_OEM_PLUS) + .value("VK_OEM_COMMA" , ACCELERATOR_VK_CODES::VK_OEM_COMMA) + .value("VK_OEM_MINUS" , ACCELERATOR_VK_CODES::VK_OEM_MINUS) + .value("VK_OEM_PERIOD" , ACCELERATOR_VK_CODES::VK_OEM_PERIOD) + .value("VK_OEM_2" , ACCELERATOR_VK_CODES::VK_OEM_2) + .value("VK_OEM_4" , ACCELERATOR_VK_CODES::VK_OEM_4) + .value("VK_OEM_5" , ACCELERATOR_VK_CODES::VK_OEM_5) + .value("VK_OEM_6" , ACCELERATOR_VK_CODES::VK_OEM_6) + .value("VK_OEM_7" , ACCELERATOR_VK_CODES::VK_OEM_7) + .value("VK_OEM_8" , ACCELERATOR_VK_CODES::VK_OEM_8) + .value("VK_OEM_102" , ACCELERATOR_VK_CODES::VK_OEM_102) + .value("VK_PROCESSKEY" , ACCELERATOR_VK_CODES::VK_PROCESSKEY) + .value("VK_PACKET" , ACCELERATOR_VK_CODES::VK_PACKET) + .value("VK_ATTN" , ACCELERATOR_VK_CODES::VK_ATTN) + .value("VK_CRSEL" , ACCELERATOR_VK_CODES::VK_CRSEL) + .value("VK_EXSEL" , ACCELERATOR_VK_CODES::VK_EXSEL) + .value("VK_EREOF" , ACCELERATOR_VK_CODES::VK_EREOF) + .value("VK_PLAY" , ACCELERATOR_VK_CODES::VK_PLAY) + .value("VK_ZOOM" , ACCELERATOR_VK_CODES::VK_ZOOM) + .value("VK_NONAME" , ACCELERATOR_VK_CODES::VK_NONAME) + .value("VK_PA1" , ACCELERATOR_VK_CODES::VK_PA1) + .value("VK_OEM_CLEAR" , ACCELERATOR_VK_CODES::VK_OEM_CLEAR); + + LIEF::enum_(m, "ALGORITHMS") + .value(PY_ENUM(ALGORITHMS::UNKNOWN)) + .value(PY_ENUM(ALGORITHMS::SHA_512)) + .value(PY_ENUM(ALGORITHMS::SHA_384)) + .value(PY_ENUM(ALGORITHMS::SHA_256)) + .value(PY_ENUM(ALGORITHMS::SHA_1)) + .value(PY_ENUM(ALGORITHMS::MD5)) + .value(PY_ENUM(ALGORITHMS::MD4)) + .value(PY_ENUM(ALGORITHMS::MD2)) + .value(PY_ENUM(ALGORITHMS::RSA)) + .value(PY_ENUM(ALGORITHMS::EC)) + + .value(PY_ENUM(ALGORITHMS::MD5_RSA)) + .value(PY_ENUM(ALGORITHMS::SHA1_DSA)) + .value(PY_ENUM(ALGORITHMS::SHA1_RSA)) + + .value(PY_ENUM(ALGORITHMS::SHA_256_RSA)) + .value(PY_ENUM(ALGORITHMS::SHA_384_RSA)) + .value(PY_ENUM(ALGORITHMS::SHA_512_RSA)) + + .value(PY_ENUM(ALGORITHMS::SHA1_ECDSA)) + .value(PY_ENUM(ALGORITHMS::SHA_256_ECDSA)) + .value(PY_ENUM(ALGORITHMS::SHA_384_ECDSA)) + .value(PY_ENUM(ALGORITHMS::SHA_512_ECDSA)); + + + LIEF::enum_(m, "SIG_ATTRIBUTE_TYPES") + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::UNKNOWN)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::CONTENT_TYPE)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::GENERIC_TYPE)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::MS_COUNTER_SIGN)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST)) + .value(PY_ENUM(SIG_ATTRIBUTE_TYPES::PKCS9_SIGNING_TIME)); } } diff --git a/api/python/PE/pyPE.cpp b/api/python/PE/pyPE.cpp index 5a0cc94..ce892c9 100644 --- a/api/python/PE/pyPE.cpp +++ b/api/python/PE/pyPE.cpp @@ -78,10 +78,19 @@ void init_objects(py::module& m) { CREATE(ResourceAccelerator, m); CREATE(Signature, m); CREATE(x509, m); - CREATE(SignerInfo, m); CREATE(ContentInfo, m); - CREATE(AuthenticatedAttributes, m); + CREATE(SignerInfo, m); CREATE(CodeIntegrity, m); + CREATE(Attribute, m); + CREATE(ContentType, m); + CREATE(GenericType, m); + CREATE(MsSpcNestedSignature, m); + CREATE(MsSpcStatementType, m); + CREATE(PKCS9AtSequenceNumber, m); + CREATE(PKCS9CounterSignature, m); + CREATE(PKCS9MessageDigest, m); + CREATE(PKCS9SigningTime, m); + CREATE(SpcSpOpusInfo, m); CREATE(LoadConfiguration, m); CREATE(LoadConfigurationV0, m); diff --git a/api/python/PE/pyPE.hpp b/api/python/PE/pyPE.hpp index b6bc4b7..6381ac8 100644 --- a/api/python/PE/pyPE.hpp +++ b/api/python/PE/pyPE.hpp @@ -81,13 +81,23 @@ SPECIALIZE_CREATE(ResourceStringTable); SPECIALIZE_CREATE(ResourceDialog); SPECIALIZE_CREATE(ResourceDialogItem); SPECIALIZE_CREATE(ResourceAccelerator); + SPECIALIZE_CREATE(Signature); SPECIALIZE_CREATE(x509); SPECIALIZE_CREATE(SignerInfo); +SPECIALIZE_CREATE(Attribute); SPECIALIZE_CREATE(ContentInfo); -SPECIALIZE_CREATE(AuthenticatedAttributes); -SPECIALIZE_CREATE(CodeIntegrity); +SPECIALIZE_CREATE(ContentType); +SPECIALIZE_CREATE(GenericType); +SPECIALIZE_CREATE(MsSpcNestedSignature); +SPECIALIZE_CREATE(MsSpcStatementType); +SPECIALIZE_CREATE(PKCS9AtSequenceNumber); +SPECIALIZE_CREATE(PKCS9CounterSignature); +SPECIALIZE_CREATE(PKCS9MessageDigest); +SPECIALIZE_CREATE(PKCS9SigningTime); +SPECIALIZE_CREATE(SpcSpOpusInfo); +SPECIALIZE_CREATE(CodeIntegrity); SPECIALIZE_CREATE(LoadConfiguration); SPECIALIZE_CREATE(LoadConfigurationV0); SPECIALIZE_CREATE(LoadConfigurationV1); diff --git a/api/python/pyIterators.cpp b/api/python/pyIterators.cpp index a16e726..0fe3dac 100644 --- a/api/python/pyIterators.cpp +++ b/api/python/pyIterators.cpp @@ -56,10 +56,13 @@ void init_LIEF_iterators(py::module& m) { init_ref_iterator(m); init_ref_iterator(m); init_ref_iterator(m); - init_ref_iterator(m); init_ref_iterator(m); init_ref_iterator(m); init_ref_iterator(m); + init_ref_iterator(m); + init_ref_iterator(m); + init_ref_iterator(m); + init_ref_iterator(m); #endif diff --git a/api/python/pyLIEF.hpp b/api/python/pyLIEF.hpp index 8424c47..5742b2f 100644 --- a/api/python/pyLIEF.hpp +++ b/api/python/pyLIEF.hpp @@ -33,6 +33,9 @@ #define RST_ATTR_REF(X) ":attr:`~"#X"`" #define RST_ATTR_REF_FULL(X) ":attr:`"#X"`" +#define RST_METH_REF(X) ":class:`~"#X"`" +#define RST_METH_REF_FULL(X) ":class:`"#X"`" + namespace py = pybind11; using namespace pybind11::literals; diff --git a/cmake/LIEFDependencies.cmake b/cmake/LIEFDependencies.cmake index c81de83..6ee189a 100644 --- a/cmake/LIEFDependencies.cmake +++ b/cmake/LIEFDependencies.cmake @@ -6,8 +6,8 @@ set(__add_lief_dependencies ON) # Json # ---- if (LIEF_ENABLE_JSON) - set(LIBJSON_VERSION 3.7.3) - set(LIBJSON_SHA256 SHA256=e46d26550e8cafc7d7d2564fdf09d20bd14a72c417396bf7ca815b94894d1631) + set(LIBJSON_VERSION 3.9.1) + set(LIBJSON_SHA256 SHA256=5db3b7b3356a0742e06b27b6ee744f8ee487ed9c0f8cf3f9778a2076e7a933ba) set(LIBJSON_URL "${THIRD_PARTY_DIRECTORY}/json-${LIBJSON_VERSION}.zip" CACHE STRING "URL to the JSON lib repo") ExternalProject_Add(lief_libjson URL ${LIBJSON_URL} @@ -29,8 +29,8 @@ endif() # mbed TLS # -------- -set(MBED_TLS_VERSION 2.23.0) -set(MBED_TLS_SHA256 SHA256=bbf9c3cc6b7603f2f15bbba7badcf6cf188a9d5aaa63c4df2d61213f459c2f5f) +set(MBED_TLS_VERSION 2.7.17) +set(MBED_TLS_SHA256 SHA256=a009059b0b4b882b884e8ef7013ff068b1254d8a2d98243e000c67b1737956b6) set(MBED_TLS_URL "${THIRD_PARTY_DIRECTORY}/mbedtls-${MBED_TLS_VERSION}.zip" CACHE STRING "URL to MbedTLS") set(MBED_TLS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/mbed_tls") @@ -53,7 +53,6 @@ set(mbedtls_src_crypto "${MBEDTLS_SOURCE_DIR}/library/aes.c" "${MBEDTLS_SOURCE_DIR}/library/aesni.c" "${MBEDTLS_SOURCE_DIR}/library/arc4.c" - "${MBEDTLS_SOURCE_DIR}/library/aria.c" "${MBEDTLS_SOURCE_DIR}/library/asn1parse.c" "${MBEDTLS_SOURCE_DIR}/library/asn1write.c" "${MBEDTLS_SOURCE_DIR}/library/base64.c" @@ -61,13 +60,10 @@ set(mbedtls_src_crypto "${MBEDTLS_SOURCE_DIR}/library/blowfish.c" "${MBEDTLS_SOURCE_DIR}/library/camellia.c" "${MBEDTLS_SOURCE_DIR}/library/ccm.c" - "${MBEDTLS_SOURCE_DIR}/library/chacha20.c" - "${MBEDTLS_SOURCE_DIR}/library/chachapoly.c" "${MBEDTLS_SOURCE_DIR}/library/cipher.c" "${MBEDTLS_SOURCE_DIR}/library/cipher_wrap.c" "${MBEDTLS_SOURCE_DIR}/library/cmac.c" "${MBEDTLS_SOURCE_DIR}/library/ctr_drbg.c" - "${MBEDTLS_SOURCE_DIR}/library/debug.c" "${MBEDTLS_SOURCE_DIR}/library/des.c" "${MBEDTLS_SOURCE_DIR}/library/dhm.c" "${MBEDTLS_SOURCE_DIR}/library/ecdh.c" @@ -80,15 +76,13 @@ set(mbedtls_src_crypto "${MBEDTLS_SOURCE_DIR}/library/error.c" "${MBEDTLS_SOURCE_DIR}/library/gcm.c" "${MBEDTLS_SOURCE_DIR}/library/havege.c" - "${MBEDTLS_SOURCE_DIR}/library/hkdf.c" "${MBEDTLS_SOURCE_DIR}/library/hmac_drbg.c" "${MBEDTLS_SOURCE_DIR}/library/md.c" "${MBEDTLS_SOURCE_DIR}/library/md2.c" "${MBEDTLS_SOURCE_DIR}/library/md4.c" "${MBEDTLS_SOURCE_DIR}/library/md5.c" + "${MBEDTLS_SOURCE_DIR}/library/md_wrap.c" "${MBEDTLS_SOURCE_DIR}/library/memory_buffer_alloc.c" - "${MBEDTLS_SOURCE_DIR}/library/net_sockets.c" - "${MBEDTLS_SOURCE_DIR}/library/nist_kw.c" "${MBEDTLS_SOURCE_DIR}/library/oid.c" "${MBEDTLS_SOURCE_DIR}/library/padlock.c" "${MBEDTLS_SOURCE_DIR}/library/pem.c" @@ -99,8 +93,6 @@ set(mbedtls_src_crypto "${MBEDTLS_SOURCE_DIR}/library/pkparse.c" "${MBEDTLS_SOURCE_DIR}/library/pkwrite.c" "${MBEDTLS_SOURCE_DIR}/library/platform.c" - "${MBEDTLS_SOURCE_DIR}/library/platform_util.c" - "${MBEDTLS_SOURCE_DIR}/library/poly1305.c" "${MBEDTLS_SOURCE_DIR}/library/ripemd160.c" "${MBEDTLS_SOURCE_DIR}/library/rsa.c" "${MBEDTLS_SOURCE_DIR}/library/rsa_internal.c" @@ -112,19 +104,6 @@ set(mbedtls_src_crypto "${MBEDTLS_SOURCE_DIR}/library/version.c" "${MBEDTLS_SOURCE_DIR}/library/version_features.c" "${MBEDTLS_SOURCE_DIR}/library/xtea.c" - "${MBEDTLS_SOURCE_DIR}/library/aria.c" - "${MBEDTLS_SOURCE_DIR}/library/chacha20.c" - "${MBEDTLS_SOURCE_DIR}/library/chachapoly.c" - "${MBEDTLS_SOURCE_DIR}/library/hkdf.c" - "${MBEDTLS_SOURCE_DIR}/library/nist_kw.c" - "${MBEDTLS_SOURCE_DIR}/library/platform_util.c" - "${MBEDTLS_SOURCE_DIR}/library/poly1305.c" - "${MBEDTLS_SOURCE_DIR}/library/psa_crypto.c" - "${MBEDTLS_SOURCE_DIR}/library/psa_crypto_se.c" - "${MBEDTLS_SOURCE_DIR}/library/psa_crypto_slot_management.c" - "${MBEDTLS_SOURCE_DIR}/library/psa_crypto_storage.c" - "${MBEDTLS_SOURCE_DIR}/library/psa_its_file.c" - "${MBEDTLS_SOURCE_DIR}/library/rsa_internal.c" ) set(mbedtls_src_x509 @@ -149,7 +128,6 @@ set(mbedtls_src_tls "${MBEDTLS_SOURCE_DIR}/library/ssl_srv.c" "${MBEDTLS_SOURCE_DIR}/library/ssl_ticket.c" "${MBEDTLS_SOURCE_DIR}/library/ssl_tls.c" - "${MBEDTLS_SOURCE_DIR}/library/ssl_msg.c" ) #set_source_files_properties("${MBEDTLS_SOURCE_DIR}/library/bignum.c" PROPERTIES COMPILE_FLAGS -Wno-overlength-strings) @@ -170,18 +148,18 @@ set(SPDLOG_SOURCE_DIR "${SOURCE_DIR}") # Fuzzing # ~~~~~~~ -set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O1) +set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O2) set(FUZZING_LINKER_FLAGS) -list(APPEND FUZZING_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard) -list(APPEND FUZZING_LINKER_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard) +list(APPEND FUZZING_FLAGS -fsanitize=address,fuzzer) +list(APPEND FUZZING_LINKER_FLAGS -fsanitize=address,fuzzer) set(LIBFUZZER_SRC_FILES) if (LIEF_FUZZING) message(STATUS "Fuzzing Enabled") - set(LIBFUZZER_VERSION 8ff5640b48c4c4a3b974daa10a5f445e86ed7428) - set(LIBFUZZER_SHA256 SHA256=ed067ebc72b993571854edb113e9f3ef74367dfb8bab1a252009aff72e287614) + set(LIBFUZZER_VERSION 6f13445) + set(LIBFUZZER_SHA256 SHA256=cf9a4f5025beb9005181b9136a88e142f1360a3f8ccd490ec1b8f773cefc51e1) set(LIBFUZZER_URL "${THIRD_PARTY_DIRECTORY}/LibFuzzer-${LIBFUZZER_VERSION}.zip") ExternalProject_Add(lief_libfuzzer URL ${LIBFUZZER_URL} @@ -195,36 +173,32 @@ if (LIEF_FUZZING) set(LIBFUZZER_SOURCE_DIR "${SOURCE_DIR}") set(LIBFUZZER_SRC_FILES - "${LIBFUZZER_SOURCE_DIR}/FuzzerSHA1.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilLinux.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerIO.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerMain.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerShmemWindows.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilWindows.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerUtil.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsym.cpp" - #${LIBFUZZER_SOURCE_DIR}/afl/afl_driver.cpp - "${LIBFUZZER_SOURCE_DIR}/FuzzerShmemPosix.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilDarwin.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerIOWindows.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsymWin.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerCrossOver.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerDataFlowTrace.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerDriver.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsym.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeak.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilPosix.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeakAlias.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerIOPosix.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerMerge.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerTracePC.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerMutate.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWindows.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerExtraCounters.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerFork.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerIO.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerIOPosix.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerIOWindows.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerLoop.cpp" - "${LIBFUZZER_SOURCE_DIR}/FuzzerClangCounters.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerMerge.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerMutate.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerSHA1.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerTracePC.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtil.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilDarwin.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilFuchsia.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilLinux.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilPosix.cpp" + "${LIBFUZZER_SOURCE_DIR}/FuzzerUtilWindows.cpp" ) list(APPEND LIBLIEF_SOURCE_FILES ${LIBFUZZER_SRC_FILES}) - set_source_files_properties(${LIBFUZZER_SRC_FILES} PROPERTIES GENERATED TRUE) - add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing") endif() @@ -251,3 +225,19 @@ if (LIEF_SUPPORT_CXX14 AND NOT LIEF_DISABLE_FROZEN) set(FROZEN_INCLUDE_DIR "${SOURCE_DIR}/include") endif() + +# Boost leaf +# ---------- +set(LEAF_VERSION 0.3.0) +set(LEAF_SHA256 SHA256=0a256cba80d9ec53adece74d231c28a79ddb7d96e8f79daeed72cad0c7855dfe ) +set(LEAF_URL "${THIRD_PARTY_DIRECTORY}/leaf-${LEAF_VERSION}.zip" CACHE STRING "URL to Leaf") +ExternalProject_Add(lief_leaf # :) + URL ${LEAF_URL} + URL_HASH ${LEAF_SHA256} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND "") + +ExternalProject_get_property(lief_leaf SOURCE_DIR) +set(LEAF_INCLUDE_DIR "${SOURCE_DIR}/include") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 0a7c0c4..9c4f3b8 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -8,7 +8,7 @@ elseif(NOT SPHINX_FOUND) elseif(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) message(STATUS "You have to build the doc in another directory !") else() - + message(STATUS "Sphinx: ${SPHINX_EXECUTABLE}") add_custom_target(lief-doxygen COMMAND ${CMAKE_COMMAND} -E env @@ -23,7 +23,7 @@ else() add_custom_target(lief-sphinx COMMAND ${CMAKE_COMMAND} -E env - "PYTHONPATH=${PROJECT_BINARY_DIR}/api/python:$ENV{PYTHONPATH}" + "PYTHONPATH=${CMAKE_SOURCE_DIR}:${CMAKE_BINARY_DIR}/../:${CMAKE_BINARY_DIR}/api/python:$ENV{PYTHONPATH}" "LIEF_DOXYGEN_XML=${CMAKE_CURRENT_BINARY_DIR}/doxygen/xml/" ${SPHINX_EXECUTABLE} -a -E -j4 -w ${CMAKE_BINARY_DIR}/sphinx-warn.log ${CMAKE_SOURCE_DIR}/doc/sphinx sphinx-doc DEPENDS pyLIEF lief-doxygen @@ -37,7 +37,7 @@ else() add_custom_target(lief-quick-sphinx COMMAND ${CMAKE_COMMAND} -E env - "PYTHONPATH=${PROJECT_BINARY_DIR}/api/python:$ENV{PYTHONPATH}" + "PYTHONPATH=${CMAKE_SOURCE_DIR}:${CMAKE_BINARY_DIR}/../:${CMAKE_BINARY_DIR}/api/python:$ENV{PYTHONPATH}" "LIEF_DOXYGEN_XML=${CMAKE_CURRENT_BINARY_DIR}/doxygen/xml/" "FORCE_RTD_THEME=0" ${SPHINX_EXECUTABLE} -j4 -w ${CMAKE_BINARY_DIR}/sphinx-warn.log ${CMAKE_SOURCE_DIR}/doc/sphinx sphinx-doc diff --git a/doc/sphinx/api/cpp/pe.rst b/doc/sphinx/api/cpp/pe.rst index 7c90f89..fa60c30 100644 --- a/doc/sphinx/api/cpp/pe.rst +++ b/doc/sphinx/api/cpp/pe.rst @@ -153,15 +153,113 @@ Signature ---------- -AuthenticatedAttributes -*********************** +Signature Attribute +******************* -.. doxygenclass:: LIEF::PE::AuthenticatedAttributes +.. doxygenclass:: LIEF::PE::Attribute :project: lief ---------- +Signature ContentType +********************* + +.. doxygenclass:: LIEF::PE::ContentType + :project: lief + + +---------- + +Signature GenericType +********************* + +.. doxygenclass:: LIEF::PE::GenericType + :project: lief + + +---------- + +Signature MsSpcNestedSignature +******************************* + +.. doxygenclass:: LIEF::PE::MsSpcNestedSignature + :project: lief + + +---------- + + +Signature MsSpcStatementType +**************************** + +.. doxygenclass:: LIEF::PE::MsSpcStatementType + :project: lief + + +---------- + + +Signature PKCS9AtSequenceNumber +******************************* + +.. doxygenclass:: LIEF::PE::PKCS9AtSequenceNumber + :project: lief + + +---------- + + +Signature PKCS9CounterSignature +******************************* + +.. doxygenclass:: LIEF::PE::PKCS9CounterSignature + :project: lief + + +---------- + + +Signature PKCS9MessageDigest +**************************** + +.. doxygenclass:: LIEF::PE::PKCS9MessageDigest + :project: lief + + +---------- + + +Signature PKCS9SigningTime +************************** + +.. doxygenclass:: LIEF::PE::PKCS9SigningTime + :project: lief + + +---------- + + +Signature SpcSpOpusInfo +*********************** + +.. doxygenclass:: LIEF::PE::SpcSpOpusInfo + :project: lief + + +---------- + + +RsaInfo +******* + +.. doxygenclass:: LIEF::PE::RsaInfo + :project: lief + + +---------- + + x509 **** @@ -171,6 +269,7 @@ x509 ---------- + ContentInfo *********** @@ -526,5 +625,8 @@ Enums .. doxygenenum:: LIEF::PE::GUARD_CF_FLAGS :project: lief -.. doxygenenum:: LIEF::PE::POGO_SIGNATURES +.. doxygenenum:: LIEF::PE::ALGORITHMS + :project: lief + +.. doxygenenum:: LIEF::PE::SIG_ATTRIBUTE_TYPES :project: lief diff --git a/doc/sphinx/api/python/pe.rst b/doc/sphinx/api/python/pe.rst index 59cb40b..66fb7f8 100644 --- a/doc/sphinx/api/python/pe.rst +++ b/doc/sphinx/api/python/pe.rst @@ -162,10 +162,91 @@ Signature ---------- -AuthenticatedAttributes -*********************** +Signature Attribute +******************* -.. autoclass:: lief.PE.AuthenticatedAttributes +.. autoclass:: lief.PE.Attribute + :members: + :inherited-members: + :undoc-members: + +---------- + + +Signature ContentType +********************* + +.. autoclass:: lief.PE.ContentType + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature GenericType +********************* + +.. autoclass:: lief.PE.GenericType + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature MsSpcNestedSignature +****************************** + +.. autoclass:: lief.PE.MsSpcNestedSignature + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature MsSpcStatementType +**************************** + +.. autoclass:: lief.PE.MsSpcStatementType + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature PKCS9AtSequenceNumber +******************************* + +.. autoclass:: lief.PE.PKCS9AtSequenceNumber + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature PKCS9CounterSignature +******************************* + +.. autoclass:: lief.PE.PKCS9CounterSignature + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature PKCS9MessageDigest +**************************** + +.. autoclass:: lief.PE.PKCS9MessageDigest + :members: + :inherited-members: + :undoc-members: + +---------- + +Signature PKCS9SigningTime +************************** + +.. autoclass:: lief.PE.PKCS9SigningTime :members: :inherited-members: :undoc-members: @@ -831,3 +912,21 @@ POGO_SIGNATURES :members: :inherited-members: :undoc-members: + + +ALGORITHMS +~~~~~~~~~~ + +.. autoclass:: lief.PE.ALGORITHMS + :members: + :inherited-members: + :undoc-members: + + +SIG_ATTRIBUTE_TYPES +~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: lief.PE.SIG_ATTRIBUTE_TYPES + :members: + :inherited-members: + :undoc-members: diff --git a/doc/sphinx/changelog.rst b/doc/sphinx/changelog.rst index 679239a..44077e6 100644 --- a/doc/sphinx/changelog.rst +++ b/doc/sphinx/changelog.rst @@ -20,6 +20,7 @@ Changelog * Bug fix in the symbols table reconstruction (ELF) :PE: + * Enhance PE Authenticode. See `PE Authenticode `_ * :attr:`~lief.PE.LangCodeItem.items` now returns a dictionary whose values are **bytes** (instead of ``str`` object). This change is related to ``utf-16`` support. * :github_user:`kohnakagawa` fixed wrong enums values: :commit:`c03125045e32a9cd65c613585eb4d0385350c6d2`, :commit:`6ee808a1e4611d09c6cf0aea82a612be69584db9`, :commit:`cd05f34bae681fc8af4b5e7cc28eaef816802b6f` @@ -38,7 +39,7 @@ Changelog * Upgrade ``mbedtls`` to 2.16.6 :Documentation: - * :github_user:`aguinet` updated the `bin2lib tutorial `_ with the support + * :github_user:`aguinet` updated the `bin2lib tutorial `_ with the support of the new glibc versions (:commit:`7884e57aa1d103f3bd37682e47f412bfe7a3aa34`) * Global update and enable to build the documentation out-of-tree * Changing the theme diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst index 2497a7a..f61747e 100644 --- a/doc/sphinx/index.rst +++ b/doc/sphinx/index.rst @@ -25,7 +25,7 @@ Welcome to LIEF's documentation! tutorials/10_android_formats tutorials/11_macho_modification tutorials/12_elf_coredump - + tutorials/13_pe_authenticode .. toctree:: :caption: API diff --git a/doc/sphinx/tutorials/13_pe_authenticode.rst b/doc/sphinx/tutorials/13_pe_authenticode.rst new file mode 100644 index 0000000..90d19cf --- /dev/null +++ b/doc/sphinx/tutorials/13_pe_authenticode.rst @@ -0,0 +1,48 @@ +13 - PE Authenticode +-------------------- + +This tutorial introduces the new API deal with PE Authenticode processing. + +By Romain Thomas - `@rh0main `_ + +------ + +Introduction +~~~~~~~~~~~~ + +.. TODO + + + +.. rubric:: References + + +.. TODO + + +.. rubric:: API + +* :meth:`lief.PE.Binary.verify_signature` +* :meth:`lief.PE.Binary.authentihash` +* :attr:`lief.PE.Binary.authentihash_md5` +* :attr:`lief.PE.Binary.authentihash_sha1` +* :attr:`lief.PE.Binary.authentihash_sha256` +* :attr:`lief.PE.Binary.authentihash_sha512` +* :attr:`lief.PE.Binary.signatures` + +* :class:`lief.PE.Signature` +* :class:`lief.PE.x509` +* :class:`lief.PE.ContentInfo` +* :class:`lief.PE.SignerInfo` +* :class:`lief.PE.Attribute` +* :class:`lief.PE.ContentType` +* :class:`lief.PE.GenericType` +* :class:`lief.PE.MsCounterSign` +* :class:`lief.PE.MsSpcNestedSignature` +* :class:`lief.PE.MsSpcStatementType` +* :class:`lief.PE.PKCS9AtSequenceNumber` +* :class:`lief.PE.PKCS9CounterSignature` +* :class:`lief.PE.PKCS9MessageDigest` +* :class:`lief.PE.PKCS9SigningTime` +* :class:`lief.PE.SpcSpOpusInfo` + diff --git a/examples/cpp/pe_reader.cpp b/examples/cpp/pe_reader.cpp index f90e286..78db0c8 100644 --- a/examples/cpp/pe_reader.cpp +++ b/examples/cpp/pe_reader.cpp @@ -100,13 +100,10 @@ int main(int argc, char **argv) { std::cout << binary->resources_manager() << std::endl; } - - if (binary->has_signature()) { + for (const Signature& sig : binary->signatures()) { std::cout << "== Signature ==" << std::endl; - std::cout << binary->signature() << std::endl; + std::cout << sig << std::endl; } - - return 0; } diff --git a/examples/python/pe_reader.py b/examples/python/pe_reader.py index 1b5f121..0d86a2a 100644 --- a/examples/python/pe_reader.py +++ b/examples/python/pe_reader.py @@ -298,45 +298,8 @@ def print_debug(binary): def print_signature(binary): format_str = "{:<33} {:<30}" format_dec = "{:<33} {:<30d}" - - signature = binary.signature - print("== Signature ==") - print(format_dec.format("Version:", signature.version)) - print(format_str.format("Digest Algorithm:", oid_to_string(signature.digest_algorithm))) - print("") - - print("-- Content Info --") - content_info = signature.content_info - print(format_str.format("Content Type:", oid_to_string(content_info.content_type))) - print(format_str.format("Type:", oid_to_string(content_info.type))) - print(format_str.format("Digest Algorithm:", oid_to_string(content_info.digest_algorithm))) - print("") - - print("-- Certificates --") - certificates = signature.certificates - - for crt in certificates: - sn_str = ":".join(map(lambda e : "{:02x}".format(e), crt.serial_number)) - valid_from_str = "-".join(map(str, crt.valid_from[:3])) + " " + ":".join(map(str, crt.valid_from[3:])) - valid_to_str = "-".join(map(str, crt.valid_to[:3])) + " " + ":".join(map(str, crt.valid_to[3:])) - print(format_dec.format("Version:", crt.version)) - print(format_str.format("Serial Number:", sn_str)) - print(format_str.format("Signature Algorithm:", oid_to_string(crt.signature_algorithm))) - print(format_str.format("Valid from:", valid_from_str)) - print(format_str.format("Valid to:", valid_to_str)) - print(format_str.format("Issuer:", crt.issuer)) - print(format_str.format("Subject:", crt.subject)) - print("") - - print("-- Signer Info --") - signer_info = signature.signer_info - print(format_dec.format("Version:", signer_info.version)) - print(format_str.format("Issuer:", signer_info.issuer[0])) - print(format_str.format("Digest Algorithm:", oid_to_string(signer_info.digest_algorithm))) - print(format_str.format("Signature algorithm:", oid_to_string(signer_info.signature_algorithm))) - print(format_str.format("Program name:", signer_info.authenticated_attributes.program_name)) - print(format_str.format("Url:", signer_info.authenticated_attributes.more_info)) - print("") + for signature in binary.signatures: + print(signature) @exceptions_handler(Exception) def print_rich_header(binary): @@ -616,7 +579,7 @@ def main(): if (args.show_debug or args.show_all) and binary.has_debug: print_debug(binary) - if (args.show_signature or args.show_all) and binary.has_signature: + if (args.show_signature or args.show_all) and binary.has_signatures: print_signature(binary) if (args.show_richheader or args.show_all) and binary.has_rich_header: diff --git a/examples/python/pe_sign/authenticode.py b/examples/python/pe_sign/authenticode.py new file mode 100644 index 0000000..507469c --- /dev/null +++ b/examples/python/pe_sign/authenticode.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +import lief +import sys +import os + +# Parse PE file +pe = lief.parse(sys.argv[1]) + +# Get authenticode +print(pe.authentihash_md5.hex(":")) # 1c:a0:91:53:dc:9a:3a:5f:34:1d:7f:9b:b9:56:69:4d +print(pe.authentihash(lief.PE.ALGORITHMS.SHA_1).hex(":")) # 1e:ad:dc:29:1e:db:41:a2:69:c2:ba:ae:4b:fb:9d:31:e7:bb:ab:59 + +# Check signature according to PKCS #7 and Microsoft documentation +print(pe.verify_signature()) # Return VERIFICATION_FLAGS.OK + +bin_ca = None +# Look for the root CA in the PE file +for crt in pe.signatures[0].certificates: + if crt.issuer == "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA": + bin_ca = crt + +# Verify CA chain +bundle_path = os.getenv("LIEF_CA_BUNDLE", None) # Path to CA bundle (one can use those from signify: + # signify/certs/authenticode-bundle.pem) +if bundle_path is not None: + # Parse cert bundle and return a list of lief.PE.x509 objects + bundle = lief.PE.x509.parse(bundle_path) + print(bin_ca.is_trusted_by(bundle)) # VERIFICATION_FLAGS.OK + + +# Get the certificate used by the signer +cert_signer = pe.signatures[0].signers[0].cert +print(cert_signer) +bin_ca.verify(cert_signer) # Verify that cert_signer is signed the the CA + +# running with: +# LIEF_CA_BUNDLE=signify/signify/certs/authenticode-bundle.pem python ./authenticode.py avast_free_antivirus_setup_online.exe +# +# 1c:a0:91:53:dc:9a:3a:5f:34:1d:7f:9b:b9:56:69:4d +# 1e:ad:dc:29:1e:db:41:a2:69:c2:ba:ae:4b:fb:9d:31:e7:bb:ab:59 +# VERIFICATION_FLAGS.OK +# cert. version : 3 +# serial number : 04:09:18:1B:5F:D5:BB:66:75:53:43:B5:6F:95:50:08 +# issuer name : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA +# subject name : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 Assured ID Code Signing CA +# issued on : 2013-10-22 12:00:00 +# expires on : 2028-10-22 12:00:00 +# signed using : RSA with SHA-256 +# RSA key size : 2048 bits +# basic constraints : CA=true, max_pathlen=0 +# key usage : Digital Signature, Key Cert Sign, CRL Sign +# ext key usage : Code Signing +# +# VERIFICATION_FLAGS.OK diff --git a/examples/python/pe_sign/sig_info.py b/examples/python/pe_sign/sig_info.py new file mode 100644 index 0000000..87e2992 --- /dev/null +++ b/examples/python/pe_sign/sig_info.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +import lief +import argparse +import json +import sys +from prettyprinter import pprint + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("pe_file") + + # Logging setup + logger_group = parser.add_argument_group('Logger') + verbosity = logger_group.add_mutually_exclusive_group() + + verbosity.add_argument('--debug', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.DEBUG) + + verbosity.add_argument('--trace', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.TRACE) + + verbosity.add_argument('--info', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.INFO) + + verbosity.add_argument('--warn', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.WARNING) + + verbosity.add_argument('--err', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.ERROR) + + verbosity.add_argument('--critical', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.CRITICAL) + + parser.set_defaults(main_verbosity=lief.logging.LOGGING_LEVEL.WARNING) + + args = parser.parse_args() + lief.logging.set_level(args.main_verbosity) + + binary = None + try: + binary = lief.PE.parse(args.pe_file) + except lief.exception as e: + print(e) + sys.exit(1) + + for sig in binary.signatures: + print(sig) + +if __name__ == "__main__": + main() diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index e4cbed9..c795a61 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -4,6 +4,7 @@ set(LIEF_FUZZER_SRC pe_fuzzer.cpp macho_fuzzer.cpp pme_fuzzer.cpp + pkcs7_signature.cpp ) foreach(fuzzer ${LIEF_FUZZER_SRC}) @@ -35,7 +36,8 @@ ExternalProject_Add(lief_fuzzer_corpus INSTALL_COMMAND "" GIT_REPOSITORY ${SAMPLES_GIT_URL} GIT_TAG ${SAMPLES_TAG} - #UPDATE_COMMAND ${GIT_EXECUTABLE} pull + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE UPDATE_COMMAND "" LOG_DOWNLOAD 1 ) @@ -119,4 +121,18 @@ add_custom_target("fuzz-macho" COMMENT "Run MachO fuzzer") +# PKCS7-Signature parsing +# ======================= +set(PKCS7_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/pkcs7-output) +set(PKCS7_NEW_CASES ${PKCS7_WORKING_DIR}/new_cases) + +add_custom_target(build-pkcs7-fuzz-output + COMMAND ${CMAKE_COMMAND} -E make_directory ${PKCS7_WORKING_DIR} ${PKCS7_NEW_CASES}) + +add_custom_target("fuzz-pkcs7" + COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS="${ASAN_OPTIONS}" ${CMAKE_CURRENT_BINARY_DIR}/pkcs7_signature ${LIB_FUZZER_ARGS} ${LIEF_CORUPUS_DIRECTORY}/pkcs7 ${PKCS7_NEW_CASES} + DEPENDS pkcs7_signature LIB_LIEF build-pkcs7-fuzz-output lief_fuzzer_corpus + WORKING_DIRECTORY ${PKCS7_WORKING_DIR} + COMMENT "Run PKCS7 fuzzer") + diff --git a/fuzzing/pkcs7_signature.cpp b/fuzzing/pkcs7_signature.cpp new file mode 100644 index 0000000..9c7aadb --- /dev/null +++ b/fuzzing/pkcs7_signature.cpp @@ -0,0 +1,12 @@ +#include "LIEF/PE/signature/SignatureParser.hpp" +#include "LIEF/logging.hpp" + +__attribute__((constructor)) void foo(){ + LIEF::logging::disable(); +} + +LIEF_API extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + LIEF::PE::SignatureParser::parse({data, data + size}); + return 0; // Non-zero return values are reserved for future use. +} + diff --git a/include/LIEF/Abstract/type_traits.hpp b/include/LIEF/Abstract/type_traits.hpp index acaed2f..cd0d8d9 100644 --- a/include/LIEF/Abstract/type_traits.hpp +++ b/include/LIEF/Abstract/type_traits.hpp @@ -22,13 +22,13 @@ class Symbol; class Section; class Relocation; -using sections_t = std::vector; -using it_sections = ref_iterator; -using it_const_sections = const_ref_iterator; +using sections_t = std::vector; ///< Default container for abstract sections +using it_sections = ref_iterator; ///< Iterator over abstract sections +using it_const_sections = const_ref_iterator; ///< **Const** iterator over abstract sections -using symbols_t = std::vector; -using it_symbols = ref_iterator; -using it_const_symbols = const_ref_iterator; +using symbols_t = std::vector; ///< Default container for abstract symbols +using it_symbols = ref_iterator; ///< Iterator over abstract symbols +using it_const_symbols = const_ref_iterator; ///< Iterator over abstract symbols using relocations_t = std::vector; ///< Container used to transfert abstract relocations from binary formats using it_relocations = ref_iterator; ///< Iterator over Abstract LIEF::Relocation (read only) diff --git a/include/LIEF/BinaryStream/BinaryStream.hpp b/include/LIEF/BinaryStream/BinaryStream.hpp index dc6577f..ac64e79 100644 --- a/include/LIEF/BinaryStream/BinaryStream.hpp +++ b/include/LIEF/BinaryStream/BinaryStream.hpp @@ -24,6 +24,11 @@ #include #include "LIEF/BinaryStream/Convert.hpp" +#include "LIEF/errors.hpp" + +struct mbedtls_x509_crt; +struct mbedtls_x509_time; + namespace LIEF { class BinaryStream { public: @@ -100,6 +105,19 @@ class BinaryStream { void set_endian_swap(bool swap); + // ASN1 related functions + virtual result asn1_read_tag(int tag) = 0; + virtual result asn1_read_len() = 0; + virtual result asn1_read_alg() = 0; + virtual result asn1_read_oid() = 0; + virtual result asn1_read_int() = 0; + virtual result> asn1_read_bitstring() = 0; + virtual result> asn1_read_octet_string() = 0; + virtual result> asn1_read_cert() = 0; + virtual result x509_read_names() = 0; + virtual result> x509_read_serial() = 0; + virtual result> x509_read_time() = 0; + protected: virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const = 0; mutable size_t pos_{0}; diff --git a/include/LIEF/BinaryStream/VectorStream.hpp b/include/LIEF/BinaryStream/VectorStream.hpp index b4f8b40..f2b3bed 100644 --- a/include/LIEF/BinaryStream/VectorStream.hpp +++ b/include/LIEF/BinaryStream/VectorStream.hpp @@ -31,6 +31,36 @@ class VectorStream : public BinaryStream { const std::vector& content(void) const; + inline uint8_t* p() { + return this->binary_.data() + this->pos(); + } + + inline const uint8_t* p() const { + return this->binary_.data() + this->pos(); + } + + + inline uint8_t* end() { + return this->binary_.data() + this->binary_.size(); + } + + inline const uint8_t* end() const { + return this->binary_.data() + this->binary_.size(); + } + + virtual result asn1_read_tag(int tag) override; + virtual result asn1_read_len() override; + result asn1_peek_len(); + virtual result asn1_read_alg() override; + virtual result asn1_read_oid() override; + virtual result asn1_read_int() override; + virtual result> asn1_read_bitstring() override; + virtual result> asn1_read_octet_string() override; + virtual result> asn1_read_cert() override; + virtual result x509_read_names() override; + virtual result> x509_read_serial() override; + virtual result> x509_read_time() override; + protected: virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const override; std::vector binary_; diff --git a/include/LIEF/ELF/NoteDetails/NoteAbi.hpp b/include/LIEF/ELF/NoteDetails/NoteAbi.hpp index eeeb788..fb4cc88 100644 --- a/include/LIEF/ELF/NoteDetails/NoteAbi.hpp +++ b/include/LIEF/ELF/NoteDetails/NoteAbi.hpp @@ -31,7 +31,7 @@ class Parser; class Builder; class Binary; -//! Class representing the ".note.android.ident" section +//! Class representing the ``.note.android.ident`` section //! //! @see: https://android.googlesource.com/platform/ndk/+/ndk-release-r16/sources/crt/crtbrand.S#39 class LIEF_API NoteAbi : public NoteDetails { diff --git a/include/LIEF/PE.hpp b/include/LIEF/PE.hpp index b1b0652..fef2df1 100644 --- a/include/LIEF/PE.hpp +++ b/include/LIEF/PE.hpp @@ -62,7 +62,8 @@ #include "LIEF/PE/AuxiliarySymbol.hpp" #include "LIEF/PE/CodeIntegrity.hpp" -#include "LIEF/PE/signature/AuthenticatedAttributes.hpp" +#include "LIEF/PE/signature/attributes.hpp" +#include "LIEF/PE/signature/Attribute.hpp" #include "LIEF/PE/signature/ContentInfo.hpp" #include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/Signature.hpp" diff --git a/include/LIEF/PE/Binary.hpp b/include/LIEF/PE/Binary.hpp index 8445400..8cc806d 100644 --- a/include/LIEF/PE/Binary.hpp +++ b/include/LIEF/PE/Binary.hpp @@ -111,8 +111,8 @@ class LIEF_API Binary : public LIEF::Binary { //! @see Import bool has_imports(void) const; - //! Check if the current binary is signed - bool has_signature(void) const; + //! Check if the current binary conatains signatures + bool has_signatures(void) const; //! Check if the current binary has exports. //! @@ -138,11 +138,31 @@ class LIEF_API Binary : public LIEF::Binary { //! Check if the current binary has been built has reproducible, replacing timestamps by a compile hash. //! - //! @see Debug + //! @see Debug bool is_reproducible_build(void) const; - //! Return the Signature object if the bianry is signed - const Signature& signature(void) const; + //! Return the Signature object(s) if the bianry is signed + it_const_signatures signatures(void) const; + + //! Verify the binary against the embedded signature(s) (if any) + //! Firstly, it checks that the embedded signatures are correct (c.f. Signature::check) + //! and then it checks that the authentihash matches ContentInfo::digest + Signature::VERIFICATION_FLAGS verify_signature() const; + + //! Verify the binary with the Signature object provided in the first parameter + //! It can be used to verify a detached signature: + //! + //! \code{.cpp} + //! result detached = LIEF::PE::SignatureParser::parse("sig.pkcs7") + //! if (detached) { + //! binary->verify_signature(detached.value()); + //! } + //! \endcode + Signature::VERIFICATION_FLAGS verify_signature(const Signature& sig) const; + + //! Compute the authentihash according to the algorithm provided in the first + //! parameter + std::vector authentihash(ALGORITHMS algo) const; //! Try to predict the RVA of the function `function` in the import library `library` //! @@ -411,27 +431,26 @@ class LIEF_API Binary : public LIEF::Binary { void update_lookup_address_table_offset(void); void update_iat(void); - PE_TYPE type_; - DosHeader dos_header_; - RichHeader rich_header_; - Header header_; - OptionalHeader optional_header_; + PE_TYPE type_; + DosHeader dos_header_; + RichHeader rich_header_; + Header header_; + OptionalHeader optional_header_; - int32_t available_sections_space_; + int32_t available_sections_space_; - bool has_rich_header_; - bool has_tls_; - bool has_imports_; - bool has_signature_; - bool has_exports_; - bool has_resources_; - bool has_exceptions_; - bool has_relocations_; - bool has_debug_; - bool has_configuration_; - bool is_reproducible_build_; + bool has_rich_header_; + bool has_tls_; + bool has_imports_; + bool has_exports_; + bool has_resources_; + bool has_exceptions_; + bool has_relocations_; + bool has_debug_; + bool has_configuration_; + bool is_reproducible_build_; - Signature signature_; + signatures_t signatures_; TLS tls_; sections_t sections_; data_directories_t data_directories_; @@ -442,8 +461,10 @@ class LIEF_API Binary : public LIEF::Binary { imports_t imports_; Export export_; debug_entries_t debug_; + uint64_t overlay_offset_ = 0; std::vector overlay_; std::vector dos_stub_; + std::vector section_offset_padding_; LoadConfiguration* load_configuration_{nullptr}; diff --git a/include/LIEF/PE/EnumToString.hpp b/include/LIEF/PE/EnumToString.hpp index 42492a6..5e7c4ee 100644 --- a/include/LIEF/PE/EnumToString.hpp +++ b/include/LIEF/PE/EnumToString.hpp @@ -67,6 +67,9 @@ LIEF_API const char* to_string(GUARD_CF_FLAGS e); LIEF_API const char* to_string(ACCELERATOR_FLAGS e); LIEF_API const char* to_string(ACCELERATOR_VK_CODES e); +LIEF_API const char* to_string(ALGORITHMS e); +LIEF_API const char* to_string(SIG_ATTRIBUTE_TYPES e); + } // namespace PE } // namespace LIEF #endif diff --git a/include/LIEF/PE/Section.hpp b/include/LIEF/PE/Section.hpp index 0b657f9..0a75073 100644 --- a/include/LIEF/PE/Section.hpp +++ b/include/LIEF/PE/Section.hpp @@ -58,6 +58,9 @@ class LIEF_API Section : public LIEF::Section { // LIEF::Section implementation // ============================ virtual std::vector content(void) const override; + inline const std::vector& padding() const { + return this->padding_; + } uint32_t pointerto_raw_data(void) const; @@ -100,14 +103,15 @@ class LIEF_API Section : public LIEF::Section { private: std::vector& content_ref(void); - uint32_t virtualSize_; - std::vector content_; - uint32_t pointerToRelocations_; - uint32_t pointerToLineNumbers_; - uint16_t numberOfRelocations_; - uint16_t numberOfLineNumbers_; - uint32_t characteristics_; - std::set types_; + std::vector content_; + std::vector padding_; + uint32_t virtual_size_ = 0; + uint32_t pointer_to_relocations_ = 0; + uint32_t pointer_to_linenumbers_ = 0; + uint16_t number_of_relocations_ = 0; + uint16_t number_of_linenumbers_ = 0; + uint32_t characteristics_ = 0; + std::set types_ = {PE_SECTION_TYPES::UNKNOWN}; }; } // namespace PE diff --git a/include/LIEF/PE/enums.hpp.in b/include/LIEF/PE/enums.hpp.in index 0531295..3ba5cec 100644 --- a/include/LIEF/PE/enums.hpp.in +++ b/include/LIEF/PE/enums.hpp.in @@ -11,7 +11,7 @@ namespace PE { @LIEF_PE_ENUMS@ -// Common section type +//! Common section type enum class PE_SECTION_TYPES : uint8_t { TEXT = 0, TLS = 1, @@ -31,6 +31,51 @@ enum class PE_TYPE : uint16_t { PE32_PLUS = 0x20b ///< 64 bits }; +//! Cryptography algorithms +enum class ALGORITHMS { + UNKNOWN = 0, + SHA_512, + SHA_384, + SHA_256, + SHA_1, + + MD5, + MD4, + MD2, + + RSA, + EC, + + MD5_RSA, + SHA1_DSA, + SHA1_RSA, + SHA_256_RSA, + SHA_384_RSA, + SHA_512_RSA, + SHA1_ECDSA, + SHA_256_ECDSA, + SHA_384_ECDSA, + SHA_512_ECDSA, +}; + +//! Typed enum for LIEF::PE::Attribute +enum class SIG_ATTRIBUTE_TYPES { + UNKNOWN = 0, + CONTENT_TYPE, + GENERIC_TYPE, + + SPC_SP_OPUS_INFO, + + MS_COUNTER_SIGN, + MS_SPC_NESTED_SIGN, + MS_SPC_STATEMENT_TYPE, + + PKCS9_AT_SEQUENCE_NUMBER, + PKCS9_COUNTER_SIGNATURE, + PKCS9_MESSAGE_DIGEST, + PKCS9_SIGNING_TIME, +}; + static const RESOURCE_TYPES resource_types_array[] = { RESOURCE_TYPES::CURSOR, diff --git a/include/LIEF/PE/hash.hpp b/include/LIEF/PE/hash.hpp index 9fce922..9ef348b 100644 --- a/include/LIEF/PE/hash.hpp +++ b/include/LIEF/PE/hash.hpp @@ -60,7 +60,18 @@ class ResourceAccelerator; class Signature; class x509; class SignerInfo; -class AuthenticatedAttributes; +class ContentInfo; +class Attribute; +class ContentType; +class GenericType; +//class MsCounterSign; +class MsSpcNestedSignature; +class MsSpcStatementType; +class PKCS9AtSequenceNumber; +class PKCS9CounterSignature; +class PKCS9MessageDigest; +class PKCS9SigningTime; +class SpcSpOpusInfo; class CodeIntegrity; class LoadConfiguration; class LoadConfigurationV0; @@ -120,19 +131,28 @@ class LIEF_API Hash : public LIEF::Hash { virtual void visit(const Signature& signature) override; virtual void visit(const x509& x509) override; 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 ContentInfo& contentinfo) override; + virtual void visit(const Attribute& attr) override; + virtual void visit(const ContentType& attr) override; + virtual void visit(const GenericType& attr) override; + //virtual void visit(const MsCounterSign& attr) override; + virtual void visit(const MsSpcNestedSignature& attr) override; + virtual void visit(const MsSpcStatementType& attr) override; + virtual void visit(const PKCS9AtSequenceNumber& attr) override; + virtual void visit(const PKCS9CounterSignature& attr) override; + virtual void visit(const PKCS9MessageDigest& attr) override; + virtual void visit(const PKCS9SigningTime& attr) override; + virtual void visit(const SpcSpOpusInfo& attr) 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 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 Pogo& pogo) override; virtual void visit(const PogoEntry& entry) override; diff --git a/include/LIEF/PE/json.hpp b/include/LIEF/PE/json.hpp index 90ef43c..19308b5 100644 --- a/include/LIEF/PE/json.hpp +++ b/include/LIEF/PE/json.hpp @@ -65,7 +65,17 @@ class Signature; class x509; class SignerInfo; class ContentInfo; -class AuthenticatedAttributes; +class Attribute; +class ContentType; +class GenericType; +//class MsCounterSign; +class MsSpcNestedSignature; +class MsSpcStatementType; +class PKCS9AtSequenceNumber; +class PKCS9CounterSignature; +class PKCS9MessageDigest; +class PKCS9SigningTime; +class SpcSpOpusInfo; class CodeIntegrity; class LoadConfiguration; class LoadConfigurationV0; @@ -124,18 +134,27 @@ class LIEF_API JsonVisitor : public LIEF::JsonVisitor { virtual void visit(const x509& x509) override; 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 Attribute& attr) override; + virtual void visit(const ContentType& attr) override; + virtual void visit(const GenericType& attr) override; + //virtual void visit(const MsCounterSign& attr) override; + virtual void visit(const MsSpcNestedSignature& attr) override; + virtual void visit(const MsSpcStatementType& attr) override; + virtual void visit(const PKCS9AtSequenceNumber& attr) override; + virtual void visit(const PKCS9CounterSignature& attr) override; + virtual void visit(const PKCS9MessageDigest& attr) override; + virtual void visit(const PKCS9SigningTime& attr) override; + virtual void visit(const SpcSpOpusInfo& attr) 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 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 Pogo& pogo) override; virtual void visit(const PogoEntry& entry) override; diff --git a/include/LIEF/PE/signature/Attribute.hpp b/include/LIEF/PE/signature/Attribute.hpp new file mode 100644 index 0000000..ba12f62 --- /dev/null +++ b/include/LIEF/PE/signature/Attribute.hpp @@ -0,0 +1,65 @@ +/* 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_ATTRIBUTES_H_ +#define LIEF_PE_ATTRIBUTES_H_ +#include +#include "LIEF/Object.hpp" +#include "LIEF/visibility.h" + +#include "LIEF/PE/enums.hpp" + +namespace LIEF { +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over PKCS #7 attribute +class LIEF_API Attribute : public Object { + + friend class Parser; + friend class SignatureParser; + + public: + Attribute(void); + Attribute(const Attribute&); + Attribute& operator=(const Attribute&); + + virtual std::unique_ptr clone(void) const = 0; + + //! Concrete type of the attribute + inline virtual SIG_ATTRIBUTE_TYPES type() const { + return this->type_; + } + + //! Print information about the underlying attribute + virtual std::string print() const = 0; + + virtual void accept(Visitor& visitor) const override; + + virtual ~Attribute(); + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Attribute& Attribute); + + protected: + Attribute(SIG_ATTRIBUTE_TYPES type); + SIG_ATTRIBUTE_TYPES type_ = SIG_ATTRIBUTE_TYPES::UNKNOWN; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/AuthenticatedAttributes.hpp b/include/LIEF/PE/signature/AuthenticatedAttributes.hpp deleted file mode 100644 index c698df0..0000000 --- a/include/LIEF/PE/signature/AuthenticatedAttributes.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* 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_AUTHENTICATED_ATTRIBUTES_H_ -#define LIEF_PE_AUTHENTICATED_ATTRIBUTES_H_ - -#include "LIEF/Object.hpp" -#include "LIEF/visibility.h" - -#include "LIEF/PE/signature/types.hpp" - -namespace LIEF { -namespace PE { - -class Parser; -class SignatureParser; - -class LIEF_API AuthenticatedAttributes : public Object { - - friend class Parser; - friend class SignatureParser; - - public: - AuthenticatedAttributes(void); - AuthenticatedAttributes(const AuthenticatedAttributes&); - AuthenticatedAttributes& operator=(const AuthenticatedAttributes&); - - //! @brief Should return the ``messageDigest`` OID - const oid_t& content_type(void) const; - - //! @brief Return an hash of the signed attributes - const std::vector& message_digest(void) const; - - //! @brief Return the program description (if any) - const std::u16string& program_name(void) const; - - //! @brief Return an URL to website with more information about the signer - const std::string& more_info(void) const; - - //! @brief Return the raw bytes associated with the AuthenticatedAttributes - const std::vector& raw(void) const; - - virtual void accept(Visitor& visitor) const override; - - virtual ~AuthenticatedAttributes(void); - - LIEF_API friend std::ostream& operator<<(std::ostream& os, const AuthenticatedAttributes& authenticated_attributes); - - private: - oid_t content_type_; // should holds 1.2.840.113549.1.9.4 - - std::vector message_digest_; - - std::u16string program_name_; - std::string more_info_; - std::vector raw_; - -}; - -} -} - -#endif diff --git a/include/LIEF/PE/signature/ContentInfo.hpp b/include/LIEF/PE/signature/ContentInfo.hpp index cbe6697..4539299 100644 --- a/include/LIEF/PE/signature/ContentInfo.hpp +++ b/include/LIEF/PE/signature/ContentInfo.hpp @@ -20,6 +20,7 @@ #include "LIEF/visibility.h" #include "LIEF/PE/signature/types.hpp" +#include "LIEF/PE/enums.hpp" namespace LIEF { namespace PE { @@ -27,6 +28,44 @@ namespace PE { class Parser; class SignatureParser; +/** ContentInfo as described in the RFC2315 (https://tools.ietf.org/html/rfc2315#section-7) + * + * ```raw + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL + * } + * + * ContentType ::= OBJECT IDENTIFIER + * + * In the case of PE signature, ContentType **must** be set to SPC_INDIRECT_DATA_OBJID + * OID: ``1.3.6.1.4.1.311.2.1.4`` and content is defined by the structure: ``SpcIndirectDataContent`` + * + * SpcIndirectDataContent ::= SEQUENCE { + * data SpcAttributeTypeAndOptionalValue, + * messageDigest DigestInfo + * } + * + * SpcAttributeTypeAndOptionalValue ::= SEQUENCE { + * type ObjectID, + * value [0] EXPLICIT ANY OPTIONAL + * } + * + * For PE signature, ``SpcAttributeTypeAndOptionalValue.type`` + * is set to ``SPC_PE_IMAGE_DATAOBJ`` (OID: ``1.3.6.1.4.1.311.2.1.15``) and the value is defined by + * ``SpcPeImageData`` + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTETSTRING + * } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm ObjectID, + * parameters [0] EXPLICIT ANY OPTIONAL + * } + * ``` + */ class LIEF_API ContentInfo : public Object { friend class Parser; @@ -37,21 +76,29 @@ class LIEF_API ContentInfo : public Object { ContentInfo(const ContentInfo&); ContentInfo& operator=(const ContentInfo&); - //! @brief OID of the content type. - //! This value should match ``SPC_INDIRECT_DATA_OBJID`` - const oid_t& content_type(void) const; + //! Return the OID that describes the content wrapped by this object. + //! It should match SPC_INDIRECT_DATA_OBJID (1.3.6.1.4.1.311.2.1.4) + inline oid_t content_type() const { + return content_type_; + } - const oid_t& type(void) const; + //! Digest used to hash the file + //! + //! It should match LIEF::PE::SignerInfo::digest_algorithm + inline ALGORITHMS digest_algorithm() const { + return this->digest_algorithm_; + } - //! @brief Algorithm (OID) used to hash the file. - //! This value should match SignerInfo::digest_algorithm and Signature::digest_algorithm - const oid_t& digest_algorithm(void) const; + //! PE's authentihash + //! + //! @see LIEF::PE::Binary::authentihash + inline const std::vector& digest() const { + return this->digest_; + } - //! @brief The digest - const std::vector& digest(void) const; - - //! @brief Return the raw bytes associated with the ContentInfo - const std::vector& raw(void) const; + inline const std::string& file() const { + return this->file_; + } virtual void accept(Visitor& visitor) const override; @@ -60,14 +107,11 @@ class LIEF_API ContentInfo : public Object { LIEF_API friend std::ostream& operator<<(std::ostream& os, const ContentInfo& content_info); private: - oid_t content_type_; // SPC_INDIRECT_DATA_OBJID - - oid_t type_; // SPC_PE_IMAGE_DATAOBJ - //TODO: value - - oid_t digest_algorithm_; // algorithm used to hash the file (should match Signature::digest_algorithms_) - std::vector digest_; //hash value - std::vector raw_; // raw bytes + oid_t content_type_; + std::string file_; + uint8_t flags_ = 0; + ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN; + std::vector digest_; }; diff --git a/include/LIEF/PE/signature/RsaInfo.hpp b/include/LIEF/PE/signature/RsaInfo.hpp new file mode 100644 index 0000000..3889d23 --- /dev/null +++ b/include/LIEF/PE/signature/RsaInfo.hpp @@ -0,0 +1,65 @@ +/* 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_SIGNATURE_RSA_INFO_H_ +#define LIEF_PE_SIGNATURE_RSA_INFO_H_ +#include +#include + +#include "LIEF/types.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +namespace PE { +class x509; + +class LIEF_API RsaInfo { + friend class x509; + + public: + using rsa_ctx_handle = void*; + using bignum_wrapper_t = std::vector; + + public: + RsaInfo(const RsaInfo& other); + RsaInfo(RsaInfo&& other); + RsaInfo& operator=(RsaInfo other); + + bool has_public_key(void) const; + bool has_private_key(void) const; + + bignum_wrapper_t N(void) const; + bignum_wrapper_t E(void) const; + + bignum_wrapper_t D(void) const; + bignum_wrapper_t P(void) const; + bignum_wrapper_t Q(void) const; + + void swap(RsaInfo& other); + operator bool() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const RsaInfo& info); + + ~RsaInfo(void); + + private: + RsaInfo(void); + RsaInfo(const rsa_ctx_handle ctx); + rsa_ctx_handle ctx_; +}; + +} +} +#endif diff --git a/include/LIEF/PE/signature/Signature.hpp b/include/LIEF/PE/signature/Signature.hpp index 7b12322..a94f366 100644 --- a/include/LIEF/PE/signature/Signature.hpp +++ b/include/LIEF/PE/signature/Signature.hpp @@ -24,64 +24,112 @@ #include "LIEF/PE/signature/ContentInfo.hpp" #include "LIEF/PE/signature/types.hpp" +#include "LIEF/PE/enums.hpp" +#include "LIEF/enums.hpp" namespace LIEF { namespace PE { class SignatureParser; +class Binary; +//! Main interface for the PKCS #7 signature scheme class LIEF_API Signature : public Object { friend class SignatureParser; friend class Parser; + friend class Binary; public: + //! Hash the input given the algorithm + static std::vector hash(const std::vector& input, ALGORITHMS algo); + + public: + //! Flags returned by verification fonctions + enum class VERIFICATION_FLAGS { + OK = 0, + INVALID_SIGNER = 1 << 0, + UNSUPPORTED_ALGORITHM = 1 << 1, + INCONSISTENT_DIGEST_ALGORITHM = 1 << 2, + CERT_NOT_FOUND = 1 << 3, + CORRUPTED_CONTENT_INFO = 1 << 4, + CORRUPTED_AUTH_DATA = 1 << 5, + MISSING_PKCS9_MESSAGE_DIGEST = 1 << 6, + BAD_DIGEST = 1 << 7, + BAD_SIGNATURE = 1 << 8, + NO_SIGNATURE = 1 << 9, + }; + Signature(void); Signature(const Signature&); Signature& operator=(const Signature&); - //! @brief Should be 1 + //! Should be 1 uint32_t version(void) const; - //! @brief Return the algorithm (OID) used to - //! sign the content of ContentInfo - const oid_t& digest_algorithm(void) const; + //! Algorithm used to *digest* the file. + //! + //! It should match SignerInfo::digest_algorithm + inline ALGORITHMS digest_algorithm() const { + return this->digest_algorithm_; + } - //! @brief Return the ContentInfo + //! Return the ContentInfo const ContentInfo& content_info(void) const; - //! @brief Return an iterator over x509 certificates + //! Return an iterator over x509 certificates it_const_crt certificates(void) const; - //! @brief Return the SignerInfo object - const SignerInfo& signer_info(void) const; + //! Return an iterator over the signers (SignerInfo) defined in the PKCS #7 signature + it_const_signers_t signers(void) const; - //! @brief Return the raw original signature - const std::vector& original_signature(void) const; + //! Return the raw original PKCS7 signature + const std::vector& raw_der(void) const; virtual void accept(Visitor& visitor) const override; + //! Check if this signature is valid according to the Authenticode/PKCS #7 verification scheme + //! + //! 1. It must contain only **one** signer info + //! 2. Signature::digest_algorithm must match: + //! * ContentInfo::digest_algorithm + //! * SignerInfo::digest_algorithm + //! 3. The x509 certificate specified by SignerInfo::serial_number **and** SignerInfo::issuer + //! must exists within Signature::certificates + //! 4. Given the x509 certificate, compare SignerInfo::encrypted_digest against either: + //! * hash of authenticated attributes if present there are authenticated attributes + //! * hash ContentInfo + //! 5. If the are Authenticated attributes, check that a PKCS9_MESSAGE_DIGEST attribute exists + //! and that its value matches hash of ContentInfo + VERIFICATION_FLAGS check() const; + virtual ~Signature(void); LIEF_API friend std::ostream& operator<<(std::ostream& os, const Signature& signature); private: - uint32_t version_; - oid_t digest_algorithm_; - ContentInfo content_info_; - std::vector certificates_; - SignerInfo signer_info_; + uint32_t version_ = 0; + ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN; + ContentInfo content_info_; + std::vector certificates_; + std::vector signers_; + + uint64_t content_info_start_ = 0; + uint64_t content_info_end_ = 0; + + uint64_t auth_start_ = 0; + uint64_t auth_end_ = 0; std::vector original_raw_signature_; - - - }; + } } +ENABLE_BITMASK_OPERATORS(LIEF::PE::Signature::VERIFICATION_FLAGS); + #endif diff --git a/include/LIEF/PE/signature/SignatureParser.hpp b/include/LIEF/PE/signature/SignatureParser.hpp index 096a68c..0511fb0 100644 --- a/include/LIEF/PE/signature/SignatureParser.hpp +++ b/include/LIEF/PE/signature/SignatureParser.hpp @@ -17,6 +17,9 @@ #define LIEF_PE_SIGNATURE_PARSER_H_ #include #include +#include + +#include "LIEF/errors.hpp" #include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/OIDToString.hpp" @@ -26,41 +29,64 @@ class VectorStream; namespace PE { class Parser; +class Attribute; class LIEF_API SignatureParser { - friend class Parser; + struct SpcPeImageData { + uint32_t flags; + std::string file; + }; + + struct SpcSpOpusInfo { + std::string program_name; + std::string more_info; + }; + struct range_t { + uint64_t start = 0; + uint64_t end = 0; + }; public: - static Signature parse(const std::vector& data); + using attributes_t = std::vector>; + using signer_infos_t = std::vector; + using x509_certificates_t = std::vector; + using time_t = std::array; + + //! Parse a PKCS #7 signature given a raw blob + static result parse(std::vector data, bool skip_header = false); + + //! Parse a PKCS #7 signature from a file path + static result parse(const std::string& path); private: - SignatureParser(const std::vector& data); - ~SignatureParser(void); - SignatureParser(void); + SignatureParser(std::vector data); + ~SignatureParser(); + SignatureParser(); - void parse_signature(void); + result parse_signature(); - void parse_header(void); - int32_t get_signed_data_version(void); - std::string get_signed_data_digest_algorithms(void); + result parse_content_info(VectorStream& stream, range_t& range); + result parse_certificates(VectorStream& stream); + result parse_signer_infos(VectorStream& stream, range_t& auth_attr); + result parse_attributes(VectorStream& stream); + result> parse_content_type(VectorStream& stream); - ContentInfo parse_content_info(void); - std::string get_content_info_type(void); - - void parse_certificates(void); - - SignerInfo get_signer_info(void); - AuthenticatedAttributes get_authenticated_attributes(void); + result parse_pkcs9_counter_sign(VectorStream& stream); + result> parse_pkcs9_message_digest(VectorStream& stream); + result parse_pkcs9_at_sequence_number(VectorStream& stream); + result parse_pkcs9_signing_time(VectorStream& stream); + result parse_ms_counter_sign(VectorStream& stream); + result parse_ms_spc_nested_signature(VectorStream& stream); + result parse_ms_spc_statement_type(VectorStream& stream); + result parse_spc_sp_opus_info(VectorStream& stream); + result parse_spc_string(VectorStream& stream); + result parse_spc_link(VectorStream& stream); + result parse_spc_pe_image_data(VectorStream& stream); size_t current_offset(void) const; - Signature signature_; - uint8_t* p_{nullptr}; - const uint8_t* end_{nullptr}; - const uint8_t* signature_ptr_{nullptr}; std::unique_ptr stream_; - }; } diff --git a/include/LIEF/PE/signature/SignerInfo.hpp b/include/LIEF/PE/signature/SignerInfo.hpp index 5aa7a20..977fa67 100644 --- a/include/LIEF/PE/signature/SignerInfo.hpp +++ b/include/LIEF/PE/signature/SignerInfo.hpp @@ -15,19 +15,22 @@ */ #ifndef LIEF_PE_SIGNER_INFO_H_ #define LIEF_PE_SIGNER_INFO_H_ +#include #include "LIEF/Object.hpp" #include "LIEF/visibility.h" -#include "LIEF/PE/signature/AuthenticatedAttributes.hpp" #include "LIEF/PE/signature/types.hpp" +#include "LIEF/PE/enums.hpp" namespace LIEF { namespace PE { +class Attribute; class Parser; class SignatureParser; +class x509; class LIEF_API SignerInfo : public Object { @@ -35,29 +38,71 @@ class LIEF_API SignerInfo : public Object { friend class SignatureParser; public: + using encrypted_digest_t = std::vector; SignerInfo(void); - SignerInfo(const SignerInfo&); - SignerInfo& operator=(const SignerInfo&); - //! @brief Should be 1 + SignerInfo(const SignerInfo& signinfo); + SignerInfo& operator=(SignerInfo signinfo); + + SignerInfo(SignerInfo&&); + SignerInfo& operator=(SignerInfo&&); + + void swap(SignerInfo& other); + + //! Should be 1 uint32_t version(void) const; - //! @brief Issuer and serial number - const issuer_t& issuer(void) const; + //! Return the serial number associated with the x509 certificate + //! used by this signer. + //! + //! @see + //! LIEF::PE::x509::serial_number + //! SignerInfo::issuer + inline const std::vector& serial_number() const { + return this->serialno_; + } - //! @brief Algorithm (OID) used to hash the file. - //! This value should match ContentInfo::digest_algorithm and Signature::digest_algorithm - const oid_t& digest_algorithm(void) const; + //! Return the x509::issuer used by this signer + inline const std::string& issuer() const { + return this->issuer_; + }; - //! @brief Return the AuthenticatedAttributes object - const AuthenticatedAttributes& authenticated_attributes(void) const; + //! Algorithm (OID) used to hash the file. + //! + //! This value should match LIEF::PE::ContentInfo::digest_algorithm and + //! LIEF::PE::Signature::digest_algorithm + ALGORITHMS digest_algorithm(void) const; - //! @brief Return the signature algorithm (OID) - const oid_t& signature_algorithm(void) const; + //! Return the (public-key) algorithm used to encrypt + //! the signature + ALGORITHMS encryption_algorithm(void) const; - //! @brief Return the signature created by the signing + //! Return the signature created by the signing //! certificate's private key - const std::vector& encrypted_digest(void) const; + const encrypted_digest_t& encrypted_digest(void) const; + + //! Iterator over LIEF::PE::Attribute for **authenticated** attributes + it_const_attributes_t authenticated_attributes() const; + + //! Iterator over LIEF::PE::Attribute for **unauthenticated** attributes + it_const_attributes_t unauthenticated_attributes() const; + + //! Return the authenticated or un-authenticated attribute matching the + //! given PE::SIG_ATTRIBUTE_TYPES. + //! + //! It returns **the first** entry that matches the given type. If it can't be + //! found, it returns a nullptr. + const Attribute* get_attribute(PE::SIG_ATTRIBUTE_TYPES type) const; + + //! x509 certificate used by this signer. If it can't be found, it returns a nullptr + inline const x509* cert() const { + return this->cert_.get(); + } + + //! x509 certificate used by this signer. If it can't be found, it returns a nullptr + inline x509* cert() { + return this->cert_.get(); + } virtual void accept(Visitor& visitor) const override; @@ -66,13 +111,18 @@ class LIEF_API SignerInfo : public Object { LIEF_API friend std::ostream& operator<<(std::ostream& os, const SignerInfo& signer_info); private: - uint32_t version_; - issuer_t issuer_; - oid_t digest_algorithm_; + uint32_t version_; + std::string issuer_; + std::vector serialno_; - AuthenticatedAttributes authenticated_attributes_; - oid_t signature_algorithm_; - std::vector encrypted_digest_; + ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN; + ALGORITHMS digest_enc_algorithm_ = ALGORITHMS::UNKNOWN; + + encrypted_digest_t encrypted_digest_; + std::vector> authenticated_attributes_; + std::vector> unauthenticated_attributes_; + + std::unique_ptr cert_; }; diff --git a/include/LIEF/PE/signature/attributes.hpp b/include/LIEF/PE/signature/attributes.hpp new file mode 100644 index 0000000..aa87110 --- /dev/null +++ b/include/LIEF/PE/signature/attributes.hpp @@ -0,0 +1,14 @@ +#ifndef LIEF_PE_SIGNATURE_ATTRIBUTES_H_ +#define LIEF_PE_SIGNATURE_ATTRIBUTES_H_ +#include "LIEF/PE/signature/attributes/ContentType.hpp" +#include "LIEF/PE/signature/attributes/GenericType.hpp" +#include "LIEF/PE/signature/attributes/MsCounterSign.hpp" +#include "LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp" +#include "LIEF/PE/signature/attributes/MsSpcStatementType.hpp" +#include "LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp" +#include "LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp" +#include "LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp" +#include "LIEF/PE/signature/attributes/PKCS9SigningTime.hpp" +#include "LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp" +#endif + diff --git a/include/LIEF/PE/signature/attributes/ContentType.hpp b/include/LIEF/PE/signature/attributes/ContentType.hpp new file mode 100644 index 0000000..d9fe353 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/ContentType.hpp @@ -0,0 +1,71 @@ +/* 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_ATTRIBUTES_CONTENT_TYPE_H_ +#define LIEF_PE_ATTRIBUTES_CONTENT_TYPE_H_ +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.2.840.113549.1.9.3`` (PKCS #9) +//! +//! The internal structure is described in the +//! [RFC #2985: PKCS #9 - Selected Object Classes and Attribute Types Version 2.0](https://tools.ietf.org/html/rfc2985) +//! +//! ```raw +//! ContentType ::= OBJECT IDENTIFIER +//! ``` +class LIEF_API ContentType : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + ContentType(); + ContentType(oid_t oid); + ContentType(const ContentType&); + ContentType& operator=(const ContentType&); + + //! OID as described in RFC #2985 + inline const oid_t& oid() const { + return this->oid_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual std::unique_ptr clone(void) const override; + + virtual void accept(Visitor& visitor) const override; + virtual ~ContentType(); + + private: + oid_t oid_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/GenericType.hpp b/include/LIEF/PE/signature/attributes/GenericType.hpp new file mode 100644 index 0000000..e356878 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/GenericType.hpp @@ -0,0 +1,71 @@ +/* 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_ATTRIBUTES_GENERIC_TYPE_H_ +#define LIEF_PE_ATTRIBUTES_GENERIC_TYPE_H_ +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over an attribute whose the internal structure is not supported by LIEF +class LIEF_API GenericType : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + GenericType(); + GenericType(oid_t oid, std::vector raw); + GenericType(const GenericType&); + GenericType& operator=(const GenericType&); + + virtual std::unique_ptr clone(void) const override; + + //! OID of the original attribute + inline const oid_t& oid() const { + return this->oid_; + } + + //! Original DER blob of the attribute + inline const std::vector& raw_content() const { + return this->raw_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + + virtual ~GenericType(); + + private: + oid_t oid_; + std::vector raw_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/MsCounterSign.hpp b/include/LIEF/PE/signature/attributes/MsCounterSign.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp b/include/LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp new file mode 100644 index 0000000..6396eed --- /dev/null +++ b/include/LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp @@ -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_ATTRIBUTES_MS_SPC_NESTED_SIG_H_ +#define LIEF_PE_ATTRIBUTES_MS_SPC_NESTED_SIG_H_ + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/Signature.hpp" + + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.3.6.1.4.1.311.2.4.1`` +//! +//! The internal structure is not documented but we can infer the following structure: +//! +//! ```raw +//! MsSpcNestedSignature ::= SET OF SignedData +//! ``` +//! +//! ``SignedData`` is the structure described in PKCS #7 RFC (LIEF::PE::Signature) +class LIEF_API MsSpcNestedSignature : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + MsSpcNestedSignature(); + MsSpcNestedSignature(Signature sig); + MsSpcNestedSignature(const MsSpcNestedSignature&); + MsSpcNestedSignature& operator=(const MsSpcNestedSignature&); + + virtual std::unique_ptr clone(void) const override; + + //! Underlying Signature object + inline const Signature& sig() const { + return this->sig_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + + virtual ~MsSpcNestedSignature(); + + private: + Signature sig_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/MsSpcStatementType.hpp b/include/LIEF/PE/signature/attributes/MsSpcStatementType.hpp new file mode 100644 index 0000000..463a1c4 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/MsSpcStatementType.hpp @@ -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_ATTRIBUTES_MS_SPC_STATEMENT_TYPE_H_ +#define LIEF_PE_ATTRIBUTES_MS_SPC_STATEMENT_TYPE_H_ + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.3.6.1.4.1.311.2.1.11`` +//! +//! The internal structure is described in the official document: +//! [Windows Authenticode Portable Executable Signature Format](http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx) +//! +//! ```raw +//! SpcStatementType ::= SEQUENCE of OBJECT IDENTIFIER +//! ``` +class LIEF_API MsSpcStatementType : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + MsSpcStatementType(); + MsSpcStatementType(oid_t oid); + MsSpcStatementType(const MsSpcStatementType&); + MsSpcStatementType& operator=(const MsSpcStatementType&); + + virtual std::unique_ptr clone(void) const override; + + //! According to the documentation: + //! > The SpcStatementType MUST contain one Object Identifier with either + //! > the value ``1.3.6.1.4.1.311.2.1.21 (SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID)`` or + //! > ``1.3.6.1.4.1.311.2.1.22 (SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID)``. + inline const oid_t& oid() const { + return this->oid_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + virtual ~MsSpcStatementType(); + + private: + oid_t oid_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp b/include/LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp new file mode 100644 index 0000000..d859036 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp @@ -0,0 +1,76 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LIEF_PE_ATTRIBUTES_PKCS9_AT_SEQUENCE_NUMBER_H_ +#define LIEF_PE_ATTRIBUTES_PKCS9_AT_SEQUENCE_NUMBER_H_ + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.2.840.113549.1.9.25.4`` (PKCS #9) +//! +//! The internal structure is described in the +//! [RFC #2985: PKCS #9 - Selected Object Classes and Attribute Types Version 2.0](https://tools.ietf.org/html/rfc2985) +//! +//! ```raw +//! sequenceNumber ATTRIBUTE ::= { +//! WITH SYNTAX SequenceNumber +//! EQUALITY MATCHING RULE integerMatch +//! SINGLE VALUE TRUE +//! ID pkcs-9-at-sequenceNumber +//! } +//! +//! SequenceNumber ::= INTEGER (1..MAX) +//! ``` +class LIEF_API PKCS9AtSequenceNumber : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + PKCS9AtSequenceNumber(); + PKCS9AtSequenceNumber(uint32_t num); + PKCS9AtSequenceNumber(const PKCS9AtSequenceNumber&); + PKCS9AtSequenceNumber& operator=(const PKCS9AtSequenceNumber&); + + virtual std::unique_ptr clone(void) const override; + + //! Number as described in the RFC + inline uint32_t number() const { + return this->number_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + virtual ~PKCS9AtSequenceNumber(); + + private: + uint32_t number_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp b/include/LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp new file mode 100644 index 0000000..7a76705 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp @@ -0,0 +1,76 @@ +/* Copyright 2017 R. Thomas + * Copyright 2017 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LIEF_PE_ATTRIBUTES_PKCS9_COUNTER_SIG_H_ +#define LIEF_PE_ATTRIBUTES_PKCS9_COUNTER_SIG_H_ + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/SignerInfo.hpp" +#include "LIEF/PE/signature/types.hpp" + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + + +//! Interface over the structure described by the OID ``1.2.840.113549.1.9.6`` (PKCS #9) +//! +//! The internal structure is described in the +//! [RFC #2985: PKCS #9 - Selected Object Classes and Attribute Types Version 2.0](https://tools.ietf.org/html/rfc2985) +//! +//! ```raw +//! counterSignature ATTRIBUTE ::= { +//! WITH SYNTAX SignerInfo +//! ID pkcs-9-at-counterSignature +//! } +//! ``` +class LIEF_API PKCS9CounterSignature : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + PKCS9CounterSignature(); + PKCS9CounterSignature(std::vector signers); + PKCS9CounterSignature(const PKCS9CounterSignature&); + PKCS9CounterSignature& operator=(const PKCS9CounterSignature&); + + virtual std::unique_ptr clone(void) const override; + + //! Iterator over the SignerInfo as described in the RFC + inline it_const_signers_t signers() const { + return this->signers_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + + virtual ~PKCS9CounterSignature(); + + private: + std::vector signers_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp b/include/LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp new file mode 100644 index 0000000..5442b1d --- /dev/null +++ b/include/LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp @@ -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. + */ +#ifndef LIEF_PE_ATTRIBUTES_PKCS9_MESSAGE_DIGEST_H_ +#define LIEF_PE_ATTRIBUTES_PKCS9_MESSAGE_DIGEST_H_ + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.2.840.113549.1.9.4`` (PKCS #9) +//! +//! The internal structure is described in the +//! [RFC #2985: PKCS #9 - Selected Object Classes and Attribute Types Version 2.0](https://tools.ietf.org/html/rfc2985) +//! +//! ```raw +//! messageDigest ATTRIBUTE ::= { +//! WITH SYNTAX MessageDigest +//! EQUALITY MATCHING RULE octetStringMatch +//! SINGLE VALUE TRUE +//! ID pkcs-9-at-messageDigest +//! } +//! +//! MessageDigest ::= OCTET STRING +//! ``` +class LIEF_API PKCS9MessageDigest : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + PKCS9MessageDigest(); + PKCS9MessageDigest(std::vector digest); + PKCS9MessageDigest(const PKCS9MessageDigest&); + PKCS9MessageDigest& operator=(const PKCS9MessageDigest&); + + virtual std::unique_ptr clone(void) const override; + + //! Message digeset as a blob of bytes as described in the RFC + inline const std::vector& digest() const { + return this->digest_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + + virtual ~PKCS9MessageDigest(); + + private: + std::vector digest_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/PKCS9SigningTime.hpp b/include/LIEF/PE/signature/attributes/PKCS9SigningTime.hpp new file mode 100644 index 0000000..33f537f --- /dev/null +++ b/include/LIEF/PE/signature/attributes/PKCS9SigningTime.hpp @@ -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. + */ +#ifndef LIEF_PE_ATTRIBUTES_PKCS9_SIGNING_TIME_H_ +#define LIEF_PE_ATTRIBUTES_PKCS9_SIGNING_TIME_H_ +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.2.840.113549.1.9.5`` (PKCS #9) +//! +//! The internal structure is described in the +//! [RFC #2985: PKCS #9 - Selected Object Classes and Attribute Types Version 2.0](https://tools.ietf.org/html/rfc2985) +//! +//! ```raw +//! signingTime ATTRIBUTE ::= { +//! WITH SYNTAX SigningTime +//! EQUALITY MATCHING RULE signingTimeMatch +//! SINGLE VALUE TRUE +//! ID pkcs-9-at-signingTime +//! } +//! +//! SigningTime ::= Time -- imported from ISO/IEC 9594-8 +//! ``` +class LIEF_API PKCS9SigningTime : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + //! Time as an array [year, month, day, hour, min, sec] + using time_t = std::array; + + PKCS9SigningTime(); + PKCS9SigningTime(time_t time); + PKCS9SigningTime(const PKCS9SigningTime&); + PKCS9SigningTime& operator=(const PKCS9SigningTime&); + + //! Time as an array [year, month, day, hour, min, sec] + const time_t& time() const { + return this->time_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual std::unique_ptr clone(void) const override; + + virtual void accept(Visitor& visitor) const override; + virtual ~PKCS9SigningTime(); + + private: + time_t time_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp b/include/LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp new file mode 100644 index 0000000..0649d01 --- /dev/null +++ b/include/LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp @@ -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. + */ +#ifndef LIEF_PE_ATTRIBUTES_SPC_SP_OPUS_INFO_H_ +#define LIEF_PE_ATTRIBUTES_SPC_SP_OPUS_INFO_H_ +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + + +namespace LIEF { +class VectorStream; +namespace PE { + +class Parser; +class SignatureParser; + +//! Interface over the structure described by the OID ``1.3.6.1.4.1.311.2.1.12`` +//! +//! The internal structure is described in the official document: +//! [Windows Authenticode Portable Executable Signature Format](http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx) +//! +//! ```raw +//! SpcSpOpusInfo ::= SEQUENCE { +//! programName [0] EXPLICIT SpcString OPTIONAL, +//! moreInfo [1] EXPLICIT SpcLink OPTIONAL +//! } +//! ``` +class LIEF_API SpcSpOpusInfo : public Attribute { + + friend class Parser; + friend class SignatureParser; + + public: + SpcSpOpusInfo(); + SpcSpOpusInfo(std::string program_name, std::string more_info); + SpcSpOpusInfo(const SpcSpOpusInfo&); + SpcSpOpusInfo& operator=(const SpcSpOpusInfo&); + + virtual std::unique_ptr clone(void) const override; + + //! Program description provided by the publisher + inline const std::string& program_name() const { + return this->program_name_; + } + + //! Other information such as an url + inline const std::string& more_info() const { + return this->more_info_; + } + + //! Print information about the attribute + virtual std::string print() const override; + + virtual void accept(Visitor& visitor) const override; + + virtual ~SpcSpOpusInfo(); + + private: + std::string program_name_; + std::string more_info_; +}; + +} +} + +#endif diff --git a/include/LIEF/PE/signature/types.hpp b/include/LIEF/PE/signature/types.hpp index 0dc9f69..7338399 100644 --- a/include/LIEF/PE/signature/types.hpp +++ b/include/LIEF/PE/signature/types.hpp @@ -24,10 +24,13 @@ namespace LIEF { namespace PE { class x509; +class SignerInfo; +class Attribute; -using oid_t = std::string; -using issuer_t = std::pair>; -using it_const_crt = const_ref_iterator&>; +using oid_t = std::string; +using it_const_crt = const_ref_iterator&>; +using it_const_signers_t = const_ref_iterator&>; +using it_const_attributes_t = const_ref_iterator>; } } diff --git a/include/LIEF/PE/signature/x509.hpp b/include/LIEF/PE/signature/x509.hpp index d006726..2c2c4c8 100644 --- a/include/LIEF/PE/signature/x509.hpp +++ b/include/LIEF/PE/signature/x509.hpp @@ -15,13 +15,18 @@ */ #ifndef LIEF_PE_X509_H_ #define LIEF_PE_X509_H_ -#include +#include +#include #include "LIEF/Object.hpp" #include "LIEF/visibility.h" +#include "LIEF/PE/enums.hpp" + #include "LIEF/PE/signature/types.hpp" +#include "LIEF/enums.hpp" + struct mbedtls_x509_crt; namespace LIEF { @@ -30,44 +35,106 @@ namespace PE { class Parser; class SignatureParser; +class RsaInfo; + class LIEF_API x509 : public Object { friend class Parser; friend class SignatureParser; public: - //! @brief Tuple (Year, Month, Day, Hour, Minute, Second) + //! Tuple (Year, Month, Day, Hour, Minute, Second) using date_t = std::array; + using certificates_t = std::vector; + + static certificates_t parse(const std::string& path); + static certificates_t parse(const std::vector& content); + + //! Public key scheme + enum class KEY_TYPES { + NONE = 0, + RSA, + ECKEY, + ECKEY_DH, + ECDSA, + RSA_ALT, + RSASSA_PSS, + }; + + //! Mirror of mbedtls's X509 Verify codes: MBEDTLS_X509_XX + //! + //! It must be sync with include/mbedtls/x509.h + enum class VERIFICATION_FLAGS { + OK = 0, /**< The verification succeed */ + BADCERT_EXPIRED = 1 << 0, /**< The certificate validity has expired. */ + BADCERT_REVOKED = 1 << 1, /**< The certificate has been revoked (is on a CRL). */ + BADCERT_CN_MISMATCH = 1 << 2, /**< The certificate Common Name (CN) does not match with the expected CN. */ + BADCERT_NOT_TRUSTED = 1 << 3, /**< The certificate is not correctly signed by the trusted CA. */ + BADCRL_NOT_TRUSTED = 1 << 4, /**< The CRL is not correctly signed by the trusted CA. */ + BADCRL_EXPIRED = 1 << 5, /**< The CRL is expired. */ + BADCERT_MISSING = 1 << 6, /**< Certificate was missing. */ + BADCERT_SKIP_VERIFY = 1 << 7, /**< Certificate verification was skipped. */ + BADCERT_OTHER = 1 << 8, /**< Other reason (can be used by verify callback) */ + BADCERT_FUTURE = 1 << 9, /**< The certificate validity starts in the future. */ + BADCRL_FUTURE = 1 << 10, /**< The CRL is from the future */ + BADCERT_KEY_USAGE = 1 << 11, /**< Usage does not match the keyUsage extension. */ + BADCERT_EXT_KEY_USAGE = 1 << 12, /**< Usage does not match the extendedKeyUsage extension. */ + BADCERT_NS_CERT_TYPE = 1 << 13, /**< Usage does not match the nsCertType extension. */ + BADCERT_BAD_MD = 1 << 14, /**< The certificate is signed with an unacceptable hash. */ + BADCERT_BAD_PK = 1 << 15, /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ + BADCERT_BAD_KEY = 1 << 16, /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ + BADCRL_BAD_MD = 1 << 17, /**< The CRL is signed with an unacceptable hash. */ + BADCRL_BAD_PK = 1 << 18, /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ + BADCRL_BAD_KEY = 1 << 19, /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + }; + x509(mbedtls_x509_crt* ca); x509(const x509& other); x509& operator=(x509 other); void swap(x509& other); - //! @brief X.509 version. (1=v1, 2=v2, 3=v3) + //! X.509 version. (1=v1, 2=v2, 3=v3) uint32_t version(void) const; - //! @brief Unique id for certificate issued by a specific CA. + //! Unique id for certificate issued by a specific CA. std::vector serial_number(void) const; - //! @brief Signature algorithm (OID) + //! Signature algorithm (OID) oid_t signature_algorithm(void) const; - //! @brief Start time of certificate validity + //! Start time of certificate validity x509::date_t valid_from(void) const; - //! @brief End time of certificate validity + //! End time of certificate validity x509::date_t valid_to(void) const; - //! @brief Issuer informations + //! Issuer informations std::string issuer(void) const; - //! @brief Subject informations + //! Subject informations std::string subject(void) const; - //! @brief The raw x509 bytes (DER encoded) + //! Try to decrypt the given signature and check if it matches the given hash according to + //! the hash algorithm provided + bool check_signature(const std::vector& hash, const std::vector& signature, ALGORITHMS digest) const; + + //! The raw x509 bytes (DER encoded) std::vector raw(void) const; + //! Return the underlying public-key scheme + KEY_TYPES key_type() const; + + //! **If** the underlying public-key scheme is RSA, return the Rsa information. + //! Otherwise, return a nullptr + std::unique_ptr rsa_info() const; + + //! Verify that this certificate has been used **to trust** the given certificate + VERIFICATION_FLAGS verify(const x509& child) const; + + //! Verify that this certificate **is trusted** by the given CA list + VERIFICATION_FLAGS is_trusted_by(const std::vector& ca) const; + virtual void accept(Visitor& visitor) const override; virtual ~x509(void); @@ -76,11 +143,13 @@ class LIEF_API x509 : public Object { private: x509(void); - mbedtls_x509_crt *x509_cert_; + mbedtls_x509_crt* x509_cert_ = nullptr; }; } } +ENABLE_BITMASK_OPERATORS(LIEF::PE::x509::VERIFICATION_FLAGS); + #endif diff --git a/include/LIEF/PE/type_traits.hpp b/include/LIEF/PE/type_traits.hpp index a961a97..09b032c 100644 --- a/include/LIEF/PE/type_traits.hpp +++ b/include/LIEF/PE/type_traits.hpp @@ -16,6 +16,7 @@ #ifndef LIEF_PE_TYPE_TRAITS_H_ #define LIEF_PE_TYPE_TRAITS_H_ #include +#include #include "LIEF/iterators.hpp" #include "LIEF/PE/enums.hpp" @@ -30,6 +31,7 @@ class RichEntry; class RelocationEntry; class Debug; class PogoEntry; +class Signature; class Import; class ImportEntry; @@ -95,6 +97,10 @@ using rich_entries_t = std::vector; using it_rich_entries = ref_iterator; using it_const_rich_entries = const_ref_iterator; +using signatures_t = std::vector; +using it_signatures = ref_iterator; +using it_const_signatures = const_ref_iterator; + template using flags_list_t = std::set; diff --git a/include/LIEF/PE/utils.hpp b/include/LIEF/PE/utils.hpp index 4e20e19..f2ae68e 100644 --- a/include/LIEF/PE/utils.hpp +++ b/include/LIEF/PE/utils.hpp @@ -62,6 +62,8 @@ LIEF_API std::string get_imphash(const Binary& binary); //! //! @return The PE::import resolved with PE::ImportEntry::name set LIEF_API Import resolve_ordinals(const Import& import, bool strict=false); + +LIEF_API ALGORITHMS algo_from_oid(const std::string& oid); } } #endif diff --git a/include/LIEF/Visitor.hpp b/include/LIEF/Visitor.hpp index 9f4b800..28a0c98 100644 --- a/include/LIEF/Visitor.hpp +++ b/include/LIEF/Visitor.hpp @@ -79,11 +79,23 @@ LIEF_PE_FORWARD(ResourceDialog) LIEF_PE_FORWARD(ResourceDialogItem) LIEF_PE_FORWARD(ResourceStringTable) LIEF_PE_FORWARD(ResourceAccelerator) + LIEF_PE_FORWARD(Signature) LIEF_PE_FORWARD(x509) LIEF_PE_FORWARD(SignerInfo) LIEF_PE_FORWARD(ContentInfo) -LIEF_PE_FORWARD(AuthenticatedAttributes) +LIEF_PE_FORWARD(Attribute) +LIEF_PE_FORWARD(ContentType) +LIEF_PE_FORWARD(GenericType) +//LIEF_PE_FORWARD(MsCounterSign) +LIEF_PE_FORWARD(MsSpcNestedSignature) +LIEF_PE_FORWARD(MsSpcStatementType) +LIEF_PE_FORWARD(PKCS9AtSequenceNumber) +LIEF_PE_FORWARD(PKCS9CounterSignature) +LIEF_PE_FORWARD(PKCS9MessageDigest) +LIEF_PE_FORWARD(PKCS9SigningTime) +LIEF_PE_FORWARD(SpcSpOpusInfo) + LIEF_PE_FORWARD(CodeIntegrity) LIEF_PE_FORWARD(LoadConfiguration) LIEF_PE_FORWARD(LoadConfigurationV0) @@ -196,189 +208,216 @@ LIEF_ART_FORWARD(Header) class LIEF_API Visitor { -public: -Visitor(void); -virtual ~Visitor(void); + public: + Visitor(void); + virtual ~Visitor(void); -virtual void operator()(void); + virtual void operator()(void); -template -void operator()(Arg1&& arg1, Args&&... args); + template + void operator()(Arg1&& arg1, Args&&... args); -virtual void visit(const Object&); + virtual void visit(const Object&); -// Abstract Part -// ============= + // Abstract Part + // ============= -//! Method to visit a LIEF::Binary -LIEF_ABSTRACT_VISITABLE(Binary) + //! Method to visit a LIEF::Binary + LIEF_ABSTRACT_VISITABLE(Binary) -//! Method to visit a LIEF::Header -LIEF_ABSTRACT_VISITABLE(Header) + //! Method to visit a LIEF::Header + LIEF_ABSTRACT_VISITABLE(Header) -//! Method to visit a LIEF::Section -LIEF_ABSTRACT_VISITABLE(Section) + //! Method to visit a LIEF::Section + LIEF_ABSTRACT_VISITABLE(Section) -//! Method to visit a LIEF::Symbol -LIEF_ABSTRACT_VISITABLE(Symbol) + //! Method to visit a LIEF::Symbol + LIEF_ABSTRACT_VISITABLE(Symbol) -//! Method to visit a LIEF::Relocation -LIEF_ABSTRACT_VISITABLE(Relocation) + //! Method to visit a LIEF::Relocation + LIEF_ABSTRACT_VISITABLE(Relocation) -//! Method to visit a LIEF::Function -LIEF_ABSTRACT_VISITABLE(Function) + //! Method to visit a LIEF::Function + LIEF_ABSTRACT_VISITABLE(Function) -LIEF_ELF_VISITABLE(Binary) -LIEF_ELF_VISITABLE(Header) -LIEF_ELF_VISITABLE(Section) -LIEF_ELF_VISITABLE(Segment) -LIEF_ELF_VISITABLE(DynamicEntry) -LIEF_ELF_VISITABLE(DynamicEntryArray) -LIEF_ELF_VISITABLE(DynamicEntryLibrary) -LIEF_ELF_VISITABLE(DynamicSharedObject) -LIEF_ELF_VISITABLE(DynamicEntryRunPath) -LIEF_ELF_VISITABLE(DynamicEntryRpath) -LIEF_ELF_VISITABLE(DynamicEntryFlags) -LIEF_ELF_VISITABLE(Symbol) -LIEF_ELF_VISITABLE(Relocation) -LIEF_ELF_VISITABLE(SymbolVersion) -LIEF_ELF_VISITABLE(SymbolVersionRequirement) -LIEF_ELF_VISITABLE(SymbolVersionDefinition) -LIEF_ELF_VISITABLE(SymbolVersionAux) -LIEF_ELF_VISITABLE(SymbolVersionAuxRequirement) -LIEF_ELF_VISITABLE(Note) -LIEF_ELF_VISITABLE(NoteDetails) -LIEF_ELF_VISITABLE(AndroidNote) -LIEF_ELF_VISITABLE(NoteAbi) -LIEF_ELF_VISITABLE(CorePrPsInfo) -LIEF_ELF_VISITABLE(CorePrStatus) -LIEF_ELF_VISITABLE(CoreAuxv) -LIEF_ELF_VISITABLE(CoreSigInfo) -LIEF_ELF_VISITABLE(CoreFile) -LIEF_ELF_VISITABLE(GnuHash) -LIEF_ELF_VISITABLE(SysvHash) + LIEF_ELF_VISITABLE(Binary) + LIEF_ELF_VISITABLE(Header) + LIEF_ELF_VISITABLE(Section) + LIEF_ELF_VISITABLE(Segment) + LIEF_ELF_VISITABLE(DynamicEntry) + LIEF_ELF_VISITABLE(DynamicEntryArray) + LIEF_ELF_VISITABLE(DynamicEntryLibrary) + LIEF_ELF_VISITABLE(DynamicSharedObject) + LIEF_ELF_VISITABLE(DynamicEntryRunPath) + LIEF_ELF_VISITABLE(DynamicEntryRpath) + LIEF_ELF_VISITABLE(DynamicEntryFlags) + LIEF_ELF_VISITABLE(Symbol) + LIEF_ELF_VISITABLE(Relocation) + LIEF_ELF_VISITABLE(SymbolVersion) + LIEF_ELF_VISITABLE(SymbolVersionRequirement) + LIEF_ELF_VISITABLE(SymbolVersionDefinition) + LIEF_ELF_VISITABLE(SymbolVersionAux) + LIEF_ELF_VISITABLE(SymbolVersionAuxRequirement) + LIEF_ELF_VISITABLE(Note) + LIEF_ELF_VISITABLE(NoteDetails) + LIEF_ELF_VISITABLE(AndroidNote) + LIEF_ELF_VISITABLE(NoteAbi) + LIEF_ELF_VISITABLE(CorePrPsInfo) + LIEF_ELF_VISITABLE(CorePrStatus) + LIEF_ELF_VISITABLE(CoreAuxv) + LIEF_ELF_VISITABLE(CoreSigInfo) + LIEF_ELF_VISITABLE(CoreFile) + LIEF_ELF_VISITABLE(GnuHash) + LIEF_ELF_VISITABLE(SysvHash) -// PE Part -// ======= -//! Method to visit a LIEF::PE::Binary -LIEF_PE_VISITABLE(Binary) + // PE Part + // ======= + //! Method to visit a LIEF::PE::Binary + LIEF_PE_VISITABLE(Binary) -//! Method to visit a LIEF::PE::DosHeader -LIEF_PE_VISITABLE(DosHeader) + //! Method to visit a LIEF::PE::DosHeader + LIEF_PE_VISITABLE(DosHeader) -//! Method to visit a LIEF::PE:RichHeader -LIEF_PE_VISITABLE(RichHeader) + //! Method to visit a LIEF::PE:RichHeader + LIEF_PE_VISITABLE(RichHeader) -//! Method to visit a LIEF::PE:RichEntry -LIEF_PE_VISITABLE(RichEntry) + //! Method to visit a LIEF::PE:RichEntry + LIEF_PE_VISITABLE(RichEntry) -//! Method to visit a LIEF::PE::Header -LIEF_PE_VISITABLE(Header) + //! Method to visit a LIEF::PE::Header + LIEF_PE_VISITABLE(Header) -//! Method to visit a LIEF::PE::OptionalHeader -LIEF_PE_VISITABLE(OptionalHeader) + //! Method to visit a LIEF::PE::OptionalHeader + LIEF_PE_VISITABLE(OptionalHeader) -//! Method to visit a LIEF::PE::DataDirectory -LIEF_PE_VISITABLE(DataDirectory) + //! Method to visit a LIEF::PE::DataDirectory + LIEF_PE_VISITABLE(DataDirectory) -//! Method to visit a LIEF::PE::TLS -LIEF_PE_VISITABLE(TLS) + //! Method to visit a LIEF::PE::TLS + LIEF_PE_VISITABLE(TLS) -//! Method to visit a LIEF::PE::Symbol -LIEF_PE_VISITABLE(Symbol) + //! Method to visit a LIEF::PE::Symbol + LIEF_PE_VISITABLE(Symbol) -//! Method to visit a LIEF::PE::Section -LIEF_PE_VISITABLE(Section) + //! Method to visit a LIEF::PE::Section + LIEF_PE_VISITABLE(Section) -//! Method to visit a LIEF::PE::Relocation -LIEF_PE_VISITABLE(Relocation) + //! Method to visit a LIEF::PE::Relocation + LIEF_PE_VISITABLE(Relocation) -//! Method to visit a LIEF::PE::RelocationEntry -LIEF_PE_VISITABLE(RelocationEntry) + //! Method to visit a LIEF::PE::RelocationEntry + LIEF_PE_VISITABLE(RelocationEntry) -//! Method to visit a LIEF::PE::Export -LIEF_PE_VISITABLE(Export) + //! Method to visit a LIEF::PE::Export + LIEF_PE_VISITABLE(Export) -//! Method to visit a LIEF::PE::ExportEntry -LIEF_PE_VISITABLE(ExportEntry) + //! Method to visit a LIEF::PE::ExportEntry + LIEF_PE_VISITABLE(ExportEntry) -//! Method to visit a LIEF::PE::Debug -LIEF_PE_VISITABLE(Debug) + //! Method to visit a LIEF::PE::Debug + LIEF_PE_VISITABLE(Debug) -//! Method to visit a LIEF::PE::CodeView -LIEF_PE_VISITABLE(CodeView) + //! Method to visit a LIEF::PE::CodeView + LIEF_PE_VISITABLE(CodeView) -//! Method to visit a LIEF::PE::CodeViewPDB -LIEF_PE_VISITABLE(CodeViewPDB) + //! Method to visit a LIEF::PE::CodeViewPDB + LIEF_PE_VISITABLE(CodeViewPDB) -//! Method to visit a LIEF::PE::Import -LIEF_PE_VISITABLE(Import) + //! Method to visit a LIEF::PE::Import + LIEF_PE_VISITABLE(Import) -//! Method to visit a LIEF::PE::ImportEntry -LIEF_PE_VISITABLE(ImportEntry) + //! Method to visit a LIEF::PE::ImportEntry + LIEF_PE_VISITABLE(ImportEntry) -//! Method to visit a LIEF::PE::ResourceNode -LIEF_PE_VISITABLE(ResourceNode) + //! Method to visit a LIEF::PE::ResourceNode + LIEF_PE_VISITABLE(ResourceNode) -//! Method to visit a LIEF::PE::ResourceData -LIEF_PE_VISITABLE(ResourceData) + //! Method to visit a LIEF::PE::ResourceData + LIEF_PE_VISITABLE(ResourceData) -//! Method to visit a LIEF::PE::ResourceDirectory -LIEF_PE_VISITABLE(ResourceDirectory) + //! Method to visit a LIEF::PE::ResourceDirectory + LIEF_PE_VISITABLE(ResourceDirectory) -//! Method to visit a LIEF::PE::ResourceVersion -LIEF_PE_VISITABLE(ResourcesManager) + //! Method to visit a LIEF::PE::ResourceVersion + LIEF_PE_VISITABLE(ResourcesManager) -//! Method to visit a LIEF::PE::ResourceVersion -LIEF_PE_VISITABLE(ResourceVersion) + //! Method to visit a LIEF::PE::ResourceVersion + LIEF_PE_VISITABLE(ResourceVersion) -//! Method to visit a LIEF::PE::ResourceStringFileInfo -LIEF_PE_VISITABLE(ResourceStringFileInfo) + //! Method to visit a LIEF::PE::ResourceStringFileInfo + LIEF_PE_VISITABLE(ResourceStringFileInfo) -//! Method to visit a LIEF::PE::ResourceFixedFileInfo -LIEF_PE_VISITABLE(ResourceFixedFileInfo) + //! Method to visit a LIEF::PE::ResourceFixedFileInfo + LIEF_PE_VISITABLE(ResourceFixedFileInfo) -//! Method to visit a LIEF::PE::ResourceVarFileInfo -LIEF_PE_VISITABLE(ResourceVarFileInfo) + //! Method to visit a LIEF::PE::ResourceVarFileInfo + LIEF_PE_VISITABLE(ResourceVarFileInfo) -//! Method to visit a LIEF::PE::ResourceStringTable -LIEF_PE_VISITABLE(ResourceStringTable) + //! Method to visit a LIEF::PE::ResourceStringTable + LIEF_PE_VISITABLE(ResourceStringTable) -//! Method to visit a LIEF::PE::ResourceAccelerator -LIEF_PE_VISITABLE(ResourceAccelerator) + //! Method to visit a LIEF::PE::ResourceAccelerator + LIEF_PE_VISITABLE(ResourceAccelerator) -//! Method to visit a LIEF::PE::LangCodeItem -LIEF_PE_VISITABLE(LangCodeItem) + //! Method to visit a LIEF::PE::LangCodeItem + LIEF_PE_VISITABLE(LangCodeItem) -//! Method to visit a LIEF::PE::ResourceIcon -LIEF_PE_VISITABLE(ResourceIcon) + //! Method to visit a LIEF::PE::ResourceIcon + LIEF_PE_VISITABLE(ResourceIcon) -//! Method to visit a LIEF::PE::ResourceDialog -LIEF_PE_VISITABLE(ResourceDialog) + //! Method to visit a LIEF::PE::ResourceDialog + LIEF_PE_VISITABLE(ResourceDialog) -//! Method to visit a LIEF::PE::ResourceDialogItem -LIEF_PE_VISITABLE(ResourceDialogItem) + //! Method to visit a LIEF::PE::ResourceDialogItem + LIEF_PE_VISITABLE(ResourceDialogItem) -//! Method to visit a LIEF::PE::Signature -LIEF_PE_VISITABLE(Signature) + //! Method to visit a LIEF::PE::Signature + LIEF_PE_VISITABLE(Signature) -//! Method to visit a LIEF::PE::x509 -LIEF_PE_VISITABLE(x509) + //! Method to visit a LIEF::PE::x509 + LIEF_PE_VISITABLE(x509) -//! Method to visit a LIEF::PE::SignerInfo -LIEF_PE_VISITABLE(SignerInfo) + //! Method to visit a LIEF::PE::SignerInfo + LIEF_PE_VISITABLE(SignerInfo) -//! Method to visit a LIEF::PE::ContentInfo -LIEF_PE_VISITABLE(ContentInfo) + //! Method to visit a LIEF::PE::ContentInfo + LIEF_PE_VISITABLE(ContentInfo) -//! Method to visit a LIEF::PE::AuthenticatedAttributes -LIEF_PE_VISITABLE(AuthenticatedAttributes) + //! Method to visit a LIEF::PE::Attribute + LIEF_PE_VISITABLE(Attribute) -//! Method to visit a LIEF::PE::issuer_t -LIEF_PE_VISITABLE(issuer_t) + //! Method to visit a LIEF::PE::ContentType + LIEF_PE_VISITABLE(ContentType) -//! Method to visit a LIEF::PE::LoadConfiguration -LIEF_PE_VISITABLE(LoadConfiguration) + //! Method to visit a LIEF::PE::GenericType + LIEF_PE_VISITABLE(GenericType) + + //! Method to visit a LIEF::PE::MsCounterSign + //LIEF_PE_VISITABLE(MsCounterSign) + + //! Method to visit a LIEF::PE::MsSpcNestedSignature + LIEF_PE_VISITABLE(MsSpcNestedSignature) + + //! Method to visit a LIEF::PE::MsSpcStatementType + LIEF_PE_VISITABLE(MsSpcStatementType) + + //! Method to visit a LIEF::PE::PKCS9AtSequenceNumber + LIEF_PE_VISITABLE(PKCS9AtSequenceNumber) + + //! Method to visit a LIEF::PE::PKCS9CounterSignature + LIEF_PE_VISITABLE(PKCS9CounterSignature) + + //! Method to visit a LIEF::PE::PKCS9MessageDigest + LIEF_PE_VISITABLE(PKCS9MessageDigest) + + //! Method to visit a LIEF::PE::PKCS9SigningTime + LIEF_PE_VISITABLE(PKCS9SigningTime) + + //! Method to visit a LIEF::PE::SpcSpOpusInfo + LIEF_PE_VISITABLE(SpcSpOpusInfo) + + //! Method to visit a LIEF::PE::LoadConfiguration + LIEF_PE_VISITABLE(LoadConfiguration) //! Method to visit a LIEF::PE::LoadConfigurationV0 LIEF_PE_VISITABLE(LoadConfigurationV0) diff --git a/include/LIEF/errors.hpp b/include/LIEF/errors.hpp new file mode 100644 index 0000000..97ba5b2 --- /dev/null +++ b/include/LIEF/errors.hpp @@ -0,0 +1,81 @@ +#ifndef LIEF_ERROR_H_ +#define LIEF_ERROR_H_ +#include +#include + +//! LIEF error codes definition +enum class lief_errors { + read_error = 1, + not_found, + not_implemented, + not_supported, + + corrupted, + conversion_error, + + read_out_of_bound, + asn1_bad_tag, + file_error, +}; + +const std::error_category& error_category(); +std::error_code make_error_code(lief_errors e); + +namespace std { + template<> + struct is_error_code_enum: std::true_type + {}; +} + +const std::error_category& lief_error_category(); + +//! Create an standard error code from lief_errors +inline std::error_code make_error_code(lief_errors e) { + return std::error_code(int(e), lief_error_category()); +} + + +namespace LIEF { + + +//! Wrapper that contains an Object or an error +//! +//! The LEAF implementation exposes the method ``value()`` to access the underlying object (if no error) +//! +//! Typical usage is: +//! \code{.cpp} +//! result intval = my_function(); +//! if (intval) { +//! int val = intval.value(); +//! } else { // There is an error +//! std::cout << get_error(intval).message() << "\n"; +//! } +//! \endcode +//! +//! See https://boostorg.github.io/leaf/ for more details +template +using result = boost::leaf::result; + +//! Abstraction over the implementation +template +using error_result_t = typename result::error_resul; + +//! Abstraction over the implementation +using error_t = boost::leaf::error_id; + +//! Create an error_t from a lief_errors +error_t return_error(lief_errors); + +//! Get the error code associated with the result +template +std::error_code get_error(result& err) { + return make_error_code(lief_errors(boost::leaf::error_id(err.error()).value())); +} + +} + + + + + +#endif diff --git a/include/LIEF/iostream.hpp b/include/LIEF/iostream.hpp index 99f1cf7..3e9b1f8 100644 --- a/include/LIEF/iostream.hpp +++ b/include/LIEF/iostream.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "LIEF/BinaryStream/Convert.hpp" @@ -39,6 +40,7 @@ class vector_iostream { vector_iostream& write(std::vector&& s); vector_iostream& write(const std::string& s); vector_iostream& write(size_t count, uint8_t value); + vector_iostream& write_sized_int(uint64_t value, size_t size); template vector_iostream& write_conv(const T& t); @@ -54,17 +56,23 @@ class vector_iostream { this->raw_.resize(static_cast(this->tellp()) + sizeof(Integer)); } - auto&& it = std::begin(this->raw_); - std::advance(it, static_cast(this->tellp())); + auto int_p = reinterpret_cast(&integer); std::copy( - reinterpret_cast(&integer), - reinterpret_cast(&integer) + sizeof(Integer), - it); + int_p, int_p + sizeof(Integer), + std::begin(this->raw_) + static_cast(this->tellp())); this->current_pos_ += sizeof(Integer); return *this; } + template::value>> + vector_iostream& write(const std::array& t) { + for (T val : t) { + this->write(val); + } + return *this; + } + vector_iostream& write_uleb128(uint64_t value); vector_iostream& write_sleb128(int64_t value); diff --git a/include/LIEF/utils.hpp b/include/LIEF/utils.hpp index 1462ace..e3f30f3 100644 --- a/include/LIEF/utils.hpp +++ b/include/LIEF/utils.hpp @@ -71,6 +71,8 @@ LIEF_API std::u16string u8tou16(const std::string& string); LIEF_API std::string hex_str(uint8_t c); +LIEF_API std::string hex_dump(const std::vector& data, std::string sep = ":"); + //! Check if the given string in printable LIEF_API bool is_printable(const std::string& str); diff --git a/src/BinaryStream/VectorStream.cpp b/src/BinaryStream/VectorStream.cpp index 9514d8d..087490e 100644 --- a/src/BinaryStream/VectorStream.cpp +++ b/src/BinaryStream/VectorStream.cpp @@ -21,11 +21,28 @@ #include #include +#include +#include +#include +#include +#include + #include "logging.hpp" #include "LIEF/BinaryStream/VectorStream.hpp" #include "LIEF/exception.hpp" namespace LIEF { + +inline void free_names(mbedtls_x509_name& names) { + mbedtls_x509_name *name_cur; + name_cur = names.next; + while (name_cur != nullptr) { + mbedtls_x509_name *name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_free(name_prv); + } +} + VectorStream::VectorStream(const std::string& filename) { std::ifstream binary(filename, std::ios::in | std::ios::binary); @@ -70,6 +87,251 @@ const void* VectorStream::read_at(uint64_t offset, uint64_t size, bool throw_err return this->binary_.data() + offset; } + +result VectorStream::asn1_read_tag(int tag) { + size_t out = 0; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_asn1_get_tag(&p, end, &out, tag); + + if (ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA) { + return make_error_code(lief_errors::read_out_of_bound); + } + else if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return make_error_code(lief_errors::asn1_bad_tag); + } + else if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return out; +} + +result VectorStream::asn1_peek_len() { + const uint64_t pos = this->pos(); + auto len = this->asn1_read_len(); + this->setpos(pos); + return len; +} + +result VectorStream::asn1_read_len() { + size_t len = 0; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_asn1_get_len(&p, end, &len); + + if (ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA) { + return make_error_code(lief_errors::read_out_of_bound); + } + else if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return len; +} + +result VectorStream::asn1_read_alg() { + mbedtls_asn1_buf alg_oid; + char oid_str[256] = {0}; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + + if (ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA) { + return make_error_code(lief_errors::read_out_of_bound); + } + else if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + ret = mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &alg_oid); + if (ret <= 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::string(oid_str); +} + +result VectorStream::asn1_read_oid() { + mbedtls_asn1_buf buf; + char oid_str[256] = {0}; + + auto len = this->asn1_read_tag(MBEDTLS_ASN1_OID); + if (not len) { + return len.error(); + } + + buf.len = len.value(); + buf.p = this->p(); + buf.tag = MBEDTLS_ASN1_OID; + + int ret = mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &buf); + if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { + LIEF_DEBUG("asn1_read_oid: mbedtls_oid_get_numeric_string return MBEDTLS_ERR_OID_BUF_TOO_SMALL"); + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(buf.len); + return std::string(oid_str); +} + + +result VectorStream::asn1_read_int() { + int32_t value = 0; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_asn1_get_int(&p, end, &value); + + if (ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA) { + return make_error_code(lief_errors::read_out_of_bound); + } + else if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return value; +} + +result> VectorStream::asn1_read_bitstring() { + mbedtls_asn1_bitstring bs = {0, 0, nullptr}; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_asn1_get_bitstring(&p, end, &bs); + + if (ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA) { + return make_error_code(lief_errors::read_out_of_bound); + } + else if (ret == MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) { + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::vector{bs.p, bs.p + bs.len}; + } + else if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::vector{bs.p, bs.p + bs.len}; +} + + +result> VectorStream::asn1_read_octet_string() { + auto tag = this->asn1_read_tag(MBEDTLS_ASN1_OCTET_STRING); + if (not tag) { + return tag.error(); + } + std::vector raw = {this->p(), this->p() + tag.value()}; + this->increment_pos(tag.value()); + return raw; +} + +result> VectorStream::asn1_read_cert() { + std::unique_ptr ca{new mbedtls_x509_crt{}}; + mbedtls_x509_crt_init(ca.get()); + + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + const uintptr_t buff_len = reinterpret_cast(end) - reinterpret_cast(p); + + int ret = mbedtls_x509_crt_parse_der(ca.get(), p, /* buff len */ buff_len); + if (ret != 0) { + LIEF_DEBUG("asn1_read_cert(): {:x}", ret); + return make_error_code(lief_errors::read_error); + } + if (ca->raw.len <= 0) { + return make_error_code(lief_errors::read_error); + } + this->increment_pos(ca->raw.len); + return ca; +} + +result VectorStream::x509_read_names() { + mbedtls_x509_name name; + std::memset(&name, 0, sizeof(name)); + + auto tag = this->asn1_read_tag(/* Name */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} for x509_read_names (pos: {:d})", + this->peek(), this->pos()); + return tag.error(); + } + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = p + tag.value(); + int ret = mbedtls_x509_get_name(&p, end, &name); + if (ret != 0) { + free_names(name); + LIEF_DEBUG("mbedtls_x509_get_name failed with {:d}", ret); + return make_error_code(lief_errors::read_error); + } + char buffer[1024]; + ret = mbedtls_x509_dn_gets(buffer, sizeof(buffer), &name); + free_names(name); + + if (ret < 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::string(buffer); +} + +result> VectorStream::x509_read_serial() { + mbedtls_x509_buf serial; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_x509_get_serial(&p, end, &serial); + + if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::vector{serial.p, serial.p + serial.len}; +} + +result> VectorStream::x509_read_time() { + std::unique_ptr tm{new mbedtls_x509_time{}}; + + const uint8_t* cur_p = this->p(); + uint8_t* p = this->p(); + const uint8_t* end = this->end(); + + int ret = mbedtls_x509_get_time(&p, end, tm.get()); + + if (ret != 0) { + return make_error_code(lief_errors::read_error); + } + + this->increment_pos(reinterpret_cast(p) - reinterpret_cast(cur_p)); + return std::move(tm); +} + + + const std::vector& VectorStream::content(void) const { return this->binary_; } diff --git a/src/PE/Binary.cpp b/src/PE/Binary.cpp index dd4a947..37296b8 100644 --- a/src/PE/Binary.cpp +++ b/src/PE/Binary.cpp @@ -21,10 +21,12 @@ #include #include "logging.hpp" +#include "hash_stream.hpp" #include "LIEF/exception.hpp" #include "LIEF/utils.hpp" #include "LIEF/BinaryStream/VectorStream.hpp" +#include "LIEF/iostream.hpp" #include "LIEF/Abstract/Relocation.hpp" @@ -98,7 +100,6 @@ Binary::Binary(void) : has_rich_header_{false}, has_tls_{false}, has_imports_{false}, - has_signature_{false}, has_exports_{false}, has_resources_{false}, has_exceptions_{false}, @@ -347,8 +348,8 @@ bool Binary::has_imports(void) const { return this->has_imports_; } -bool Binary::has_signature(void) const { - return this->has_signature_; +bool Binary::has_signatures(void) const { + return not this->signatures_.empty(); } bool Binary::has_exports(void) const { @@ -1011,8 +1012,228 @@ const debug_entries_t& Binary::debug(void) const { // ///////////////////// -const Signature& Binary::signature(void) const { - return this->signature_; +it_const_signatures Binary::signatures(void) const { + return this->signatures_; +} + +std::vector Binary::authentihash(ALGORITHMS algo) const { + static const std::map HMAP = { + {ALGORITHMS::MD5, hashstream::HASH::MD5}, + {ALGORITHMS::SHA_1, hashstream::HASH::SHA1}, + {ALGORITHMS::SHA_256, hashstream::HASH::SHA256}, + {ALGORITHMS::SHA_384, hashstream::HASH::SHA384}, + {ALGORITHMS::SHA_512, hashstream::HASH::SHA512}, + }; + auto it_hash = HMAP.find(algo); + if (it_hash == std::end(HMAP)) { + LIEF_WARN("Unsupported hash algorithm: {}", to_string(algo)); + return {}; + } + const size_t sizeof_ptr = this->type_ == PE_TYPE::PE32 ? sizeof(uint32_t) : sizeof(uint64_t); + const hashstream::HASH hash_type = it_hash->second; + hashstream ios(hash_type); + //vector_iostream ios; + ios // Hash dos header + .write(this->dos_header_.magic()) + .write(this->dos_header_.used_bytes_in_the_last_page()) + .write(this->dos_header_.file_size_in_pages()) + .write(this->dos_header_.numberof_relocation()) + .write(this->dos_header_.header_size_in_paragraphs()) + .write(this->dos_header_.minimum_extra_paragraphs()) + .write(this->dos_header_.maximum_extra_paragraphs()) + .write(this->dos_header_.initial_relative_ss()) + .write(this->dos_header_.initial_sp()) + .write(this->dos_header_.checksum()) + .write(this->dos_header_.initial_ip()) + .write(this->dos_header_.initial_relative_cs()) + .write(this->dos_header_.addressof_relocation_table()) + .write(this->dos_header_.overlay_number()) + .write(this->dos_header_.reserved()) + .write(this->dos_header_.oem_id()) + .write(this->dos_header_.oem_info()) + .write(this->dos_header_.reserved2()) + .write(this->dos_header_.addressof_new_exeheader()) + .write(this->dos_stub_); + + ios // Hash PE Header + .write(this->header_.signature()) + .write(static_cast(this->header_.machine())) + .write(this->header_.numberof_sections()) + .write(this->header_.time_date_stamp()) + .write(this->header_.pointerto_symbol_table()) + .write(this->header_.numberof_symbols()) + .write(this->header_.sizeof_optional_header()) + .write(static_cast(this->header_.characteristics())); + + ios // Hash OptionalHeader + .write(static_cast(this->optional_header_.magic())) + .write(this->optional_header_.major_linker_version()) + .write(this->optional_header_.minor_linker_version()) + .write(this->optional_header_.sizeof_code()) + .write(this->optional_header_.sizeof_initialized_data()) + .write(this->optional_header_.sizeof_uninitialized_data()) + .write(this->optional_header_.addressof_entrypoint()) + .write(this->optional_header_.baseof_code()); + + if (this->type_ == PE_TYPE::PE32) { + ios.write(this->optional_header_.baseof_data()); + } + ios // Continuation of optional header + .write_sized_int(this->optional_header_.imagebase(), sizeof_ptr) + .write(this->optional_header_.section_alignment()) + .write(this->optional_header_.file_alignment()) + .write(this->optional_header_.major_operating_system_version()) + .write(this->optional_header_.minor_operating_system_version()) + .write(this->optional_header_.major_image_version()) + .write(this->optional_header_.minor_image_version()) + .write(this->optional_header_.major_subsystem_version()) + .write(this->optional_header_.minor_subsystem_version()) + .write(this->optional_header_.win32_version_value()) + .write(this->optional_header_.sizeof_image()) + .write(this->optional_header_.sizeof_headers()) + // this->optional_header_.checksum()) is not a part of the hash + .write(static_cast(this->optional_header_.subsystem())) + .write(static_cast(this->optional_header_.dll_characteristics())) + .write_sized_int(this->optional_header_.sizeof_stack_reserve(), sizeof_ptr) + .write_sized_int(this->optional_header_.sizeof_stack_commit(), sizeof_ptr) + .write_sized_int(this->optional_header_.sizeof_heap_reserve(), sizeof_ptr) + .write_sized_int(this->optional_header_.sizeof_heap_commit(), sizeof_ptr) + .write(this->optional_header_.loader_flags()) + .write(this->optional_header_.numberof_rva_and_size()); + + for (const DataDirectory* dir : this->data_directories_) { + if (dir->type() == DATA_DIRECTORY::CERTIFICATE_TABLE) { + continue; + } + ios + .write(dir->RVA()) + .write(dir->size()); + } + + // Empty data directory + ios + .write(0) + .write(0); + + for (const Section* sec : this->sections_) { + std::array name = {0}; + const std::string& sec_name = sec->name(); + uint32_t name_length = std::min(sec_name.size() + 1, sizeof(name)); + std::copy(sec_name.c_str(), sec_name.c_str() + name_length, std::begin(name)); + ios + .write(name) + .write(sec->virtual_size()) + .write(sec->virtual_address()) + .write(sec->sizeof_raw_data()) + .write(sec->pointerto_raw_data()) + .write(sec->pointerto_relocation()) + .write(sec->pointerto_line_numbers()) + .write(sec->numberof_relocations()) + .write(sec->numberof_line_numbers()) + .write(static_cast(sec->characteristics())); + } + //LIEF_DEBUG("Section padding at 0x{:x}", ios.tellp()); + ios.write(this->section_offset_padding_); + + std::vector sections = this->sections_; + + // Sort by file offset + std::sort( + std::begin(sections), + std::end(sections), + [] (const Section* lhs, const Section* rhs) { + return lhs->pointerto_raw_data() < rhs->pointerto_raw_data(); + }); + + uint64_t position = 0; + for (const Section* sec : sections) { + const std::vector& pad = sec->padding(); + const std::vector& content = sec->content(); + LIEF_DEBUG("Authentihash: Append section {:<8}: [0x{:04x}, 0x{:04x}] + [0x{:04x}] = [0x{:04x}, 0x{:04x}]", + sec->name(), + sec->offset(), sec->offset() + content.size(), pad.size(), + sec->offset(), sec->offset() + content.size() + pad.size()); + if (/* overlapping */ sec->offset() < position) { + // Trunc the beginning of the overlap + if (position <= sec->offset() + content.size()) { + const uint64_t start_p = position - sec->offset(); + const uint64_t size = content.size() - start_p; + ios + .write(content.data() + start_p, size) + .write(pad); + } else { + LIEF_WARN("Overlapping in the padding area"); + } + } else { + ios + .write(content) + .write(pad); + } + position = sec->offset() + content.size() + pad.size(); + } + if (this->overlay_.size() > 0) { + const DataDirectory& cert_dir = this->data_directory(DATA_DIRECTORY::CERTIFICATE_TABLE); + LIEF_DEBUG("Add overlay and omit 0x{:08x} - 0x{:08x}", cert_dir.RVA(), cert_dir.RVA() + cert_dir.size()); + if (cert_dir.RVA() > 0 and cert_dir.size() > 0) { + const uint64_t start_cert_offset = cert_dir.RVA() - this->overlay_offset_; + const uint64_t end_cert_offset = start_cert_offset + cert_dir.size(); + LIEF_DEBUG("Add [0x{:x}, 0x{:x}]", this->overlay_offset_, this->overlay_offset_ + start_cert_offset); + LIEF_DEBUG("Add [0x{:x}, 0x{:x}]", + this->overlay_offset_ + end_cert_offset, this->overlay_offset_ + this->overlay_.size() - end_cert_offset); + ios + .write(this->overlay_.data(), start_cert_offset) + .write(this->overlay_.data() + end_cert_offset, this->overlay_.size() - end_cert_offset); + } + } + //ios.write(this->overlay_); + // When something gets wrong with the hash: + // std::vector out = ios.raw(); + // std::ofstream output_file{"/tmp/hash.blob", std::ios::out | std::ios::binary | std::ios::trunc}; + // if (output_file) { + // std::copy( + // std::begin(out), + // std::end(out), + // std::ostreambuf_iterator(output_file)); + // } + // std::vector hash = hashstream(hash_type).write(out).raw(); + + std::vector hash = ios.raw(); + LIEF_DEBUG("{}", hex_dump(hash)); + return hash; +} + +Signature::VERIFICATION_FLAGS Binary::verify_signature() const { + if (not this->has_signatures()) { + return Signature::VERIFICATION_FLAGS::NO_SIGNATURE; + } + + for (size_t i = 0; i < this->signatures_.size(); ++i) { + const Signature& sig = this->signatures_[i]; + Signature::VERIFICATION_FLAGS flags = this->verify_signature(sig); + if (flags != Signature::VERIFICATION_FLAGS::OK) { + LIEF_INFO("Verification failed for signature #{:d} (0b{:b})", i, static_cast(flags)); + return flags; + } + } + return Signature::VERIFICATION_FLAGS::OK; +} + +Signature::VERIFICATION_FLAGS Binary::verify_signature(const Signature& sig) const { + const Signature::VERIFICATION_FLAGS value = sig.check(); + if (value != Signature::VERIFICATION_FLAGS::OK) { + LIEF_INFO("Bad signature (0b{:b})", static_cast(value)); + return value; + } + + // Check that the authentihash matches Content Info's digest + const std::vector& authhash = this->authentihash(sig.digest_algorithm()); + const std::vector& chash = sig.content_info().digest(); + if (authhash != chash) { + LIEF_INFO("Authentihash and Content info's digest does not match:\n {}\n {}", + hex_dump(authhash), hex_dump(chash)); + return Signature::VERIFICATION_FLAGS::BAD_SIGNATURE; + } + return Signature::VERIFICATION_FLAGS::OK; } @@ -1407,10 +1628,12 @@ std::ostream& Binary::print(std::ostream& os) const { } - if (this->has_signature()) { - os << "Signature" << std::endl; - os << "=========" << std::endl; - os << this->signature() << std::endl; + if (this->has_signatures()) { + os << "Signatures" << std::endl; + os << "==========" << std::endl; + for (const Signature& sig : this->signatures_) { + os << sig << std::endl; + } os << std::endl; } diff --git a/src/PE/Builder.cpp b/src/PE/Builder.cpp index d6382ae..26f33e1 100644 --- a/src/PE/Builder.cpp +++ b/src/PE/Builder.cpp @@ -444,33 +444,33 @@ void Builder::build_overlay(void) { Builder& Builder::operator<<(const DosHeader& dos_header) { - pe_dos_header dosHeader; - dosHeader.Magic = static_cast(dos_header.magic()); - dosHeader.UsedBytesInTheLastPage = static_cast(dos_header.used_bytes_in_the_last_page()); - dosHeader.FileSizeInPages = static_cast(dos_header.file_size_in_pages()); - dosHeader.NumberOfRelocationItems = static_cast(dos_header.numberof_relocation()); - dosHeader.HeaderSizeInParagraphs = static_cast(dos_header.header_size_in_paragraphs()); - dosHeader.MinimumExtraParagraphs = static_cast(dos_header.minimum_extra_paragraphs()); - dosHeader.MaximumExtraParagraphs = static_cast(dos_header.maximum_extra_paragraphs()); - dosHeader.InitialRelativeSS = static_cast(dos_header.initial_relative_ss()); - dosHeader.InitialSP = static_cast(dos_header.initial_sp()); - dosHeader.Checksum = static_cast(dos_header.checksum()); - dosHeader.InitialIP = static_cast(dos_header.initial_ip()); - dosHeader.InitialRelativeCS = static_cast(dos_header.initial_relative_cs()); - dosHeader.AddressOfRelocationTable = static_cast(dos_header.addressof_relocation_table()); - dosHeader.OverlayNumber = static_cast(dos_header.overlay_number()); - dosHeader.OEMid = static_cast(dos_header.oem_id()); - dosHeader.OEMinfo = static_cast(dos_header.oem_info()); - dosHeader.AddressOfNewExeHeader = static_cast(dos_header.addressof_new_exeheader()); + pe_dos_header raw_dos_header; + raw_dos_header.Magic = static_cast(dos_header.magic()); + raw_dos_header.UsedBytesInTheLastPage = static_cast(dos_header.used_bytes_in_the_last_page()); + raw_dos_header.FileSizeInPages = static_cast(dos_header.file_size_in_pages()); + raw_dos_header.NumberOfRelocationItems = static_cast(dos_header.numberof_relocation()); + raw_dos_header.HeaderSizeInParagraphs = static_cast(dos_header.header_size_in_paragraphs()); + raw_dos_header.MinimumExtraParagraphs = static_cast(dos_header.minimum_extra_paragraphs()); + raw_dos_header.MaximumExtraParagraphs = static_cast(dos_header.maximum_extra_paragraphs()); + raw_dos_header.InitialRelativeSS = static_cast(dos_header.initial_relative_ss()); + raw_dos_header.InitialSP = static_cast(dos_header.initial_sp()); + raw_dos_header.Checksum = static_cast(dos_header.checksum()); + raw_dos_header.InitialIP = static_cast(dos_header.initial_ip()); + raw_dos_header.InitialRelativeCS = static_cast(dos_header.initial_relative_cs()); + raw_dos_header.AddressOfRelocationTable = static_cast(dos_header.addressof_relocation_table()); + raw_dos_header.OverlayNumber = static_cast(dos_header.overlay_number()); + raw_dos_header.OEMid = static_cast(dos_header.oem_id()); + raw_dos_header.OEMinfo = static_cast(dos_header.oem_info()); + raw_dos_header.AddressOfNewExeHeader = static_cast(dos_header.addressof_new_exeheader()); const DosHeader::reserved_t& reserved = dos_header.reserved(); const DosHeader::reserved2_t& reserved2 = dos_header.reserved2(); - std::copy(std::begin(reserved), std::end(reserved), std::begin(dosHeader.Reserved)); - std::copy(std::begin(reserved2), std::end(reserved2), std::begin(dosHeader.Reserved2)); + std::copy(std::begin(reserved), std::end(reserved), std::begin(raw_dos_header.Reserved)); + std::copy(std::begin(reserved2), std::end(reserved2), std::begin(raw_dos_header.Reserved2)); this->ios_.seekp(0); - this->ios_.write(reinterpret_cast(&dosHeader), sizeof(pe_dos_header)); + this->ios_.write(reinterpret_cast(&raw_dos_header), sizeof(pe_dos_header)); if (this->binary_->dos_stub().size() > 0 and this->build_dos_stub_) { if (sizeof(pe_dos_header) + this->binary_->dos_stub().size() > dos_header.addressof_new_exeheader()) { diff --git a/src/PE/CMakeLists.txt b/src/PE/CMakeLists.txt index 2567a8b..68cb0fa 100644 --- a/src/PE/CMakeLists.txt +++ b/src/PE/CMakeLists.txt @@ -29,13 +29,6 @@ set(LIEF_PE_SRC "${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" - "${CMAKE_CURRENT_LIST_DIR}/signature/SignerInfo.cpp" - "${CMAKE_CURRENT_LIST_DIR}/signature/x509.cpp" - "${CMAKE_CURRENT_LIST_DIR}/signature/OIDToString.cpp" - "${CMAKE_CURRENT_LIST_DIR}/signature/SignatureParser.cpp" "${CMAKE_CURRENT_LIST_DIR}/Builder.tcc" "${CMAKE_CURRENT_LIST_DIR}/Parser.tcc" "${CMAKE_CURRENT_LIST_DIR}/resources/ResourceVersion.cpp" @@ -125,7 +118,7 @@ set(LIEF_PE_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/ResourceNode.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/ResourcesManager.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/Section.hpp" - "${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/PE/Structures.hpp" # Do we want to do this since it's autogenerated? + #"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/PE/Structures.hpp" # Do we want to do this since it's autogenerated? "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/Symbol.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/TLS.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/type_traits.hpp" @@ -146,18 +139,6 @@ set(LIEF_PE_LOAD_CONFIGURATION_INCLUDE "${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" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/OIDToString.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/Signature.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/SignatureParser.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/SignerInfo.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/types.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/x509.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/src/PE/signature/pkcs7.h" -) - set(LIEF_PE_RESOURCES_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/resources/ResourceVersion.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/resources/ResourceDialog.hpp" @@ -199,7 +180,6 @@ list(APPEND LIEF_PE_INCLUDE_FILES ${LIEF_PE_HASH_HDR}) 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}) @@ -215,3 +195,5 @@ if (LIEF_PE) ${LIEF_PE_LOAD_CONFIGURATION_INCLUDE} ) endif() + +include("${CMAKE_CURRENT_LIST_DIR}/signature/CMakeLists.txt") diff --git a/src/PE/EnumToString.cpp b/src/PE/EnumToString.cpp index 3ba2222..3a93ffe 100644 --- a/src/PE/EnumToString.cpp +++ b/src/PE/EnumToString.cpp @@ -1337,5 +1337,54 @@ const char* to_string(ACCELERATOR_VK_CODES e) { return it != enumStrings.end() ? it->second : "Undefined or reserved"; } +const char* to_string(ALGORITHMS e) { + CONST_MAP(ALGORITHMS, const char*, 20) enumStrings { + { ALGORITHMS::UNKNOWN, "UNKNOWN" }, + { ALGORITHMS::SHA_512, "SHA_512" }, + { ALGORITHMS::SHA_384, "SHA_384" }, + { ALGORITHMS::SHA_256, "SHA_256" }, + { ALGORITHMS::SHA_1, "SHA_1" }, + + { ALGORITHMS::MD5, "MD5" }, + { ALGORITHMS::MD4, "MD4" }, + { ALGORITHMS::MD2, "MD2" }, + + { ALGORITHMS::RSA, "RSA" }, + { ALGORITHMS::EC, "EC" }, + + { ALGORITHMS::MD5_RSA, "MD5_RSA" }, + { ALGORITHMS::SHA1_DSA, "SHA1_DSA" }, + { ALGORITHMS::SHA1_RSA, "SHA1_RSA" }, + { ALGORITHMS::SHA_256_RSA, "SHA_256_RSA" }, + { ALGORITHMS::SHA_384_RSA, "SHA_384_RSA" }, + { ALGORITHMS::SHA_512_RSA, "SHA_512_RSA" }, + { ALGORITHMS::SHA1_ECDSA, "SHA1_ECDSA" }, + { ALGORITHMS::SHA_256_ECDSA, "SHA_256_ECDSA" }, + { ALGORITHMS::SHA_384_ECDSA, "SHA_384_ECDSA" }, + { ALGORITHMS::SHA_512_ECDSA, "SHA_512_ECDSA" }, + }; + auto it = enumStrings.find(e); + return it == enumStrings.end() ? "UNKNOWN" : it->second; +} + + +const char* to_string(SIG_ATTRIBUTE_TYPES e) { + CONST_MAP(SIG_ATTRIBUTE_TYPES, const char*, 11) enumStrings { + { SIG_ATTRIBUTE_TYPES::UNKNOWN, "UNKNOWN" }, + { SIG_ATTRIBUTE_TYPES::CONTENT_TYPE, "CONTENT_TYPE" }, + { SIG_ATTRIBUTE_TYPES::GENERIC_TYPE, "GENERIC_TYPE" }, + { SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO, "SPC_SP_OPUS_INFO" }, + { SIG_ATTRIBUTE_TYPES::MS_COUNTER_SIGN, "MS_COUNTER_SIGN" }, + { SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN, "MS_SPC_NESTED_SIGN" }, + { SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE, "MS_SPC_STATEMENT_TYPE" }, + { SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER, "PKCS9_AT_SEQUENCE_NUMBER" }, + { SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE, "PKCS9_COUNTER_SIGNATURE" }, + { SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST, "PKCS9_MESSAGE_DIGEST" }, + { SIG_ATTRIBUTE_TYPES::PKCS9_SIGNING_TIME, "PKCS9_SIGNING_TIME" }, + }; + auto it = enumStrings.find(e); + return it == enumStrings.end() ? "UNKNOWN" : it->second; +} + } // namespace PE } // namespace LIEF diff --git a/src/PE/Parser.cpp b/src/PE/Parser.cpp index 8736065..c864a36 100644 --- a/src/PE/Parser.cpp +++ b/src/PE/Parser.cpp @@ -115,7 +115,7 @@ void Parser::parse_dos_stub(void) { } const uint64_t sizeof_dos_stub = dos_header.addressof_new_exeheader() - sizeof(pe_dos_header); - LIEF_DEBUG("DOS Stub size: 0x{:x}", sizeof_dos_stub); + LIEF_DEBUG("DOS stub: @0x{:x}:0x{:x}", sizeof(pe_dos_header), sizeof_dos_stub); const uint8_t* ptr_to_dos_stub = this->stream_->peek_array(sizeof(pe_dos_header), sizeof_dos_stub, /* check */false); if (ptr_to_dos_stub == nullptr) { @@ -224,7 +224,9 @@ void Parser::parse_sections(void) { uint32_t size_to_read = 0; uint32_t offset = sections[i].PointerToRawData; - first_section_offset = std::min(first_section_offset, offset); + if (offset > 0) { + first_section_offset = std::min(first_section_offset, offset); + } if (sections[i].VirtualSize > 0) { size_to_read = std::min(sections[i].VirtualSize, sections[i].SizeOfRawData); // According to Corkami @@ -250,10 +252,22 @@ void Parser::parse_sections(void) { ptr_to_rawdata + size_to_read }; } + const uint64_t padding_size = section->size() - size_to_read; + const uint8_t* ptr_to_padding = this->stream_->peek_array(offset + size_to_read, padding_size, /* check */false); + if (ptr_to_padding != nullptr) { + section->padding_ = {ptr_to_padding, ptr_to_padding + padding_size}; + } } this->binary_->sections_.push_back(section.release()); } + const uint32_t last_section_header_offset = sections_offset + numberof_sections * sizeof(pe_section); + const size_t padding_size = first_section_offset - last_section_header_offset; + const uint8_t* padding_ptr = this->stream_->peek_array(last_section_header_offset, padding_size, + /* check */ false); + if (padding_ptr != nullptr) { + this->binary_->section_offset_padding_ = {padding_ptr, padding_ptr + padding_size}; + } this->binary_->available_sections_space_ = (first_section_offset - last_section_header_offset) / sizeof(pe_section) - 1; LIEF_DEBUG("Number of sections that could be added: #{:d}", this->binary_->available_sections_space_); } @@ -865,23 +879,41 @@ void Parser::parse_exports(void) { void Parser::parse_signature(void) { LIEF_DEBUG("== Parsing signature =="); + static constexpr size_t SIZEOF_HEADER = 8; /*** /!\ In this data directory, RVA is used as an **OFFSET** /!\ ****/ /*********************************************************************/ const uint32_t signature_offset = this->binary_->data_directory(DATA_DIRECTORY::CERTIFICATE_TABLE).RVA(); const uint32_t signature_size = this->binary_->data_directory(DATA_DIRECTORY::CERTIFICATE_TABLE).size(); + const uint64_t end_p = signature_offset + signature_size; LIEF_DEBUG("Signature Offset: 0x{:04x}", signature_offset); LIEF_DEBUG("Signature Size: 0x{:04x}", signature_size); - const uint8_t* signature_ptr = this->stream_->peek_array(signature_offset, signature_size, /* check */false); - if (signature_ptr == nullptr) { - return; - } - std::vector raw_signature = {signature_ptr, signature_ptr + signature_size}; + this->stream_->setpos(signature_offset); + while (this->stream_->pos() < end_p) { + const uint64_t current_p = this->stream_->pos(); + auto length = this->stream_->read(); + auto revision = this->stream_->read(); + auto certificate_type = this->stream_->read(); + LIEF_DEBUG("Signature {}r0x{:x} (0x{:x} bytes)", certificate_type, revision, length); + const uint8_t* data_ptr = this->stream_->read_array(length - SIZEOF_HEADER, /* check */false); + if (data_ptr == nullptr) { + LIEF_INFO("Can't read 0x{:x} bytes", length); + break; + } + std::vector raw_signature = {data_ptr, data_ptr + length - SIZEOF_HEADER}; + auto sign = SignatureParser::parse(std::move(raw_signature)); - //TODO: Deal with header (+8) - this->binary_->signature_ = SignatureParser::parse(raw_signature); - this->binary_->has_signature_ = true; + if (sign) { + this->binary_->signatures_.push_back(std::move(sign.value())); + } else { + LIEF_INFO("Unable to parse the signature"); + } + this->stream_->align(8); + if (this->stream_->pos() <= current_p) { + break; + } + } } @@ -907,6 +939,7 @@ void Parser::parse_overlay(void) { ptr_to_overlay, ptr_to_overlay + overlay_size }; + this->binary_->overlay_offset_ = last_section_offset; } } else { this->binary_->overlay_ = {}; diff --git a/src/PE/Section.cpp b/src/PE/Section.cpp index d8881d1..bfeb409 100644 --- a/src/PE/Section.cpp +++ b/src/PE/Section.cpp @@ -31,28 +31,18 @@ namespace PE { Section::~Section(void) = default; -Section::Section(void) : - LIEF::Section{}, - virtualSize_{0}, - content_{}, - pointerToRelocations_{0}, - pointerToLineNumbers_{0}, - numberOfRelocations_{0}, - numberOfLineNumbers_{0}, - characteristics_{0}, - types_{PE_SECTION_TYPES::UNKNOWN} -{} +Section::Section(void) = default; Section& Section::operator=(const Section&) = default; Section::Section(const Section&) = default; Section::Section(const pe_section* header) : - virtualSize_{header->VirtualSize}, - pointerToRelocations_{header->PointerToRelocations}, - pointerToLineNumbers_{header->PointerToLineNumbers}, - numberOfRelocations_{header->NumberOfRelocations}, - numberOfLineNumbers_{header->NumberOfLineNumbers}, + virtual_size_{header->VirtualSize}, + pointer_to_relocations_{header->PointerToRelocations}, + pointer_to_linenumbers_{header->PointerToLineNumbers}, + number_of_relocations_{header->NumberOfRelocations}, + number_of_linenumbers_{header->NumberOfLineNumbers}, characteristics_{header->Characteristics}, types_{PE_SECTION_TYPES::UNKNOWN} { @@ -60,7 +50,6 @@ Section::Section(const pe_section* header) : this->virtual_address_ = header->VirtualAddress; this->size_ = header->SizeOfRawData; this->offset_ = header->PointerToRawData; - } Section::Section(const std::vector& data, const std::string& name, uint32_t characteristics) : @@ -80,7 +69,7 @@ Section::Section(const std::string& name) : uint32_t Section::virtual_size(void) const { - return this->virtualSize_; + return this->virtual_size_; } @@ -103,20 +92,20 @@ uint32_t Section::pointerto_raw_data(void) const { uint32_t Section::pointerto_relocation(void) const { - return this->pointerToRelocations_; + return this->pointer_to_relocations_; } uint32_t Section::pointerto_line_numbers(void) const { - return this->pointerToLineNumbers_; + return this->pointer_to_linenumbers_; } uint16_t Section::numberof_relocations(void) const { - return this->numberOfRelocations_; + return this->number_of_relocations_; } uint16_t Section::numberof_line_numbers(void) const { - return this->numberOfLineNumbers_; + return this->number_of_linenumbers_; } uint32_t Section::characteristics(void) const { @@ -164,7 +153,7 @@ void Section::content(const std::vector& data) { void Section::virtual_size(uint32_t virtualSize) { - this->virtualSize_ = virtualSize; + this->virtual_size_ = virtualSize; } @@ -174,22 +163,22 @@ void Section::pointerto_raw_data(uint32_t pointerToRawData) { void Section::pointerto_relocation(uint32_t pointerToRelocation) { - this->pointerToRelocations_ = pointerToRelocation; + this->pointer_to_relocations_ = pointerToRelocation; } void Section::pointerto_line_numbers(uint32_t pointerToLineNumbers) { - this->pointerToLineNumbers_ = pointerToLineNumbers; + this->pointer_to_linenumbers_ = pointerToLineNumbers; } void Section::numberof_relocations(uint16_t numberOfRelocations) { - this->numberOfRelocations_ = numberOfRelocations; + this->number_of_relocations_ = numberOfRelocations; } void Section::numberof_line_numbers(uint16_t numberOfLineNumbers) { - this->numberOfLineNumbers_ = numberOfLineNumbers; + this->number_of_linenumbers_ = numberOfLineNumbers; } void Section::sizeof_raw_data(uint32_t sizeOfRawData) { diff --git a/src/PE/hash.cpp b/src/PE/hash.cpp index b2545c2..16c8519 100644 --- a/src/PE/hash.cpp +++ b/src/PE/hash.cpp @@ -437,17 +437,14 @@ void Hash::visit(const ResourceAccelerator& accelerator) { } void Hash::visit(const Signature& signature) { - this->process(signature.version()); this->process(signature.digest_algorithm()); this->process(signature.content_info()); this->process(std::begin(signature.certificates()), std::end(signature.certificates())); - this->process(signature.signer_info()); - this->process(signature.original_signature()); + this->process(std::begin(signature.signers()), std::end(signature.signers())); } void Hash::visit(const x509& x509) { - this->process(x509.subject()); this->process(x509.issuer()); this->process(x509.valid_to()); @@ -460,19 +457,65 @@ void Hash::visit(const x509& x509) { void Hash::visit(const SignerInfo& signerinfo) { this->process(signerinfo.version()); - //this->process(signerinfo.issuer()); + this->process(signerinfo.serial_number()); + this->process(signerinfo.issuer()); + this->process(signerinfo.encryption_algorithm()); this->process(signerinfo.digest_algorithm()); - this->process(signerinfo.authenticated_attributes()); - this->process(signerinfo.signature_algorithm()); this->process(signerinfo.encrypted_digest()); + this->process(std::begin(signerinfo.authenticated_attributes()), std::end(signerinfo.authenticated_attributes())); + this->process(std::begin(signerinfo.unauthenticated_attributes()), std::end(signerinfo.unauthenticated_attributes())); } -void Hash::visit(const AuthenticatedAttributes& auth) { +void Hash::visit(const Attribute& attr) { + this->process(attr.type()); +} - this->process(auth.content_type()); - this->process(auth.message_digest()); - this->process(u16tou8(auth.program_name())); - this->process(auth.more_info()); +void Hash::visit(const ContentInfo& info) { + this->process(info.content_type()); + this->process(info.digest_algorithm()); + this->process(info.digest()); + this->process(info.file()); +} + + +void Hash::visit(const ContentType& attr) { + this->visit(*attr.as()); + this->process(attr.oid()); +} +void Hash::visit(const GenericType& attr) { + this->visit(*attr.as()); + this->process(attr.raw_content()); + this->process(attr.oid()); +} +void Hash::visit(const MsSpcNestedSignature& attr) { + this->visit(*attr.as()); + this->process(attr.sig()); +} +void Hash::visit(const MsSpcStatementType& attr) { + this->visit(*attr.as()); + this->process(attr.oid()); +} +void Hash::visit(const PKCS9AtSequenceNumber& attr) { + this->visit(*attr.as()); + this->process(attr.number()); +} +void Hash::visit(const PKCS9CounterSignature& attr) { + this->visit(*attr.as()); + it_const_signers_t signers = attr.signers(); + this->process(std::begin(signers), std::end(signers)); +} +void Hash::visit(const PKCS9MessageDigest& attr) { + this->visit(*attr.as()); + this->process(attr.digest()); +} +void Hash::visit(const PKCS9SigningTime& attr) { + this->visit(*attr.as()); + this->process(attr.time()); +} +void Hash::visit(const SpcSpOpusInfo& attr) { + this->visit(*attr.as()); + this->process(attr.program_name()); + this->process(attr.more_info()); } void Hash::visit(const CodeIntegrity& code_integrity) { diff --git a/src/PE/json.cpp b/src/PE/json.cpp index 5c7050c..35d2e94 100644 --- a/src/PE/json.cpp +++ b/src/PE/json.cpp @@ -22,6 +22,8 @@ #include "LIEF/PE/json.hpp" #include "LIEF/PE.hpp" +#include "Object.tcc" + namespace LIEF { namespace PE { @@ -165,11 +167,15 @@ void JsonVisitor::visit(const Binary& binary) { } - // Signature - if (binary.has_signature()) { - JsonVisitor visitor; - visitor(binary.signature()); - this->node_["signature"] = visitor.get(); + // Signatures + std::vector sigs; + if (binary.has_signatures()) { + for (const Signature& sig : binary.signatures()) { + JsonVisitor visitor; + visitor(sig); + sigs.push_back(std::move(visitor.get())); + } + this->node_["signatures"] = sigs; } std::vector symbols; @@ -762,20 +768,25 @@ void JsonVisitor::visit(const Signature& signature) { JsonVisitor content_info_visitor; content_info_visitor(signature.content_info()); - JsonVisitor signer_info_visitor; - signer_info_visitor(signature.signer_info()); + std::vector jsigners; + for (const SignerInfo& signer : signature.signers()) { + JsonVisitor visitor; + visitor(signer); + jsigners.emplace_back(std::move(visitor.get())); + } std::vector crts; for (const x509& crt : signature.certificates()) { JsonVisitor crt_visitor; crt_visitor(crt); - crts.emplace_back(crt_visitor.get()); + crts.emplace_back(std::move(crt_visitor.get())); } - this->node_["version"] = signature.version(); - this->node_["content_info"] = content_info_visitor.get(); - this->node_["signer_info"] = signer_info_visitor.get(); - this->node_["certificates"] = crts; + this->node_["digest_algorithm"] = to_string(signature.digest_algorithm()); + this->node_["version"] = signature.version(); + this->node_["content_info"] = content_info_visitor.get(); + this->node_["signer_info"] = jsigners; + this->node_["certificates"] = crts; } void JsonVisitor::visit(const x509& x509) { @@ -789,27 +800,93 @@ void JsonVisitor::visit(const x509& x509) { } void JsonVisitor::visit(const SignerInfo& signerinfo) { - JsonVisitor authenticated_attributes_visitor; - authenticated_attributes_visitor(signerinfo.authenticated_attributes()); + std::vector auth_attrs; + for (const Attribute& attr : signerinfo.authenticated_attributes()) { + JsonVisitor visitor; + visitor(attr); + auth_attrs.emplace_back(std::move(visitor.get())); + } - this->node_["version"] = signerinfo.version(); - this->node_["digest_algorithm"] = signerinfo.digest_algorithm(); - this->node_["signature_algorithm"] = signerinfo.signature_algorithm(); - this->node_["authenticated_attributes"] = authenticated_attributes_visitor.get(); - this->node_["issuer"] = std::get<0>(signerinfo.issuer()); + std::vector unauth_attrs; + for (const Attribute& attr : signerinfo.unauthenticated_attributes()) { + JsonVisitor visitor; + visitor(attr); + auth_attrs.emplace_back(std::move(visitor.get())); + } + + this->node_["version"] = signerinfo.version(); + this->node_["digest_algorithm"] = to_string(signerinfo.digest_algorithm()); + this->node_["encryption_algorithm"] = to_string(signerinfo.encryption_algorithm()); + this->node_["encrypted_digest"] = signerinfo.encrypted_digest(); + this->node_["issuer"] = signerinfo.issuer(); + this->node_["serial_number"] = signerinfo.serial_number(); + this->node_["authenticated_attributes"] = auth_attrs; + this->node_["unauthenticated_attributes"] = unauth_attrs; } void JsonVisitor::visit(const ContentInfo& contentinfo) { this->node_["content_type"] = contentinfo.content_type(); - this->node_["type"] = contentinfo.type(); - this->node_["digest_algorithm"] = contentinfo.digest_algorithm(); + this->node_["digest_algorithm"] = to_string(contentinfo.digest_algorithm()); + this->node_["digest"] = contentinfo.digest(); + this->node_["file"] = contentinfo.file(); } -void JsonVisitor::visit(const AuthenticatedAttributes& auth) { - this->node_["content_type"] = auth.content_type(); - this->node_["program_name"] = u16tou8(auth.program_name()); - this->node_["url"] = auth.more_info(); - this->node_["message_digest"] = auth.message_digest(); +void JsonVisitor::visit(const Attribute& auth) { + this->node_["type"] = to_string(auth.type()); +} + +void JsonVisitor::visit(const ContentType& attr) { + this->visit(*attr.as()); + this->node_["oid"] = attr.oid(); +} + +void JsonVisitor::visit(const GenericType& attr) { + this->visit(*attr.as()); + this->node_["oid"] = attr.oid(); +} + +void JsonVisitor::visit(const MsSpcNestedSignature& attr) { + this->visit(*attr.as()); + JsonVisitor visitor; + visitor(attr.sig()); + this->node_["signature"] = std::move(visitor.get()); +} + +void JsonVisitor::visit(const MsSpcStatementType& attr) { + this->visit(*attr.as()); + this->node_["oid"] = attr.oid(); +} + +void JsonVisitor::visit(const PKCS9AtSequenceNumber& attr) { + this->visit(*attr.as()); + this->node_["number"] = attr.number(); +} +void JsonVisitor::visit(const PKCS9CounterSignature& attr) { + this->visit(*attr.as()); + + std::vector signers; + for (const SignerInfo& signer : attr.signers()) { + JsonVisitor visitor; + visitor(signer); + signers.emplace_back(std::move(visitor.get())); + } + this->node_["signers"] = std::move(signers); +} + +void JsonVisitor::visit(const PKCS9MessageDigest& attr) { + this->visit(*attr.as()); + this->node_["digest"] = attr.digest(); +} + +void JsonVisitor::visit(const PKCS9SigningTime& attr) { + this->visit(*attr.as()); + this->node_["time"] = attr.time(); +} + +void JsonVisitor::visit(const SpcSpOpusInfo& attr) { + this->visit(*attr.as()); + this->node_["more_info"] = attr.more_info(); + this->node_["program_name"] = attr.program_name(); } void JsonVisitor::visit(const CodeIntegrity& code_integrity) { diff --git a/src/PE/signature/Attribute.cpp b/src/PE/signature/Attribute.cpp new file mode 100644 index 0000000..0a24f48 --- /dev/null +++ b/src/PE/signature/Attribute.cpp @@ -0,0 +1,54 @@ +/* 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 + +#include "LIEF/utils.hpp" +#include "LIEF/PE/utils.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +namespace LIEF { +namespace PE { + +Attribute::Attribute(void) = default; + +Attribute::Attribute(SIG_ATTRIBUTE_TYPES type) : + type_{type} +{} + +Attribute::Attribute(const Attribute& other) : + type_{other.type_} +{} + +Attribute& Attribute::operator=(const Attribute& other) { + if (this != &other) { + this->type_ = other.type_; + } + return *this; +} + +Attribute::~Attribute(void) = default; + +void Attribute::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::ostream& operator<<(std::ostream& os, const Attribute& attribute) { + os << attribute.print(); + return os; +} + +} +} diff --git a/src/PE/signature/AuthenticatedAttributes.cpp b/src/PE/signature/AuthenticatedAttributes.cpp deleted file mode 100644 index 05e3022..0000000 --- a/src/PE/signature/AuthenticatedAttributes.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* 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 - -#include "LIEF/utils.hpp" -#include "LIEF/PE/utils.hpp" -#include "LIEF/PE/signature/AuthenticatedAttributes.hpp" - -namespace LIEF { -namespace PE { - -AuthenticatedAttributes::AuthenticatedAttributes(void) = default; -AuthenticatedAttributes::AuthenticatedAttributes(const AuthenticatedAttributes&) = default; -AuthenticatedAttributes& AuthenticatedAttributes::operator=(const AuthenticatedAttributes&) = default; -AuthenticatedAttributes::~AuthenticatedAttributes(void) = default; - - -const oid_t& AuthenticatedAttributes::content_type(void) const { - return this->content_type_; -} - -const std::vector& AuthenticatedAttributes::message_digest(void) const { - return this->message_digest_; -} - -const std::u16string& AuthenticatedAttributes::program_name(void) const { - return this->program_name_; -} - -const std::string& AuthenticatedAttributes::more_info(void) const { - return this->more_info_; -} - -const std::vector& AuthenticatedAttributes::raw(void) const { - return this->raw_; -} - -void AuthenticatedAttributes::accept(Visitor& visitor) const { - visitor.visit(*this); -} - -std::ostream& operator<<(std::ostream& os, const AuthenticatedAttributes& authenticated_attributes) { - constexpr uint8_t wsize = 30; - std::string content_type = authenticated_attributes.content_type(); - if (content_type.empty()) { - content_type = "N/A"; - } - std::string program_name = u16tou8(authenticated_attributes.program_name()); - if (program_name.empty()) { - program_name = "N/A"; - } - std::string url = authenticated_attributes.more_info(); - if (url.empty()) { - url = "N/A"; - } - os << std::hex << std::left; - os << std::setw(wsize) << std::setfill(' ') << "Content type: " << content_type << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Program name: " << program_name << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "URL : " << url << std::endl; - - return os; -} - -} -} diff --git a/src/PE/signature/CMakeLists.txt b/src/PE/signature/CMakeLists.txt new file mode 100644 index 0000000..0a36d20 --- /dev/null +++ b/src/PE/signature/CMakeLists.txt @@ -0,0 +1,36 @@ +set(LIEF_PE_SIGNATURE_SRC + "${CMAKE_CURRENT_LIST_DIR}/Attribute.cpp" + "${CMAKE_CURRENT_LIST_DIR}/ContentInfo.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Signature.cpp" + "${CMAKE_CURRENT_LIST_DIR}/SignerInfo.cpp" + "${CMAKE_CURRENT_LIST_DIR}/x509.cpp" + "${CMAKE_CURRENT_LIST_DIR}/OIDToString.cpp" + "${CMAKE_CURRENT_LIST_DIR}/SignatureParser.cpp" + "${CMAKE_CURRENT_LIST_DIR}/RsaInfo.cpp" +) + + +set(LIEF_PE_SIGNATURE_INCLUDES + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/Attribute.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/ContentInfo.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/OIDToString.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/Signature.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/SignatureParser.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/SignerInfo.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/types.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/x509.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/RsaInfo.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/PE/signature/pkcs7.h" +) + +source_group("Header Files\\PE\\signature" FILES ${LIEF_PE_SIGNATURE_SRC}) +source_group("Header Files\\PE\\signature" FILES ${LIEF_PE_SIGNATURE_INCLUDES}) + +if (LIEF_PE) + target_sources(LIB_LIEF PRIVATE + ${LIEF_PE_SIGNATURE_SRC} + ${LIEF_PE_SIGNATURE_INCLUDES} + ) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/attributes/CMakeLists.txt") diff --git a/src/PE/signature/ContentInfo.cpp b/src/PE/signature/ContentInfo.cpp index 35fb939..2913828 100644 --- a/src/PE/signature/ContentInfo.cpp +++ b/src/PE/signature/ContentInfo.cpp @@ -17,6 +17,8 @@ #include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/ContentInfo.hpp" +#include "LIEF/PE/EnumToString.hpp" +#include "LIEF/utils.hpp" namespace LIEF { namespace PE { @@ -26,27 +28,6 @@ ContentInfo::ContentInfo(const ContentInfo&) = default; ContentInfo& ContentInfo::operator=(const ContentInfo&) = default; ContentInfo::~ContentInfo(void) = default; -const oid_t& ContentInfo::content_type(void) const { - return this->content_type_; -} - -const oid_t& ContentInfo::type(void) const { - return this->type_; -} - - -const oid_t& ContentInfo::digest_algorithm(void) const { - return this->digest_algorithm_; -} - - -const std::vector& ContentInfo::digest(void) const { - return this->digest_; -} - -const std::vector& ContentInfo::raw(void) const { - return this->raw_; -} void ContentInfo::accept(Visitor& visitor) const { visitor.visit(*this); @@ -54,12 +35,8 @@ void ContentInfo::accept(Visitor& visitor) const { std::ostream& operator<<(std::ostream& os, const ContentInfo& content_info) { - constexpr uint8_t wsize = 30; - - os << std::hex << std::left; - os << std::setw(wsize) << std::setfill(' ') << "Content Type: " << oid_to_string(content_info.content_type()) << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Type: " << oid_to_string(content_info.type()) << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Digest Algorithm: " << oid_to_string(content_info.digest_algorithm()) << std::endl; + os << "Authentihash: " << hex_dump(content_info.digest()) + << "(" << to_string(content_info.digest_algorithm()) << ")\n"; return os; } diff --git a/src/PE/signature/OIDToString.cpp b/src/PE/signature/OIDToString.cpp index 9a3749f..5f7119e 100644 --- a/src/PE/signature/OIDToString.cpp +++ b/src/PE/signature/OIDToString.cpp @@ -499,7 +499,7 @@ const char* oid_to_string(const oid_t& oid) { { "1.2.840.10040.2.3", "REJECT" }, { "1.2.840.10040.2.4", "PICKUP_TOKEN" }, { "1.2.840.10040.3", "ATTRIBUTE" }, - { "1.2.840.10040.3.1", "COUNTERSIGNATURE" }, + { "1.2.840.10040.3.1", "COUNTER_SIGNATURE" }, { "1.2.840.10040.3.2", "ATTRIBUTE_CERT" }, { "1.2.840.10040.4", "ALGORITHM" }, { "1.2.840.10040.4.1", "DSA" }, @@ -616,7 +616,7 @@ const char* oid_to_string(const oid_t& oid) { { "1.2.840.113549.1.9.3", "CONTENT_TYPE" }, { "1.2.840.113549.1.9.4", "MESSAGE_DIGEST" }, { "1.2.840.113549.1.9.5", "SIGNING_TIME" }, - { "1.2.840.113549.1.9.6", "COUNTERSIGNATURE" }, + { "1.2.840.113549.1.9.6", "COUNTER_SIGNATURE" }, { "1.2.840.113549.1.9.7", "CHALLENGE_PASSWORD" }, { "1.2.840.113549.1.9.8", "UNSTRUCTURED_ADDRESS" }, { "1.2.840.113549.1.9.9", "EXTENDED_CERTIFICATE_ATTRIBUTES" }, @@ -976,7 +976,7 @@ const char* oid_to_string(const oid_t& oid) { { "1.2.840.113635.100.6.1.1", "APPLE_CERTIFICATE_EXTENSION_APPLE_SIGNING" }, { "1.2.840.113635.100.6.1.2", "APPLE_CERTIFICATE_EXTENSION_ADC_DEVELOPER_SIGNING" }, { "1.2.840.113635.100.6.1.3", "APPLE_CERTIFICATE_EXTENSION_ADC_APPLE_SIGNING" }, - { "1.3.6.1.4.1.311.2.1.4", "SPC_INDIRECT_DATA_CONTEXT" }, + { "1.3.6.1.4.1.311.2.1.4", "SPC_INDIRECT_DATA_CONTENT" }, { "1.3.6.1.4.1.311.2.1.10", "SPC_AGENCY_INFO" }, { "1.3.6.1.4.1.311.2.1.11", "SPC_STATEMENT_TYPE" }, { "1.3.6.1.4.1.311.2.1.12", "SPC_SP_OPUS_INFO" }, @@ -2241,10 +2241,11 @@ const char* oid_to_string(const oid_t& oid) { { "2.16.840.1.114404.1.1.2.4.1", "TRUST_WAVE_EV_POLICY" }, { "1.3.6.1.4.1.40869.1.1.22.3", "TWCA_EV_POLICY" }, { "2.16.840.1.113733.1.7.23.6", "VERI_SIGN_EV_POLICY" }, - { "2.16.840.1.114171.500.9", "WELLS_FARGO_EV_POLICY" } + { "2.16.840.1.114171.500.9", "WELLS_FARGO_EV_POLICY" }, + { "1.3.6.1.4.1.311.3.3.1", "MS_COUNTER_SIGN" } }; auto it = oid_to_str.find(oid); - return it == oid_to_str.end() ? "Out of range" : it->second; + return it == oid_to_str.end() ? oid.c_str() : it->second; } } diff --git a/src/PE/signature/RsaInfo.cpp b/src/PE/signature/RsaInfo.cpp new file mode 100644 index 0000000..4f38dc2 --- /dev/null +++ b/src/PE/signature/RsaInfo.cpp @@ -0,0 +1,123 @@ + +#include "LIEF/PE/signature/RsaInfo.hpp" + +#include +#include + +#include +#include +#include +#include +#include + + +namespace LIEF { +namespace PE { + +RsaInfo::RsaInfo(void) = default; + +RsaInfo::RsaInfo(const RsaInfo::rsa_ctx_handle ctx) { + const mbedtls_rsa_context* pctx = reinterpret_cast(ctx); + mbedtls_rsa_context* local_ctx = new mbedtls_rsa_context{}; + mbedtls_rsa_init(local_ctx, pctx->padding, pctx->hash_id); + mbedtls_rsa_copy(local_ctx, pctx); + this->ctx_ = reinterpret_cast(local_ctx); +} + +RsaInfo::RsaInfo(const RsaInfo& other) +{ + if (other) { + const mbedtls_rsa_context* octx = reinterpret_cast(other.ctx_); + mbedtls_rsa_context* local_ctx = new mbedtls_rsa_context{}; + mbedtls_rsa_init(local_ctx, octx->padding, octx->hash_id); + mbedtls_rsa_copy(local_ctx, octx); + this->ctx_ = reinterpret_cast(local_ctx); + } +} + + +RsaInfo::RsaInfo(RsaInfo&& other) : + ctx_{std::move(other.ctx_)} +{} + +RsaInfo& RsaInfo::operator=(RsaInfo other) { + this->swap(other); + return *this; +} + +void RsaInfo::swap(RsaInfo& other) { + std::swap(this->ctx_, other.ctx_); +} + +RsaInfo::operator bool() const { + return this->ctx_ != nullptr; +} + +bool RsaInfo::has_public_key(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + return mbedtls_rsa_check_pubkey(lctx) == 0; +} + +bool RsaInfo::has_private_key(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + return mbedtls_rsa_check_privkey(lctx) == 0; +} + + +RsaInfo::bignum_wrapper_t RsaInfo::N(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + bignum_wrapper_t N(mbedtls_mpi_bitlen(&lctx->N)); + mbedtls_mpi_write_binary(&lctx->N, N.data(), N.size()); + return N; +} + +RsaInfo::bignum_wrapper_t RsaInfo::E(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + bignum_wrapper_t E(mbedtls_mpi_bitlen(&lctx->E)); + mbedtls_mpi_write_binary(&lctx->E, E.data(), E.size()); + return E; +} + +RsaInfo::bignum_wrapper_t RsaInfo::D(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + bignum_wrapper_t D(mbedtls_mpi_bitlen(&lctx->D)); + mbedtls_mpi_write_binary(&lctx->D, D.data(), D.size()); + return D; +} + +RsaInfo::bignum_wrapper_t RsaInfo::P(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + bignum_wrapper_t P(mbedtls_mpi_bitlen(&lctx->P)); + mbedtls_mpi_write_binary(&lctx->P, P.data(), P.size()); + return P; +} + +RsaInfo::bignum_wrapper_t RsaInfo::Q(void) const { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + bignum_wrapper_t Q(mbedtls_mpi_bitlen(&lctx->Q)); + mbedtls_mpi_write_binary(&lctx->Q, Q.data(), Q.size()); + return Q; +} + + +RsaInfo::~RsaInfo(void) { + if (this->ctx_) { + mbedtls_rsa_context* lctx = reinterpret_cast(this->ctx_); + mbedtls_rsa_free(lctx); + delete lctx; + } +} + + +std::ostream& operator<<(std::ostream& os, const RsaInfo& info) { + if (not info) { + os << ""; + } else { + // TODO + } + + return os; +} + +} +} diff --git a/src/PE/signature/Signature.cpp b/src/PE/signature/Signature.cpp index 726b4c8..0e2e29c 100644 --- a/src/PE/signature/Signature.cpp +++ b/src/PE/signature/Signature.cpp @@ -14,39 +14,256 @@ * limitations under the License. */ #include +#include + +#include "logging.hpp" + +#include "LIEF/utils.hpp" #include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/OIDToString.hpp" +#include "LIEF/PE/EnumToString.hpp" + +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes.hpp" + +#include +#include +#include + +#include +#include +#include + +#include "mbedtls/x509_crt.h" + namespace LIEF { namespace PE { -Signature::Signature(void) = default; // TODO + +Signature::Signature(void) = default; Signature::Signature(const Signature&) = default; Signature& Signature::operator=(const Signature&) = default; Signature::~Signature(void) = default; + +std::vector Signature::hash(const std::vector& input, ALGORITHMS algo) { + switch (algo) { + + case ALGORITHMS::SHA_512: + { + std::vector out(64); + int ret = mbedtls_sha512_ret(input.data(), input.size(), out.data(), /* is384 */ false); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with SHA-512 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::SHA_384: + { + std::vector out(64); + int ret = mbedtls_sha512_ret(input.data(), input.size(), out.data(), /* is384 */ true); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with SHA-384 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::SHA_256: + { + std::vector out(32); + int ret = mbedtls_sha256_ret(input.data(), input.size(), out.data(), /* is224 */ false); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with SHA-256 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::SHA_1: + { + std::vector out(20); + int ret = mbedtls_sha1_ret(input.data(), input.size(), out.data()); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with SHA-1 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::MD5: + { + std::vector out(16); + int ret = mbedtls_md5_ret(input.data(), input.size(), out.data()); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with MD5 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::MD4: + { + std::vector out(16); + int ret = mbedtls_md4_ret(input.data(), input.size(), out.data()); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with MD4 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + case ALGORITHMS::MD2: + { + std::vector out(16); + int ret = mbedtls_md2_ret(input.data(), input.size(), out.data()); + if (ret != 0) { + LIEF_ERR("Hashing {} bytes with MD2 failed! (ret: 0x{:x})", input.size(), ret); + return {}; + } + return out; + } + + default: + { + LIEF_ERR("Unsupported hash algorithm {}", to_string(algo)); + } + } + return {}; +} + uint32_t Signature::version(void) const { return this->version_; } -const oid_t& Signature::digest_algorithm(void) const { - return this->digest_algorithm_; -} const ContentInfo& Signature::content_info(void) const { return this->content_info_; } it_const_crt Signature::certificates(void) const { - return {this->certificates_}; + return this->certificates_; } -const SignerInfo& Signature::signer_info(void) const { - return this->signer_info_; +it_const_signers_t Signature::signers(void) const { + return this->signers_; } -const std::vector& Signature::original_signature(void) const { +Signature::VERIFICATION_FLAGS Signature::check() const { + // According to the Authenticode documentation, + // *SignerInfos contains one SignerInfo structure* + const size_t nb_signers = this->signers_.size(); + VERIFICATION_FLAGS flags = VERIFICATION_FLAGS::OK; + if (nb_signers == 0) { + LIEF_WARN("No signer associated with the signature"); + return flags | VERIFICATION_FLAGS::INVALID_SIGNER; + } + + if (nb_signers > 1) { + LIEF_WARN("More than ONE signer ({:d} signers)", nb_signers); + return flags | VERIFICATION_FLAGS::INVALID_SIGNER; + } + const SignerInfo& signer = this->signers_.back(); + + // Check that Signature.digest_algorithm matches: + // - SignerInfo.digest_algorithm + // - ContentInfo.digest_algorithm + + if (this->digest_algorithm_ == ALGORITHMS::UNKNOWN) { + LIEF_WARN("Unsupported digest algorithm"); + return flags | VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM; + } + + if (this->digest_algorithm_ != this->content_info_.digest_algorithm()) { + LIEF_WARN("Digest algorithm is different from ContentInfo"); + return flags | VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM; + } + + if (this->digest_algorithm_ != signer.digest_algorithm()) { + LIEF_WARN("Digest algorithm is different from Signer"); + return flags | VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM; + } + + const ALGORITHMS digest_algo = this->content_info().digest_algorithm(); + + if (signer.cert() == nullptr) { + LIEF_WARN("Can't find certificate whose the issuer is {}", signer.issuer()); + return flags | VERIFICATION_FLAGS::CERT_NOT_FOUND; + } + const x509& cert = *signer.cert(); + const SignerInfo::encrypted_digest_t& enc_digest = signer.encrypted_digest(); + + if (this->content_info_start_ == 0 or this->content_info_end_ == 0) { + return flags | VERIFICATION_FLAGS::CORRUPTED_CONTENT_INFO; + } + + std::vector raw_content_info = { + std::begin(this->original_raw_signature_) + this->content_info_start_, + std::begin(this->original_raw_signature_) + this->content_info_end_ + }; + + const std::vector content_info_hash = Signature::hash(std::move(raw_content_info), digest_algo); + + if (this->auth_start_ == 0 or this->auth_end_ == 0) { + flags |= VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA; + } + + // Copy authenticated attributes + it_const_attributes_t auth_attrs = signer.authenticated_attributes(); + if (auth_attrs.size() > 0 and + (flags & VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA) != VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA) { + std::vector auth_data = { + std::begin(this->original_raw_signature_) + this->auth_start_, + std::begin(this->original_raw_signature_) + this->auth_end_ + }; + + // According to the RFC: + // + // "[...] The Attributes value's tag is SET OF, and the DER encoding of + // the SET OF tag, rather than of the IMPLICIT [0] tag [...]" + auth_data[0] = /* SET OF */ 0x31; + + const std::vector auth_attr_hash = Signature::hash(auth_data, digest_algo); + LIEF_DEBUG("Authenticated attribute digest: {}", hex_dump(auth_attr_hash)); + bool check_sig = cert.check_signature(auth_attr_hash, enc_digest, digest_algo); + + if (not check_sig) { + return flags | VERIFICATION_FLAGS::BAD_SIGNATURE; + } + + // Check that content_info_hash matches pkcs9-message-digest + auto it_pkcs9_digest = std::find_if(std::begin(auth_attrs), std::end(auth_attrs), + [] (const Attribute& attr) { + return attr.type() == SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST; + }); + + if (it_pkcs9_digest == std::end(auth_attrs)) { + return flags | VERIFICATION_FLAGS::MISSING_PKCS9_MESSAGE_DIGEST; + } + + const auto& digest_attr = reinterpret_cast(*it_pkcs9_digest); + LIEF_DEBUG("pkcs9-message-digest:\n {}\n {}", hex_dump(digest_attr.digest()), hex_dump(content_info_hash)); + if (digest_attr.digest() != content_info_hash) { + return flags | VERIFICATION_FLAGS::BAD_DIGEST; + } + + return flags; + } + /* + * If there is no authenticated attributes, then encrypted digested should match ENC(content_info_hash) + */ + if (not cert.check_signature(content_info_hash, enc_digest, digest_algo)) { + return flags | VERIFICATION_FLAGS::BAD_SIGNATURE; + } + return flags; +} + + +const std::vector& Signature::raw_der(void) const { return this->original_raw_signature_; } @@ -54,28 +271,140 @@ void Signature::accept(Visitor& visitor) const { visitor.visit(*this); } -std::ostream& operator<<(std::ostream& os, const Signature& signature) { - constexpr uint8_t wsize = 30; - os << std::hex << std::left; - os << std::setw(wsize) << std::setfill(' ') << "Version: " << signature.version() << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Digest Algorithm: " << oid_to_string(signature.digest_algorithm()) << std::endl; +inline void print_attr(it_const_attributes_t& attrs, std::ostream& os) { + for (const Attribute& attr : attrs) { + std::string suffix; + switch (attr.type()) { + case SIG_ATTRIBUTE_TYPES::CONTENT_TYPE: + { + const auto& ct = reinterpret_cast(attr); + suffix = ct.oid() + " (" + oid_to_string(ct.oid()) + ")"; + break; + } - os << "Content Info" << std::endl; - os << "============" << std::endl; - os << signature.content_info() << std::endl << std::endl; + case SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE: + { + const auto& ct = reinterpret_cast(attr); + suffix = ct.oid() + " (" + oid_to_string(ct.oid()) + ")"; + break; + } + case SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO: + { + const auto& ct = reinterpret_cast(attr); + if (not ct.program_name().empty()) { + suffix = ct.program_name(); + } + if (not ct.more_info().empty()) { + if (not suffix.empty()) { + suffix += " - "; + } + suffix += ct.more_info(); + } + break; + } + + case SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST: + { + const auto& ct = reinterpret_cast(attr); + suffix = hex_dump(ct.digest()).substr(0, 41) + "..."; + break; + } + + case SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN: + { + const auto& nested_attr = reinterpret_cast(attr); + const Signature& ct = nested_attr.sig(); + auto signers = ct.signers(); + auto crts = ct.certificates(); + if (signers.size() > 0) { + suffix = signers[0].issuer(); + } else if (crts.size() > 0) { + suffix = crts[0].issuer(); + } + break; + } + + case SIG_ATTRIBUTE_TYPES::GENERIC_TYPE: + { + const auto& ct = reinterpret_cast(attr); + suffix = ct.oid(); + break; + } + + case SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER: + { + const auto& ct = reinterpret_cast(attr); + suffix = std::to_string(ct.number()); + break; + } + + case SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE: + { + const auto& ct = reinterpret_cast(attr); + it_const_signers_t signers = ct.signers(); + + if (signers.size() > 1 or signers.size() == 0) { + suffix = std::to_string(signers.size()) + " signers"; + break; + } + const SignerInfo& signer = signers[0]; + suffix = signer.issuer(); + break; + } + + case SIG_ATTRIBUTE_TYPES::PKCS9_SIGNING_TIME: + { + const auto& ct = reinterpret_cast(attr); + const PKCS9SigningTime::time_t time = ct.time(); + suffix = fmt::format("{}/{}/{} - {}:{}:{}", + time[0], time[1], time[2], time[3], time[4], time[5]); + break; + } + + default: + { + } + } + os << fmt::format(" {}: {}\n", to_string(attr.type()), suffix); - os << "Certificates" << std::endl; - os << "============" << std::endl; - for (const x509& crt : signature.certificates()) { - os << crt << std::endl;; } - os << std::endl; +} - os << "Signer Info" << std::endl; - os << "===========" << std::endl; - os << signature.signer_info() << std::endl << std::endl; +std::ostream& operator<<(std::ostream& os, const Signature& signature) { + const ContentInfo& cinfo = signature.content_info(); + os << fmt::format("Version: {:d}\n", signature.version()); + os << fmt::format("Digest Algorithm: {}\n", to_string(signature.digest_algorithm())); + os << fmt::format("Content Info Digest: {}\n", hex_dump(cinfo.digest())); + if (not cinfo.file().empty()) { + os << fmt::format("Content Info File: {}\n", cinfo.file()); + } + it_const_crt certs = signature.certificates(); + os << fmt::format("#{:d} certificate(s):\n", certs.size()); + for (const x509& crt : certs) { + os << fmt::format(" - {}\n", crt.issuer()); // TODO(romain): RSA-2048, ... + } + it_const_signers_t signers = signature.signers(); + os << fmt::format("#{:d} signer(s):\n", signers.size()); + for (const SignerInfo& signer : signers) { + os << fmt::format("Issuer: {}\n", signer.issuer()); + os << fmt::format("Digest: {}\n", to_string(signer.digest_algorithm())); + os << fmt::format("Encryption: {}\n", to_string(signer.encryption_algorithm())); + os << fmt::format("Encrypted DG: {} ...\n", hex_dump(signer.encrypted_digest()).substr(0, 41)); + it_const_attributes_t auth_attr = signer.authenticated_attributes(); + if (auth_attr.size() > 0) { + os << fmt::format("#{:d} authenticated attributes:\n", auth_attr.size()); + print_attr(auth_attr, os); + } + + it_const_attributes_t unauth_attr = signer.unauthenticated_attributes(); + if (unauth_attr.size() > 0) { + os << fmt::format("#{:d} un-authenticated attributes:\n", unauth_attr.size()); + print_attr(unauth_attr, os); + } + + } return os; } diff --git a/src/PE/signature/SignatureParser.cpp b/src/PE/signature/SignatureParser.cpp index e686f84..d7e4d70 100644 --- a/src/PE/signature/SignatureParser.cpp +++ b/src/PE/signature/SignatureParser.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include @@ -25,8 +26,22 @@ #include "LIEF/BinaryStream/VectorStream.hpp" +#include "LIEF/PE/utils.hpp" + #include "LIEF/PE/signature/SignatureParser.hpp" #include "LIEF/PE/signature/Signature.hpp" + +#include "LIEF/PE/signature/Attribute.hpp" +#include "LIEF/PE/signature/attributes/ContentType.hpp" +#include "LIEF/PE/signature/attributes/GenericType.hpp" +#include "LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp" +#include "LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp" +#include "LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp" +#include "LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp" +#include "LIEF/PE/signature/attributes/PKCS9SigningTime.hpp" +#include "LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp" +#include "LIEF/PE/signature/attributes/MsSpcStatementType.hpp" + #include "LIEF/PE/signature/OIDToString.hpp" #include "utf8.h" @@ -36,685 +51,1083 @@ namespace LIEF { namespace PE { +inline uint8_t stream_get_tag(VectorStream& stream) { + if (stream.can_read()) { + return stream.peek(); + } + return 0; +} + SignatureParser::~SignatureParser(void) = default; SignatureParser::SignatureParser(void) = default; -SignatureParser::SignatureParser(const std::vector& data) : - signature_{}, - p_{nullptr}, - end_{nullptr}, - signature_ptr_{nullptr}, - stream_{std::unique_ptr(new VectorStream{data})} -{ +SignatureParser::SignatureParser(std::vector data) : + stream_{std::unique_ptr(new VectorStream{std::move(data)})} +{} - const uint8_t* sig = this->stream_->peek_array(8, this->stream_->size() - 8, /* check */false); - if (sig != nullptr) { - this->signature_ptr_ = sig; - this->end_ = this->signature_ptr_ + this->stream_->size() - 8; - this->p_ = const_cast(this->signature_ptr_); - try { - this->parse_signature(); - } catch (const std::exception& e) { - LIEF_DEBUG(e.what()); +result SignatureParser::parse(const std::string& path) { + std::ifstream binary(path, std::ios::in | std::ios::binary); + if (not binary) { + LIEF_ERR("Can't open {}", path); + return make_error_code(lief_errors::file_error); + } + binary.unsetf(std::ios::skipws); + binary.seekg(0, std::ios::end); + const auto size = static_cast(binary.tellg()); + binary.seekg(0, std::ios::beg); + std::vector raw_blob(size, 0); + binary.read(reinterpret_cast(raw_blob.data()), size); + return SignatureParser::parse(std::move(raw_blob)); +} + +result SignatureParser::parse(std::vector data, bool skip_header) { + if (data.size() < 10) { + return make_error_code(lief_errors::read_error); + } + std::vector sig_data = skip_header ? + std::vector{std::begin(data) + 8, std::end(data)} : + /* else */ + std::move(data); + + SignatureParser parser{std::move(sig_data)}; + auto sig = parser.parse_signature(); + if (not sig) { + LIEF_ERR("Error while parsing the signature"); + return sig.error(); + } + return std::move(sig.value()); +} + +size_t SignatureParser::current_offset() const { + return this->stream_->pos(); +} + + +result SignatureParser::parse_signature() { + Signature signature; + signature.original_raw_signature_ = this->stream_->content(); + auto tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(*this->stream_), this->stream_->pos()); + return tag.error(); + } + + auto oid = this->stream_->asn1_read_oid(); + if (not oid) { + LIEF_INFO("Can't read OID value (pos: {})", this->stream_->pos()); + return oid.error(); + } + std::string& oid_str = oid.value(); + + if (oid_str != /* pkcs7-signedData */ "1.2.840.113549.1.7.2") { + LIEF_INFO("Expecting OID pkcs7-signed-data at {:d} but got {}", + this->stream_->pos(), oid_to_string(oid_str)); + return make_error_code(lief_errors::read_error); + } + + tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(*this->stream_), this->stream_->pos()); + return tag.error(); + } + tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(*this->stream_), this->stream_->pos()); + return tag.error(); + } + + /* + * Defined in https://tools.ietf.org/html/rfc2315 + * SignedData ::= SEQUENCE { + * version Version, + * digestAlgorithms DigestAlgorithmIdentifiers, + * contentInfo ContentInfo, + * certificates + * [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL, + * crls + * [1] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos + * } + * + * Version ::= INTEGER + * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier + * SignerInfos ::= SET OF SignerInfo + * + * + * SignerInfo ::= SEQUENCE { + * version Version, + * issuerAndSerialNumber IssuerAndSerialNumber, + * digestAlgorithm DigestAlgorithmIdentifier, + * authenticatedAttributes + * [0] IMPLICIT Attributes OPTIONAL, + * digestEncryptionAlgorithm + * DigestEncryptionAlgorithmIdentifier, + * encryptedDigest EncryptedDigest, + * unauthenticatedAttributes + * [1] IMPLICIT Attributes OPTIONAL + * } + * + */ + + // ============================================================================== + // Version + // + // Version ::= INTEGER + // ============================================================================== + auto version = this->stream_->asn1_read_int(); + if (not version) { + LIEF_INFO("Can't parse version (pos: {:d})", this->stream_->pos()); + return tag.error(); + } + const int32_t version_val = version.value(); + LIEF_DEBUG("pkcs7-signed-data.version: {:d}", version_val); + if (version_val != 1) { + LIEF_INFO("pkcs7-signed-data.version is not 1 ({:d})", version_val); + return make_error_code(lief_errors::not_supported); + } + signature.version_ = version_val; + + // ============================================================================== + // Digest Algorithms + // + // DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier + // ============================================================================== + tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(*this->stream_), this->stream_->pos()); + return tag.error(); + } + const uintptr_t end_set = this->stream_->pos() + tag.value(); + std::vector algorithms; + while (this->stream_->pos() < end_set) { + const size_t current_p = this->stream_->pos(); + auto alg = this->stream_->asn1_read_alg(); + if (not alg) { + LIEF_INFO("Can't parse signed data digest algorithm (pos: {:d})", this->stream_->pos()); + break; + } + if (this->stream_->pos() == current_p) break; + LIEF_DEBUG("pkcs7-signed-data.digest-algorithms: {}", oid_to_string(alg.value())); + algorithms.push_back(std::move(alg.value())); + } + if (algorithms.size() == 0) { + LIEF_INFO("pkcs7-signed-data.digest-algorithms no algorithms found"); + return make_error_code(lief_errors::read_error); + } + else if (algorithms.size() > 1) { + LIEF_INFO("pkcs7-signed-data.digest-algorithms {:d} algorithms found. Expecting only 1", algorithms.size()); + return make_error_code(lief_errors::read_error); + } + else { + ALGORITHMS algo = algo_from_oid(algorithms.back()); + if (algo == ALGORITHMS::UNKNOWN) { + LIEF_WARN("LIEF does not handle algorithm {}", algorithms.back()); + } else { + signature.digest_algorithm_ = algo; + } + + } + + // Content Info + // ========================================================= + tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} can't parse content info (pos: {:d})", + stream_get_tag(*this->stream_), this->stream_->pos()); + return tag.error(); + } + + /* Content Info */ { + std::vector raw_content_info = + {this->stream_->p(), this->stream_->p() + tag.value()}; + VectorStream content_info_stream{std::move(raw_content_info)}; + + range_t range = {0, 0}; + auto content_info = this->parse_content_info(content_info_stream, range); + if (not content_info) { + LIEF_INFO("Fail to parse pkcs7-signed-data.content-info"); + } else { + signature.content_info_ = std::move(content_info.value()); + signature.content_info_start_ = this->stream_->pos() + range.start; + signature.content_info_end_ = this->stream_->pos() + range.end; + LIEF_DEBUG("ContentInfo range: {:d} -> {:d}", + signature.content_info_start_, signature.content_info_end_); + } + this->stream_->increment_pos(raw_content_info.size()); + } + + // X509 Certificates (optional) + // ========================================================= + + tag = this->stream_->asn1_read_tag(/* certificates */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (tag) { + LIEF_DEBUG("Parse pkcs7-signed-data.certificates offset: {:d}", this->stream_->pos()); + std::vector raw_content = + {this->stream_->p(), this->stream_->p() + tag.value()}; + + VectorStream certificate_stream{std::move(raw_content)}; + this->stream_->increment_pos(raw_content.size()); + + auto certificates = this->parse_certificates(certificate_stream); + if (not certificates) { + LIEF_INFO("Fail to parse pkcs7-signed-data.certificates"); + } else { + // Makes chain + std::vector certs = certificates.value(); + //mbedtls_x509_crt* next = certs.back().x509_cert_; + //for (size_t i = 1; i < certs.size(); ++i) { + // certs[certs.size() - i - 1].x509_cert_->next = next; + // next = certs[certs.size() - i - 1].x509_cert_->next; + //} + signature.certificates_ = std::move(certs); } } + + // CRLS (optional) + // ========================================================= + tag = this->stream_->asn1_read_tag(/* certificates */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1); + if (tag) { + LIEF_DEBUG("Parse pkcs7-signed-data.crls offset: {:d}", this->stream_->pos()); + std::vector raw_content = + {this->stream_->p(), this->stream_->p() + tag.value()}; + // TODO(romain): Process crls certificates + this->stream_->increment_pos(raw_content.size()); + } + + // SignerInfos + // ========================================================= + tag = this->stream_->asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); + if (tag) { + const uint64_t current_pos = this->stream_->pos(); + LIEF_DEBUG("Parse pkcs7-signed-data.signer-infos offset: {:d}", this->stream_->pos()); + std::vector raw_content = + {this->stream_->p(), this->stream_->p() + tag.value()}; + VectorStream stream{std::move(raw_content)}; + this->stream_->increment_pos(raw_content.size()); + range_t auth_attr; + auto signer_info = this->parse_signer_infos(stream, auth_attr); + signature.auth_start_ = current_pos + auth_attr.start; + signature.auth_end_ = current_pos + auth_attr.end; + LIEF_DEBUG("Authenticated attributes: {} -> {}", signature.auth_start_, signature.auth_end_); + if (not signer_info) { + LIEF_INFO("Fail to parse pkcs7-signed-data.signer-infos"); + } else { + signature.signers_ = std::move(signer_info.value()); + } + } + + // Tied signer info with x509 certificates + for (SignerInfo& signer : signature.signers_) { + auto it_cert = std::find_if(std::begin(signature.certificates_), std::end(signature.certificates_), + [&signer] (const x509& cert) { + return cert.issuer() == signer.issuer() and cert.serial_number() == signer.serial_number(); + }); + if (it_cert == std::end(signature.certificates_)) { + LIEF_INFO("Can't find x509 certificate associated with signer '{}'", signer.issuer()); + continue; + } + signer.cert_ = std::unique_ptr(new x509{*it_cert}); + } + + return signature; } - -Signature SignatureParser::parse(const std::vector& data) { - SignatureParser parser{data}; - return parser.signature_; -} - -size_t SignatureParser::current_offset(void) const { - return (reinterpret_cast(this->p_) - reinterpret_cast(this->signature_ptr_)); -} - - -void SignatureParser::parse_header(void) { - mbedtls_asn1_buf buf; - int ret = 0; - size_t tag; - char oid_str[256] = { 0 }; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); - } - - buf.tag = *this->p_; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &buf.len, MBEDTLS_ASN1_OID)) != 0) { - throw corrupted("Error while reading tag"); - } - - buf.p = this->p_; - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &buf); - LIEF_DEBUG("OID (signedData): {}", oid_str); - this->p_ += buf.len; - - if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_SIGNED_DATA, &buf) != 0) { - throw corrupted("Wrong OID: " + std::string(oid_str) + " (expect PKCS7_SIGNED_DATA)"); - } - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signature corrupted"); - } - - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); - } - -} - - -int32_t SignatureParser::get_signed_data_version(void) { - LIEF_DEBUG("Parse signed data - version"); - int ret = 0; - - int32_t version; - if ((ret = mbedtls_asn1_get_int(&(this->p_), this->end_, &version)) != 0) { - throw corrupted("Signature corrupted"); - } - - LIEF_DEBUG("Version: {}", version); - if (version != 1) { - LIEF_WARN("Version should be equal to 1 ({:d})", version); - } - return version; -} - - -std::string SignatureParser::get_signed_data_digest_algorithms(void) { - LIEF_DEBUG("Parse signed data - digest algorithm"); - int ret = 0; - size_t tag; - char oid_str[256] = { 0 }; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { - throw corrupted("Signature corrupted"); - } - - mbedtls_asn1_buf alg_oid; - - if ((ret = mbedtls_asn1_get_alg_null(&(this->p_), this->end_, &alg_oid)) != 0) { - throw corrupted("Signature corrupted"); - } - - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &alg_oid); - - LIEF_DEBUG("digestAlgorithms: {}", oid_str); - return oid_str; - -} - - -ContentInfo SignatureParser::parse_content_info(void) { - LIEF_DEBUG("Parse signed data - content info"); - - mbedtls_asn1_buf content_type_oid; - mbedtls_asn1_buf alg_oid; - int ret = 0; - size_t tag; - char oid_str[256] = { 0 }; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); - } - +result SignatureParser::parse_content_info(VectorStream& stream, range_t& range) { + // ============================================================================== + // ContentInfo + // ContentInfo ::= SEQUENCE { + // contentType ContentType, + // content + // [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL + // } + // ContentType ::= OBJECT IDENTIFIER + // ============================================================================== ContentInfo content_info; - content_info.content_type_ = this->get_content_info_type(); - // content - SpcIndirectDataContent - // |_ SpcAttributeTypeAndOptionalValue - // |_ DigestInfo - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - LIEF_DEBUG("Parsing SpcIndirectDataContent (offset: {:d})", this->current_offset()); - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signature corrupted"); + // First, process contentType which must match SPC_INDIRECT_DATA_CONTEXT + { + auto content_type = stream.asn1_read_oid(); + if (not content_type) { + LIEF_INFO("Can't parse content-info.content-type (pos: {:d})", stream.pos()); + return content_type.error(); + } + const std::string& ctype_str = content_type.value(); + LIEF_DEBUG("content-info.content-type: {}", oid_to_string(ctype_str)); + if (ctype_str != /* SPC_INDIRECT_DATA_CONTEXT */ "1.3.6.1.4.1.311.2.1.4") { + LIEF_WARN("Expecting OID SPC_INDIRECT_DATA_CONTEXT at {:d} but got {}", + stream.pos(), oid_to_string(ctype_str)); + return make_error_code(lief_errors::read_error); + } + content_info.content_type_ = ctype_str; } - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); + + // ============================================================================== + // Then process SpcIndirectDataContent, which has this structure: + // + // SpcIndirectDataContent ::= SEQUENCE { + // data SpcAttributeTypeAndOptionalValue, + // messageDigest DigestInfo + // } + // + // SpcAttributeTypeAndOptionalValue ::= SEQUENCE { + // type ObjectID, // Should be SPC_PE_IMAGE_DATA + // value [0] EXPLICIT ANY OPTIONAL + // } + // + // DigestInfo ::= SEQUENCE { + // digestAlgorithm AlgorithmIdentifier, + // digest OCTETSTRING + // } + // + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm ObjectID, + // parameters [0] EXPLICIT ANY OPTIONAL + // } + // ============================================================================== + auto tag = stream.asn1_read_tag(/* [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL */ + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(stream), stream.pos()); + return tag.error(); + } + range.end = stream.size(); + + tag = stream.asn1_read_tag(/* SpcIndirectDataContent */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(stream), stream.pos()); + return tag.error(); } - // Save off raw now so that it covers everything else in the ContentInfo - content_info.raw_ = {this->p_, this->p_ + tag}; - - // SpcAttributeTypeAndOptionalValue - // |_ SPC_PE_IMAGE_DATAOBJ - // |_ SpcPeImageData - // ++++++++++++++++++++++++++++++++ - LIEF_DEBUG("Parsing SpcAttributeTypeAndOptionalValue (offset: {:d})", this->current_offset()); - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); + range.start = stream.pos(); + tag = stream.asn1_read_tag(/* SpcAttributeTypeAndOptionalValue */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(stream), stream.pos()); + return tag.error(); } - content_type_oid.tag = *this->p_; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) { - throw corrupted("Signature corrupted"); + // SpcAttributeTypeAndOptionalValue.type + auto spc_attr_type = stream.asn1_read_oid(); + if (not spc_attr_type) { + LIEF_INFO("Can't parse spc-attribute-type-and-optional-value.type (pos: {:d})", stream.pos()); + return spc_attr_type.error(); } - content_type_oid.p = this->p_; - - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid); - LIEF_DEBUG("SpcAttributeTypeAndOptionalValue->type {}", oid_str); - - content_info.type_ = oid_str; - this->p_ += content_type_oid.len; - - // SpcPeImageData - // |_ SpcPeImageFlags - // |_ SpcLink - // ++++++++++++++ - LIEF_DEBUG("Parsing SpcPeImageData (offset: {:d})", this->current_offset()); - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); + const std::string& spc_attr_type_str = spc_attr_type.value(); + LIEF_DEBUG("spc-attribute-type-and-optional-value.type: {}", oid_to_string(spc_attr_type_str)); + if (spc_attr_type_str != /* SPC_PE_IMAGE_DATA */ "1.3.6.1.4.1.311.2.1.15") { + LIEF_WARN("Expecting OID SPC_PE_IMAGE_DATA at {:d} but got {}", + stream.pos(), oid_to_string(spc_attr_type_str)); + return make_error_code(lief_errors::read_error); } - // SpcPeImageFlags - // ^^^^^^^^^^^^^^^ - LIEF_DEBUG("Parsing SpcPeImageFlags (offset: {:d})", this->current_offset()); - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_BIT_STRING)) != 0) { - throw corrupted("Signature corrupted"); - } - this->p_ += tag; // skip - // SpcLink - // ^^^^^^^ - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signature corrupted"); - } - this->p_ += tag; // skip + tag = stream.asn1_read_tag(/* SpcPeImageData ::= SEQUENCE */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); - // DigestInfo - // ++++++++++ - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - throw corrupted("Signature corrupted"); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} (pos: {:d})", + stream_get_tag(stream), stream.pos()); + return tag.error(); } - if ((ret = mbedtls_asn1_get_alg_null(&(this->p_), this->end_, &alg_oid)) != 0) { - throw corrupted("Signature corrupted"); + + /* SpcPeImageData */ { + const size_t length = tag.value(); + std::vector raw = {stream.p(), stream.p() + length}; + VectorStream spc_data_stream{std::move(raw)}; + stream.increment_pos(spc_data_stream.size()); + + auto spc_data = this->parse_spc_pe_image_data(spc_data_stream); + if (not spc_data) { + LIEF_INFO("Can't parse SpcPeImageData"); + } else { + const SpcPeImageData& spc_data_value = spc_data.value(); + content_info.file_ = spc_data_value.file; + content_info.flags_ = spc_data_value.flags; + } } - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &alg_oid); - LIEF_DEBUG("DigestInfo->digestAlgorithm: {}", oid_str); + // ================================================ + // DigestInfo ::= SEQUENCE + // ================================================ + tag = stream.asn1_read_tag(/* DigestInfo */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); - content_info.digest_algorithm_ = oid_str; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - throw corrupted("Signature corrupted"); + if (not tag) { + LIEF_INFO("Wrong tag 0x{:x} for DigestInfo ::= SEQUENCE (pos: {:d})", + stream_get_tag(stream), stream.pos()); + return tag.error(); } - content_info.digest_ = {this->p_, this->p_ + tag}; - //TODO: Read hash - this->p_ += tag; + auto alg_identifier = stream.asn1_read_alg(); + if (not alg_identifier) { + LIEF_INFO("Can't parse SignedData.contentInfo.messageDigest.digestAlgorithm (pos: {:d})", + stream.pos()); + return alg_identifier.error(); + } + LIEF_DEBUG("spc-indirect-data-content.digest-algorithm {}", oid_to_string(alg_identifier.value())); + ALGORITHMS algo = algo_from_oid(alg_identifier.value()); + if (algo == ALGORITHMS::UNKNOWN) { + LIEF_WARN("LIEF does not handle {}", alg_identifier.value()); + } else { + content_info.digest_algorithm_ = algo; + } + + // From the documentation: + // The value must match the digestAlgorithm value specified + // in SignerInfo and the parent PKCS #7 digestAlgorithms fields. + auto digest = stream.asn1_read_octet_string(); + if (not digest) { + LIEF_INFO("Can't parse SignedData.contentInfo.messageDigest.digest (pos: {:d})", + stream.pos()); + return digest.error(); + } + content_info.digest_ = std::move(digest.value()); + LIEF_DEBUG("spc-indirect-data-content.digest: {}", hex_dump(content_info.digest_)); return content_info; } +result SignatureParser::parse_certificates(VectorStream& stream) { + x509_certificates_t certificates; + const uint64_t cert_end_p = stream.size(); + while (stream.pos() < cert_end_p) { + auto cert = stream.asn1_read_cert(); + if (not cert) { + LIEF_INFO("Can't parse X509 cert pkcs7-signed-data.certificates (pos: {:d})", + stream.pos()); + return cert.error(); + //break; + } + std::unique_ptr cert_p = std::move(cert.value()); -std::string SignatureParser::get_content_info_type(void) { - LIEF_DEBUG("Parse signed data - content info - content type"); - - mbedtls_asn1_buf content_type_oid; - int ret = 0; - char oid_str[256] = { 0 }; - - content_type_oid.tag = *this->p_; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) { - throw corrupted("Signature corrupted"); + if /* constexpr */(lief_logging_debug) { + char buffer[1024]; + std::memset(buffer, 0, sizeof(buffer)); + mbedtls_x509_crt_info(buffer, sizeof(buffer), "", cert_p.get()); + LIEF_DEBUG("\n{}\n", buffer); + } + certificates.emplace_back(cert_p.release()); } - - content_type_oid.p = this->p_; - - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid); - - if (MBEDTLS_OID_CMP(MBEDTLS_SPC_INDIRECT_DATA_OBJID, &content_type_oid) != 0) { - throw corrupted(std::string(oid_str) + " is not SPC_INDIRECT_DATA_OBJID"); - } - LIEF_DEBUG("contentType: {} ({})", oid_str, oid_to_string(oid_str)); - this->p_ += content_type_oid.len; - - return {oid_str}; + return certificates; } -void SignatureParser::parse_certificates(void) { - LIEF_DEBUG("Parsing Certificates (offset: {:d})", this->current_offset()); +result SignatureParser::parse_signer_infos(VectorStream& stream, range_t& auth_attr) { + const uintptr_t end_set = stream.size(); - int ret = 0; - size_t tag; - char buffer[1024]; + signer_infos_t infos; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signature corrupted"); - } + while (stream.pos() < end_set) { + SignerInfo signer; + const size_t current_p = stream.pos(); - uint8_t* cert_end = this->p_ + tag; - while (this->p_ < cert_end) { - std::memset(buffer, 0, sizeof(buffer)); - - std::unique_ptr ca{new mbedtls_x509_crt{}}; - mbedtls_x509_crt_init(ca.get()); - mbedtls_x509_crt_parse_der(ca.get(), this->p_, this->end_ - this->p_); - if (ca->raw.len <= 0) { + auto tag = stream.asn1_read_tag(/* SignerInfo */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} for pkcs7-signed-data.signer-infos SEQUENCE (pos: {:d})", + stream_get_tag(stream), stream.pos()); break; } - mbedtls_x509_crt_info(buffer, sizeof(buffer), "", ca.get()); - LIEF_DEBUG("\n{}\n", buffer); - - this->signature_.certificates_.emplace_back(ca.get()); - this->p_ += ca->raw.len; - ca.release(); - } - - // If one of the certificates failed to parse for some reason, skip past - // the certificate section so that we have a chance of parsing the rest - // of the signature. - if (this->p_ < cert_end) { - this->p_ = cert_end; - } -} - -AuthenticatedAttributes SignatureParser::get_authenticated_attributes(void) { - LIEF_DEBUG("Parsing authenticatedAttributes (offset: {:d})", this->current_offset()); - - int ret = 0; - size_t tag; - char oid_str[256] = { 0 }; - mbedtls_asn1_buf content_type_oid; - - AuthenticatedAttributes authenticated_attributes; - - uint8_t *p_start = this->p_; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Authenticated attributes corrupted"); - } - - authenticated_attributes.raw_ = {p_start, p_start + (this->p_ - p_start) + tag}; - - uint8_t* p_end = this->p_ + tag; - while(this->p_ < p_end) { - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Authenticated attributes corrupted"); + // ======================================================= + // version Version + // ======================================================= + auto version = stream.asn1_read_int(); + if (not version) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-info.version (pos: {:d})", stream.pos()); + break; } - content_type_oid.tag = *this->p_; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) { - throw corrupted("Authenticated attributes corrupted"); + int32_t version_val = version.value(); + LIEF_DEBUG("pkcs7-signed-data.signer-info.version: {}", version_val); + if (version_val != 1) { + LIEF_DEBUG("pkcs7-signed-data.signer-info.version: Bad version ({:d})", version_val); + break; } - content_type_oid.p = this->p_; + signer.version_ = version_val; - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid); - - this->p_ += content_type_oid.len; - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Authenticated attributes corrupted"); + // ======================================================= + // IssuerAndSerialNumber ::= SEQUENCE { + // issuer Name, + // serialNumber CertificateSerialNumber + // } + // + // For Name see: https://github.com/ARMmbed/mbedtls/blob/9e4d4387f07326fff227a40f76c25e5181b1b1e2/library/x509_crt.c#L1180 + // ======================================================= + tag = stream.asn1_read_tag(/* Name */ + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag: 0x{:x} for \ + pkcs7-signed-data.signer-infos.issuer-and-serial-number.issuer (pos: {:d})", + stream_get_tag(stream), stream.pos()); + break; } - if (std::string(oid_str) == "1.2.840.113549.1.9.3") { - // contentType - // |_ OID (PKCS #9 Message Digest) - // |_ SET -> OID - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - LIEF_DEBUG("Parsing contentType (offset: {:d})", this->current_offset()); - content_type_oid.tag = *this->p_; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) { - throw corrupted("Authenticated attributes corrupted"); + auto issuer = stream.x509_read_names(); + if (not issuer) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-infos.issuer-and-serial-number.issuer (pos: {:d})", + stream.pos()); + break; + } + + LIEF_DEBUG("pkcs7-signed-data.signer-infos.issuer-and-serial-number.issuer: {} (pos: {:d})", + issuer.value(), stream.pos()); + signer.issuer_ = std::move(issuer.value()); + + auto sn = stream.x509_read_serial(); + if (not sn) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-infos.issuer-and-serial-number.serial-number (pos: {:d})", + stream.pos()); + break; + } + + LIEF_DEBUG("pkcs7-signed-data.signer-infos.issuer-and-serial-number.serial-number {}", + hex_dump(sn.value())); + signer.serialno_ = std::move(sn.value()); + + // ======================================================= + // Digest Encryption Algorithm + // ======================================================= + { + auto digest_alg = stream.asn1_read_alg(); + + if (not digest_alg) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-infos.digest-algorithm (pos: {:d})", stream.pos()); + break; } - content_type_oid.p = this->p_; - - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid); - authenticated_attributes.content_type_ = oid_str; - this->p_ += content_type_oid.len; - continue; - - } else if (std::string(oid_str) == "1.2.840.113549.1.9.4") { - // messageDigest (Octet string) - // |_ OID (PKCS #9 Message Digest) - // |_ SET -> OCTET STING - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - LIEF_DEBUG("Parsing messageDigest (offset: {:d})", this->current_offset()); - LIEF_DEBUG("{} ({})", oid_str, oid_to_string(oid_str)); // 1.2.840.113549.1.9.4 - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - throw corrupted("Signature corrupted: Can't read 'ASN1_OCTET_STRING'"); - } - authenticated_attributes.message_digest_ = {this->p_, this->p_ + tag}; - this->p_ += tag; - continue; - - } else if (std::string(oid_str) == "1.3.6.1.4.1.311.2.1.12") { - // SpcSpOpusInfo - // |_ programName (utf16) - // |_ moreInfo - // ~~~~~~~~~~~~~~~~~~~~~~ - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Authenticated attributes corrupted"); - } - - if (tag == 0) { - LIEF_DEBUG("No program name or more info specified"); - authenticated_attributes.program_name_ = u""; - authenticated_attributes.more_info_ = ""; - continue; - } - - uint8_t *seq_end = this->p_ + tag; - - if (*this->p_ == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) { - this->p_ += 1; - if ((ret = mbedtls_asn1_get_len(&(this->p_), this->end_, &tag)) != 0) { - LIEF_DEBUG("Unexpected format for SpcSpOpusInfo [0] block"); - throw corrupted("Authenticated attributes corrupted"); - } - - // Two cases to handle here: - // SpcString ::= CHOICE { - // unicode [0] IMPLICIT BMPSTRING, - // ascii [1] IMPLICIT IA5STRING - // } - - if (*this->p_ == (MBEDTLS_ASN1_CONTEXT_SPECIFIC) || - *this->p_ == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1)) { - this->p_ += 1; - if ((ret = mbedtls_asn1_get_len(&(this->p_), this->end_, &tag)) != 0) { - LIEF_DEBUG("Unexpected format for SpcString block"); - throw corrupted("Authenticated attributes corrupted"); - } - - LIEF_DEBUG("Offset: {:d} | Size: {:d}", this->current_offset(), tag); - - // u8 -> u16 due to endiness - std::string u8progname{reinterpret_cast(this->p_), tag}; - std::u16string progname; - try { - utf8::unchecked::utf8to16(std::begin(u8progname), std::end(u8progname), std::back_inserter(progname)); - } catch (const utf8::exception&) { - LIEF_WARN("utf8 error when parsing progname"); - } - - authenticated_attributes.program_name_ = progname; - LIEF_DEBUG("ProgName: {}", u16tou8(progname)); - this->p_ += tag; - - } else { - LIEF_DEBUG("Unexpected format for SpcString block"); - throw corrupted("Authenticated attributes corrupted"); - } - - if (this->p_ >= seq_end) { - LIEF_DEBUG("No more info specified"); - authenticated_attributes.more_info_ = ""; - continue; - } + LIEF_DEBUG("pkcs7-signed-data.signer-infos.digest-algorithm: {}", oid_to_string(digest_alg.value())); + ALGORITHMS dg_algo = algo_from_oid(digest_alg.value()); + if (dg_algo == ALGORITHMS::UNKNOWN) { + LIEF_WARN("LIEF does not handle algorithm {}", digest_alg.value()); } else { - LIEF_DEBUG("No program name specified"); - authenticated_attributes.program_name_ = u""; + signer.digest_algorithm_ = dg_algo; } + } - // moreInfo - // ++++++++ - if (*this->p_ == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_BOOLEAN)) { - this->p_ += 1; - if ((ret = mbedtls_asn1_get_len(&(this->p_), this->end_, &tag)) != 0) { - LIEF_DEBUG("Unexpected format for SpcSpOpusInfo [1] block"); - throw corrupted("Authenticated attributes corrupted"); - } - - uint8_t p_val = *this->p_; - - this->p_ += 1; - if ((ret = mbedtls_asn1_get_len(&(this->p_), this->end_, &tag)) != 0) { - LIEF_DEBUG("Unexpected format for SpcLink block"); - throw corrupted("Authenticated attributes corrupted"); - } - - // Three cases to handle here: - // SpcLink ::= CHOICE { - // url [0] IMPLICIT IA5STRING, - // moniker [1] IMPLICIT SpcSerializedObject, - // file [2] EXPLICIT SpcString - // } - - if (p_val == (MBEDTLS_ASN1_CONTEXT_SPECIFIC)) { - - std::string more_info{reinterpret_cast(this->p_), tag}; // moreInfo - authenticated_attributes.more_info_ = more_info; - LIEF_DEBUG("{}", more_info); - this->p_ += tag; - - } else if (p_val == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1)) { - LIEF_DEBUG("Parsing MoreInfo 'moniker' option not currently supported"); - authenticated_attributes.more_info_ = ""; - - } else if (p_val == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) { - LIEF_DEBUG("Parsing MoreInfo 'file' option not currently supported"); - authenticated_attributes.more_info_ = ""; - - } else { - LIEF_DEBUG("Unexpected format for SpcLink block"); - throw corrupted("Authenticated attributes corrupted"); - } - continue; + // ======================================================= + // Authenticated Attributes + // ======================================================= + { + auth_attr.start = stream.pos(); + tag = stream.asn1_read_tag(/* authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL */ + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED); + if (tag) { + auth_attr.end = stream.pos() + tag.value(); + std::vector raw_authenticated_attributes = + {stream.p(), stream.p() + tag.value()}; + VectorStream auth_stream(std::move(raw_authenticated_attributes)); + stream.increment_pos(auth_stream.size()); + auto authenticated_attributes = this->parse_attributes(auth_stream); + if (not authenticated_attributes) { + LIEF_INFO("Fail to parse pkcs7-signed-data.signer-infos.authenticated-attributes"); + } else { + signer.authenticated_attributes_ = std::move(authenticated_attributes.value()); + } + } else { + auth_attr.start = 0; } + } - } else { - LIEF_DEBUG("Skipping OID {}", oid_str); - this->p_ += tag; - continue; + // ======================================================= + // Digest Encryption Algorithm + // ======================================================= + { + auto digest_enc_alg = stream.asn1_read_alg(); + if (not digest_enc_alg) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-infos.digest-encryption-algorithm (pos: {:d})", + stream.pos()); + return digest_enc_alg.error(); + } + LIEF_DEBUG("pkcs7-signed-data.signer-infos.digest-encryption-algorithm: {}", + oid_to_string(digest_enc_alg.value())); + + ALGORITHMS dg_enc_algo = algo_from_oid(digest_enc_alg.value()); + if (dg_enc_algo == ALGORITHMS::UNKNOWN) { + LIEF_WARN("LIEF does not handle algorithm {}", digest_enc_alg.value()); + } else { + signer.digest_enc_algorithm_ = dg_enc_algo; + } + } + + // ======================================================= + // Encrypted Digest + // ======================================================= + { + auto enc_digest = stream.asn1_read_octet_string(); + if (not enc_digest) { + LIEF_INFO("Can't parse pkcs7-signed-data.signer-infos.encrypted-digest (pos: {:d})", + stream.pos()); + return enc_digest.error(); + } + LIEF_DEBUG("pkcs7-signed-data.signer-infos.encrypted-digest: {}", hex_dump(enc_digest.value())); + signer.encrypted_digest_ = enc_digest.value(); + } + + // ======================================================= + // Unauthenticated Attributes + // ======================================================= + { + tag = stream.asn1_read_tag(/* unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL */ + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1); + if (tag) { + std::vector raw_unauthenticated_attributes = + {stream.p(), stream.p() + tag.value()}; + VectorStream unauth_stream(std::move(raw_unauthenticated_attributes)); + stream.increment_pos(unauth_stream.size()); + auto unauthenticated_attributes = this->parse_attributes(unauth_stream); + if (not unauthenticated_attributes) { + LIEF_INFO("Fail to parse pkcs7-signed-data.signer-infos.unauthenticated-attributes"); + } else { + signer.unauthenticated_attributes_ = std::move(unauthenticated_attributes.value()); + } + } + } + infos.push_back(std::move(signer)); + + if (stream.pos() <= current_p) { + break; } } - - return authenticated_attributes; + return infos; } -SignerInfo SignatureParser::get_signer_info(void) { - int ret = 0; - size_t tag; - char oid_str[256] = { 0 }; - mbedtls_asn1_buf alg_oid; +result SignatureParser::parse_attributes(VectorStream& stream) { + // Attributes ::= SET OF Attribute + // + // Attribute ::= SEQUENCE + // { + // type EncodedObjectID, + // values AttributeSetValue + // } + attributes_t attributes; + const uint64_t end_pos = stream.size(); + while (stream.pos() < end_pos) { + auto tag = stream.asn1_read_tag(/* Attribute ::= SEQUENCE */ + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED); + if (not tag) { + LIEF_INFO("Can't parse attribute (pos: {:d})", stream.pos()); + break; + } - SignerInfo signer_info; - int32_t version; - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signer info corrupted"); + auto oid = stream.asn1_read_oid(); + if (not oid) { + LIEF_INFO("Can't parse attribute.type (pos: {:d})", stream.pos()); + break; + } + tag = stream.asn1_read_tag(/* AttributeSetValue */ + MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED); + if (not tag) { + LIEF_DEBUG("attribute.values: Unable to get set for {}", oid.value()); + break; + } + const size_t value_set_size = tag.value(); + LIEF_DEBUG("attribute.values: {} ({:d} bytes)", oid_to_string(oid.value()), value_set_size); + + std::vector raw = {stream.p(), stream.p() + value_set_size}; + VectorStream value_stream(std::move(raw)); + + while (value_stream.pos() < value_stream.size()) { + const uint64_t current_p = value_stream.pos(); + const std::string& oid_str = oid.value(); + + if (oid_str == /* contentType */ "1.2.840.113549.1.9.3") { + auto res = this->parse_content_type(value_stream); + if (not res or res.value() == nullptr) { + LIEF_INFO("Can't parse content-type attribute"); + } else { + attributes.push_back(std::move(res.value())); + } + } + + else if (oid_str == /* SpcSpOpusInfo */ "1.3.6.1.4.1.311.2.1.12") { + auto res = this->parse_spc_sp_opus_info(value_stream); + if (not res) { + LIEF_INFO("Can't parse spc-sp-opus-info attribute"); + } else { + SpcSpOpusInfo info = std::move(res.value()); + attributes.emplace_back(new PE::SpcSpOpusInfo{std::move(info.program_name), std::move(info.more_info)}); + } + } + // TODO(romain): Parse the internal DER of Ms-CounterSign + // else if (oid_str == /* Ms-CounterSign */ "1.3.6.1.4.1.311.3.3.1") { + // auto res = this->parse_ms_counter_sign(value_stream); + // if (not res) { + // LIEF_INFO("Can't parse ms-counter-sign attribute"); + // } + // } + + else if (oid_str == /* pkcs9-CounterSignature */ "1.2.840.113549.1.9.6") { + auto res = this->parse_pkcs9_counter_sign(value_stream); + if (not res) { + LIEF_INFO("Can't parse pkcs9-counter-sign attribute"); + } else { + attributes.emplace_back(new PKCS9CounterSignature(std::move(res.value()))); + } + } + + else if (oid_str == /* Ms-SpcNestedSignature */ "1.3.6.1.4.1.311.2.4.1") { + auto res = this->parse_ms_spc_nested_signature(value_stream); + if (not res) { + LIEF_INFO("Can't parse ms-spc-nested-signature attribute"); + } else { + attributes.emplace_back(new MsSpcNestedSignature(std::move(res.value()))); + } + } + + else if (oid_str == /* pkcs9-MessageDigest */ "1.2.840.113549.1.9.4") { + auto res = this->parse_pkcs9_message_digest(value_stream); + if (not res) { + LIEF_INFO("Can't parse pkcs9-message-digest attribute"); + } else { + attributes.emplace_back(new PKCS9MessageDigest(std::move(res.value()))); + } + } + + else if (oid_str == /* Ms-SpcStatementType */ "1.3.6.1.4.1.311.2.1.11") { + auto res = this->parse_ms_spc_statement_type(value_stream); + if (not res) { + LIEF_INFO("Can't parse ms-spc-statement-type attribute"); + } else { + attributes.emplace_back(new MsSpcStatementType(std::move(res.value()))); + } + } + + else if (oid_str == /* pkcs9-at-SequenceNumber */ "1.2.840.113549.1.9.25.4") { + auto res = this->parse_pkcs9_at_sequence_number(value_stream); + if (not res) { + LIEF_INFO("Can't parse ms-spc-statement-type attribute"); + } else { + attributes.emplace_back(new PKCS9AtSequenceNumber(res.value())); + } + } + + else if (oid_str == /* pkcs9-signing-time */ "1.2.840.113549.1.9.5") { + auto res = this->parse_pkcs9_signing_time(value_stream); + if (not res) { + LIEF_INFO("Can't parse ms-spc-statement-type attribute"); + } else { + attributes.emplace_back(new PKCS9SigningTime(std::move(res.value()))); + } + } + + else { + LIEF_INFO("Unknown OID: {}", oid_str); + attributes.emplace_back(new GenericType{oid_str, value_stream.content()}); + break; + } + + if (current_p >= value_stream.pos()) { + LIEF_INFO("End-loop detected!"); + break; + } + } + stream.increment_pos(value_set_size); } - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signer info corrupted"); - } - - if ((ret = mbedtls_asn1_get_int(&(this->p_), this->end_, &version)) != 0) { - throw corrupted("Signer info corrupted"); - } - - LIEF_DEBUG("Version: {:d}", version); - - if (version != 1) { - LIEF_WARN("SignerInfo's version should be equal to 1 ({:d})", version); - } - signer_info.version_ = version; - - // issuerAndSerialNumber - // --------------------- - LIEF_DEBUG("Parsing issuerAndSerialNumber (offset: {:d})", this->current_offset()); - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signer info corrupted"); - } - - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { - throw corrupted("Signer info corrupted"); - } - - // Name - // ~~~~ - mbedtls_x509_name name; - char buffer[1024]; - - uint8_t* p_end = this->p_ + tag; - - std::memset(&name, 0, sizeof(name)); - if ((ret = mbedtls_x509_get_name(&(this->p_), p_end, &name)) != 0) { - throw corrupted("Signer info corrupted"); - } - - mbedtls_x509_dn_gets(buffer, sizeof(buffer), &name); - - std::string issuer_name {buffer}; - - LIEF_DEBUG("Issuer: {}", issuer_name); - - mbedtls_x509_name *name_cur; - - name_cur = name.next; - while( name_cur != NULL ) - { - mbedtls_x509_name *name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_free( name_prv ); - } - - // CertificateSerialNumber (issuer SN) - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - mbedtls_x509_buf serial; - if ((ret = mbedtls_x509_get_serial(&(this->p_), this->end_, &serial)) != 0) { - throw corrupted("Signer info corrupted"); - } - std::vector certificate_sn = {serial.p, serial.p + serial.len}; - - signer_info.issuer_ = {issuer_name, certificate_sn}; - - // digestAlgorithm - // --------------- - LIEF_DEBUG("Parsing digestAlgorithm (offset: {:d})", this->current_offset()); - if ((ret = mbedtls_asn1_get_alg_null(&(this->p_), this->end_, &alg_oid)) != 0) { - throw corrupted("Signer info corrupted"); - } - - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &alg_oid); - LIEF_DEBUG("signerInfo->digestAlgorithm: {}", oid_str); - - signer_info.digest_algorithm_ = oid_str; - // authenticatedAttributes (IMPLICIT OPTIONAL) - // |_ contentType - // |_ messageDigest - // |_ SpcSpOpusInfo - // ----------------------- - - try { - signer_info.authenticated_attributes_ = this->get_authenticated_attributes(); - } - catch (const corrupted& c) { - LIEF_ERR("{}", c.what()); - } - - // digestEncryptionAlgorithm - // ------------------------- - if ((ret = mbedtls_asn1_get_alg_null(&(this->p_), this->end_, &alg_oid)) != 0) { - throw corrupted("Signer info corrupted"); - } - std::memset(oid_str, 0, sizeof(oid_str)); - mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &alg_oid); - signer_info.signature_algorithm_ = oid_str; - - LIEF_DEBUG("digestEncryptionAlgorithm: {}", oid_str); - - // encryptedDigest - // --------------- - if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - throw corrupted("Signer info corrupted"); - } - - signer_info.encrypted_digest_ = {this->p_, this->p_ + tag}; - this->p_ += tag; - - //TODO: - // unauthenticatedAttributes - return signer_info; - + return attributes; } -void SignatureParser::parse_signature(void) { - this->parse_header(); +result> SignatureParser::parse_content_type(VectorStream& stream) { + /* + * + * ContentType ::= OBJECT IDENTIFIER + * Content type as defined in https://tools.ietf.org/html/rfc2315#section-6.8 + */ - // Version - // ======= - int32_t version = this->get_signed_data_version(); - this->signature_.version_ = static_cast(version); - - // Algo (digestAlgorithms) - // ======================= - try { - this->signature_.digest_algorithm_ = this->get_signed_data_digest_algorithms(); + auto oid = stream.asn1_read_oid(); + if (not oid) { + LIEF_INFO("Can't parse content-type.oid (pos: {:d})", stream.pos()); + return oid.error(); } - catch (const corrupted& c) { - LIEF_ERR(c.what()); + const std::string& oid_str = oid.value(); + LIEF_DEBUG("content-type.oid: {}", oid_to_string(oid_str)); + LIEF_DEBUG("content-type remaining bytes: {}", stream.size() - stream.pos()); + return std::unique_ptr{new ContentType{oid_str}}; +} + +result SignatureParser::parse_spc_sp_opus_info(VectorStream& stream) { + // SpcSpOpusInfo ::= SEQUENCE { + // programName [0] EXPLICIT SpcString OPTIONAL, + // moreInfo [1] EXPLICIT SpcLink OPTIONAL + // } + LIEF_DEBUG("Parse spc-sp-opus-info"); + SpcSpOpusInfo info; + auto tag = stream.asn1_read_tag(/* SpcSpOpusInfo ::= SEQUENCE */ + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED); + if (not tag) { + LIEF_INFO("Wrong tag for spc-sp-opus-info SEQUENCE : 0x{:x} (pos: {:d})", + stream_get_tag(stream), this->stream_->pos()); + return tag.error(); } - // contentInfo - // |_ contentType - // |_ content (SpcIndirectDataContent) - // =================================== - try { - this->signature_.content_info_ = this->parse_content_info(); + tag = stream.asn1_read_tag(/* programName [0] EXPLICIT SpcString OPTIONAL */ + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED); + if (tag) { + std::vector raw = {stream.p(), stream.p() + tag.value()}; + VectorStream spc_string_stream(std::move(raw)); + auto program_name = this->parse_spc_string(spc_string_stream); + if (not program_name) { + LIEF_INFO("Fail to parse spc-sp-opus-info.program-name"); + } else { + info.program_name = program_name.value(); + } + stream.increment_pos(spc_string_stream.size()); } - catch (const corrupted& c) { - LIEF_ERR(c.what()); + tag = stream.asn1_read_tag(/* moreInfo [1] EXPLICIT SpcLink OPTIONAL */ + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1); + if (tag) { + std::vector raw = {stream.p(), stream.p() + tag.value()}; + VectorStream spc_link_stream(std::move(raw)); + auto more_info = this->parse_spc_link(spc_link_stream); + if (not more_info) { + LIEF_INFO("Fail to parse spc-sp-opus-info.more-info"); + } else { + info.more_info = more_info.value(); + } + stream.increment_pos(spc_link_stream.size()); + } + return info; +} + +result SignatureParser::parse_ms_counter_sign(VectorStream& stream) { + LIEF_DEBUG("Parsing Ms-CounterSign ({} bytes)", stream.size()); + LIEF_DEBUG("TODO: Ms-CounterSign"); + stream.increment_pos(stream.size()); + return {}; +} + +result SignatureParser::parse_pkcs9_counter_sign(VectorStream& stream) { + // + // counterSignature ATTRIBUTE ::= { + // WITH SYNTAX SignerInfo + // ID pkcs-9-at-counterSignature + // } + LIEF_DEBUG("Parsing pkcs9-CounterSign ({} bytes)", stream.size()); + range_t auth_attr; + auto counter_sig = this->parse_signer_infos(stream, auth_attr); + if (not counter_sig) { + LIEF_INFO("Fail to parse pkcs9-counter-signature"); + return counter_sig.error(); + } + LIEF_DEBUG("pkcs9-counter-signature remaining bytes: {}", stream.size() - stream.pos()); + return counter_sig.value(); +} + +result SignatureParser::parse_ms_spc_nested_signature(VectorStream& stream) { + // SET of pkcs7-signed data + LIEF_DEBUG("Parsing Ms-SpcNestedSignature ({} bytes)", stream.size()); + auto sign = SignatureParser::parse(stream.content(), /* skip header */ false); + if (not sign) { + LIEF_INFO("Ms-SpcNestedSignature finished with errors"); + return sign.error(); + } + LIEF_DEBUG("ms-spc-nested-signature remaining bytes: {}", stream.size() - stream.pos()); + return sign.value(); +} + +result> SignatureParser::parse_pkcs9_message_digest(VectorStream& stream) { + auto digest = stream.asn1_read_octet_string(); + if (not digest) { + LIEF_INFO("Can't process OCTET STREAM for attribute.pkcs9-message-digest (pos: {})", + stream.pos()); + return digest.error(); + } + const std::vector& raw_digest = digest.value(); + LIEF_DEBUG("attribute.pkcs9-message-digest {}", hex_dump(raw_digest)); + LIEF_DEBUG("pkcs9-message-digest remaining bytes: {}", stream.size() - stream.pos()); + return raw_digest; +} + +result SignatureParser::parse_ms_spc_statement_type(VectorStream& stream) { + // SpcStatementType ::= SEQUENCE of OBJECT IDENTIFIER + LIEF_DEBUG("Parsing Ms-SpcStatementType ({} bytes)", stream.size()); + auto tag = stream.asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (not tag) { + LIEF_INFO("Wrong tag for ms-spc-statement-type: 0x{:x} (pos: {:d})", + stream_get_tag(stream), this->stream_->pos()); + return tag.error(); } - // Certificates - // ============ - try { - this->parse_certificates(); + auto oid = stream.asn1_read_oid(); + if (not oid) { + LIEF_INFO("Can't parse ms-spc-statement-type.oid (pos: {:d})", stream.pos()); + return oid.error(); } - catch (const corrupted& c) { - LIEF_ERR(c.what()); + const oid_t& oid_str = oid.value(); + LIEF_DEBUG("ms-spc-statement-type.oid: {}", oid_to_string(oid_str)); + LIEF_DEBUG("ms-spc-statement-type remaining bytes: {}", stream.size() - stream.pos()); + return oid_str; +} + +result SignatureParser::parse_pkcs9_at_sequence_number(VectorStream& stream) { + LIEF_DEBUG("Parsing pkcs9-at-SequenceNumber ({} bytes)", stream.size()); + auto value = stream.asn1_read_int(); + if (not value) { + LIEF_INFO("pkcs9-at-sequence-number: Can't parse integer"); + return value.error(); + } + LIEF_DEBUG("pkcs9-at-sequence-number.int: {}", value.value()); + LIEF_DEBUG("pkcs9-at-sequence-number remaining bytes: {}", stream.size() - stream.pos()); + return value.value(); +} + +result SignatureParser::parse_spc_string(VectorStream& stream) { + // SpcString ::= CHOICE { + // unicode [0] IMPLICIT BMPSTRING, + // ascii [1] IMPLICIT IA5STRING + // } + LIEF_DEBUG("Parse SpcString ({} bytes)", stream.size()); + auto choice = stream.asn1_read_tag(MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0); + if (choice) { + LIEF_DEBUG("SpcString: Unicode choice"); + const size_t length = choice.value(); + LIEF_DEBUG("spc-string.program-name length: {} (pos: {})", length, stream.pos()); + const char* str = stream.read_array(length); + if (str == nullptr) { + LIEF_INFO("Can't read spc-string.program-name"); + return make_error_code(lief_errors::read_error); + } + + std::string u8progname = {str, str + length}; + std::u16string progname; + try { + progname = u8tou16(u8progname); + } catch (const utf8::exception&) { + LIEF_INFO("Error while converting utf-8 spc-string.program-name to utf16"); + return make_error_code(lief_errors::conversion_error); + } + LIEF_DEBUG("spc-string.program-name: {}", u16tou8(progname)); + return u16tou8(progname); + } + else if ((choice = stream.asn1_read_tag(MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1))) { + LIEF_DEBUG("SpcString: ASCII choice"); + const size_t length = choice.value(); + const char* str = stream.read_array(length); + if (str == nullptr) { + LIEF_INFO("Can't read spc-string.program-name"); + return make_error_code(lief_errors::read_error); + } + std::string u8progname{str, str + length}; + LIEF_DEBUG("spc-string.program-name: {}", u8progname); + return u8progname; + } + else { + LIEF_INFO("Can't select choice for SpcString (pos: {})", stream.pos()); + return make_error_code(lief_errors::read_error); } + return {}; +} - // signerInfo - // ========== - try { - this->signature_.signer_info_ = this->get_signer_info(); +result SignatureParser::parse_spc_link(VectorStream& stream) { + // SpcLink ::= CHOICE { + // url [0] IMPLICIT IA5STRING, + // moniker [1] IMPLICIT SpcSerializedObject, + // file [2] EXPLICIT SpcString + // } + LIEF_DEBUG("Parse SpcLink ({} bytes)", stream.size()); + auto choice = stream.asn1_read_tag(/* url */ MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0); + if (choice) { + const size_t length = choice.value(); + const char* str = stream.read_array(length); + if (str == nullptr) { + LIEF_INFO("Can't read spc-link.url"); + return make_error_code(lief_errors::read_error); + } + std::string url{str, str + length}; + LIEF_DEBUG("spc-link.url: {}", url); + return url; } - catch (const corrupted& c) { - LIEF_ERR(c.what()); + else if ((choice = stream.asn1_read_tag(/* moniker */ MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1))) { + LIEF_INFO("Parsing spc-link.moniker is not supported"); + return make_error_code(lief_errors::not_supported); } - //LIEF_DEBUG("Signature: {}" << std::endl << this->signature_; + else if ((choice = stream.asn1_read_tag(/* file */ MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2))) { + LIEF_INFO("Parsing spc-link.file is not supported"); + return make_error_code(lief_errors::not_supported); + } + else { + LIEF_INFO("Corrupted choice for spc-link (choice: 0x{:x})", stream_get_tag(stream)); + return make_error_code(lief_errors::corrupted); + } + return {}; +} + + +result SignatureParser::parse_pkcs9_signing_time(VectorStream& stream) { + // See: https://tools.ietf.org/html/rfc2985#page-20 + // UTCTIME :171116220536Z + auto tm = stream.x509_read_time(); + if (not tm) { + LIEF_INFO("Can't read pkcs9-signing-time (pos: {})", stream.pos()); + return tm.error(); + } + std::unique_ptr time = std::move(tm.value()); + LIEF_INFO("pkcs9-signing-time {}/{}/{}", time->day, time->mon, time->year); + return SignatureParser::time_t{time->year, time->mon, time->day, time->hour, time->min, time->sec}; +} + + +result SignatureParser::parse_spc_pe_image_data(VectorStream& stream) { + // SpcPeImageData ::= SEQUENCE { + // flags SpcPeImageFlags DEFAULT { includeResources }, + // file SpcLink + // } + // + // SpcPeImageFlags ::= BIT STRING { + // includeResources (0), + // includeDebugInfo (1), + // includeImportAddressTable (2) + // } + // + // SpcLink ::= CHOICE { + // url [0] IMPLICIT IA5STRING, + // moniker [1] IMPLICIT SpcSerializedObject, + // file [2] EXPLICIT SpcString + // } + // + // SpcString ::= CHOICE { + // unicode [0] IMPLICIT BMPSTRING, + // ascii [1] IMPLICIT IA5STRING + // } + //LIEF_DEBUG("Parse SpcPeImageData ({} bytes)", stream.size()); + //auto tag = stream.asn1_read_tag(MBEDTLS_ASN1_BIT_STRING); + //if (not tag) { + // LIEF_INFO("Wrong tag for spc-pe-image-data.flags \ + // Expecting BIT-STRING but got 0x{:x} (off: {:d})", stream.peek(), stream.pos()); + // return tag.error(); + //} + //LIEF_DEBUG("Length: {}", tag.value()); + //uint8_t flag = stream.read(); + //LIEF_DEBUG("flag: {:b}", flag); + + //tag = stream.asn1_read_tag(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + //if (not tag) { + // LIEF_INFO("Wrong tag for spc-pe-image-data.flags \ + // Expecting BIT-STRING but got 0x{:x} (off: {:d})", stream.peek(), stream.pos()); + // return tag.error(); + //} + ////LIEF_INFO("spc-pe-image-data.flags length: {:d}", flags.value().size()); + //auto file = this->parse_spc_link(stream); + //if (not file) { + // LIEF_INFO("Can't parse spc-pe-image-data.file (pos: {})", stream.pos()); + // return file.error(); + //} + + return {}; } diff --git a/src/PE/signature/SignerInfo.cpp b/src/PE/signature/SignerInfo.cpp index 0008835..bb22656 100644 --- a/src/PE/signature/SignerInfo.cpp +++ b/src/PE/signature/SignerInfo.cpp @@ -18,80 +18,132 @@ #include #include +#include + +#include "LIEF/PE/signature/x509.hpp" #include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/SignerInfo.hpp" +#include "LIEF/PE/signature/Attribute.hpp" + +#include "LIEF/PE/EnumToString.hpp" namespace LIEF { namespace PE { SignerInfo::SignerInfo(void) = default; -SignerInfo::SignerInfo(const SignerInfo&) = default; -SignerInfo& SignerInfo::operator=(const SignerInfo&) = default; SignerInfo::~SignerInfo(void) = default; +SignerInfo::SignerInfo(SignerInfo&&) = default; +SignerInfo& SignerInfo::operator=(SignerInfo&&) = default; + +SignerInfo::SignerInfo(const SignerInfo& other) : + Object::Object(other), + version_{other.version_}, + issuer_{other.issuer_}, + serialno_{other.serialno_}, + digest_algorithm_{other.digest_algorithm_}, + digest_enc_algorithm_{other.digest_enc_algorithm_}, + encrypted_digest_{other.encrypted_digest_} +{ + for (const std::unique_ptr& attr : other.authenticated_attributes_) { + this->authenticated_attributes_.push_back(attr->clone()); + } + + for (const std::unique_ptr& attr : other.unauthenticated_attributes_) { + this->unauthenticated_attributes_.push_back(attr->clone()); + } + + if (other.cert_ != nullptr) { + this->cert_ = std::unique_ptr(new x509{*other.cert_}); + } +} + +SignerInfo& SignerInfo::operator=(SignerInfo other) { + this->swap(other); + return *this; +} + +void SignerInfo::swap(SignerInfo& other) { + std::swap(this->version_, other.version_); + std::swap(this->issuer_, other.issuer_); + std::swap(this->serialno_, other.serialno_); + std::swap(this->digest_algorithm_, other.digest_algorithm_); + std::swap(this->digest_enc_algorithm_, other.digest_enc_algorithm_); + std::swap(this->encrypted_digest_, other.encrypted_digest_); + std::swap(this->authenticated_attributes_, other.authenticated_attributes_); + std::swap(this->unauthenticated_attributes_, other.unauthenticated_attributes_); + std::swap(this->cert_, other.cert_); +} + uint32_t SignerInfo::version(void) const { return this->version_; } - -const issuer_t& SignerInfo::issuer(void) const { - return this->issuer_; -} - - -const oid_t& SignerInfo::digest_algorithm(void) const { +ALGORITHMS SignerInfo::digest_algorithm(void) const { return this->digest_algorithm_; } - -const AuthenticatedAttributes& SignerInfo::authenticated_attributes(void) const { - return this->authenticated_attributes_; +ALGORITHMS SignerInfo::encryption_algorithm(void) const { + return this->digest_enc_algorithm_; } - -const oid_t& SignerInfo::signature_algorithm(void) const { - return this->signature_algorithm_; -} - - -const std::vector& SignerInfo::encrypted_digest(void) const { +const SignerInfo::encrypted_digest_t& SignerInfo::encrypted_digest(void) const { return this->encrypted_digest_; } +it_const_attributes_t SignerInfo::authenticated_attributes() const { + std::vector attrs(this->authenticated_attributes_.size(), nullptr); + for (size_t i = 0; i < this->authenticated_attributes_.size(); ++i) { + attrs[i] = this->authenticated_attributes_[i].get(); + } + return attrs; +} + +it_const_attributes_t SignerInfo::unauthenticated_attributes() const { + std::vector attrs(this->unauthenticated_attributes_.size(), nullptr); + for (size_t i = 0; i < this->unauthenticated_attributes_.size(); ++i) { + attrs[i] = this->unauthenticated_attributes_[i].get(); + } + return attrs; +} + + +const Attribute* SignerInfo::get_attribute(PE::SIG_ATTRIBUTE_TYPES type) const { + // First look for the attribute in the authenticated ones + auto it_auth = std::find_if(std::begin(this->authenticated_attributes_), std::end(this->authenticated_attributes_), + [type] (const std::unique_ptr& attr) { + return attr->type() == type; + }); + if (it_auth != std::end(this->authenticated_attributes_)) { + return it_auth->get(); + } + + // Then in the UN-authenticated ones + auto it_uauth = std::find_if(std::begin(this->unauthenticated_attributes_), std::end(this->unauthenticated_attributes_), + [type] (const std::unique_ptr& attr) { + return attr->type() == type; + }); + if (it_uauth != std::end(this->unauthenticated_attributes_)) { + return it_uauth->get(); + } + + // ... not found -> return nullptr + return nullptr; +} + void SignerInfo::accept(Visitor& visitor) const { visitor.visit(*this); } std::ostream& operator<<(std::ostream& os, const SignerInfo& signer_info) { - - constexpr uint8_t wsize = 30; - const issuer_t& issuer = signer_info.issuer(); - std::string issuer_str = std::get<0>(issuer); - - const std::vector& sn = std::get<1>(issuer);; - std::string sn_str = std::accumulate( - std::begin(sn), - std::end(sn), - std::string(""), - [] (std::string lhs, uint8_t x) { - std::stringstream ss; - ss << std::setw(2) << std::setfill('0') << std::hex << static_cast(x); - return lhs.empty() ? ss.str() : lhs + ":" + ss.str(); - }); - - - os << std::hex << std::left; - - os << std::setw(wsize) << std::setfill(' ') << "Version: " << signer_info.version() << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Serial Number: " << sn_str << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Issuer DN: " << issuer_str << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Digest Algorithm: " << oid_to_string(signer_info.digest_algorithm()) << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Signature algorithm: " << oid_to_string(signer_info.signature_algorithm()) << std::endl; - - os << signer_info.authenticated_attributes() << std::endl; - + os << fmt::format("{}/{} - {} - {:d} auth attr - {:d} unauth attr", + to_string(signer_info.digest_algorithm()), + to_string(signer_info.encryption_algorithm()), + signer_info.issuer(), + signer_info.authenticated_attributes().size(), + signer_info.unauthenticated_attributes().size()); return os; } diff --git a/src/PE/signature/attributes/CMakeLists.txt b/src/PE/signature/attributes/CMakeLists.txt new file mode 100644 index 0000000..b218104 --- /dev/null +++ b/src/PE/signature/attributes/CMakeLists.txt @@ -0,0 +1,42 @@ +set(LIEF_PE_SIGNATURE_ATTRIBUTES_SRC + "${CMAKE_CURRENT_LIST_DIR}/GenericType.cpp" + "${CMAKE_CURRENT_LIST_DIR}/ContentType.cpp" + + "${CMAKE_CURRENT_LIST_DIR}/SpcSpOpusInfo.cpp" + + "${CMAKE_CURRENT_LIST_DIR}/MsCounterSign.cpp" + "${CMAKE_CURRENT_LIST_DIR}/MsSpcNestedSignature.cpp" + "${CMAKE_CURRENT_LIST_DIR}/MsSpcStatementType.cpp" + + "${CMAKE_CURRENT_LIST_DIR}/PKCS9AtSequenceNumber.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PKCS9CounterSignature.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PKCS9MessageDigest.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PKCS9SigningTime.cpp" +) + +set(LIEF_PE_SIGNATURE_ATTRIBUTES_INCLUDES + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/GenericType.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/ContentType.hpp" + + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp" + + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/MsCounterSign.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/MsSpcStatementType.hpp" + + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/signature/attributes/PKCS9SigningTime.hpp" +) + +source_group("Header Files\\PE\\signature\\attributes" FILES ${LIEF_PE_SIGNATURE_ATTRIBUTES_SRC}) +source_group("Header Files\\PE\\signature\\attributes" FILES ${LIEF_PE_SIGNATURE_ATTRIBUTES_INCLUDES}) + +if (LIEF_PE) + target_sources(LIB_LIEF PRIVATE + ${LIEF_PE_SIGNATURE_ATTRIBUTES_SRC} + ${LIEF_PE_SIGNATURE_ATTRIBUTES_INCLUDES} + ) +endif() + diff --git a/src/PE/signature/attributes/ContentType.cpp b/src/PE/signature/attributes/ContentType.cpp new file mode 100644 index 0000000..8109cbc --- /dev/null +++ b/src/PE/signature/attributes/ContentType.cpp @@ -0,0 +1,36 @@ +#include "LIEF/PE/signature/attributes/ContentType.hpp" +#include "LIEF/PE/signature/OIDToString.hpp" + +namespace LIEF { +namespace PE { + +ContentType::ContentType() : + Attribute(SIG_ATTRIBUTE_TYPES::CONTENT_TYPE) +{} + +ContentType::ContentType(const ContentType&) = default; +ContentType& ContentType::operator=(const ContentType&) = default; + +std::unique_ptr ContentType::clone(void) const { + return std::unique_ptr(new ContentType{*this}); +} + +ContentType::ContentType(oid_t oid) : + Attribute(SIG_ATTRIBUTE_TYPES::CONTENT_TYPE), + oid_{std::move(oid)} +{} + +void ContentType::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string ContentType::print() const { + return this->oid() + " (" + oid_to_string(this->oid()) + ")"; +} + + +ContentType::~ContentType() = default; + + +} +} diff --git a/src/PE/signature/attributes/GenericType.cpp b/src/PE/signature/attributes/GenericType.cpp new file mode 100644 index 0000000..8745e32 --- /dev/null +++ b/src/PE/signature/attributes/GenericType.cpp @@ -0,0 +1,34 @@ +#include "LIEF/PE/signature/attributes/GenericType.hpp" +namespace LIEF { +namespace PE { + +GenericType::GenericType() : + Attribute(SIG_ATTRIBUTE_TYPES::GENERIC_TYPE) +{} + +GenericType::GenericType(const GenericType&) = default; +GenericType& GenericType::operator=(const GenericType&) = default; + +std::unique_ptr GenericType::clone(void) const { + return std::unique_ptr(new GenericType{*this}); +} + +GenericType::GenericType(oid_t oid, std::vector raw) : + Attribute(SIG_ATTRIBUTE_TYPES::GENERIC_TYPE), + oid_{std::move(oid)}, + raw_{std::move(raw)} +{} + +void GenericType::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string GenericType::print() const { + return this->oid() + " (" + std::to_string(this->raw_content().size()) + " bytes)"; +} + + +GenericType::~GenericType() = default; + +} +} diff --git a/src/PE/signature/attributes/MsCounterSign.cpp b/src/PE/signature/attributes/MsCounterSign.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/PE/signature/attributes/MsSpcNestedSignature.cpp b/src/PE/signature/attributes/MsSpcNestedSignature.cpp new file mode 100644 index 0000000..3c3142a --- /dev/null +++ b/src/PE/signature/attributes/MsSpcNestedSignature.cpp @@ -0,0 +1,40 @@ +#include + +#include "LIEF/PE/signature/attributes/MsSpcNestedSignature.hpp" + +namespace LIEF { +namespace PE { + +MsSpcNestedSignature::MsSpcNestedSignature() : + Attribute(SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN) +{} + +MsSpcNestedSignature::MsSpcNestedSignature(const MsSpcNestedSignature&) = default; +MsSpcNestedSignature& MsSpcNestedSignature::operator=(const MsSpcNestedSignature&) = default; + +MsSpcNestedSignature::MsSpcNestedSignature(Signature sig) : + Attribute(SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN), + sig_{std::move(sig)} +{} + +std::unique_ptr MsSpcNestedSignature::clone(void) const { + return std::unique_ptr(new MsSpcNestedSignature{*this}); +} + + +void MsSpcNestedSignature::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string MsSpcNestedSignature::print() const { + std::ostringstream oss; + oss << "Nested signature:\n"; + oss << this->sig(); + return oss.str(); +} + + +MsSpcNestedSignature::~MsSpcNestedSignature() = default; + +} +} diff --git a/src/PE/signature/attributes/MsSpcStatementType.cpp b/src/PE/signature/attributes/MsSpcStatementType.cpp new file mode 100644 index 0000000..1fc3cc0 --- /dev/null +++ b/src/PE/signature/attributes/MsSpcStatementType.cpp @@ -0,0 +1,34 @@ +#include "LIEF/PE/signature/attributes/MsSpcStatementType.hpp" +#include "LIEF/PE/signature/OIDToString.hpp" +namespace LIEF { +namespace PE { + +MsSpcStatementType::MsSpcStatementType() : + Attribute(SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE) +{} + +MsSpcStatementType::MsSpcStatementType(const MsSpcStatementType&) = default; +MsSpcStatementType& MsSpcStatementType::operator=(const MsSpcStatementType&) = default; + +std::unique_ptr MsSpcStatementType::clone(void) const { + return std::unique_ptr(new MsSpcStatementType{*this}); +} + +MsSpcStatementType::MsSpcStatementType(oid_t oid) : + Attribute(SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE), + oid_{std::move(oid)} +{} + +void MsSpcStatementType::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string MsSpcStatementType::print() const { + return this->oid() + " (" + oid_to_string(this->oid()) + ")"; +} + + +MsSpcStatementType::~MsSpcStatementType() = default; + +} +} diff --git a/src/PE/signature/attributes/PKCS9AtSequenceNumber.cpp b/src/PE/signature/attributes/PKCS9AtSequenceNumber.cpp new file mode 100644 index 0000000..132c8cd --- /dev/null +++ b/src/PE/signature/attributes/PKCS9AtSequenceNumber.cpp @@ -0,0 +1,34 @@ +#include "LIEF/PE/signature/attributes/PKCS9AtSequenceNumber.hpp" + +namespace LIEF { +namespace PE { + +PKCS9AtSequenceNumber::PKCS9AtSequenceNumber() : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER) +{} + +PKCS9AtSequenceNumber::PKCS9AtSequenceNumber(const PKCS9AtSequenceNumber&) = default; +PKCS9AtSequenceNumber& PKCS9AtSequenceNumber::operator=(const PKCS9AtSequenceNumber&) = default; + +std::unique_ptr PKCS9AtSequenceNumber::clone(void) const { + return std::unique_ptr(new PKCS9AtSequenceNumber{*this}); +} + +PKCS9AtSequenceNumber::PKCS9AtSequenceNumber(uint32_t num) : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER), + number_{num} +{} + +void PKCS9AtSequenceNumber::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string PKCS9AtSequenceNumber::print() const { + return std::to_string(this->number()); +} + + +PKCS9AtSequenceNumber::~PKCS9AtSequenceNumber() = default; + +} +} diff --git a/src/PE/signature/attributes/PKCS9CounterSignature.cpp b/src/PE/signature/attributes/PKCS9CounterSignature.cpp new file mode 100644 index 0000000..0fc29f2 --- /dev/null +++ b/src/PE/signature/attributes/PKCS9CounterSignature.cpp @@ -0,0 +1,41 @@ +#include "LIEF/PE/signature/attributes/PKCS9CounterSignature.hpp" +#include +namespace LIEF { +namespace PE { + +PKCS9CounterSignature::PKCS9CounterSignature() : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE) +{} + +PKCS9CounterSignature::PKCS9CounterSignature(const PKCS9CounterSignature&) = default; +PKCS9CounterSignature& PKCS9CounterSignature::operator=(const PKCS9CounterSignature&) = default; + +PKCS9CounterSignature::PKCS9CounterSignature(std::vector signers) : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE), + signers_{std::move(signers)} +{} + +std::unique_ptr PKCS9CounterSignature::clone(void) const { + return std::unique_ptr(new PKCS9CounterSignature{*this}); +} + + +void PKCS9CounterSignature::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string PKCS9CounterSignature::print() const { + std::ostringstream oss; + it_const_signers_t signers = this->signers(); + oss << std::to_string(signers.size()) << " signer(s): \n"; + for (const SignerInfo& signer : signers) { + oss << signer << "\n"; + } + return oss.str(); +} + + +PKCS9CounterSignature::~PKCS9CounterSignature() = default; + +} +} diff --git a/src/PE/signature/attributes/PKCS9MessageDigest.cpp b/src/PE/signature/attributes/PKCS9MessageDigest.cpp new file mode 100644 index 0000000..9e8ed44 --- /dev/null +++ b/src/PE/signature/attributes/PKCS9MessageDigest.cpp @@ -0,0 +1,36 @@ +#include "LIEF/PE/signature/attributes/PKCS9MessageDigest.hpp" +#include "LIEF/utils.hpp" + +namespace LIEF { +namespace PE { + +PKCS9MessageDigest::PKCS9MessageDigest() : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST) +{} + +PKCS9MessageDigest::PKCS9MessageDigest(const PKCS9MessageDigest&) = default; +PKCS9MessageDigest& PKCS9MessageDigest::operator=(const PKCS9MessageDigest&) = default; + +PKCS9MessageDigest::PKCS9MessageDigest(std::vector digest) : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_MESSAGE_DIGEST), + digest_{std::move(digest)} +{} + +std::unique_ptr PKCS9MessageDigest::clone(void) const { + return std::unique_ptr(new PKCS9MessageDigest{*this}); +} + + +void PKCS9MessageDigest::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string PKCS9MessageDigest::print() const { + return hex_dump(this->digest()); +} + + +PKCS9MessageDigest::~PKCS9MessageDigest() = default; + +} +} diff --git a/src/PE/signature/attributes/PKCS9SigningTime.cpp b/src/PE/signature/attributes/PKCS9SigningTime.cpp new file mode 100644 index 0000000..b1b42c0 --- /dev/null +++ b/src/PE/signature/attributes/PKCS9SigningTime.cpp @@ -0,0 +1,36 @@ +#include +#include "LIEF/PE/signature/attributes/PKCS9SigningTime.hpp" +namespace LIEF { +namespace PE { + +PKCS9SigningTime::PKCS9SigningTime() : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_SIGNING_TIME) +{} + +PKCS9SigningTime::PKCS9SigningTime(const PKCS9SigningTime&) = default; +PKCS9SigningTime& PKCS9SigningTime::operator=(const PKCS9SigningTime&) = default; + +std::unique_ptr PKCS9SigningTime::clone(void) const { + return std::unique_ptr(new PKCS9SigningTime{*this}); +} + +PKCS9SigningTime::PKCS9SigningTime(time_t time) : + Attribute(SIG_ATTRIBUTE_TYPES::PKCS9_SIGNING_TIME), + time_{std::move(time)} +{} + +void PKCS9SigningTime::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string PKCS9SigningTime::print() const { + const time_t& time = this->time(); + return fmt::format("{}/{}/{} - {}:{}:{}", + time[0], time[1], time[2], time[3], time[4], time[5]); +} + + +PKCS9SigningTime::~PKCS9SigningTime() = default; + +} +} diff --git a/src/PE/signature/attributes/SpcSpOpusInfo.cpp b/src/PE/signature/attributes/SpcSpOpusInfo.cpp new file mode 100644 index 0000000..d7c464a --- /dev/null +++ b/src/PE/signature/attributes/SpcSpOpusInfo.cpp @@ -0,0 +1,44 @@ +#include "LIEF/PE/signature/attributes/SpcSpOpusInfo.hpp" +namespace LIEF { +namespace PE { + +SpcSpOpusInfo::SpcSpOpusInfo() : + Attribute(SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO) +{} + +SpcSpOpusInfo::SpcSpOpusInfo(const SpcSpOpusInfo&) = default; +SpcSpOpusInfo& SpcSpOpusInfo::operator=(const SpcSpOpusInfo&) = default; + +std::unique_ptr SpcSpOpusInfo::clone(void) const { + return std::unique_ptr(new SpcSpOpusInfo{*this}); +} + +SpcSpOpusInfo::SpcSpOpusInfo(std::string program_name, std::string more_info) : + Attribute(SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO), + program_name_{std::move(program_name)}, + more_info_{std::move(more_info)} +{} + +void SpcSpOpusInfo::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +std::string SpcSpOpusInfo::print() const { + std::string out; + if (not this->program_name().empty()) { + out = this->program_name(); + } + if (not this->more_info().empty()) { + if (not out.empty()) { + out += " - "; + } + out += this->more_info(); + } + return out; +} + + +SpcSpOpusInfo::~SpcSpOpusInfo() = default; + +} +} diff --git a/src/PE/signature/x509.cpp b/src/PE/signature/x509.cpp index bf53052..f9aa118 100644 --- a/src/PE/signature/x509.cpp +++ b/src/PE/signature/x509.cpp @@ -17,21 +17,67 @@ #include #include #include +#include +#include #include "mbedtls/x509_crt.h" #include "mbedtls/asn1.h" -#include +#include "mbedtls/oid.h" +#include "mbedtls/error.h" + +#include "logging.hpp" #include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/x509.hpp" +#include "LIEF/PE/signature/RsaInfo.hpp" +#include "LIEF/PE/EnumToString.hpp" namespace LIEF { namespace PE { -x509::x509(void) : - x509_cert_{nullptr} -{} +x509::certificates_t x509::parse(const std::string& path) { + std::ifstream cert_fs(path); + if (not cert_fs) { + LIEF_WARN("Can't open {}", path); + return {}; + } + cert_fs.unsetf(std::ios::skipws); + cert_fs.seekg(0, std::ios::end); + const size_t size = cert_fs.tellg(); + cert_fs.seekg(0, std::ios::beg); + + std::vector raw(size + 1, 0); + cert_fs.read(reinterpret_cast(raw.data()), raw.size()); + return x509::parse(std::move(raw)); +} + +x509::certificates_t x509::parse(const std::vector& content) { + std::unique_ptr ca{new mbedtls_x509_crt{}}; + mbedtls_x509_crt_init(ca.get()); + //LIEF_INFO("{}", reinterpret_cast(content.data())); + int ret = mbedtls_x509_crt_parse(ca.get(), content.data(), content.size()); + if (ret != 0) { + std::string strerr(1024, 0); + mbedtls_strerror(ret, const_cast(strerr.data()), strerr.size()); + LIEF_WARN("Fail to parse certificate blob: '{}'", strerr); + return {}; + } + std::vector crts; + + mbedtls_x509_crt* prev = nullptr; + mbedtls_x509_crt* current = ca.release(); + while (current != nullptr and current != prev) { + mbedtls_x509_crt* next = current->next; + current->next = nullptr; + crts.emplace_back(current); + prev = current; + current = next; + } + return crts; +} + +x509::x509() = default; x509::x509(mbedtls_x509_crt* ca) : x509_cert_{ca} @@ -45,7 +91,6 @@ x509::x509(const x509& other) : mbedtls_x509_crt_parse_der(crt, other.x509_cert_->raw.p, other.x509_cert_->raw.len); this->x509_cert_ = crt; - } x509& x509::operator=(x509 other) { @@ -99,19 +144,162 @@ x509::date_t x509::valid_to(void) const { std::string x509::issuer(void) const { char buffer[1024]; mbedtls_x509_dn_gets(buffer, sizeof(buffer), &this->x509_cert_->issuer); - return {buffer}; + return buffer; } std::string x509::subject(void) const { char buffer[1024]; mbedtls_x509_dn_gets(buffer, sizeof(buffer), &this->x509_cert_->subject); - return {buffer}; + return buffer; } std::vector x509::raw(void) const { return {this->x509_cert_->raw.p, this->x509_cert_->raw.p + this->x509_cert_->raw.len}; } + +x509::KEY_TYPES x509::key_type() const { + static const std::map mtype2asi = { + {MBEDTLS_PK_NONE, KEY_TYPES::NONE }, + {MBEDTLS_PK_RSA, KEY_TYPES::RSA }, + {MBEDTLS_PK_ECKEY, KEY_TYPES::ECKEY }, + {MBEDTLS_PK_ECKEY_DH, KEY_TYPES::ECKEY_DH }, + {MBEDTLS_PK_ECDSA, KEY_TYPES::ECDSA }, + {MBEDTLS_PK_RSA_ALT, KEY_TYPES::RSA_ALT }, + {MBEDTLS_PK_RSASSA_PSS, KEY_TYPES::RSASSA_PSS }, + }; + + mbedtls_pk_context* ctx = &(this->x509_cert_->pk); + mbedtls_pk_type_t type = mbedtls_pk_get_type(ctx); + + auto&& it_key = mtype2asi.find(type); + if (it_key != std::end(mtype2asi)) { + return it_key->second; + } + return KEY_TYPES::NONE; +} + + +std::unique_ptr x509::rsa_info(void) const { + if (this->key_type() == KEY_TYPES::RSA) { + mbedtls_pk_context& ctx = this->x509_cert_->pk; + mbedtls_rsa_context* rsa_ctx = mbedtls_pk_rsa(ctx); + return std::unique_ptr{new RsaInfo{rsa_ctx}}; + } + return nullptr; +} + +bool x509::check_signature(const std::vector& hash, const std::vector& signature, ALGORITHMS algo) const { + static const std::map LIEF2MBED_MD = { + {ALGORITHMS::MD2, MBEDTLS_MD_MD2}, + {ALGORITHMS::MD4, MBEDTLS_MD_MD4}, + {ALGORITHMS::MD5, MBEDTLS_MD_MD5}, + + {ALGORITHMS::SHA_1, MBEDTLS_MD_SHA1}, + {ALGORITHMS::SHA_256, MBEDTLS_MD_SHA256}, + {ALGORITHMS::SHA_384, MBEDTLS_MD_SHA384}, + {ALGORITHMS::SHA_512, MBEDTLS_MD_SHA512}, + }; + + auto it_md = LIEF2MBED_MD.find(algo); + if (it_md == std::end(LIEF2MBED_MD)) { + LIEF_ERR("Can't find algorithm {}", to_string(algo)); + return false; + } + mbedtls_pk_context& ctx = this->x509_cert_->pk; + + int ret = mbedtls_pk_verify(&ctx, + /* MD_HASH_ALGO */ it_md->second, + /* Input Hash */ hash.data(), hash.size(), + /* Signature provided */ signature.data(), signature.size()); + + if (ret != 0) { + std::string strerr(1024, 0); + mbedtls_strerror(ret, const_cast(strerr.data()), strerr.size()); + LIEF_INFO("decrypt() failed with error: '{}'", strerr); + return false; + } + return true; +} + + +x509::VERIFICATION_FLAGS x509::is_trusted_by(const std::vector& ca) const { + std::vector ca_list = ca; // Explicit copy since we will modify mbedtls_x509_crt->next + for (size_t i = 0; i < ca_list.size() - 1; ++i) { + ca_list[i].x509_cert_->next = ca_list[i + 1].x509_cert_; + } + + uint32_t flags = 0; + mbedtls_x509_crt_profile profile = { + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_MD5) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1 /* Min RSA key */, + }; + + int ret = mbedtls_x509_crt_verify_with_profile( + /* crt */ this->x509_cert_, + /* Trusted CA */ ca_list.front().x509_cert_, + /* CA's CRLs */ nullptr, + /* profile */ &profile, + /* Common Name */ nullptr, + /* Verification */ &flags, + /* verification function */ nullptr, + /* verification params */ nullptr); + + if (ret != 0) { + std::string strerr(1024, 0); + mbedtls_strerror(ret, const_cast(strerr.data()), strerr.size()); + std::string out(1024, 0); + mbedtls_x509_crt_verify_info(const_cast(out.data()), out.size(), "", flags); + LIEF_WARN("X509 verify failed with: {} (0x{:x})\n{}", strerr, ret, out); + } + + // Clear the chain since ~x509() will delete each object + for (size_t i = 0; i < ca_list.size(); ++i) { + ca_list[i].x509_cert_->next = nullptr; + } + return static_cast(flags); +} + +x509::VERIFICATION_FLAGS x509::verify(const x509& ca) const { + uint32_t flags = 0; + mbedtls_x509_crt_profile profile = { + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1 /* Min RSA key */, + }; + + int ret = mbedtls_x509_crt_verify_with_profile( + /* crt */ ca.x509_cert_, + /* Trusted CA */ this->x509_cert_, + /* CA's CRLs */ nullptr, + /* profile */ &profile, + /* Common Name */ nullptr, + /* Verification */ &flags, + /* verification function */ nullptr, + /* verification params */ nullptr); + + if (ret != 0) { + std::string strerr(1024, 0); + mbedtls_strerror(ret, const_cast(strerr.data()), strerr.size()); + std::string out(1024, 0); + mbedtls_x509_crt_verify_info(const_cast(out.data()), out.size(), "", flags); + LIEF_WARN("X509 verify failed with: {} (0x{:x})\n{}", strerr, ret, out); + } + return static_cast(flags); +} + void x509::accept(Visitor& visitor) const { visitor.visit(*this); } @@ -122,56 +310,14 @@ x509::~x509(void) { } std::ostream& operator<<(std::ostream& os, const x509& x509_cert) { - - constexpr uint8_t wsize = 30; - const std::vector& sn = x509_cert.serial_number(); - std::string sn_str = std::accumulate( - std::begin(sn), - std::end(sn), - std::string(""), - [] (std::string lhs, uint8_t x) { - std::stringstream ss; - ss << std::setw(2) << std::setfill('0') << std::hex << static_cast(x); - return lhs.empty() ? ss.str() : lhs + ":" + ss.str(); - }); - - const x509::date_t& valid_from = x509_cert.valid_from(); - const x509::date_t& valid_to = x509_cert.valid_to(); - - //// 2018-01-11 20:39:31 - std::string valid_from_str = - std::to_string(valid_from[0]) + "-" + - std::to_string(valid_from[1]) + "-" + - std::to_string(valid_from[2]) + " " + - std::to_string(valid_from[3]) + ":" + - std::to_string(valid_from[4]) + ":" + - std::to_string(valid_from[5]); - - - std::string valid_to_str = - std::to_string(valid_to[0]) + "-" + - std::to_string(valid_to[1]) + "-" + - std::to_string(valid_to[2]) + " " + - std::to_string(valid_to[3]) + ":" + - std::to_string(valid_to[4]) + ":" + - std::to_string(valid_to[5]); - - - os << std::hex << std::left; - os << std::setw(wsize) << std::setfill(' ') << "Version: " << x509_cert.version() << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Serial Number: " << sn_str << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Signature Algorithm: " << oid_to_string(x509_cert.signature_algorithm()) << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Valid from: " << valid_from_str << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Valid to: " << valid_to_str << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Issuer: " << x509_cert.issuer() << std::endl; - os << std::setw(wsize) << std::setfill(' ') << "Subject: " << x509_cert.subject() << std::endl; - - - //os << std::endl << std::endl; - //std::vector buffer(2048, 0); - //mbedtls_x509_crt_info(buffer.data(), buffer.size(), "", x509_cert.x509_cert_); - //std::string foo(buffer.data()); - //os << foo; + std::vector buffer(2048, 0); + int ret = mbedtls_x509_crt_info(buffer.data(), buffer.size(), "", x509_cert.x509_cert_); + if (ret < 0) { + os << "Can't print certificate information\n"; + return os; + } + std::string crt_str(buffer.data()); + os << crt_str; return os; } diff --git a/src/PE/utils.cpp b/src/PE/utils.cpp index 40b1dde..f67d7a0 100644 --- a/src/PE/utils.cpp +++ b/src/PE/utils.cpp @@ -265,6 +265,40 @@ Import resolve_ordinals(const Import& import, bool strict) { return resolved_import; } +ALGORITHMS algo_from_oid(const std::string& oid) { + static const std::unordered_map OID_MAP = { + { "2.16.840.1.101.3.4.2.3", ALGORITHMS::SHA_512 }, + { "2.16.840.1.101.3.4.2.2", ALGORITHMS::SHA_384 }, + { "2.16.840.1.101.3.4.2.1", ALGORITHMS::SHA_256 }, + { "1.3.14.3.2.26", ALGORITHMS::SHA_1 }, + + { "1.2.840.113549.2.5", ALGORITHMS::MD5 }, + { "1.2.840.113549.2.4", ALGORITHMS::MD4 }, + { "1.2.840.113549.2.2", ALGORITHMS::MD2 }, + + { "1.2.840.113549.1.1.1", ALGORITHMS::RSA }, + { "1.2.840.10045.2.1", ALGORITHMS::EC }, + + { "1.2.840.113549.1.1.4", ALGORITHMS::MD5_RSA }, + { "1.2.840.10040.4.3", ALGORITHMS::SHA1_DSA }, + { "1.2.840.113549.1.1.5", ALGORITHMS::SHA1_RSA }, + { "1.2.840.113549.1.1.11", ALGORITHMS::SHA_256_RSA }, + { "1.2.840.113549.1.1.12", ALGORITHMS::SHA_384_RSA }, + { "1.2.840.113549.1.1.13", ALGORITHMS::SHA_512_RSA }, + { "1.2.840.10045.4.1", ALGORITHMS::SHA1_ECDSA }, + { "1.2.840.10045.4.3.2", ALGORITHMS::SHA_256_ECDSA }, + { "1.2.840.10045.4.3.3", ALGORITHMS::SHA_384_ECDSA }, + { "1.2.840.10045.4.3.4", ALGORITHMS::SHA_512_ECDSA }, + }; + + + const auto& it = OID_MAP.find(oid.c_str()); + if (it == std::end(OID_MAP)) { + return ALGORITHMS::UNKNOWN; + } + return it->second; +} + } } diff --git a/src/errors.cpp b/src/errors.cpp new file mode 100644 index 0000000..dde8a43 --- /dev/null +++ b/src/errors.cpp @@ -0,0 +1,32 @@ +#include "LIEF/errors.hpp" + +const std::error_category& lief_error_category() { + struct category: std::error_category { + const char* name() const noexcept override { + return "LIEF"; + } + + std::string message(int code) const override { + switch (lief_errors(code)) { + case lief_errors::read_error: return "read_error"; + case lief_errors::not_found: return "not_found"; + case lief_errors::not_implemented: return "not_implemented"; + case lief_errors::not_supported: return "not_supported"; + case lief_errors::corrupted: return "corrupted"; + case lief_errors::conversion_error: return "conversion_error"; + case lief_errors::read_out_of_bound: return "read_out_of_bound"; + case lief_errors::asn1_bad_tag: return "asn1_bad_tag"; + case lief_errors::file_error: return "file_error"; + default: return "error"; + } + } + }; + + static category c; + return c; +} + + +LIEF::error_t LIEF::return_error(lief_errors e) { + return boost::leaf::new_error(e); +} diff --git a/src/hash_stream.cpp b/src/hash_stream.cpp new file mode 100644 index 0000000..dba151b --- /dev/null +++ b/src/hash_stream.cpp @@ -0,0 +1,138 @@ +/* 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 "logging.hpp" +#include "hash_stream.hpp" +#include "mbedtls/md.h" + +namespace LIEF { + +inline mbedtls_md_context_t* cast(std::unique_ptr& in) { + return reinterpret_cast(in.get()); +} + +hashstream::hashstream(HASH type) : + ctx_{reinterpret_cast(new mbedtls_md_context_t{})} +{ + int ret = 0; + mbedtls_md_init(cast(this->ctx_)); + switch (type) { + case HASH::MD5: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + + case HASH::SHA1: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + + case HASH::SHA224: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + + case HASH::SHA256: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + + case HASH::SHA384: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + + + case HASH::SHA512: + { + const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); + ret = mbedtls_md_setup(cast(this->ctx_), info, 0); + this->output_.resize(mbedtls_md_get_size(info)); + break; + } + } + mbedtls_md_starts(cast(this->ctx_)); +} + +hashstream& hashstream::put(uint8_t c) { + return this->write(&c, 1); +} + +hashstream& hashstream::write(const uint8_t* s, size_t n) { + int ret = mbedtls_md_update(cast(this->ctx_), s, n); + if (ret != 0) { + LIEF_WARN("mbedtls_md_update(0x{}, 0x{:x}) failed with retcode: 0x{:x}", reinterpret_cast(s), n, ret); + } + return *this; +} + +hashstream& hashstream::write(const std::vector& s) { + return this->write(s.data(), s.size()); +} + +hashstream& hashstream::write(const std::string& s) { + return this->write(reinterpret_cast(s.c_str()), s.size() + 1); +} + +hashstream& hashstream::write(size_t count, uint8_t value) { + return this->write(std::vector(count, value)); +} + +hashstream& hashstream::write_sized_int(uint64_t value, size_t size) { + return this->write(reinterpret_cast(&value), size); +} + +hashstream& hashstream::get(std::vector& c) { + this->flush(); + c = this->output_; + return *this; +} + +hashstream& hashstream::flush() { + int ret = mbedtls_md_finish(cast(this->ctx_), this->output_.data()); + if (ret != 0) { + LIEF_WARN("mbedtls_md_finish() failed with retcode: 0x{:x}", ret); + } + return *this; +} + +std::vector& hashstream::raw(void) { + this->flush(); + return this->output_; +} + +hashstream::~hashstream() { + mbedtls_md_free(cast(this->ctx_)); +} + + + +} + diff --git a/src/hash_stream.hpp b/src/hash_stream.hpp new file mode 100644 index 0000000..617d52f --- /dev/null +++ b/src/hash_stream.hpp @@ -0,0 +1,79 @@ +/* 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_HASH_STREAM_H_ +#define LIEF_HASH_STREAM_H_ +#include +#include +#include +#include + +namespace LIEF { +class hashstream { + public: + enum class HASH { + MD5, + SHA1, + SHA224, + SHA256, + SHA384, + SHA512 + }; + hashstream(HASH type); + + hashstream& put(uint8_t c); + hashstream& write(const uint8_t* s, size_t n); + hashstream& write(const std::vector& s); + hashstream& write(const std::string& s); + hashstream& write(size_t count, uint8_t value); + hashstream& write_sized_int(uint64_t value, size_t size); + + template + hashstream& write_conv(const T& t); + + template + hashstream& write_conv_array(const std::vector& v); + + hashstream& align(size_t size, uint8_t val = 0); + + template::value>> + hashstream& write(Integer integer) { + auto int_p = reinterpret_cast(&integer); + return this->write(int_p, sizeof(Integer)); + } + + template::value>> + hashstream& write(const std::array& t) { + for (T val : t) { + this->write(val); + } + return *this; + } + + hashstream& get(std::vector& c); + hashstream& flush(); + + std::vector& raw(void); + ~hashstream(); + + private: + std::vector output_; + using md_context_t = intptr_t; + std::unique_ptr ctx_; +}; + + +} +#endif diff --git a/src/iostream.cpp b/src/iostream.cpp index eb71007..25595ea 100644 --- a/src/iostream.cpp +++ b/src/iostream.cpp @@ -80,6 +80,11 @@ vector_iostream& vector_iostream::write(const std::vector& s) { return *this; } +vector_iostream& vector_iostream::write_sized_int(uint64_t value, size_t size) { + const uint64_t stack_val = value; + return this->write(reinterpret_cast(&stack_val), size); +} + vector_iostream& vector_iostream::write(std::vector&& s) { if (this->raw_.size() < (static_cast(this->tellp()) + s.size())) { @@ -111,15 +116,15 @@ vector_iostream& vector_iostream::write(const std::string& s) { vector_iostream& vector_iostream::write_uleb128(uint64_t value) { uint8_t byte; - do { + do { byte = value & 0x7F; - value &= ~0x7F; - if (value != 0) { - byte |= 0x80; + value &= ~0x7F; + if (value != 0) { + byte |= 0x80; } this->write(byte); - value = value >> 7; - } while (byte >= 0x80); + value = value >> 7; + } while (byte >= 0x80); return *this; } @@ -127,22 +132,22 @@ vector_iostream& vector_iostream::write_uleb128(uint64_t value) { vector_iostream& vector_iostream::write_sleb128(int64_t value) { bool is_neg = (value < 0); - uint8_t byte; - bool more; - do { - byte = value & 0x7F; - value = value >> 7; + uint8_t byte; + bool more; + do { + byte = value & 0x7F; + value = value >> 7; if (is_neg) { - more = ((value != -1) || ((byte & 0x40) == 0)); + more = ((value != -1) || ((byte & 0x40) == 0)); } else { - more = ((value != 0) || ((byte & 0x40) != 0)); + more = ((value != 0) || ((byte & 0x40) != 0)); } - if (more) { - byte |= 0x80; + if (more) { + byte |= 0x80; } this->write(byte); - } while (more); + } while (more); return *this; } @@ -263,6 +268,7 @@ vector_iostream& vector_iostream::write(size_t count, uint8_t value) { /* count */ count, /* value */ value ); + this->current_pos_ += count; return *this; } diff --git a/src/utils.cpp b/src/utils.cpp index ff1c618..5e52a82 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include "LIEF/utils.hpp" #include "utf8.h" @@ -85,6 +87,16 @@ std::string hex_str(uint8_t c) { return ss.str(); } +std::string hex_dump(const std::vector& data, std::string sep) { + + std::string hexstring = std::accumulate(std::begin(data), std::end(data), std::string{}, + [sep] (const std::string& a, uint8_t b) { + return a.empty() ? fmt::format("{:02x}", b) : a + sep + fmt::format("{:02x}", b); + }); + + return hexstring; +} + bool is_printable(const std::string& str) { return std::all_of(std::begin(str), std::end(str), diff --git a/tests/pe/CMakeLists.txt b/tests/pe/CMakeLists.txt index 5204cc7..23f0fe2 100644 --- a/tests/pe/CMakeLists.txt +++ b/tests/pe/CMakeLists.txt @@ -36,7 +36,7 @@ if (LIEF_EXAMPLES) endif() # Python tests -# ============ +# ============ if (PYTHON_TESTS_ENABLED) ADD_PYTHON_TEST(EXAMPLE_PYTHON_pe_reader_kernel32 @@ -72,6 +72,10 @@ if (PYTHON_TESTS_ENABLED) ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test_forward_information.py") + ADD_PYTHON_TEST(PE_PYTHON_authenticode + ${PYTHON_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/test_authenticode.py") + endif() diff --git a/tests/pe/test_authenticode.py b/tests/pe/test_authenticode.py new file mode 100644 index 0000000..0245547 --- /dev/null +++ b/tests/pe/test_authenticode.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +import itertools +import logging +import os +import random +import stat +import json +import subprocess +import sys +import tempfile +import unittest +from unittest import TestCase + +import lief +from utils import get_sample + +lief.logging.set_level(lief.logging.LOGGING_LEVEL.INFO) + +def from_hex(x): + return bytes.fromhex(x.replace(":", "")) + +class TestAuthenticode(TestCase): + + def setUp(self): + self.logger = logging.getLogger(__name__) + + def test_api(self): + avast = lief.PE.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online.exe")) + + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.MD5), from_hex("1c:a0:91:53:dc:9a:3a:5f:34:1d:7f:9b:b9:56:69:4d")) + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.MD5), avast.authentihash_md5) + + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_1), from_hex("1e:ad:dc:29:1e:db:41:a2:69:c2:ba:ae:4b:fb:9d:31:e7:bb:ab:59")) + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_1), avast.authentihash_sha1) + + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_256), from_hex("a7:38:da:44:46:a4:e7:8a:b6:47:db:7e:53:42:7e:b0:79:61:c9:94:31:7f:4c:59:d7:ed:be:a5:cc:78:6d:80")) + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_256), avast.authentihash_sha256) + + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_512), from_hex("2a:e7:4c:81:0d:65:7b:6a:49:48:94:ab:b9:7d:fa:03:18:5d:48:cf:cd:4e:c2:99:f6:49:5f:db:30:64:78:03:f6:60:90:ab:04:84:01:36:7e:b0:6e:f6:29:b1:d1:a8:49:51:c3:4e:b3:75:89:c9:74:62:a2:2e:d2:ac:6e:96")) + self.assertEqual(avast.authentihash(lief.PE.ALGORITHMS.SHA_512), avast.authentihash_sha512) + + self.assertEqual(len(avast.signatures), 1) + sig = avast.signatures[0] + + self.assertEqual(sig.version, 1) + self.assertEqual(sig.digest_algorithm, lief.PE.ALGORITHMS.SHA_256) + + # Verify ContentInfo + content_info = sig.content_info + + self.assertEqual(content_info.content_type, "1.3.6.1.4.1.311.2.1.4") + self.assertEqual(content_info.digest_algorithm, lief.PE.ALGORITHMS.SHA_256) + self.assertEqual(content_info.digest, from_hex("a7:38:da:44:46:a4:e7:8a:b6:47:db:7e:53:42:7e:b0:79:61:c9:94:31:7f:4c:59:d7:ed:be:a5:cc:78:6d:80")) + + # Verify embedded certificates + certs = sig.certificates + self.assertEqual(len(certs), 2) + cert_ca, cert_signer = certs + + self.assertEqual(cert_ca.version, 3) + self.assertEqual(cert_ca.serial_number, from_hex("04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08")) + self.assertEqual(cert_ca.signature_algorithm, "1.2.840.113549.1.1.11") + self.assertEqual(cert_ca.valid_from, [2013, 10, 22, 12, 0, 0]) + self.assertEqual(cert_ca.valid_to, [2028, 10, 22, 12, 0, 0]) + self.assertEqual(cert_ca.issuer, "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA") + self.assertEqual(cert_ca.subject, "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 Assured ID Code Signing CA") + + self.assertEqual(cert_signer.version, 3) + self.assertEqual(cert_signer.serial_number, from_hex("09:70:EF:4B:AD:5C:C4:4A:1C:2B:C3:D9:64:01:67:4C")) + self.assertEqual(cert_signer.signature_algorithm, "1.2.840.113549.1.1.11") + self.assertEqual(cert_signer.valid_from, [2020, 4, 2, 0, 0, 0]) + self.assertEqual(cert_signer.valid_to, [2023, 3, 9, 12, 0, 0]) + self.assertEqual(cert_signer.issuer, "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 Assured ID Code Signing CA") + self.assertEqual(cert_signer.subject, "C=CZ, L=Praha, O=Avast Software s.r.o., OU=RE stapler cistodc, CN=Avast Software s.r.o.") + + self.assertEqual(cert_ca.verify(cert_signer), lief.PE.x509.VERIFICATION_FLAGS.OK) + self.assertEqual(cert_ca.verify(cert_ca), lief.PE.x509.VERIFICATION_FLAGS.BADCERT_NOT_TRUSTED) + self.assertEqual(cert_signer.is_trusted_by([cert_ca]), lief.PE.x509.VERIFICATION_FLAGS.OK) + + ca_bundles = lief.PE.x509.parse(get_sample("pkcs7/windows-ca-bundle.pem")) + self.assertEqual(cert_ca.is_trusted_by(ca_bundles), lief.PE.x509.VERIFICATION_FLAGS.OK) + + # Verify signer(s) + self.assertEqual(len(sig.signers), 1) + signer = sig.signers[0] + + self.assertEqual(signer.version, 1) + self.assertEqual(signer.serial_number, from_hex("09:70:ef:4b:ad:5c:c4:4a:1c:2b:c3:d9:64:01:67:4c")) + self.assertEqual(signer.issuer, "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 Assured ID Code Signing CA") + self.assertEqual(signer.digest_algorithm, lief.PE.ALGORITHMS.SHA_256) + self.assertEqual(signer.encryption_algorithm, lief.PE.ALGORITHMS.RSA) + self.assertEqual(signer.encrypted_digest.hex(":")[:23], "75:8d:b1:f4:80:eb:25:ba") + self.assertEqual(hash(signer.cert), hash(cert_signer)) + + # Check authenticated attributes + auth_attrs = signer.authenticated_attributes + self.assertEqual(len(auth_attrs), 4) + + content_type = auth_attrs[0] + self.assertEqual(content_type.oid, "1.3.6.1.4.1.311.2.1.4") + + ms_spc_statement_type = auth_attrs[1] + self.assertEqual(ms_spc_statement_type.oid, "1.3.6.1.4.1.311.2.1.21") + + spc_spopus_info = auth_attrs[2] + self.assertEqual(spc_spopus_info.program_name, "") + self.assertEqual(spc_spopus_info.more_info, "http://www.avast.com") + + pkcs9_message_digest = auth_attrs[3] + self.assertEqual(pkcs9_message_digest.digest, from_hex("39:83:81:6a:7d:1c:62:96:25:40:ec:66:fa:87:90:fa:45:d1:06:3c:b2:3e:93:36:77:de:45:9f:0b:73:c5:77")) + + # Check un-authenticated attributes + unauth_attrs = signer.unauthenticated_attributes + self.assertEqual(len(unauth_attrs), 1) + + ms_counter_sig = unauth_attrs[0] + # TODO(romain): Currently we do not support the (undocumented) Ms-CounterSignature attribute + # Therefore it is wrapped through lief.PE.GenericType. The first assert should fail when + # it will be implemented + self.assertTrue(isinstance(ms_counter_sig, lief.PE.GenericType)) + self.assertEqual(ms_counter_sig.oid, "1.3.6.1.4.1.311.3.3.1") + + self.assertEqual(avast.verify_signature(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + # Verify the signature through a fake-detached signature + pkcs7_sig = lief.PE.Signature.parse(list(sig.raw_der)) + self.assertEqual(avast.verify_signature(pkcs7_sig), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + + def test_json_serialization(self): + avast = lief.PE.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online.exe")) + with open(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online-signature.json"), "rb") as f: + json_sig = json.load(f) + self.assertEqual(json.loads(lief.to_json(avast.signatures[0])), json_sig) + + + def test_fail(self): + # Check bad-signed PE files + + avast_altered = lief.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online-altered-dos-stub.exe")) + self.assertNotEqual(avast_altered.verify_signature(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + self.assertEqual(avast_altered.signatures[0].check(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + avast_altered = lief.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online-altered-encrypted-digest.exe")) + self.assertNotEqual(avast_altered.verify_signature(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + self.assertNotEqual(avast_altered.signatures[0].check(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + avast_altered = lief.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online-altered-content-info-digest.exe")) + self.assertNotEqual(avast_altered.verify_signature(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + self.assertNotEqual(avast_altered.signatures[0].check(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + avast_altered = lief.parse(get_sample("PE/PE32_x86-64_binary_avast-free-antivirus-setup-online-altered-pkcs9-msg-digest.exe")) + self.assertNotEqual(avast_altered.verify_signature(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + self.assertNotEqual(avast_altered.signatures[0].check(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + + def test_pkcs9_signing_time(self): + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert0.p7b")) + attr = sig.signers[0].get_attribute(lief.PE.SIG_ATTRIBUTE_TYPES.PKCS9_SIGNING_TIME) + self.assertEqual(attr.time, [2018, 8, 2, 15, 0, 12]) + + def test_pkcs9_at_sequence_number(self): + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert10.p7b")) + + def test_spc_sp_opuse_info(self): + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert10.p7b")) + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert11.p7b")) + + def test_pkcs9_counter_signature(self): + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert10.p7b")) + + def test_ms_spc_nested_signature(self): + sig = lief.PE.Signature.parse(get_sample("pkcs7/cert0.p7b")) + attr = sig.signers[0].get_attribute(lief.PE.SIG_ATTRIBUTE_TYPES.MS_SPC_NESTED_SIGN) + nested_sig = attr.signature + print(nested_sig) + + self.assertEqual(nested_sig.version, 1) + self.assertEqual(nested_sig.digest_algorithm, lief.PE.ALGORITHMS.SHA_256) + + content_info = nested_sig.content_info + + self.assertEqual(content_info.content_type, "1.3.6.1.4.1.311.2.1.4") + self.assertEqual(content_info.digest_algorithm, lief.PE.ALGORITHMS.SHA_256) + self.assertEqual(content_info.digest, from_hex("90:a4:df:36:26:df:d9:8d:6b:3b:1d:42:74:5b:94:54:c5:e2:30:2e:d2:f8:23:70:16:3f:1e:e6:dd:7d:8c:91")) + + certs = nested_sig.certificates + self.assertEqual(len(certs), 3) + nvidia_cert, self_signed_ca, signer_cert = certs + + self.assertEqual(nvidia_cert.issuer, "C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 SHA256 Code Signing CA - G2") + self.assertEqual(nvidia_cert.subject, "C=US, ST=California, L=Santa Clara, O=NVIDIA Corporation, OU=IT-MIS, CN=NVIDIA Corporation") + self.assertEqual(nvidia_cert.serial_number, from_hex("62:E7:45:E9:21:65:21:3C:97:1F:5C:49:0A:EA:12:A5")) + + self.assertEqual(self_signed_ca.issuer, "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, Inc. - For authorized use only, CN=VeriSign Universal Root Certification Authority") + self.assertEqual(self_signed_ca.subject, "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, Inc. - For authorized use only, CN=VeriSign Universal Root Certification Authority") + self.assertEqual(self_signed_ca.serial_number, from_hex("40:1A:C4:64:21:B3:13:21:03:0E:BB:E4:12:1A:C5:1D")) + + self.assertEqual(signer_cert.issuer, "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, Inc. - For authorized use only, CN=VeriSign Universal Root Certification Authority") + self.assertEqual(signer_cert.subject, "C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 SHA256 Code Signing CA - G2") + self.assertEqual(signer_cert.serial_number, from_hex("7C:1B:35:35:4A:E7:DB:74:E7:41:5F:11:69:CA:6B:A8")) + + # Check self-signed + self.assertEqual(self_signed_ca.verify(self_signed_ca), lief.PE.x509.VERIFICATION_FLAGS.OK) + + self.assertEqual(signer_cert.is_trusted_by([self_signed_ca]), lief.PE.x509.VERIFICATION_FLAGS.OK) + self.assertEqual(self_signed_ca.verify(signer_cert), lief.PE.x509.VERIFICATION_FLAGS.OK) + self.assertEqual(signer_cert.verify(nvidia_cert), lief.PE.x509.VERIFICATION_FLAGS.OK) + + ca_bundles = lief.PE.x509.parse(get_sample("pkcs7/windows-ca-bundle.pem")) + self.assertEqual(self_signed_ca.is_trusted_by(ca_bundles), lief.PE.x509.VERIFICATION_FLAGS.OK) + self.assertEqual(nvidia_cert.is_trusted_by(ca_bundles), lief.PE.x509.VERIFICATION_FLAGS.BADCERT_NOT_TRUSTED) + + self.assertEqual(nested_sig.check(), lief.PE.Signature.VERIFICATION_FLAGS.OK) + + signer = nested_sig.signers[0] + + def test_self_signed(self): + selfsigned = lief.parse(get_sample("PE/PE32_x86-64_binary_self-signed.exe")) + sig = selfsigned.signatures[0] + ca_bundles = lief.PE.x509.parse(get_sample("pkcs7/windows-ca-bundle.pem")) + cert_ca, cert_signer = sig.certificates + self.assertEqual(cert_ca.verify(cert_signer), lief.PE.x509.VERIFICATION_FLAGS.OK) + self.assertEqual(cert_ca.is_trusted_by(ca_bundles), lief.PE.x509.VERIFICATION_FLAGS.BADCERT_NOT_TRUSTED) + +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) diff --git a/third-party/LibFuzzer-6f13445.zip b/third-party/LibFuzzer-6f13445.zip new file mode 100644 index 0000000..3a59ad4 Binary files /dev/null and b/third-party/LibFuzzer-6f13445.zip differ diff --git a/third-party/LibFuzzer-8ff5640b48c4c4a3b974daa10a5f445e86ed7428.zip b/third-party/LibFuzzer-8ff5640b48c4c4a3b974daa10a5f445e86ed7428.zip deleted file mode 100644 index 36ed4a4..0000000 Binary files a/third-party/LibFuzzer-8ff5640b48c4c4a3b974daa10a5f445e86ed7428.zip and /dev/null differ diff --git a/third-party/json-3.1.1.zip b/third-party/json-3.1.1.zip deleted file mode 100644 index 63610bf..0000000 Binary files a/third-party/json-3.1.1.zip and /dev/null differ diff --git a/third-party/json-3.7.3.zip b/third-party/json-3.7.3.zip deleted file mode 100644 index d8f76cb..0000000 Binary files a/third-party/json-3.7.3.zip and /dev/null differ diff --git a/third-party/json-3.9.1.zip b/third-party/json-3.9.1.zip new file mode 100644 index 0000000..3e64ea1 Binary files /dev/null and b/third-party/json-3.9.1.zip differ diff --git a/third-party/leaf-0.3.0.zip b/third-party/leaf-0.3.0.zip new file mode 100644 index 0000000..ead01db Binary files /dev/null and b/third-party/leaf-0.3.0.zip differ diff --git a/third-party/mbedtls-2.23.0.zip b/third-party/mbedtls-2.23.0.zip deleted file mode 100644 index 56e1c04..0000000 Binary files a/third-party/mbedtls-2.23.0.zip and /dev/null differ diff --git a/third-party/mbedtls-2.7.17.zip b/third-party/mbedtls-2.7.17.zip new file mode 100644 index 0000000..e51de06 Binary files /dev/null and b/third-party/mbedtls-2.7.17.zip differ