Enhance PE Authenticode

This commit is contained in:
rthomas 2021-01-05 19:26:10 +01:00 committed by Romain Thomas
parent 5b587ea88f
commit 634c2fc98e
124 changed files with 7692 additions and 2643 deletions

24
.github/deploy.py vendored
View File

@ -105,7 +105,7 @@ else:
CI_PRETTY_NAME = pretty_ci_name(CURRENT_CI) CI_PRETTY_NAME = pretty_ci_name(CURRENT_CI)
logger.info("CI: %s", CI_PRETTY_NAME) 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) BRANCH_NAME = get_branch(CURRENT_CI)
logger.info("Branch: %s", BRANCH_NAME) logger.info("Branch: %s", BRANCH_NAME)
if BRANCH_NAME not in ALLOWED_BRANCHES: if BRANCH_NAME not in ALLOWED_BRANCHES:
@ -175,13 +175,29 @@ if DEPLOY_IV is None:
# Clone package repo # Clone package repo
##################### #####################
target_branch = "gh-pages" if BRANCH_NAME == "master" else "packages-{}".format(BRANCH_NAME) target_branch = "gh-pages" if BRANCH_NAME == "master" else "packages-{}".format(BRANCH_NAME)
new_branch = False
if not LIEF_PACKAGE_DIR.is_dir(): if not LIEF_PACKAGE_DIR.is_dir():
cmd = "{} clone --branch={} -j8 --single-branch {} {}".format(GIT, target_branch, LIEF_PACKAGE_REPO, LIEF_PACKAGE_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 = subprocess.Popen(cmd, shell=True, cwd=REPODIR, stderr=subprocess.STDOUT)
p.wait() p.wait()
if p.returncode: 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) SDK_PACKAGE_DIR.mkdir(exist_ok=True)
PYPI_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: with open((SDK_PACKAGE_DIR / "index.html").as_posix(), "w") as f:
f.write(html) f.write(html)
if not SSH_DIR.is_dir(): if not SSH_DIR.is_dir():
SSH_DIR.mkdir(mode=0o700) SSH_DIR.mkdir(mode=0o700)

View File

@ -106,6 +106,8 @@ set(LIBLIEF_SOURCE_FILES
"${mbedtls_src_x509}" "${mbedtls_src_x509}"
"${mbedtls_src_tls}" "${mbedtls_src_tls}"
"${LIBFUZZER_SRC_FILES}" "${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/logging.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/exception.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/exception.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/iostream.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/iostream.cpp"
@ -121,6 +123,7 @@ set(LIBLIEF_SOURCE_FILES
# Grouping basic headers together # Grouping basic headers together
# =============================== # ===============================
set(LIEF_INC_FILES 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/ELF.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/Abstract.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/Abstract.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/exception.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/BinaryStream.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/VectorStream.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/VectorStream.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/Convert.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") "${CMAKE_CURRENT_SOURCE_DIR}/src/frozen.hpp")
set(LIEF_VISITOR_INCLUDE_FILES 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/") "${CMAKE_CURRENT_BINARY_DIR}/include/")
list(APPEND LIEF_PRIVATE_INCLUDE_DIR "${LIEF_PUBLIC_INCLUDE_DIR}" list(APPEND LIEF_PRIVATE_INCLUDE_DIR "${LIEF_PUBLIC_INCLUDE_DIR}"
"${LIBRANG_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_BINARY_DIR}")
"${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) @ONLY)
# Grouping external projects # Grouping external projects
@ -322,6 +325,15 @@ if(LIEF_FROZEN_ENABLED)
add_dependencies(LIB_LIEF lief_frozen) add_dependencies(LIB_LIEF lief_frozen)
endif() 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) add_dependencies(LIB_LIEF lief_spdlog lief_mbed_tls)
# Flags definition # 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 # SpcSpAgencyInfo Critical Extension, which mbed TLS doesn't support, so set
# MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this # MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION to have it skip this
# extension. # 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) -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
# ASAN - LSAN - TSAN - USAN # ASAN - LSAN - TSAN - USAN
@ -496,6 +509,7 @@ endif()
# Tests # Tests
# ====================== # ======================
if(LIEF_TESTS) if(LIEF_TESTS)
enable_testing() enable_testing()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests")
@ -584,7 +598,7 @@ install(
COMPONENT config) COMPONENT config)
install( install(
FILES ${PROJECT_BINARY_DIR}/LIEF.pc FILES ${CMAKE_BINARY_DIR}/LIEF.pc
DESTINATION lib/pkgconfig DESTINATION lib/pkgconfig
COMPONENT libraries) COMPONENT libraries)

View File

@ -181,8 +181,8 @@ void create<Binary>(py::module& m) {
.def("xref", .def("xref",
&Binary::xref, &Binary::xref,
"Return all **virtual address** that *use* the ``address`` given in parameter" "Return all **virtual addresses** that *use* the ``address`` given in parameter",
"virtual_address"_a) "virtual_address"_a)
.def("__str__", .def("__str__",
[] (const Binary& binary) [] (const Binary& binary)

View File

@ -16,12 +16,6 @@ set(LIEF_PYTHON_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/resources/pyResourceStringTable.cpp" "${CMAKE_CURRENT_LIST_DIR}/objects/resources/pyResourceStringTable.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/resources/pyResourceAccelerator.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/pyCodeIntegrity.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDataDirectory.cpp" "${CMAKE_CURRENT_LIST_DIR}/objects/pyDataDirectory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDosHeader.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/LoadConfigurations/CMakeLists.txt")
include("${CMAKE_CURRENT_LIST_DIR}/objects/signature/CMakeLists.txt")

View File

@ -132,8 +132,8 @@ void create<Binary>(py::module& m) {
.def_property_readonly("has_configuration", &Binary::has_configuration, .def_property_readonly("has_configuration", &Binary::has_configuration,
"``True`` if the current binary has " RST_CLASS_REF(lief.PE.LoadConfiguration) "") "``True`` if the current binary has " RST_CLASS_REF(lief.PE.LoadConfiguration) "")
.def_property_readonly("has_signature", &Binary::has_signature, .def_property_readonly("has_signatures", &Binary::has_signatures,
"``True`` if the binary is signed (" RST_CLASS_REF(lief.PE.Signature) ")") "``True`` if the binary has signatures (" RST_CLASS_REF(lief.PE.Signature) ")")
.def_property_readonly("is_reproducible_build", &Binary::is_reproducible_build, .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) ")") "``True`` if the binary was compiled with a reproducible build directive (" RST_CLASS_REF(lief.PE.Debug) ")")
@ -151,11 +151,69 @@ void create<Binary>(py::module& m) {
"Try to predict the RVA of the given function name in the given import library name", "Try to predict the RVA of the given function name in the given import library name",
"library"_a, "function"_a) "library"_a, "function"_a)
.def_property_readonly("signature", .def_property_readonly("signatures",
static_cast<const Signature& (Binary::*)(void) const>(&Binary::signature), static_cast<it_const_signatures (Binary::*)(void) const>(&Binary::signatures),
"Return the " RST_CLASS_REF(lief.PE.Signature) " object", "Return an iterator over the " RST_CLASS_REF(lief.PE.Signature) " objects",
py::return_value_policy::reference) py::return_value_policy::reference)
.def("authentihash",
[] (const Binary& bin, ALGORITHMS algo) {
const std::vector<uint8_t>& data = bin.authentihash(algo);
return py::bytes(reinterpret_cast<const char*>(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<Signature::VERIFICATION_FLAGS(Binary::*)() const>(&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<Signature::VERIFICATION_FLAGS(Binary::*)(const Signature&) const>(&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<uint8_t>& data = bin.authentihash(ALGORITHMS::MD5);
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"Authentihash **MD5** value")
.def_property_readonly("authentihash_sha1",
[] (const Binary& bin) {
const std::vector<uint8_t>& data = bin.authentihash(ALGORITHMS::SHA_1);
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"Authentihash **SHA1** value")
.def_property_readonly("authentihash_sha256",
[] (const Binary& bin) {
const std::vector<uint8_t>& data = bin.authentihash(ALGORITHMS::SHA_256);
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"Authentihash **SHA-256** value")
.def_property_readonly("authentihash_sha512",
[] (const Binary& bin) {
const std::vector<uint8_t>& data = bin.authentihash(ALGORITHMS::SHA_512);
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"Authentihash **SHA-512** value")
.def_property_readonly("debug", .def_property_readonly("debug",
static_cast<debug_entries_t& (Binary::*)(void)>(&Binary::debug), static_cast<debug_entries_t& (Binary::*)(void)>(&Binary::debug),
"Return the " RST_CLASS_REF(lief.PE.Debug) "", "Return the " RST_CLASS_REF(lief.PE.Debug) "",

View File

@ -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")

View File

@ -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})

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (ContentType::*)(void) const;
template<class T>
using setter_t = void (ContentType::*)(T);
template<>
void create<ContentType>(py::module& m) {
py::class_<ContentType, Attribute>(m, "ContentType")
.def_property_readonly("oid",
&ContentType::oid)
.def("__hash__",
[] (const ContentType& obj) {
return Hash::hash(obj);
})
.def("__str__", &ContentType::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (GenericType::*)(void) const;
template<class T>
using setter_t = void (GenericType::*)(T);
template<>
void create<GenericType>(py::module& m) {
py::class_<GenericType, Attribute>(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);
}
}
}

View File

@ -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 <string>
#include <sstream>
#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 {
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (MsSpcNestedSignature::*)(void) const;
template<class T>
using setter_t = void (MsSpcNestedSignature::*)(T);
template<>
void create<MsSpcNestedSignature>(py::module& m) {
py::class_<MsSpcNestedSignature, Attribute>(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);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (MsSpcStatementType::*)(void) const;
template<class T>
using setter_t = void (MsSpcStatementType::*)(T);
template<>
void create<MsSpcStatementType>(py::module& m) {
py::class_<MsSpcStatementType, Attribute>(m, "MsSpcStatementType")
.def_property_readonly("oid",
&MsSpcStatementType::oid)
.def("__hash__",
[] (const MsSpcStatementType& obj) {
return Hash::hash(obj);
})
.def("__str__", &MsSpcStatementType::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (PKCS9AtSequenceNumber::*)(void) const;
template<class T>
using setter_t = void (PKCS9AtSequenceNumber::*)(T);
template<>
void create<PKCS9AtSequenceNumber>(py::module& m) {
py::class_<PKCS9AtSequenceNumber, Attribute>(m, "PKCS9AtSequenceNumber")
.def_property_readonly("number",
&PKCS9AtSequenceNumber::number)
.def("__hash__",
[] (const PKCS9AtSequenceNumber& obj) {
return Hash::hash(obj);
})
.def("__str__", &PKCS9AtSequenceNumber::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (PKCS9CounterSignature::*)(void) const;
template<class T>
using setter_t = void (PKCS9CounterSignature::*)(T);
template<>
void create<PKCS9CounterSignature>(py::module& m) {
py::class_<PKCS9CounterSignature, Attribute>(m, "PKCS9CounterSignature")
.def_property_readonly("signers",
&PKCS9CounterSignature::signers)
.def("__hash__",
[] (const PKCS9CounterSignature& obj) {
return Hash::hash(obj);
})
.def("__str__", &PKCS9CounterSignature::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (PKCS9MessageDigest::*)(void) const;
template<class T>
using setter_t = void (PKCS9MessageDigest::*)(T);
template<>
void create<PKCS9MessageDigest>(py::module& m) {
py::class_<PKCS9MessageDigest, Attribute>(m, "PKCS9MessageDigest")
.def_property_readonly("digest",
[] (const PKCS9MessageDigest& digest) -> py::object {
const std::vector<uint8_t>& data = digest.digest();
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
})
.def("__hash__",
[] (const PKCS9MessageDigest& obj) {
return Hash::hash(obj);
})
.def("__str__", &PKCS9MessageDigest::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (PKCS9SigningTime::*)(void) const;
template<class T>
using setter_t = void (PKCS9SigningTime::*)(T);
template<>
void create<PKCS9SigningTime>(py::module& m) {
py::class_<PKCS9SigningTime, Attribute>(m, "PKCS9SigningTime")
.def_property_readonly("time",
&PKCS9SigningTime::time)
.def("__hash__",
[] (const PKCS9SigningTime& obj) {
return Hash::hash(obj);
})
.def("__str__", &PKCS9SigningTime::print);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (SpcSpOpusInfo::*)(void) const;
template<class T>
using setter_t = void (SpcSpOpusInfo::*)(T);
template<>
void create<SpcSpOpusInfo>(py::module& m) {
py::class_<SpcSpOpusInfo, Attribute>(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);
}
}
}

View File

@ -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 <string>
#include <sstream>
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (Attribute::*)(void) const;
template<class T>
using setter_t = void (Attribute::*)(T);
template<>
void create<Attribute>(py::module& m) {
py::class_<Attribute, Object>(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();
});
}
}
}

View File

@ -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 <string>
#include <sstream>
#include "LIEF/PE/hash.hpp"
#include "LIEF/utils.hpp"
#include "LIEF/PE/signature/AuthenticatedAttributes.hpp"
#include "pyPE.hpp"
namespace LIEF {
namespace PE {
template<class T>
using getter_t = T (AuthenticatedAttributes::*)(void) const;
template<class T>
using setter_t = void (AuthenticatedAttributes::*)(T);
template<>
void create<AuthenticatedAttributes>(py::module& m) {
py::class_<AuthenticatedAttributes, LIEF::Object>(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;
});
}
}
}

View File

@ -40,21 +40,23 @@ void create<ContentInfo>(py::module& m) {
&ContentInfo::content_type, &ContentInfo::content_type,
"OID of the content type. This value should match ``SPC_INDIRECT_DATA_OBJID``") "OID of the content type. This value should match ``SPC_INDIRECT_DATA_OBJID``")
.def_property_readonly("type", .def_property_readonly("digest_algorithm",
&ContentInfo::type)
.def_property_readonly("digest_algorithm",
&ContentInfo::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", .def_property_readonly("digest",
&ContentInfo::digest, [] (const ContentInfo& info) -> py::bytes {
"The digest") const std::vector<uint8_t>& dg = info.digest();
return py::bytes(reinterpret_cast<const char*>(dg.data()), dg.size());
},
"The digest as ``bytes`` ")
.def_property_readonly("raw", .def("__hash__",
&ContentInfo::raw, [] (const ContentInfo& info) {
"Return the raw bytes associated with the ContentInfo") return Hash::hash(info);
})
.def("__str__", .def("__str__",
[] (const ContentInfo& content_info) [] (const ContentInfo& content_info)

View File

@ -16,8 +16,11 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include "enums_wrapper.hpp"
#include "LIEF/PE/hash.hpp" #include "LIEF/PE/hash.hpp"
#include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/Signature.hpp"
#include "LIEF/PE/signature/SignatureParser.hpp"
#include "pyPE.hpp" #include "pyPE.hpp"
@ -34,7 +37,42 @@ using setter_t = void (Signature::*)(T);
template<> template<>
void create<Signature>(py::module& m) { void create<Signature>(py::module& m) {
py::class_<Signature, LIEF::Object>(m, "Signature") py::class_<Signature, LIEF::Object> signature(m, "Signature");
LIEF::enum_<Signature::VERIFICATION_FLAGS>(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<uint8_t>& 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", .def_property_readonly("version",
&Signature::version, &Signature::version,
@ -42,7 +80,8 @@ void create<Signature>(py::module& m) {
.def_property_readonly("digest_algorithm", .def_property_readonly("digest_algorithm",
&Signature::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", .def_property_readonly("content_info",
@ -57,24 +96,34 @@ void create<Signature>(py::module& m) {
py::return_value_policy::reference) py::return_value_policy::reference)
.def_property_readonly("signer_info", .def_property_readonly("signers",
&Signature::signer_info, &Signature::signers,
"Return the " RST_CLASS_REF(lief.PE.SignerInfo) "", "Return an iterator over the signers: " RST_CLASS_REF(lief.PE.SignerInfo) "",
py::return_value_policy::reference) 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", .def_property_readonly("raw_der",
&Signature::original_signature, [] (const Signature& sig) {
"Return the raw original signature") const std::vector<uint8_t>& raw = sig.raw_der();
return py::bytes(reinterpret_cast<const char*>(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__", .def("__str__",
[] (const Signature& signature) [] (const Signature& signature)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << signature; stream << signature;
std::string str = stream.str(); return stream.str();
return str;
}); });
} }

View File

@ -40,31 +40,68 @@ void create<SignerInfo>(py::module& m) {
&SignerInfo::version, &SignerInfo::version,
"Should be 1") "Should be 1")
.def_property_readonly("serial_number",
[] (const SignerInfo& info) -> py::bytes {
const std::vector<uint8_t>& data = info.serial_number();
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"The X509 serial number used to sign the signed-data")
.def_property_readonly("issuer", .def_property_readonly("issuer",
[] (const SignerInfo& object) { [] (const SignerInfo& object) {
const issuer_t& issuer = object.issuer(); return safe_string_converter(object.issuer());
return std::pair<py::object, std::vector<uint8_t>>{safe_string_converter(std::get<0>(issuer)), std::get<1>(issuer)};
}, },
"Issuer and serial number", "Issuer and serial number",
py::return_value_policy::copy) py::return_value_policy::copy)
.def_property_readonly("digest_algorithm", .def_property_readonly("digest_algorithm",
&SignerInfo::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", .def_property_readonly("encryption_algorithm",
&SignerInfo::signature_algorithm, &SignerInfo::encryption_algorithm,
"Return the signature algorithm (OID)") "Return algorithm (" RST_CLASS_REF(lief.PE.ALGORITHMS) ") used to encrypt the digest")
.def_property_readonly("encrypted_digest", .def_property_readonly("encrypted_digest",
&SignerInfo::encrypted_digest, [] (const SignerInfo& info) {
const std::vector<uint8_t>& data = info.encrypted_digest();
return py::bytes(reinterpret_cast<const char*>(data.data()), data.size());
},
"Return the signature created by the signing certificate's private key") "Return the signature created by the signing certificate's private key")
.def_property_readonly("authenticated_attributes", .def_property_readonly("authenticated_attributes",
&SignerInfo::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) 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<x509*(SignerInfo::*)()>(&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__", .def("__str__",
[] (const SignerInfo& signer_info) [] (const SignerInfo& signer_info)
{ {

View File

@ -16,6 +16,8 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include "enums_wrapper.hpp"
#include "LIEF/PE/hash.hpp" #include "LIEF/PE/hash.hpp"
#include "LIEF/PE/signature/x509.hpp" #include "LIEF/PE/signature/x509.hpp"
@ -34,14 +36,54 @@ using setter_t = void (x509::*)(T);
template<> template<>
void create<x509>(py::module& m) { void create<x509>(py::module& m) {
py::class_<x509, LIEF::Object>(m, "x509") py::class_<x509, LIEF::Object> cls_x509(m, "x509");
LIEF::enum_<x509::VERIFICATION_FLAGS>(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::certificates_t(*)(const std::string&)>(&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::certificates_t(*)(const std::vector<uint8_t>&)>(&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", .def_property_readonly("version",
&x509::version, &x509::version,
"X.509 version. (1=v1, 2=v2, 3=v3)") "X.509 version. (1=v1, 2=v2, 3=v3)")
.def_property_readonly("serial_number", .def_property_readonly("serial_number",
&x509::serial_number, [] (const x509& crt) -> py::bytes {
const std::vector<uint8_t>& sn = crt.serial_number();
return py::bytes(reinterpret_cast<const char*>(sn.data()), sn.size());
},
"Unique id for certificate issued by a specific CA.") "Unique id for certificate issued by a specific CA.")
.def_property_readonly("signature_algorithm", .def_property_readonly("signature_algorithm",
@ -58,14 +100,12 @@ void create<x509>(py::module& m) {
&x509::valid_to, &x509::valid_to,
"End time of certificate validity") "End time of certificate validity")
.def_property_readonly("issuer", .def_property_readonly("issuer",
[] (const x509& object) { [] (const x509& object) {
return safe_string_converter(object.issuer()); return safe_string_converter(object.issuer());
}, },
"Issuer informations") "Issuer informations")
.def_property_readonly("subject", .def_property_readonly("subject",
[] (const x509& object) { [] (const x509& object) {
return safe_string_converter(object.subject()); return safe_string_converter(object.subject());
@ -73,16 +113,35 @@ void create<x509>(py::module& m) {
"Subject informations") "Subject informations")
.def_property_readonly("raw", .def_property_readonly("raw",
&x509::raw, [] (const x509& crt) -> py::bytes {
const std::vector<uint8_t>& raw = crt.raw();
return py::bytes(reinterpret_cast<const char*>(raw.data()), raw.size());
},
"The raw bytes associated with this x509 cert (DER encoded)") "The raw bytes associated with this x509 cert (DER encoded)")
.def("verify",
static_cast<x509::VERIFICATION_FLAGS(x509::*)(const x509&) const>(&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__", .def("__str__",
[] (const x509& x509_crt) [] (const x509& x509_crt)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << x509_crt; stream << x509_crt;
std::string str = stream.str(); return safe_string_converter(stream.str());
return str;
}); });
} }

File diff suppressed because it is too large Load Diff

View File

@ -78,10 +78,19 @@ void init_objects(py::module& m) {
CREATE(ResourceAccelerator, m); CREATE(ResourceAccelerator, m);
CREATE(Signature, m); CREATE(Signature, m);
CREATE(x509, m); CREATE(x509, m);
CREATE(SignerInfo, m);
CREATE(ContentInfo, m); CREATE(ContentInfo, m);
CREATE(AuthenticatedAttributes, m); CREATE(SignerInfo, m);
CREATE(CodeIntegrity, 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(LoadConfiguration, m);
CREATE(LoadConfigurationV0, m); CREATE(LoadConfigurationV0, m);

View File

@ -81,13 +81,23 @@ SPECIALIZE_CREATE(ResourceStringTable);
SPECIALIZE_CREATE(ResourceDialog); SPECIALIZE_CREATE(ResourceDialog);
SPECIALIZE_CREATE(ResourceDialogItem); SPECIALIZE_CREATE(ResourceDialogItem);
SPECIALIZE_CREATE(ResourceAccelerator); SPECIALIZE_CREATE(ResourceAccelerator);
SPECIALIZE_CREATE(Signature); SPECIALIZE_CREATE(Signature);
SPECIALIZE_CREATE(x509); SPECIALIZE_CREATE(x509);
SPECIALIZE_CREATE(SignerInfo); SPECIALIZE_CREATE(SignerInfo);
SPECIALIZE_CREATE(Attribute);
SPECIALIZE_CREATE(ContentInfo); SPECIALIZE_CREATE(ContentInfo);
SPECIALIZE_CREATE(AuthenticatedAttributes); SPECIALIZE_CREATE(ContentType);
SPECIALIZE_CREATE(CodeIntegrity); 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(LoadConfiguration);
SPECIALIZE_CREATE(LoadConfigurationV0); SPECIALIZE_CREATE(LoadConfigurationV0);
SPECIALIZE_CREATE(LoadConfigurationV1); SPECIALIZE_CREATE(LoadConfigurationV1);

View File

@ -56,10 +56,13 @@ void init_LIEF_iterators(py::module& m) {
init_ref_iterator<LIEF::PE::it_export_entries>(m); init_ref_iterator<LIEF::PE::it_export_entries>(m);
init_ref_iterator<LIEF::PE::it_pogo_entries>(m); init_ref_iterator<LIEF::PE::it_pogo_entries>(m);
init_ref_iterator<LIEF::PE::it_symbols>(m); init_ref_iterator<LIEF::PE::it_symbols>(m);
init_ref_iterator<LIEF::PE::it_const_crt>(m);
init_ref_iterator<LIEF::PE::it_childs>(m); init_ref_iterator<LIEF::PE::it_childs>(m);
init_ref_iterator<LIEF::PE::it_rich_entries>(m); init_ref_iterator<LIEF::PE::it_rich_entries>(m);
init_ref_iterator<LIEF::PE::it_const_dialog_items>(m); init_ref_iterator<LIEF::PE::it_const_dialog_items>(m);
init_ref_iterator<LIEF::PE::it_const_crt>(m);
init_ref_iterator<LIEF::PE::it_const_signatures>(m);
init_ref_iterator<LIEF::PE::it_const_signers_t>(m);
init_ref_iterator<LIEF::PE::it_const_attributes_t>(m);
#endif #endif

View File

@ -33,6 +33,9 @@
#define RST_ATTR_REF(X) ":attr:`~"#X"`" #define RST_ATTR_REF(X) ":attr:`~"#X"`"
#define RST_ATTR_REF_FULL(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; namespace py = pybind11;
using namespace pybind11::literals; using namespace pybind11::literals;

View File

@ -6,8 +6,8 @@ set(__add_lief_dependencies ON)
# Json # Json
# ---- # ----
if (LIEF_ENABLE_JSON) if (LIEF_ENABLE_JSON)
set(LIBJSON_VERSION 3.7.3) set(LIBJSON_VERSION 3.9.1)
set(LIBJSON_SHA256 SHA256=e46d26550e8cafc7d7d2564fdf09d20bd14a72c417396bf7ca815b94894d1631) set(LIBJSON_SHA256 SHA256=5db3b7b3356a0742e06b27b6ee744f8ee487ed9c0f8cf3f9778a2076e7a933ba)
set(LIBJSON_URL "${THIRD_PARTY_DIRECTORY}/json-${LIBJSON_VERSION}.zip" CACHE STRING "URL to the JSON lib repo") set(LIBJSON_URL "${THIRD_PARTY_DIRECTORY}/json-${LIBJSON_VERSION}.zip" CACHE STRING "URL to the JSON lib repo")
ExternalProject_Add(lief_libjson ExternalProject_Add(lief_libjson
URL ${LIBJSON_URL} URL ${LIBJSON_URL}
@ -29,8 +29,8 @@ endif()
# mbed TLS # mbed TLS
# -------- # --------
set(MBED_TLS_VERSION 2.23.0) set(MBED_TLS_VERSION 2.7.17)
set(MBED_TLS_SHA256 SHA256=bbf9c3cc6b7603f2f15bbba7badcf6cf188a9d5aaa63c4df2d61213f459c2f5f) 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_URL "${THIRD_PARTY_DIRECTORY}/mbedtls-${MBED_TLS_VERSION}.zip" CACHE STRING "URL to MbedTLS")
set(MBED_TLS_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/mbed_tls") 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/aes.c"
"${MBEDTLS_SOURCE_DIR}/library/aesni.c" "${MBEDTLS_SOURCE_DIR}/library/aesni.c"
"${MBEDTLS_SOURCE_DIR}/library/arc4.c" "${MBEDTLS_SOURCE_DIR}/library/arc4.c"
"${MBEDTLS_SOURCE_DIR}/library/aria.c"
"${MBEDTLS_SOURCE_DIR}/library/asn1parse.c" "${MBEDTLS_SOURCE_DIR}/library/asn1parse.c"
"${MBEDTLS_SOURCE_DIR}/library/asn1write.c" "${MBEDTLS_SOURCE_DIR}/library/asn1write.c"
"${MBEDTLS_SOURCE_DIR}/library/base64.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/blowfish.c"
"${MBEDTLS_SOURCE_DIR}/library/camellia.c" "${MBEDTLS_SOURCE_DIR}/library/camellia.c"
"${MBEDTLS_SOURCE_DIR}/library/ccm.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.c"
"${MBEDTLS_SOURCE_DIR}/library/cipher_wrap.c" "${MBEDTLS_SOURCE_DIR}/library/cipher_wrap.c"
"${MBEDTLS_SOURCE_DIR}/library/cmac.c" "${MBEDTLS_SOURCE_DIR}/library/cmac.c"
"${MBEDTLS_SOURCE_DIR}/library/ctr_drbg.c" "${MBEDTLS_SOURCE_DIR}/library/ctr_drbg.c"
"${MBEDTLS_SOURCE_DIR}/library/debug.c"
"${MBEDTLS_SOURCE_DIR}/library/des.c" "${MBEDTLS_SOURCE_DIR}/library/des.c"
"${MBEDTLS_SOURCE_DIR}/library/dhm.c" "${MBEDTLS_SOURCE_DIR}/library/dhm.c"
"${MBEDTLS_SOURCE_DIR}/library/ecdh.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/error.c"
"${MBEDTLS_SOURCE_DIR}/library/gcm.c" "${MBEDTLS_SOURCE_DIR}/library/gcm.c"
"${MBEDTLS_SOURCE_DIR}/library/havege.c" "${MBEDTLS_SOURCE_DIR}/library/havege.c"
"${MBEDTLS_SOURCE_DIR}/library/hkdf.c"
"${MBEDTLS_SOURCE_DIR}/library/hmac_drbg.c" "${MBEDTLS_SOURCE_DIR}/library/hmac_drbg.c"
"${MBEDTLS_SOURCE_DIR}/library/md.c" "${MBEDTLS_SOURCE_DIR}/library/md.c"
"${MBEDTLS_SOURCE_DIR}/library/md2.c" "${MBEDTLS_SOURCE_DIR}/library/md2.c"
"${MBEDTLS_SOURCE_DIR}/library/md4.c" "${MBEDTLS_SOURCE_DIR}/library/md4.c"
"${MBEDTLS_SOURCE_DIR}/library/md5.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/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/oid.c"
"${MBEDTLS_SOURCE_DIR}/library/padlock.c" "${MBEDTLS_SOURCE_DIR}/library/padlock.c"
"${MBEDTLS_SOURCE_DIR}/library/pem.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/pkparse.c"
"${MBEDTLS_SOURCE_DIR}/library/pkwrite.c" "${MBEDTLS_SOURCE_DIR}/library/pkwrite.c"
"${MBEDTLS_SOURCE_DIR}/library/platform.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/ripemd160.c"
"${MBEDTLS_SOURCE_DIR}/library/rsa.c" "${MBEDTLS_SOURCE_DIR}/library/rsa.c"
"${MBEDTLS_SOURCE_DIR}/library/rsa_internal.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.c"
"${MBEDTLS_SOURCE_DIR}/library/version_features.c" "${MBEDTLS_SOURCE_DIR}/library/version_features.c"
"${MBEDTLS_SOURCE_DIR}/library/xtea.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 set(mbedtls_src_x509
@ -149,7 +128,6 @@ set(mbedtls_src_tls
"${MBEDTLS_SOURCE_DIR}/library/ssl_srv.c" "${MBEDTLS_SOURCE_DIR}/library/ssl_srv.c"
"${MBEDTLS_SOURCE_DIR}/library/ssl_ticket.c" "${MBEDTLS_SOURCE_DIR}/library/ssl_ticket.c"
"${MBEDTLS_SOURCE_DIR}/library/ssl_tls.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) #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 # Fuzzing
# ~~~~~~~ # ~~~~~~~
set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O1) set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O2)
set(FUZZING_LINKER_FLAGS) set(FUZZING_LINKER_FLAGS)
list(APPEND FUZZING_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard) list(APPEND FUZZING_FLAGS -fsanitize=address,fuzzer)
list(APPEND FUZZING_LINKER_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard) list(APPEND FUZZING_LINKER_FLAGS -fsanitize=address,fuzzer)
set(LIBFUZZER_SRC_FILES) set(LIBFUZZER_SRC_FILES)
if (LIEF_FUZZING) if (LIEF_FUZZING)
message(STATUS "Fuzzing Enabled") message(STATUS "Fuzzing Enabled")
set(LIBFUZZER_VERSION 8ff5640b48c4c4a3b974daa10a5f445e86ed7428) set(LIBFUZZER_VERSION 6f13445)
set(LIBFUZZER_SHA256 SHA256=ed067ebc72b993571854edb113e9f3ef74367dfb8bab1a252009aff72e287614) set(LIBFUZZER_SHA256 SHA256=cf9a4f5025beb9005181b9136a88e142f1360a3f8ccd490ec1b8f773cefc51e1)
set(LIBFUZZER_URL "${THIRD_PARTY_DIRECTORY}/LibFuzzer-${LIBFUZZER_VERSION}.zip") set(LIBFUZZER_URL "${THIRD_PARTY_DIRECTORY}/LibFuzzer-${LIBFUZZER_VERSION}.zip")
ExternalProject_Add(lief_libfuzzer ExternalProject_Add(lief_libfuzzer
URL ${LIBFUZZER_URL} URL ${LIBFUZZER_URL}
@ -195,36 +173,32 @@ if (LIEF_FUZZING)
set(LIBFUZZER_SOURCE_DIR "${SOURCE_DIR}") set(LIBFUZZER_SOURCE_DIR "${SOURCE_DIR}")
set(LIBFUZZER_SRC_FILES 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}/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}/FuzzerCrossOver.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerDataFlowTrace.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerDriver.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerDriver.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsym.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeak.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeak.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtilPosix.cpp" "${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWindows.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}/FuzzerExtraCounters.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}/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}) list(APPEND LIBLIEF_SOURCE_FILES ${LIBFUZZER_SRC_FILES})
set_source_files_properties(${LIBFUZZER_SRC_FILES} PROPERTIES GENERATED TRUE) set_source_files_properties(${LIBFUZZER_SRC_FILES} PROPERTIES GENERATED TRUE)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing")
endif() endif()
@ -251,3 +225,19 @@ if (LIEF_SUPPORT_CXX14 AND NOT LIEF_DISABLE_FROZEN)
set(FROZEN_INCLUDE_DIR "${SOURCE_DIR}/include") set(FROZEN_INCLUDE_DIR "${SOURCE_DIR}/include")
endif() 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")

View File

@ -8,7 +8,7 @@ elseif(NOT SPHINX_FOUND)
elseif(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) elseif(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
message(STATUS "You have to build the doc in another directory !") message(STATUS "You have to build the doc in another directory !")
else() else()
message(STATUS "Sphinx: ${SPHINX_EXECUTABLE}")
add_custom_target(lief-doxygen add_custom_target(lief-doxygen
COMMAND COMMAND
${CMAKE_COMMAND} -E env ${CMAKE_COMMAND} -E env
@ -23,7 +23,7 @@ else()
add_custom_target(lief-sphinx add_custom_target(lief-sphinx
COMMAND ${CMAKE_COMMAND} -E env 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/" "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 ${SPHINX_EXECUTABLE} -a -E -j4 -w ${CMAKE_BINARY_DIR}/sphinx-warn.log ${CMAKE_SOURCE_DIR}/doc/sphinx sphinx-doc
DEPENDS pyLIEF lief-doxygen DEPENDS pyLIEF lief-doxygen
@ -37,7 +37,7 @@ else()
add_custom_target(lief-quick-sphinx add_custom_target(lief-quick-sphinx
COMMAND ${CMAKE_COMMAND} -E env 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/" "LIEF_DOXYGEN_XML=${CMAKE_CURRENT_BINARY_DIR}/doxygen/xml/"
"FORCE_RTD_THEME=0" "FORCE_RTD_THEME=0"
${SPHINX_EXECUTABLE} -j4 -w ${CMAKE_BINARY_DIR}/sphinx-warn.log ${CMAKE_SOURCE_DIR}/doc/sphinx sphinx-doc ${SPHINX_EXECUTABLE} -j4 -w ${CMAKE_BINARY_DIR}/sphinx-warn.log ${CMAKE_SOURCE_DIR}/doc/sphinx sphinx-doc

View File

@ -153,15 +153,113 @@ Signature
---------- ----------
AuthenticatedAttributes Signature Attribute
*********************** *******************
.. doxygenclass:: LIEF::PE::AuthenticatedAttributes .. doxygenclass:: LIEF::PE::Attribute
:project: lief :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 x509
**** ****
@ -171,6 +269,7 @@ x509
---------- ----------
ContentInfo ContentInfo
*********** ***********
@ -526,5 +625,8 @@ Enums
.. doxygenenum:: LIEF::PE::GUARD_CF_FLAGS .. doxygenenum:: LIEF::PE::GUARD_CF_FLAGS
:project: lief :project: lief
.. doxygenenum:: LIEF::PE::POGO_SIGNATURES .. doxygenenum:: LIEF::PE::ALGORITHMS
:project: lief
.. doxygenenum:: LIEF::PE::SIG_ATTRIBUTE_TYPES
:project: lief :project: lief

View File

@ -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: :members:
:inherited-members: :inherited-members:
:undoc-members: :undoc-members:
@ -831,3 +912,21 @@ POGO_SIGNATURES
:members: :members:
:inherited-members: :inherited-members:
:undoc-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:

View File

@ -20,6 +20,7 @@ Changelog
* Bug fix in the symbols table reconstruction (ELF) * Bug fix in the symbols table reconstruction (ELF)
:PE: :PE:
* Enhance PE Authenticode. See `PE Authenticode <tutorials/13_pe_authenticode.html>`_
* :attr:`~lief.PE.LangCodeItem.items` now returns a dictionary whose values are **bytes** (instead of * :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. ``str`` object). This change is related to ``utf-16`` support.
* :github_user:`kohnakagawa` fixed wrong enums values: :commit:`c03125045e32a9cd65c613585eb4d0385350c6d2`, :commit:`6ee808a1e4611d09c6cf0aea82a612be69584db9`, :commit:`cd05f34bae681fc8af4b5e7cc28eaef816802b6f` * :github_user:`kohnakagawa` fixed wrong enums values: :commit:`c03125045e32a9cd65c613585eb4d0385350c6d2`, :commit:`6ee808a1e4611d09c6cf0aea82a612be69584db9`, :commit:`cd05f34bae681fc8af4b5e7cc28eaef816802b6f`
@ -38,7 +39,7 @@ Changelog
* Upgrade ``mbedtls`` to 2.16.6 * Upgrade ``mbedtls`` to 2.16.6
:Documentation: :Documentation:
* :github_user:`aguinet` updated the `bin2lib tutorial <https://lief.quarkslab.com/doc/latest/tutorials/08_elf_bin2lib.html>`_ with the support * :github_user:`aguinet` updated the `bin2lib tutorial <tutorials/08_elf_bin2lib.html>`_ with the support
of the new glibc versions (:commit:`7884e57aa1d103f3bd37682e47f412bfe7a3aa34`) of the new glibc versions (:commit:`7884e57aa1d103f3bd37682e47f412bfe7a3aa34`)
* Global update and enable to build the documentation out-of-tree * Global update and enable to build the documentation out-of-tree
* Changing the theme * Changing the theme

View File

@ -25,7 +25,7 @@ Welcome to LIEF's documentation!
tutorials/10_android_formats tutorials/10_android_formats
tutorials/11_macho_modification tutorials/11_macho_modification
tutorials/12_elf_coredump tutorials/12_elf_coredump
tutorials/13_pe_authenticode
.. toctree:: .. toctree::
:caption: API :caption: API

View File

@ -0,0 +1,48 @@
13 - PE Authenticode
--------------------
This tutorial introduces the new API deal with PE Authenticode processing.
By Romain Thomas - `@rh0main <https://twitter.com/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`

View File

@ -100,13 +100,10 @@ int main(int argc, char **argv) {
std::cout << binary->resources_manager() << std::endl; std::cout << binary->resources_manager() << std::endl;
} }
for (const Signature& sig : binary->signatures()) {
if (binary->has_signature()) {
std::cout << "== Signature ==" << std::endl; std::cout << "== Signature ==" << std::endl;
std::cout << binary->signature() << std::endl; std::cout << sig << std::endl;
} }
return 0; return 0;
} }

View File

@ -298,45 +298,8 @@ def print_debug(binary):
def print_signature(binary): def print_signature(binary):
format_str = "{:<33} {:<30}" format_str = "{:<33} {:<30}"
format_dec = "{:<33} {:<30d}" format_dec = "{:<33} {:<30d}"
for signature in binary.signatures:
signature = binary.signature print(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("")
@exceptions_handler(Exception) @exceptions_handler(Exception)
def print_rich_header(binary): def print_rich_header(binary):
@ -616,7 +579,7 @@ def main():
if (args.show_debug or args.show_all) and binary.has_debug: if (args.show_debug or args.show_all) and binary.has_debug:
print_debug(binary) 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) print_signature(binary)
if (args.show_richheader or args.show_all) and binary.has_rich_header: if (args.show_richheader or args.show_all) and binary.has_rich_header:

View File

@ -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

View File

@ -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()

View File

@ -4,6 +4,7 @@ set(LIEF_FUZZER_SRC
pe_fuzzer.cpp pe_fuzzer.cpp
macho_fuzzer.cpp macho_fuzzer.cpp
pme_fuzzer.cpp pme_fuzzer.cpp
pkcs7_signature.cpp
) )
foreach(fuzzer ${LIEF_FUZZER_SRC}) foreach(fuzzer ${LIEF_FUZZER_SRC})
@ -35,7 +36,8 @@ ExternalProject_Add(lief_fuzzer_corpus
INSTALL_COMMAND "" INSTALL_COMMAND ""
GIT_REPOSITORY ${SAMPLES_GIT_URL} GIT_REPOSITORY ${SAMPLES_GIT_URL}
GIT_TAG ${SAMPLES_TAG} GIT_TAG ${SAMPLES_TAG}
#UPDATE_COMMAND ${GIT_EXECUTABLE} pull GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
UPDATE_COMMAND "" UPDATE_COMMAND ""
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
) )
@ -119,4 +121,18 @@ add_custom_target("fuzz-macho"
COMMENT "Run MachO fuzzer") 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")

View File

@ -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.
}

View File

@ -22,13 +22,13 @@ class Symbol;
class Section; class Section;
class Relocation; class Relocation;
using sections_t = std::vector<Section*>; using sections_t = std::vector<Section*>; ///< Default container for abstract sections
using it_sections = ref_iterator<sections_t>; using it_sections = ref_iterator<sections_t>; ///< Iterator over abstract sections
using it_const_sections = const_ref_iterator<sections_t>; using it_const_sections = const_ref_iterator<sections_t>; ///< **Const** iterator over abstract sections
using symbols_t = std::vector<Symbol*>; using symbols_t = std::vector<Symbol*>; ///< Default container for abstract symbols
using it_symbols = ref_iterator<symbols_t>; using it_symbols = ref_iterator<symbols_t>; ///< Iterator over abstract symbols
using it_const_symbols = const_ref_iterator<symbols_t>; using it_const_symbols = const_ref_iterator<symbols_t>; ///< Iterator over abstract symbols
using relocations_t = std::vector<Relocation*>; ///< Container used to transfert abstract relocations from binary formats using relocations_t = std::vector<Relocation*>; ///< Container used to transfert abstract relocations from binary formats
using it_relocations = ref_iterator<relocations_t>; ///< Iterator over Abstract LIEF::Relocation (read only) using it_relocations = ref_iterator<relocations_t>; ///< Iterator over Abstract LIEF::Relocation (read only)

View File

@ -24,6 +24,11 @@
#include <memory> #include <memory>
#include "LIEF/BinaryStream/Convert.hpp" #include "LIEF/BinaryStream/Convert.hpp"
#include "LIEF/errors.hpp"
struct mbedtls_x509_crt;
struct mbedtls_x509_time;
namespace LIEF { namespace LIEF {
class BinaryStream { class BinaryStream {
public: public:
@ -100,6 +105,19 @@ class BinaryStream {
void set_endian_swap(bool swap); void set_endian_swap(bool swap);
// ASN1 related functions
virtual result<size_t> asn1_read_tag(int tag) = 0;
virtual result<size_t> asn1_read_len() = 0;
virtual result<std::string> asn1_read_alg() = 0;
virtual result<std::string> asn1_read_oid() = 0;
virtual result<int32_t> asn1_read_int() = 0;
virtual result<std::vector<uint8_t>> asn1_read_bitstring() = 0;
virtual result<std::vector<uint8_t>> asn1_read_octet_string() = 0;
virtual result<std::unique_ptr<mbedtls_x509_crt>> asn1_read_cert() = 0;
virtual result<std::string> x509_read_names() = 0;
virtual result<std::vector<uint8_t>> x509_read_serial() = 0;
virtual result<std::unique_ptr<mbedtls_x509_time>> x509_read_time() = 0;
protected: protected:
virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const = 0; virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const = 0;
mutable size_t pos_{0}; mutable size_t pos_{0};

View File

@ -31,6 +31,36 @@ class VectorStream : public BinaryStream {
const std::vector<uint8_t>& content(void) const; const std::vector<uint8_t>& 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<size_t> asn1_read_tag(int tag) override;
virtual result<size_t> asn1_read_len() override;
result<size_t> asn1_peek_len();
virtual result<std::string> asn1_read_alg() override;
virtual result<std::string> asn1_read_oid() override;
virtual result<int32_t> asn1_read_int() override;
virtual result<std::vector<uint8_t>> asn1_read_bitstring() override;
virtual result<std::vector<uint8_t>> asn1_read_octet_string() override;
virtual result<std::unique_ptr<mbedtls_x509_crt>> asn1_read_cert() override;
virtual result<std::string> x509_read_names() override;
virtual result<std::vector<uint8_t>> x509_read_serial() override;
virtual result<std::unique_ptr<mbedtls_x509_time>> x509_read_time() override;
protected: protected:
virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const override; virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const override;
std::vector<uint8_t> binary_; std::vector<uint8_t> binary_;

View File

@ -31,7 +31,7 @@ class Parser;
class Builder; class Builder;
class Binary; 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 //! @see: https://android.googlesource.com/platform/ndk/+/ndk-release-r16/sources/crt/crtbrand.S#39
class LIEF_API NoteAbi : public NoteDetails { class LIEF_API NoteAbi : public NoteDetails {

View File

@ -62,7 +62,8 @@
#include "LIEF/PE/AuxiliarySymbol.hpp" #include "LIEF/PE/AuxiliarySymbol.hpp"
#include "LIEF/PE/CodeIntegrity.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/ContentInfo.hpp"
#include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/OIDToString.hpp"
#include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/Signature.hpp"

View File

@ -111,8 +111,8 @@ class LIEF_API Binary : public LIEF::Binary {
//! @see Import //! @see Import
bool has_imports(void) const; bool has_imports(void) const;
//! Check if the current binary is signed //! Check if the current binary conatains signatures
bool has_signature(void) const; bool has_signatures(void) const;
//! Check if the current binary has exports. //! 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. //! 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; bool is_reproducible_build(void) const;
//! Return the Signature object if the bianry is signed //! Return the Signature object(s) if the bianry is signed
const Signature& signature(void) const; 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<Signature> 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<uint8_t> authentihash(ALGORITHMS algo) const;
//! Try to predict the RVA of the function `function` in the import library `library` //! 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_lookup_address_table_offset(void);
void update_iat(void); void update_iat(void);
PE_TYPE type_; PE_TYPE type_;
DosHeader dos_header_; DosHeader dos_header_;
RichHeader rich_header_; RichHeader rich_header_;
Header header_; Header header_;
OptionalHeader optional_header_; OptionalHeader optional_header_;
int32_t available_sections_space_; int32_t available_sections_space_;
bool has_rich_header_; bool has_rich_header_;
bool has_tls_; bool has_tls_;
bool has_imports_; bool has_imports_;
bool has_signature_; bool has_exports_;
bool has_exports_; bool has_resources_;
bool has_resources_; bool has_exceptions_;
bool has_exceptions_; bool has_relocations_;
bool has_relocations_; bool has_debug_;
bool has_debug_; bool has_configuration_;
bool has_configuration_; bool is_reproducible_build_;
bool is_reproducible_build_;
Signature signature_; signatures_t signatures_;
TLS tls_; TLS tls_;
sections_t sections_; sections_t sections_;
data_directories_t data_directories_; data_directories_t data_directories_;
@ -442,8 +461,10 @@ class LIEF_API Binary : public LIEF::Binary {
imports_t imports_; imports_t imports_;
Export export_; Export export_;
debug_entries_t debug_; debug_entries_t debug_;
uint64_t overlay_offset_ = 0;
std::vector<uint8_t> overlay_; std::vector<uint8_t> overlay_;
std::vector<uint8_t> dos_stub_; std::vector<uint8_t> dos_stub_;
std::vector<uint8_t> section_offset_padding_;
LoadConfiguration* load_configuration_{nullptr}; LoadConfiguration* load_configuration_{nullptr};

View File

@ -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_FLAGS e);
LIEF_API const char* to_string(ACCELERATOR_VK_CODES 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 PE
} // namespace LIEF } // namespace LIEF
#endif #endif

View File

@ -58,6 +58,9 @@ class LIEF_API Section : public LIEF::Section {
// LIEF::Section implementation // LIEF::Section implementation
// ============================ // ============================
virtual std::vector<uint8_t> content(void) const override; virtual std::vector<uint8_t> content(void) const override;
inline const std::vector<uint8_t>& padding() const {
return this->padding_;
}
uint32_t pointerto_raw_data(void) const; uint32_t pointerto_raw_data(void) const;
@ -100,14 +103,15 @@ class LIEF_API Section : public LIEF::Section {
private: private:
std::vector<uint8_t>& content_ref(void); std::vector<uint8_t>& content_ref(void);
uint32_t virtualSize_; std::vector<uint8_t> content_;
std::vector<uint8_t> content_; std::vector<uint8_t> padding_;
uint32_t pointerToRelocations_; uint32_t virtual_size_ = 0;
uint32_t pointerToLineNumbers_; uint32_t pointer_to_relocations_ = 0;
uint16_t numberOfRelocations_; uint32_t pointer_to_linenumbers_ = 0;
uint16_t numberOfLineNumbers_; uint16_t number_of_relocations_ = 0;
uint32_t characteristics_; uint16_t number_of_linenumbers_ = 0;
std::set<PE_SECTION_TYPES> types_; uint32_t characteristics_ = 0;
std::set<PE_SECTION_TYPES> types_ = {PE_SECTION_TYPES::UNKNOWN};
}; };
} // namespace PE } // namespace PE

View File

@ -11,7 +11,7 @@ namespace PE {
@LIEF_PE_ENUMS@ @LIEF_PE_ENUMS@
// Common section type //! Common section type
enum class PE_SECTION_TYPES : uint8_t { enum class PE_SECTION_TYPES : uint8_t {
TEXT = 0, TEXT = 0,
TLS = 1, TLS = 1,
@ -31,6 +31,51 @@ enum class PE_TYPE : uint16_t {
PE32_PLUS = 0x20b ///< 64 bits 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[] = { static const RESOURCE_TYPES resource_types_array[] = {
RESOURCE_TYPES::CURSOR, RESOURCE_TYPES::CURSOR,

View File

@ -60,7 +60,18 @@ class ResourceAccelerator;
class Signature; class Signature;
class x509; class x509;
class SignerInfo; 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 CodeIntegrity;
class LoadConfiguration; class LoadConfiguration;
class LoadConfigurationV0; class LoadConfigurationV0;
@ -120,19 +131,28 @@ class LIEF_API Hash : public LIEF::Hash {
virtual void visit(const Signature& signature) override; virtual void visit(const Signature& signature) override;
virtual void visit(const x509& x509) override; virtual void visit(const x509& x509) override;
virtual void visit(const SignerInfo& signerinfo) override; virtual void visit(const SignerInfo& signerinfo) override;
//virtual void visit(const ContentInfo& contentinfo) 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 CodeIntegrity& code_integrity) override;
virtual void visit(const LoadConfiguration& config) override;
virtual void visit(const LoadConfiguration& config) override; virtual void visit(const LoadConfigurationV0& config) override;
virtual void visit(const LoadConfigurationV0& config) override; virtual void visit(const LoadConfigurationV1& config) override;
virtual void visit(const LoadConfigurationV1& config) override; virtual void visit(const LoadConfigurationV2& config) override;
virtual void visit(const LoadConfigurationV2& config) override; virtual void visit(const LoadConfigurationV3& config) override;
virtual void visit(const LoadConfigurationV3& config) override; virtual void visit(const LoadConfigurationV4& config) override;
virtual void visit(const LoadConfigurationV4& config) override; virtual void visit(const LoadConfigurationV5& config) override;
virtual void visit(const LoadConfigurationV5& config) override; virtual void visit(const LoadConfigurationV6& config) override;
virtual void visit(const LoadConfigurationV6& config) override; virtual void visit(const LoadConfigurationV7& config) override;
virtual void visit(const LoadConfigurationV7& config) override;
virtual void visit(const Pogo& pogo) override; virtual void visit(const Pogo& pogo) override;
virtual void visit(const PogoEntry& entry) override; virtual void visit(const PogoEntry& entry) override;

View File

@ -65,7 +65,17 @@ class Signature;
class x509; class x509;
class SignerInfo; class SignerInfo;
class ContentInfo; 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 CodeIntegrity;
class LoadConfiguration; class LoadConfiguration;
class LoadConfigurationV0; class LoadConfigurationV0;
@ -124,18 +134,27 @@ class LIEF_API JsonVisitor : public LIEF::JsonVisitor {
virtual void visit(const x509& x509) override; virtual void visit(const x509& x509) override;
virtual void visit(const SignerInfo& signerinfo) override; virtual void visit(const SignerInfo& signerinfo) override;
virtual void visit(const ContentInfo& contentinfo) 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 CodeIntegrity& code_integrity) override;
virtual void visit(const LoadConfiguration& config) override;
virtual void visit(const LoadConfiguration& config) override; virtual void visit(const LoadConfigurationV0& config) override;
virtual void visit(const LoadConfigurationV0& config) override; virtual void visit(const LoadConfigurationV1& config) override;
virtual void visit(const LoadConfigurationV1& config) override; virtual void visit(const LoadConfigurationV2& config) override;
virtual void visit(const LoadConfigurationV2& config) override; virtual void visit(const LoadConfigurationV3& config) override;
virtual void visit(const LoadConfigurationV3& config) override; virtual void visit(const LoadConfigurationV4& config) override;
virtual void visit(const LoadConfigurationV4& config) override; virtual void visit(const LoadConfigurationV5& config) override;
virtual void visit(const LoadConfigurationV5& config) override; virtual void visit(const LoadConfigurationV6& config) override;
virtual void visit(const LoadConfigurationV6& config) override; virtual void visit(const LoadConfigurationV7& config) override;
virtual void visit(const LoadConfigurationV7& config) override;
virtual void visit(const Pogo& pogo) override; virtual void visit(const Pogo& pogo) override;
virtual void visit(const PogoEntry& entry) override; virtual void visit(const PogoEntry& entry) override;

View File

@ -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 <memory>
#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<Attribute> 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

View File

@ -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<uint8_t>& 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<uint8_t>& 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<uint8_t> message_digest_;
std::u16string program_name_;
std::string more_info_;
std::vector<uint8_t> raw_;
};
}
}
#endif

View File

@ -20,6 +20,7 @@
#include "LIEF/visibility.h" #include "LIEF/visibility.h"
#include "LIEF/PE/signature/types.hpp" #include "LIEF/PE/signature/types.hpp"
#include "LIEF/PE/enums.hpp"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
@ -27,6 +28,44 @@ namespace PE {
class Parser; class Parser;
class SignatureParser; 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 { class LIEF_API ContentInfo : public Object {
friend class Parser; friend class Parser;
@ -37,21 +76,29 @@ class LIEF_API ContentInfo : public Object {
ContentInfo(const ContentInfo&); ContentInfo(const ContentInfo&);
ContentInfo& operator=(const ContentInfo&); ContentInfo& operator=(const ContentInfo&);
//! @brief OID of the content type. //! Return the OID that describes the content wrapped by this object.
//! This value should match ``SPC_INDIRECT_DATA_OBJID`` //! It should match SPC_INDIRECT_DATA_OBJID (1.3.6.1.4.1.311.2.1.4)
const oid_t& content_type(void) const; 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. //! PE's authentihash
//! This value should match SignerInfo::digest_algorithm and Signature::digest_algorithm //!
const oid_t& digest_algorithm(void) const; //! @see LIEF::PE::Binary::authentihash
inline const std::vector<uint8_t>& digest() const {
return this->digest_;
}
//! @brief The digest inline const std::string& file() const {
const std::vector<uint8_t>& digest(void) const; return this->file_;
}
//! @brief Return the raw bytes associated with the ContentInfo
const std::vector<uint8_t>& raw(void) const;
virtual void accept(Visitor& visitor) const override; 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); LIEF_API friend std::ostream& operator<<(std::ostream& os, const ContentInfo& content_info);
private: private:
oid_t content_type_; // SPC_INDIRECT_DATA_OBJID oid_t content_type_;
std::string file_;
oid_t type_; // SPC_PE_IMAGE_DATAOBJ uint8_t flags_ = 0;
//TODO: value ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN;
std::vector<uint8_t> digest_;
oid_t digest_algorithm_; // algorithm used to hash the file (should match Signature::digest_algorithms_)
std::vector<uint8_t> digest_; //hash value
std::vector<uint8_t> raw_; // raw bytes
}; };

View File

@ -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 <vector>
#include <ostream>
#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<uint8_t>;
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

View File

@ -24,64 +24,112 @@
#include "LIEF/PE/signature/ContentInfo.hpp" #include "LIEF/PE/signature/ContentInfo.hpp"
#include "LIEF/PE/signature/types.hpp" #include "LIEF/PE/signature/types.hpp"
#include "LIEF/PE/enums.hpp"
#include "LIEF/enums.hpp"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
class SignatureParser; class SignatureParser;
class Binary;
//! Main interface for the PKCS #7 signature scheme
class LIEF_API Signature : public Object { class LIEF_API Signature : public Object {
friend class SignatureParser; friend class SignatureParser;
friend class Parser; friend class Parser;
friend class Binary;
public: public:
//! Hash the input given the algorithm
static std::vector<uint8_t> hash(const std::vector<uint8_t>& 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(void);
Signature(const Signature&); Signature(const Signature&);
Signature& operator=(const Signature&); Signature& operator=(const Signature&);
//! @brief Should be 1 //! Should be 1
uint32_t version(void) const; uint32_t version(void) const;
//! @brief Return the algorithm (OID) used to //! Algorithm used to *digest* the file.
//! sign the content of ContentInfo //!
const oid_t& digest_algorithm(void) const; //! 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; 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; it_const_crt certificates(void) const;
//! @brief Return the SignerInfo object //! Return an iterator over the signers (SignerInfo) defined in the PKCS #7 signature
const SignerInfo& signer_info(void) const; it_const_signers_t signers(void) const;
//! @brief Return the raw original signature //! Return the raw original PKCS7 signature
const std::vector<uint8_t>& original_signature(void) const; const std::vector<uint8_t>& raw_der(void) const;
virtual void accept(Visitor& visitor) const override; 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); virtual ~Signature(void);
LIEF_API friend std::ostream& operator<<(std::ostream& os, const Signature& signature); LIEF_API friend std::ostream& operator<<(std::ostream& os, const Signature& signature);
private: private:
uint32_t version_; uint32_t version_ = 0;
oid_t digest_algorithm_; ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN;
ContentInfo content_info_; ContentInfo content_info_;
std::vector<x509> certificates_; std::vector<x509> certificates_;
SignerInfo signer_info_; std::vector<SignerInfo> 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<uint8_t> original_raw_signature_; std::vector<uint8_t> original_raw_signature_;
}; };
} }
} }
ENABLE_BITMASK_OPERATORS(LIEF::PE::Signature::VERIFICATION_FLAGS);
#endif #endif

View File

@ -17,6 +17,9 @@
#define LIEF_PE_SIGNATURE_PARSER_H_ #define LIEF_PE_SIGNATURE_PARSER_H_
#include <memory> #include <memory>
#include <string> #include <string>
#include <array>
#include "LIEF/errors.hpp"
#include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/Signature.hpp"
#include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/OIDToString.hpp"
@ -26,41 +29,64 @@ class VectorStream;
namespace PE { namespace PE {
class Parser; class Parser;
class Attribute;
class LIEF_API SignatureParser { class LIEF_API SignatureParser {
friend class Parser; 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: public:
static Signature parse(const std::vector<uint8_t>& data); using attributes_t = std::vector<std::unique_ptr<Attribute>>;
using signer_infos_t = std::vector<SignerInfo>;
using x509_certificates_t = std::vector<x509>;
using time_t = std::array<int32_t, 6>;
//! Parse a PKCS #7 signature given a raw blob
static result<Signature> parse(std::vector<uint8_t> data, bool skip_header = false);
//! Parse a PKCS #7 signature from a file path
static result<Signature> parse(const std::string& path);
private: private:
SignatureParser(const std::vector<uint8_t>& data); SignatureParser(std::vector<uint8_t> data);
~SignatureParser(void); ~SignatureParser();
SignatureParser(void); SignatureParser();
void parse_signature(void); result<Signature> parse_signature();
void parse_header(void); result<ContentInfo> parse_content_info(VectorStream& stream, range_t& range);
int32_t get_signed_data_version(void); result<x509_certificates_t> parse_certificates(VectorStream& stream);
std::string get_signed_data_digest_algorithms(void); result<signer_infos_t> parse_signer_infos(VectorStream& stream, range_t& auth_attr);
result<attributes_t> parse_attributes(VectorStream& stream);
result<std::unique_ptr<Attribute>> parse_content_type(VectorStream& stream);
ContentInfo parse_content_info(void); result<signer_infos_t> parse_pkcs9_counter_sign(VectorStream& stream);
std::string get_content_info_type(void); result<std::vector<uint8_t>> parse_pkcs9_message_digest(VectorStream& stream);
result<int32_t> parse_pkcs9_at_sequence_number(VectorStream& stream);
void parse_certificates(void); result<time_t> parse_pkcs9_signing_time(VectorStream& stream);
SignerInfo get_signer_info(void);
AuthenticatedAttributes get_authenticated_attributes(void);
result<void> parse_ms_counter_sign(VectorStream& stream);
result<Signature> parse_ms_spc_nested_signature(VectorStream& stream);
result<oid_t> parse_ms_spc_statement_type(VectorStream& stream);
result<SpcSpOpusInfo> parse_spc_sp_opus_info(VectorStream& stream);
result<std::string> parse_spc_string(VectorStream& stream);
result<std::string> parse_spc_link(VectorStream& stream);
result<SpcPeImageData> parse_spc_pe_image_data(VectorStream& stream);
size_t current_offset(void) const; 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<VectorStream> stream_; std::unique_ptr<VectorStream> stream_;
}; };
} }

View File

@ -15,19 +15,22 @@
*/ */
#ifndef LIEF_PE_SIGNER_INFO_H_ #ifndef LIEF_PE_SIGNER_INFO_H_
#define LIEF_PE_SIGNER_INFO_H_ #define LIEF_PE_SIGNER_INFO_H_
#include <memory>
#include "LIEF/Object.hpp" #include "LIEF/Object.hpp"
#include "LIEF/visibility.h" #include "LIEF/visibility.h"
#include "LIEF/PE/signature/AuthenticatedAttributes.hpp"
#include "LIEF/PE/signature/types.hpp" #include "LIEF/PE/signature/types.hpp"
#include "LIEF/PE/enums.hpp"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
class Attribute;
class Parser; class Parser;
class SignatureParser; class SignatureParser;
class x509;
class LIEF_API SignerInfo : public Object { class LIEF_API SignerInfo : public Object {
@ -35,29 +38,71 @@ class LIEF_API SignerInfo : public Object {
friend class SignatureParser; friend class SignatureParser;
public: public:
using encrypted_digest_t = std::vector<uint8_t>;
SignerInfo(void); 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; uint32_t version(void) const;
//! @brief Issuer and serial number //! Return the serial number associated with the x509 certificate
const issuer_t& issuer(void) const; //! used by this signer.
//!
//! @see
//! LIEF::PE::x509::serial_number
//! SignerInfo::issuer
inline const std::vector<uint8_t>& serial_number() const {
return this->serialno_;
}
//! @brief Algorithm (OID) used to hash the file. //! Return the x509::issuer used by this signer
//! This value should match ContentInfo::digest_algorithm and Signature::digest_algorithm inline const std::string& issuer() const {
const oid_t& digest_algorithm(void) const; return this->issuer_;
};
//! @brief Return the AuthenticatedAttributes object //! Algorithm (OID) used to hash the file.
const AuthenticatedAttributes& authenticated_attributes(void) const; //!
//! 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) //! Return the (public-key) algorithm used to encrypt
const oid_t& signature_algorithm(void) const; //! 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 //! certificate's private key
const std::vector<uint8_t>& 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; 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); LIEF_API friend std::ostream& operator<<(std::ostream& os, const SignerInfo& signer_info);
private: private:
uint32_t version_; uint32_t version_;
issuer_t issuer_; std::string issuer_;
oid_t digest_algorithm_; std::vector<uint8_t> serialno_;
AuthenticatedAttributes authenticated_attributes_; ALGORITHMS digest_algorithm_ = ALGORITHMS::UNKNOWN;
oid_t signature_algorithm_; ALGORITHMS digest_enc_algorithm_ = ALGORITHMS::UNKNOWN;
std::vector<uint8_t> encrypted_digest_;
encrypted_digest_t encrypted_digest_;
std::vector<std::unique_ptr<Attribute>> authenticated_attributes_;
std::vector<std::unique_ptr<Attribute>> unauthenticated_attributes_;
std::unique_ptr<x509> cert_;
}; };

View File

@ -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

View File

@ -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 <memory>
#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<Attribute> clone(void) const override;
virtual void accept(Visitor& visitor) const override;
virtual ~ContentType();
private:
oid_t oid_;
};
}
}
#endif

View File

@ -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 <memory>
#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<uint8_t> raw);
GenericType(const GenericType&);
GenericType& operator=(const GenericType&);
virtual std::unique_ptr<Attribute> 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<uint8_t>& 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<uint8_t> raw_;
};
}
}
#endif

View File

@ -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<Attribute> 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

View File

@ -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<Attribute> 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

View File

@ -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<Attribute> 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

View File

@ -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<SignerInfo> signers);
PKCS9CounterSignature(const PKCS9CounterSignature&);
PKCS9CounterSignature& operator=(const PKCS9CounterSignature&);
virtual std::unique_ptr<Attribute> 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<SignerInfo> signers_;
};
}
}
#endif

View File

@ -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<uint8_t> digest);
PKCS9MessageDigest(const PKCS9MessageDigest&);
PKCS9MessageDigest& operator=(const PKCS9MessageDigest&);
virtual std::unique_ptr<Attribute> clone(void) const override;
//! Message digeset as a blob of bytes as described in the RFC
inline const std::vector<uint8_t>& 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<uint8_t> digest_;
};
}
}
#endif

View File

@ -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 <array>
#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<int32_t, 6>;
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<Attribute> clone(void) const override;
virtual void accept(Visitor& visitor) const override;
virtual ~PKCS9SigningTime();
private:
time_t time_;
};
}
}
#endif

View File

@ -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 <memory>
#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<Attribute> 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

View File

@ -24,10 +24,13 @@
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
class x509; class x509;
class SignerInfo;
class Attribute;
using oid_t = std::string; using oid_t = std::string;
using issuer_t = std::pair<std::string, std::vector<uint8_t>>; using it_const_crt = const_ref_iterator<const std::vector<x509>&>;
using it_const_crt = const_ref_iterator<const std::vector<x509>&>; using it_const_signers_t = const_ref_iterator<const std::vector<SignerInfo>&>;
using it_const_attributes_t = const_ref_iterator<std::vector<Attribute*>>;
} }
} }

View File

@ -15,13 +15,18 @@
*/ */
#ifndef LIEF_PE_X509_H_ #ifndef LIEF_PE_X509_H_
#define LIEF_PE_X509_H_ #define LIEF_PE_X509_H_
#include <tuple> #include <array>
#include <memory>
#include "LIEF/Object.hpp" #include "LIEF/Object.hpp"
#include "LIEF/visibility.h" #include "LIEF/visibility.h"
#include "LIEF/PE/enums.hpp"
#include "LIEF/PE/signature/types.hpp" #include "LIEF/PE/signature/types.hpp"
#include "LIEF/enums.hpp"
struct mbedtls_x509_crt; struct mbedtls_x509_crt;
namespace LIEF { namespace LIEF {
@ -30,44 +35,106 @@ namespace PE {
class Parser; class Parser;
class SignatureParser; class SignatureParser;
class RsaInfo;
class LIEF_API x509 : public Object { class LIEF_API x509 : public Object {
friend class Parser; friend class Parser;
friend class SignatureParser; friend class SignatureParser;
public: public:
//! @brief Tuple (Year, Month, Day, Hour, Minute, Second) //! Tuple (Year, Month, Day, Hour, Minute, Second)
using date_t = std::array<int32_t, 6>; using date_t = std::array<int32_t, 6>;
using certificates_t = std::vector<x509>;
static certificates_t parse(const std::string& path);
static certificates_t parse(const std::vector<uint8_t>& 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(mbedtls_x509_crt* ca);
x509(const x509& other); x509(const x509& other);
x509& operator=(x509 other); x509& operator=(x509 other);
void swap(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; 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<uint8_t> serial_number(void) const; std::vector<uint8_t> serial_number(void) const;
//! @brief Signature algorithm (OID) //! Signature algorithm (OID)
oid_t signature_algorithm(void) const; oid_t signature_algorithm(void) const;
//! @brief Start time of certificate validity //! Start time of certificate validity
x509::date_t valid_from(void) const; 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; x509::date_t valid_to(void) const;
//! @brief Issuer informations //! Issuer informations
std::string issuer(void) const; std::string issuer(void) const;
//! @brief Subject informations //! Subject informations
std::string subject(void) const; 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<uint8_t>& hash, const std::vector<uint8_t>& signature, ALGORITHMS digest) const;
//! The raw x509 bytes (DER encoded)
std::vector<uint8_t> raw(void) const; std::vector<uint8_t> 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<RsaInfo> 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<x509>& ca) const;
virtual void accept(Visitor& visitor) const override; virtual void accept(Visitor& visitor) const override;
virtual ~x509(void); virtual ~x509(void);
@ -76,11 +143,13 @@ class LIEF_API x509 : public Object {
private: private:
x509(void); x509(void);
mbedtls_x509_crt *x509_cert_; mbedtls_x509_crt* x509_cert_ = nullptr;
}; };
} }
} }
ENABLE_BITMASK_OPERATORS(LIEF::PE::x509::VERIFICATION_FLAGS);
#endif #endif

View File

@ -16,6 +16,7 @@
#ifndef LIEF_PE_TYPE_TRAITS_H_ #ifndef LIEF_PE_TYPE_TRAITS_H_
#define LIEF_PE_TYPE_TRAITS_H_ #define LIEF_PE_TYPE_TRAITS_H_
#include <vector> #include <vector>
#include <set>
#include "LIEF/iterators.hpp" #include "LIEF/iterators.hpp"
#include "LIEF/PE/enums.hpp" #include "LIEF/PE/enums.hpp"
@ -30,6 +31,7 @@ class RichEntry;
class RelocationEntry; class RelocationEntry;
class Debug; class Debug;
class PogoEntry; class PogoEntry;
class Signature;
class Import; class Import;
class ImportEntry; class ImportEntry;
@ -95,6 +97,10 @@ using rich_entries_t = std::vector<RichEntry>;
using it_rich_entries = ref_iterator<rich_entries_t&>; using it_rich_entries = ref_iterator<rich_entries_t&>;
using it_const_rich_entries = const_ref_iterator<const rich_entries_t&>; using it_const_rich_entries = const_ref_iterator<const rich_entries_t&>;
using signatures_t = std::vector<Signature>;
using it_signatures = ref_iterator<signatures_t&>;
using it_const_signatures = const_ref_iterator<const signatures_t&>;
template<class T> template<class T>
using flags_list_t = std::set<T>; using flags_list_t = std::set<T>;

View File

@ -62,6 +62,8 @@ LIEF_API std::string get_imphash(const Binary& binary);
//! //!
//! @return The PE::import resolved with PE::ImportEntry::name set //! @return The PE::import resolved with PE::ImportEntry::name set
LIEF_API Import resolve_ordinals(const Import& import, bool strict=false); LIEF_API Import resolve_ordinals(const Import& import, bool strict=false);
LIEF_API ALGORITHMS algo_from_oid(const std::string& oid);
} }
} }
#endif #endif

View File

@ -79,11 +79,23 @@ LIEF_PE_FORWARD(ResourceDialog)
LIEF_PE_FORWARD(ResourceDialogItem) LIEF_PE_FORWARD(ResourceDialogItem)
LIEF_PE_FORWARD(ResourceStringTable) LIEF_PE_FORWARD(ResourceStringTable)
LIEF_PE_FORWARD(ResourceAccelerator) LIEF_PE_FORWARD(ResourceAccelerator)
LIEF_PE_FORWARD(Signature) LIEF_PE_FORWARD(Signature)
LIEF_PE_FORWARD(x509) LIEF_PE_FORWARD(x509)
LIEF_PE_FORWARD(SignerInfo) LIEF_PE_FORWARD(SignerInfo)
LIEF_PE_FORWARD(ContentInfo) 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(CodeIntegrity)
LIEF_PE_FORWARD(LoadConfiguration) LIEF_PE_FORWARD(LoadConfiguration)
LIEF_PE_FORWARD(LoadConfigurationV0) LIEF_PE_FORWARD(LoadConfigurationV0)
@ -196,189 +208,216 @@ LIEF_ART_FORWARD(Header)
class LIEF_API Visitor { class LIEF_API Visitor {
public: public:
Visitor(void); Visitor(void);
virtual ~Visitor(void); virtual ~Visitor(void);
virtual void operator()(void); virtual void operator()(void);
template<typename Arg1, typename... Args> template<typename Arg1, typename... Args>
void operator()(Arg1&& arg1, Args&&... args); 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 //! Method to visit a LIEF::Binary
LIEF_ABSTRACT_VISITABLE(Binary) LIEF_ABSTRACT_VISITABLE(Binary)
//! Method to visit a LIEF::Header //! Method to visit a LIEF::Header
LIEF_ABSTRACT_VISITABLE(Header) LIEF_ABSTRACT_VISITABLE(Header)
//! Method to visit a LIEF::Section //! Method to visit a LIEF::Section
LIEF_ABSTRACT_VISITABLE(Section) LIEF_ABSTRACT_VISITABLE(Section)
//! Method to visit a LIEF::Symbol //! Method to visit a LIEF::Symbol
LIEF_ABSTRACT_VISITABLE(Symbol) LIEF_ABSTRACT_VISITABLE(Symbol)
//! Method to visit a LIEF::Relocation //! Method to visit a LIEF::Relocation
LIEF_ABSTRACT_VISITABLE(Relocation) LIEF_ABSTRACT_VISITABLE(Relocation)
//! Method to visit a LIEF::Function //! Method to visit a LIEF::Function
LIEF_ABSTRACT_VISITABLE(Function) LIEF_ABSTRACT_VISITABLE(Function)
LIEF_ELF_VISITABLE(Binary) LIEF_ELF_VISITABLE(Binary)
LIEF_ELF_VISITABLE(Header) LIEF_ELF_VISITABLE(Header)
LIEF_ELF_VISITABLE(Section) LIEF_ELF_VISITABLE(Section)
LIEF_ELF_VISITABLE(Segment) LIEF_ELF_VISITABLE(Segment)
LIEF_ELF_VISITABLE(DynamicEntry) LIEF_ELF_VISITABLE(DynamicEntry)
LIEF_ELF_VISITABLE(DynamicEntryArray) LIEF_ELF_VISITABLE(DynamicEntryArray)
LIEF_ELF_VISITABLE(DynamicEntryLibrary) LIEF_ELF_VISITABLE(DynamicEntryLibrary)
LIEF_ELF_VISITABLE(DynamicSharedObject) LIEF_ELF_VISITABLE(DynamicSharedObject)
LIEF_ELF_VISITABLE(DynamicEntryRunPath) LIEF_ELF_VISITABLE(DynamicEntryRunPath)
LIEF_ELF_VISITABLE(DynamicEntryRpath) LIEF_ELF_VISITABLE(DynamicEntryRpath)
LIEF_ELF_VISITABLE(DynamicEntryFlags) LIEF_ELF_VISITABLE(DynamicEntryFlags)
LIEF_ELF_VISITABLE(Symbol) LIEF_ELF_VISITABLE(Symbol)
LIEF_ELF_VISITABLE(Relocation) LIEF_ELF_VISITABLE(Relocation)
LIEF_ELF_VISITABLE(SymbolVersion) LIEF_ELF_VISITABLE(SymbolVersion)
LIEF_ELF_VISITABLE(SymbolVersionRequirement) LIEF_ELF_VISITABLE(SymbolVersionRequirement)
LIEF_ELF_VISITABLE(SymbolVersionDefinition) LIEF_ELF_VISITABLE(SymbolVersionDefinition)
LIEF_ELF_VISITABLE(SymbolVersionAux) LIEF_ELF_VISITABLE(SymbolVersionAux)
LIEF_ELF_VISITABLE(SymbolVersionAuxRequirement) LIEF_ELF_VISITABLE(SymbolVersionAuxRequirement)
LIEF_ELF_VISITABLE(Note) LIEF_ELF_VISITABLE(Note)
LIEF_ELF_VISITABLE(NoteDetails) LIEF_ELF_VISITABLE(NoteDetails)
LIEF_ELF_VISITABLE(AndroidNote) LIEF_ELF_VISITABLE(AndroidNote)
LIEF_ELF_VISITABLE(NoteAbi) LIEF_ELF_VISITABLE(NoteAbi)
LIEF_ELF_VISITABLE(CorePrPsInfo) LIEF_ELF_VISITABLE(CorePrPsInfo)
LIEF_ELF_VISITABLE(CorePrStatus) LIEF_ELF_VISITABLE(CorePrStatus)
LIEF_ELF_VISITABLE(CoreAuxv) LIEF_ELF_VISITABLE(CoreAuxv)
LIEF_ELF_VISITABLE(CoreSigInfo) LIEF_ELF_VISITABLE(CoreSigInfo)
LIEF_ELF_VISITABLE(CoreFile) LIEF_ELF_VISITABLE(CoreFile)
LIEF_ELF_VISITABLE(GnuHash) LIEF_ELF_VISITABLE(GnuHash)
LIEF_ELF_VISITABLE(SysvHash) LIEF_ELF_VISITABLE(SysvHash)
// PE Part // PE Part
// ======= // =======
//! Method to visit a LIEF::PE::Binary //! Method to visit a LIEF::PE::Binary
LIEF_PE_VISITABLE(Binary) LIEF_PE_VISITABLE(Binary)
//! Method to visit a LIEF::PE::DosHeader //! Method to visit a LIEF::PE::DosHeader
LIEF_PE_VISITABLE(DosHeader) LIEF_PE_VISITABLE(DosHeader)
//! Method to visit a LIEF::PE:RichHeader //! Method to visit a LIEF::PE:RichHeader
LIEF_PE_VISITABLE(RichHeader) LIEF_PE_VISITABLE(RichHeader)
//! Method to visit a LIEF::PE:RichEntry //! Method to visit a LIEF::PE:RichEntry
LIEF_PE_VISITABLE(RichEntry) LIEF_PE_VISITABLE(RichEntry)
//! Method to visit a LIEF::PE::Header //! Method to visit a LIEF::PE::Header
LIEF_PE_VISITABLE(Header) LIEF_PE_VISITABLE(Header)
//! Method to visit a LIEF::PE::OptionalHeader //! Method to visit a LIEF::PE::OptionalHeader
LIEF_PE_VISITABLE(OptionalHeader) LIEF_PE_VISITABLE(OptionalHeader)
//! Method to visit a LIEF::PE::DataDirectory //! Method to visit a LIEF::PE::DataDirectory
LIEF_PE_VISITABLE(DataDirectory) LIEF_PE_VISITABLE(DataDirectory)
//! Method to visit a LIEF::PE::TLS //! Method to visit a LIEF::PE::TLS
LIEF_PE_VISITABLE(TLS) LIEF_PE_VISITABLE(TLS)
//! Method to visit a LIEF::PE::Symbol //! Method to visit a LIEF::PE::Symbol
LIEF_PE_VISITABLE(Symbol) LIEF_PE_VISITABLE(Symbol)
//! Method to visit a LIEF::PE::Section //! Method to visit a LIEF::PE::Section
LIEF_PE_VISITABLE(Section) LIEF_PE_VISITABLE(Section)
//! Method to visit a LIEF::PE::Relocation //! Method to visit a LIEF::PE::Relocation
LIEF_PE_VISITABLE(Relocation) LIEF_PE_VISITABLE(Relocation)
//! Method to visit a LIEF::PE::RelocationEntry //! Method to visit a LIEF::PE::RelocationEntry
LIEF_PE_VISITABLE(RelocationEntry) LIEF_PE_VISITABLE(RelocationEntry)
//! Method to visit a LIEF::PE::Export //! Method to visit a LIEF::PE::Export
LIEF_PE_VISITABLE(Export) LIEF_PE_VISITABLE(Export)
//! Method to visit a LIEF::PE::ExportEntry //! Method to visit a LIEF::PE::ExportEntry
LIEF_PE_VISITABLE(ExportEntry) LIEF_PE_VISITABLE(ExportEntry)
//! Method to visit a LIEF::PE::Debug //! Method to visit a LIEF::PE::Debug
LIEF_PE_VISITABLE(Debug) LIEF_PE_VISITABLE(Debug)
//! Method to visit a LIEF::PE::CodeView //! Method to visit a LIEF::PE::CodeView
LIEF_PE_VISITABLE(CodeView) LIEF_PE_VISITABLE(CodeView)
//! Method to visit a LIEF::PE::CodeViewPDB //! Method to visit a LIEF::PE::CodeViewPDB
LIEF_PE_VISITABLE(CodeViewPDB) LIEF_PE_VISITABLE(CodeViewPDB)
//! Method to visit a LIEF::PE::Import //! Method to visit a LIEF::PE::Import
LIEF_PE_VISITABLE(Import) LIEF_PE_VISITABLE(Import)
//! Method to visit a LIEF::PE::ImportEntry //! Method to visit a LIEF::PE::ImportEntry
LIEF_PE_VISITABLE(ImportEntry) LIEF_PE_VISITABLE(ImportEntry)
//! Method to visit a LIEF::PE::ResourceNode //! Method to visit a LIEF::PE::ResourceNode
LIEF_PE_VISITABLE(ResourceNode) LIEF_PE_VISITABLE(ResourceNode)
//! Method to visit a LIEF::PE::ResourceData //! Method to visit a LIEF::PE::ResourceData
LIEF_PE_VISITABLE(ResourceData) LIEF_PE_VISITABLE(ResourceData)
//! Method to visit a LIEF::PE::ResourceDirectory //! Method to visit a LIEF::PE::ResourceDirectory
LIEF_PE_VISITABLE(ResourceDirectory) LIEF_PE_VISITABLE(ResourceDirectory)
//! Method to visit a LIEF::PE::ResourceVersion //! Method to visit a LIEF::PE::ResourceVersion
LIEF_PE_VISITABLE(ResourcesManager) LIEF_PE_VISITABLE(ResourcesManager)
//! Method to visit a LIEF::PE::ResourceVersion //! Method to visit a LIEF::PE::ResourceVersion
LIEF_PE_VISITABLE(ResourceVersion) LIEF_PE_VISITABLE(ResourceVersion)
//! Method to visit a LIEF::PE::ResourceStringFileInfo //! Method to visit a LIEF::PE::ResourceStringFileInfo
LIEF_PE_VISITABLE(ResourceStringFileInfo) LIEF_PE_VISITABLE(ResourceStringFileInfo)
//! Method to visit a LIEF::PE::ResourceFixedFileInfo //! Method to visit a LIEF::PE::ResourceFixedFileInfo
LIEF_PE_VISITABLE(ResourceFixedFileInfo) LIEF_PE_VISITABLE(ResourceFixedFileInfo)
//! Method to visit a LIEF::PE::ResourceVarFileInfo //! Method to visit a LIEF::PE::ResourceVarFileInfo
LIEF_PE_VISITABLE(ResourceVarFileInfo) LIEF_PE_VISITABLE(ResourceVarFileInfo)
//! Method to visit a LIEF::PE::ResourceStringTable //! Method to visit a LIEF::PE::ResourceStringTable
LIEF_PE_VISITABLE(ResourceStringTable) LIEF_PE_VISITABLE(ResourceStringTable)
//! Method to visit a LIEF::PE::ResourceAccelerator //! Method to visit a LIEF::PE::ResourceAccelerator
LIEF_PE_VISITABLE(ResourceAccelerator) LIEF_PE_VISITABLE(ResourceAccelerator)
//! Method to visit a LIEF::PE::LangCodeItem //! Method to visit a LIEF::PE::LangCodeItem
LIEF_PE_VISITABLE(LangCodeItem) LIEF_PE_VISITABLE(LangCodeItem)
//! Method to visit a LIEF::PE::ResourceIcon //! Method to visit a LIEF::PE::ResourceIcon
LIEF_PE_VISITABLE(ResourceIcon) LIEF_PE_VISITABLE(ResourceIcon)
//! Method to visit a LIEF::PE::ResourceDialog //! Method to visit a LIEF::PE::ResourceDialog
LIEF_PE_VISITABLE(ResourceDialog) LIEF_PE_VISITABLE(ResourceDialog)
//! Method to visit a LIEF::PE::ResourceDialogItem //! Method to visit a LIEF::PE::ResourceDialogItem
LIEF_PE_VISITABLE(ResourceDialogItem) LIEF_PE_VISITABLE(ResourceDialogItem)
//! Method to visit a LIEF::PE::Signature //! Method to visit a LIEF::PE::Signature
LIEF_PE_VISITABLE(Signature) LIEF_PE_VISITABLE(Signature)
//! Method to visit a LIEF::PE::x509 //! Method to visit a LIEF::PE::x509
LIEF_PE_VISITABLE(x509) LIEF_PE_VISITABLE(x509)
//! Method to visit a LIEF::PE::SignerInfo //! Method to visit a LIEF::PE::SignerInfo
LIEF_PE_VISITABLE(SignerInfo) LIEF_PE_VISITABLE(SignerInfo)
//! Method to visit a LIEF::PE::ContentInfo //! Method to visit a LIEF::PE::ContentInfo
LIEF_PE_VISITABLE(ContentInfo) LIEF_PE_VISITABLE(ContentInfo)
//! Method to visit a LIEF::PE::AuthenticatedAttributes //! Method to visit a LIEF::PE::Attribute
LIEF_PE_VISITABLE(AuthenticatedAttributes) LIEF_PE_VISITABLE(Attribute)
//! Method to visit a LIEF::PE::issuer_t //! Method to visit a LIEF::PE::ContentType
LIEF_PE_VISITABLE(issuer_t) LIEF_PE_VISITABLE(ContentType)
//! Method to visit a LIEF::PE::LoadConfiguration //! Method to visit a LIEF::PE::GenericType
LIEF_PE_VISITABLE(LoadConfiguration) 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 //! Method to visit a LIEF::PE::LoadConfigurationV0
LIEF_PE_VISITABLE(LoadConfigurationV0) LIEF_PE_VISITABLE(LoadConfigurationV0)

81
include/LIEF/errors.hpp Normal file
View File

@ -0,0 +1,81 @@
#ifndef LIEF_ERROR_H_
#define LIEF_ERROR_H_
#include <system_error>
#include <LIEF/third-party/boost/leaf/all.hpp>
//! 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<lief_errors>: 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<int> 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<typename T>
using result = boost::leaf::result<T>;
//! Abstraction over the implementation
template<typename T>
using error_result_t = typename result<T>::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<class T>
std::error_code get_error(result<T>& err) {
return make_error_code(lief_errors(boost::leaf::error_id(err.error()).value()));
}
}
#endif

View File

@ -19,6 +19,7 @@
#include <streambuf> #include <streambuf>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <array>
#include "LIEF/BinaryStream/Convert.hpp" #include "LIEF/BinaryStream/Convert.hpp"
@ -39,6 +40,7 @@ class vector_iostream {
vector_iostream& write(std::vector<uint8_t>&& s); vector_iostream& write(std::vector<uint8_t>&& s);
vector_iostream& write(const std::string& s); vector_iostream& write(const std::string& s);
vector_iostream& write(size_t count, uint8_t value); vector_iostream& write(size_t count, uint8_t value);
vector_iostream& write_sized_int(uint64_t value, size_t size);
template<typename T> template<typename T>
vector_iostream& write_conv(const T& t); vector_iostream& write_conv(const T& t);
@ -54,17 +56,23 @@ class vector_iostream {
this->raw_.resize(static_cast<size_t>(this->tellp()) + sizeof(Integer)); this->raw_.resize(static_cast<size_t>(this->tellp()) + sizeof(Integer));
} }
auto&& it = std::begin(this->raw_); auto int_p = reinterpret_cast<const uint8_t*>(&integer);
std::advance(it, static_cast<size_t>(this->tellp()));
std::copy( std::copy(
reinterpret_cast<const Integer*>(&integer), int_p, int_p + sizeof(Integer),
reinterpret_cast<const Integer*>(&integer) + sizeof(Integer), std::begin(this->raw_) + static_cast<size_t>(this->tellp()));
it);
this->current_pos_ += sizeof(Integer); this->current_pos_ += sizeof(Integer);
return *this; return *this;
} }
template<typename T, size_t size, typename = typename std::enable_if<std::is_integral<T>::value>>
vector_iostream& write(const std::array<T, size>& t) {
for (T val : t) {
this->write<T>(val);
}
return *this;
}
vector_iostream& write_uleb128(uint64_t value); vector_iostream& write_uleb128(uint64_t value);
vector_iostream& write_sleb128(int64_t value); vector_iostream& write_sleb128(int64_t value);

View File

@ -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_str(uint8_t c);
LIEF_API std::string hex_dump(const std::vector<uint8_t>& data, std::string sep = ":");
//! Check if the given string in printable //! Check if the given string in printable
LIEF_API bool is_printable(const std::string& str); LIEF_API bool is_printable(const std::string& str);

View File

@ -21,11 +21,28 @@
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <mbedtls/platform.h>
#include <mbedtls/asn1.h>
#include <mbedtls/error.h>
#include <mbedtls/oid.h>
#include <mbedtls/x509_crt.h>
#include "logging.hpp" #include "logging.hpp"
#include "LIEF/BinaryStream/VectorStream.hpp" #include "LIEF/BinaryStream/VectorStream.hpp"
#include "LIEF/exception.hpp" #include "LIEF/exception.hpp"
namespace LIEF { 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) { VectorStream::VectorStream(const std::string& filename) {
std::ifstream binary(filename, std::ios::in | std::ios::binary); 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; return this->binary_.data() + offset;
} }
result<size_t> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return out;
}
result<size_t> VectorStream::asn1_peek_len() {
const uint64_t pos = this->pos();
auto len = this->asn1_read_len();
this->setpos(pos);
return len;
}
result<size_t> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return len;
}
result<std::string> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::string(oid_str);
}
result<std::string> 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<int32_t> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return value;
}
result<std::vector<uint8_t>> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::vector<uint8_t>{bs.p, bs.p + bs.len};
}
else if (ret != 0) {
return make_error_code(lief_errors::read_error);
}
this->increment_pos(reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::vector<uint8_t>{bs.p, bs.p + bs.len};
}
result<std::vector<uint8_t>> VectorStream::asn1_read_octet_string() {
auto tag = this->asn1_read_tag(MBEDTLS_ASN1_OCTET_STRING);
if (not tag) {
return tag.error();
}
std::vector<uint8_t> raw = {this->p(), this->p() + tag.value()};
this->increment_pos(tag.value());
return raw;
}
result<std::unique_ptr<mbedtls_x509_crt>> VectorStream::asn1_read_cert() {
std::unique_ptr<mbedtls_x509_crt> 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<uintptr_t>(end) - reinterpret_cast<uintptr_t>(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<std::string> 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<uint8_t>(), 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::string(buffer);
}
result<std::vector<uint8_t>> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::vector<uint8_t>{serial.p, serial.p + serial.len};
}
result<std::unique_ptr<mbedtls_x509_time>> VectorStream::x509_read_time() {
std::unique_ptr<mbedtls_x509_time> 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<uintptr_t>(p) - reinterpret_cast<uintptr_t>(cur_p));
return std::move(tm);
}
const std::vector<uint8_t>& VectorStream::content(void) const { const std::vector<uint8_t>& VectorStream::content(void) const {
return this->binary_; return this->binary_;
} }

View File

@ -21,10 +21,12 @@
#include <limits> #include <limits>
#include "logging.hpp" #include "logging.hpp"
#include "hash_stream.hpp"
#include "LIEF/exception.hpp" #include "LIEF/exception.hpp"
#include "LIEF/utils.hpp" #include "LIEF/utils.hpp"
#include "LIEF/BinaryStream/VectorStream.hpp" #include "LIEF/BinaryStream/VectorStream.hpp"
#include "LIEF/iostream.hpp"
#include "LIEF/Abstract/Relocation.hpp" #include "LIEF/Abstract/Relocation.hpp"
@ -98,7 +100,6 @@ Binary::Binary(void) :
has_rich_header_{false}, has_rich_header_{false},
has_tls_{false}, has_tls_{false},
has_imports_{false}, has_imports_{false},
has_signature_{false},
has_exports_{false}, has_exports_{false},
has_resources_{false}, has_resources_{false},
has_exceptions_{false}, has_exceptions_{false},
@ -347,8 +348,8 @@ bool Binary::has_imports(void) const {
return this->has_imports_; return this->has_imports_;
} }
bool Binary::has_signature(void) const { bool Binary::has_signatures(void) const {
return this->has_signature_; return not this->signatures_.empty();
} }
bool Binary::has_exports(void) const { bool Binary::has_exports(void) const {
@ -1011,8 +1012,228 @@ const debug_entries_t& Binary::debug(void) const {
// //
///////////////////// /////////////////////
const Signature& Binary::signature(void) const { it_const_signatures Binary::signatures(void) const {
return this->signature_; return this->signatures_;
}
std::vector<uint8_t> Binary::authentihash(ALGORITHMS algo) const {
static const std::map<ALGORITHMS, hashstream::HASH> 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<uint16_t>(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<uint16_t>(this->header_.characteristics()));
ios // Hash OptionalHeader
.write(static_cast<uint16_t>(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<uint16_t>(this->optional_header_.subsystem()))
.write(static_cast<uint16_t>(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<uint32_t>(0)
.write<uint32_t>(0);
for (const Section* sec : this->sections_) {
std::array<char, 8> name = {0};
const std::string& sec_name = sec->name();
uint32_t name_length = std::min<uint32_t>(sec_name.size() + 1, sizeof(name));
std::copy(sec_name.c_str(), sec_name.c_str() + name_length, std::begin(name));
ios
.write(name)
.write(sec->virtual_size())
.write<uint32_t>(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<uint32_t>(sec->characteristics()));
}
//LIEF_DEBUG("Section padding at 0x{:x}", ios.tellp());
ios.write(this->section_offset_padding_);
std::vector<Section*> 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<uint8_t>& pad = sec->padding();
const std::vector<uint8_t>& 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<uint8_t> 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<char>(output_file));
// }
// std::vector<uint8_t> hash = hashstream(hash_type).write(out).raw();
std::vector<uint8_t> 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<uintptr_t>(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<uintptr_t>(value));
return value;
}
// Check that the authentihash matches Content Info's digest
const std::vector<uint8_t>& authhash = this->authentihash(sig.digest_algorithm());
const std::vector<uint8_t>& 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()) { if (this->has_signatures()) {
os << "Signature" << std::endl; os << "Signatures" << std::endl;
os << "=========" << std::endl; os << "==========" << std::endl;
os << this->signature() << std::endl; for (const Signature& sig : this->signatures_) {
os << sig << std::endl;
}
os << std::endl; os << std::endl;
} }

View File

@ -444,33 +444,33 @@ void Builder::build_overlay(void) {
Builder& Builder::operator<<(const DosHeader& dos_header) { Builder& Builder::operator<<(const DosHeader& dos_header) {
pe_dos_header dosHeader; pe_dos_header raw_dos_header;
dosHeader.Magic = static_cast<uint16_t>(dos_header.magic()); raw_dos_header.Magic = static_cast<uint16_t>(dos_header.magic());
dosHeader.UsedBytesInTheLastPage = static_cast<uint16_t>(dos_header.used_bytes_in_the_last_page()); raw_dos_header.UsedBytesInTheLastPage = static_cast<uint16_t>(dos_header.used_bytes_in_the_last_page());
dosHeader.FileSizeInPages = static_cast<uint16_t>(dos_header.file_size_in_pages()); raw_dos_header.FileSizeInPages = static_cast<uint16_t>(dos_header.file_size_in_pages());
dosHeader.NumberOfRelocationItems = static_cast<uint16_t>(dos_header.numberof_relocation()); raw_dos_header.NumberOfRelocationItems = static_cast<uint16_t>(dos_header.numberof_relocation());
dosHeader.HeaderSizeInParagraphs = static_cast<uint16_t>(dos_header.header_size_in_paragraphs()); raw_dos_header.HeaderSizeInParagraphs = static_cast<uint16_t>(dos_header.header_size_in_paragraphs());
dosHeader.MinimumExtraParagraphs = static_cast<uint16_t>(dos_header.minimum_extra_paragraphs()); raw_dos_header.MinimumExtraParagraphs = static_cast<uint16_t>(dos_header.minimum_extra_paragraphs());
dosHeader.MaximumExtraParagraphs = static_cast<uint16_t>(dos_header.maximum_extra_paragraphs()); raw_dos_header.MaximumExtraParagraphs = static_cast<uint16_t>(dos_header.maximum_extra_paragraphs());
dosHeader.InitialRelativeSS = static_cast<uint16_t>(dos_header.initial_relative_ss()); raw_dos_header.InitialRelativeSS = static_cast<uint16_t>(dos_header.initial_relative_ss());
dosHeader.InitialSP = static_cast<uint16_t>(dos_header.initial_sp()); raw_dos_header.InitialSP = static_cast<uint16_t>(dos_header.initial_sp());
dosHeader.Checksum = static_cast<uint16_t>(dos_header.checksum()); raw_dos_header.Checksum = static_cast<uint16_t>(dos_header.checksum());
dosHeader.InitialIP = static_cast<uint16_t>(dos_header.initial_ip()); raw_dos_header.InitialIP = static_cast<uint16_t>(dos_header.initial_ip());
dosHeader.InitialRelativeCS = static_cast<uint16_t>(dos_header.initial_relative_cs()); raw_dos_header.InitialRelativeCS = static_cast<uint16_t>(dos_header.initial_relative_cs());
dosHeader.AddressOfRelocationTable = static_cast<uint16_t>(dos_header.addressof_relocation_table()); raw_dos_header.AddressOfRelocationTable = static_cast<uint16_t>(dos_header.addressof_relocation_table());
dosHeader.OverlayNumber = static_cast<uint16_t>(dos_header.overlay_number()); raw_dos_header.OverlayNumber = static_cast<uint16_t>(dos_header.overlay_number());
dosHeader.OEMid = static_cast<uint16_t>(dos_header.oem_id()); raw_dos_header.OEMid = static_cast<uint16_t>(dos_header.oem_id());
dosHeader.OEMinfo = static_cast<uint16_t>(dos_header.oem_info()); raw_dos_header.OEMinfo = static_cast<uint16_t>(dos_header.oem_info());
dosHeader.AddressOfNewExeHeader = static_cast<uint16_t>(dos_header.addressof_new_exeheader()); raw_dos_header.AddressOfNewExeHeader = static_cast<uint16_t>(dos_header.addressof_new_exeheader());
const DosHeader::reserved_t& reserved = dos_header.reserved(); const DosHeader::reserved_t& reserved = dos_header.reserved();
const DosHeader::reserved2_t& reserved2 = dos_header.reserved2(); const DosHeader::reserved2_t& reserved2 = dos_header.reserved2();
std::copy(std::begin(reserved), std::end(reserved), std::begin(dosHeader.Reserved)); std::copy(std::begin(reserved), std::end(reserved), std::begin(raw_dos_header.Reserved));
std::copy(std::begin(reserved2), std::end(reserved2), std::begin(dosHeader.Reserved2)); std::copy(std::begin(reserved2), std::end(reserved2), std::begin(raw_dos_header.Reserved2));
this->ios_.seekp(0); this->ios_.seekp(0);
this->ios_.write(reinterpret_cast<const uint8_t*>(&dosHeader), sizeof(pe_dos_header)); this->ios_.write(reinterpret_cast<const uint8_t*>(&raw_dos_header), sizeof(pe_dos_header));
if (this->binary_->dos_stub().size() > 0 and this->build_dos_stub_) { 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()) { if (sizeof(pe_dos_header) + this->binary_->dos_stub().size() > dos_header.addressof_new_exeheader()) {

View File

@ -29,13 +29,6 @@ set(LIEF_PE_SRC
"${CMAKE_CURRENT_LIST_DIR}/RelocationEntry.cpp" "${CMAKE_CURRENT_LIST_DIR}/RelocationEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/DataDirectory.cpp" "${CMAKE_CURRENT_LIST_DIR}/DataDirectory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/CodeIntegrity.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}/Builder.tcc"
"${CMAKE_CURRENT_LIST_DIR}/Parser.tcc" "${CMAKE_CURRENT_LIST_DIR}/Parser.tcc"
"${CMAKE_CURRENT_LIST_DIR}/resources/ResourceVersion.cpp" "${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/ResourceNode.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/ResourcesManager.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/ResourcesManager.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/Section.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/Symbol.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/TLS.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/TLS.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/type_traits.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" "${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 set(LIEF_PE_RESOURCES_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/resources/ResourceVersion.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/resources/ResourceVersion.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/PE/resources/ResourceDialog.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" FILES ${LIEF_PE_SRC})
source_group("Source Files\\PE\\Load Configure" FILES ${LIEF_PE_LOAD_CONFIGURATION_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" 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\\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\\Load Configuration" FILES ${LIEF_PE_LOAD_CONFIGURATION_INCLUDE})
source_group("Header Files\\PE\\utils\\Ordinals Lookup Tables" FILES ${LIEF_PE_UTILS_INCLUDE_FILES}) 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} ${LIEF_PE_LOAD_CONFIGURATION_INCLUDE}
) )
endif() endif()
include("${CMAKE_CURRENT_LIST_DIR}/signature/CMakeLists.txt")

View File

@ -1337,5 +1337,54 @@ const char* to_string(ACCELERATOR_VK_CODES e) {
return it != enumStrings.end() ? it->second : "Undefined or reserved"; 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 PE
} // namespace LIEF } // namespace LIEF

View File

@ -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); 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<uint8_t>(sizeof(pe_dos_header), sizeof_dos_stub, /* check */false); const uint8_t* ptr_to_dos_stub = this->stream_->peek_array<uint8_t>(sizeof(pe_dos_header), sizeof_dos_stub, /* check */false);
if (ptr_to_dos_stub == nullptr) { if (ptr_to_dos_stub == nullptr) {
@ -224,7 +224,9 @@ void Parser::parse_sections(void) {
uint32_t size_to_read = 0; uint32_t size_to_read = 0;
uint32_t offset = sections[i].PointerToRawData; 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) { if (sections[i].VirtualSize > 0) {
size_to_read = std::min(sections[i].VirtualSize, sections[i].SizeOfRawData); // According to Corkami 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 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<uint8_t>(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()); this->binary_->sections_.push_back(section.release());
} }
const uint32_t last_section_header_offset = sections_offset + numberof_sections * sizeof(pe_section); 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<uint8_t>(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; 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_); 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) { void Parser::parse_signature(void) {
LIEF_DEBUG("== Parsing signature =="); LIEF_DEBUG("== Parsing signature ==");
static constexpr size_t SIZEOF_HEADER = 8;
/*** /!\ In this data directory, RVA is used as an **OFFSET** /!\ ****/ /*** /!\ 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_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 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 Offset: 0x{:04x}", signature_offset);
LIEF_DEBUG("Signature Size: 0x{:04x}", signature_size); LIEF_DEBUG("Signature Size: 0x{:04x}", signature_size);
const uint8_t* signature_ptr = this->stream_->peek_array<uint8_t>(signature_offset, signature_size, /* check */false); this->stream_->setpos(signature_offset);
if (signature_ptr == nullptr) { while (this->stream_->pos() < end_p) {
return; const uint64_t current_p = this->stream_->pos();
} auto length = this->stream_->read<uint32_t>();
std::vector<uint8_t> raw_signature = {signature_ptr, signature_ptr + signature_size}; auto revision = this->stream_->read<uint16_t>();
auto certificate_type = this->stream_->read<uint16_t>();
LIEF_DEBUG("Signature {}r0x{:x} (0x{:x} bytes)", certificate_type, revision, length);
const uint8_t* data_ptr = this->stream_->read_array<uint8_t>(length - SIZEOF_HEADER, /* check */false);
if (data_ptr == nullptr) {
LIEF_INFO("Can't read 0x{:x} bytes", length);
break;
}
std::vector<uint8_t> raw_signature = {data_ptr, data_ptr + length - SIZEOF_HEADER};
auto sign = SignatureParser::parse(std::move(raw_signature));
//TODO: Deal with header (+8) if (sign) {
this->binary_->signature_ = SignatureParser::parse(raw_signature); this->binary_->signatures_.push_back(std::move(sign.value()));
this->binary_->has_signature_ = true; } 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,
ptr_to_overlay + overlay_size ptr_to_overlay + overlay_size
}; };
this->binary_->overlay_offset_ = last_section_offset;
} }
} else { } else {
this->binary_->overlay_ = {}; this->binary_->overlay_ = {};

View File

@ -31,28 +31,18 @@ namespace PE {
Section::~Section(void) = default; Section::~Section(void) = default;
Section::Section(void) : Section::Section(void) = default;
LIEF::Section{},
virtualSize_{0},
content_{},
pointerToRelocations_{0},
pointerToLineNumbers_{0},
numberOfRelocations_{0},
numberOfLineNumbers_{0},
characteristics_{0},
types_{PE_SECTION_TYPES::UNKNOWN}
{}
Section& Section::operator=(const Section&) = default; Section& Section::operator=(const Section&) = default;
Section::Section(const Section&) = default; Section::Section(const Section&) = default;
Section::Section(const pe_section* header) : Section::Section(const pe_section* header) :
virtualSize_{header->VirtualSize}, virtual_size_{header->VirtualSize},
pointerToRelocations_{header->PointerToRelocations}, pointer_to_relocations_{header->PointerToRelocations},
pointerToLineNumbers_{header->PointerToLineNumbers}, pointer_to_linenumbers_{header->PointerToLineNumbers},
numberOfRelocations_{header->NumberOfRelocations}, number_of_relocations_{header->NumberOfRelocations},
numberOfLineNumbers_{header->NumberOfLineNumbers}, number_of_linenumbers_{header->NumberOfLineNumbers},
characteristics_{header->Characteristics}, characteristics_{header->Characteristics},
types_{PE_SECTION_TYPES::UNKNOWN} types_{PE_SECTION_TYPES::UNKNOWN}
{ {
@ -60,7 +50,6 @@ Section::Section(const pe_section* header) :
this->virtual_address_ = header->VirtualAddress; this->virtual_address_ = header->VirtualAddress;
this->size_ = header->SizeOfRawData; this->size_ = header->SizeOfRawData;
this->offset_ = header->PointerToRawData; this->offset_ = header->PointerToRawData;
} }
Section::Section(const std::vector<uint8_t>& data, const std::string& name, uint32_t characteristics) : Section::Section(const std::vector<uint8_t>& 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 { 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 { uint32_t Section::pointerto_relocation(void) const {
return this->pointerToRelocations_; return this->pointer_to_relocations_;
} }
uint32_t Section::pointerto_line_numbers(void) const { uint32_t Section::pointerto_line_numbers(void) const {
return this->pointerToLineNumbers_; return this->pointer_to_linenumbers_;
} }
uint16_t Section::numberof_relocations(void) const { uint16_t Section::numberof_relocations(void) const {
return this->numberOfRelocations_; return this->number_of_relocations_;
} }
uint16_t Section::numberof_line_numbers(void) const { uint16_t Section::numberof_line_numbers(void) const {
return this->numberOfLineNumbers_; return this->number_of_linenumbers_;
} }
uint32_t Section::characteristics(void) const { uint32_t Section::characteristics(void) const {
@ -164,7 +153,7 @@ void Section::content(const std::vector<uint8_t>& data) {
void Section::virtual_size(uint32_t virtualSize) { 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) { void Section::pointerto_relocation(uint32_t pointerToRelocation) {
this->pointerToRelocations_ = pointerToRelocation; this->pointer_to_relocations_ = pointerToRelocation;
} }
void Section::pointerto_line_numbers(uint32_t pointerToLineNumbers) { void Section::pointerto_line_numbers(uint32_t pointerToLineNumbers) {
this->pointerToLineNumbers_ = pointerToLineNumbers; this->pointer_to_linenumbers_ = pointerToLineNumbers;
} }
void Section::numberof_relocations(uint16_t numberOfRelocations) { void Section::numberof_relocations(uint16_t numberOfRelocations) {
this->numberOfRelocations_ = numberOfRelocations; this->number_of_relocations_ = numberOfRelocations;
} }
void Section::numberof_line_numbers(uint16_t numberOfLineNumbers) { void Section::numberof_line_numbers(uint16_t numberOfLineNumbers) {
this->numberOfLineNumbers_ = numberOfLineNumbers; this->number_of_linenumbers_ = numberOfLineNumbers;
} }
void Section::sizeof_raw_data(uint32_t sizeOfRawData) { void Section::sizeof_raw_data(uint32_t sizeOfRawData) {

View File

@ -437,17 +437,14 @@ void Hash::visit(const ResourceAccelerator& accelerator) {
} }
void Hash::visit(const Signature& signature) { void Hash::visit(const Signature& signature) {
this->process(signature.version()); this->process(signature.version());
this->process(signature.digest_algorithm()); this->process(signature.digest_algorithm());
this->process(signature.content_info()); this->process(signature.content_info());
this->process(std::begin(signature.certificates()), std::end(signature.certificates())); this->process(std::begin(signature.certificates()), std::end(signature.certificates()));
this->process(signature.signer_info()); this->process(std::begin(signature.signers()), std::end(signature.signers()));
this->process(signature.original_signature());
} }
void Hash::visit(const x509& x509) { void Hash::visit(const x509& x509) {
this->process(x509.subject()); this->process(x509.subject());
this->process(x509.issuer()); this->process(x509.issuer());
this->process(x509.valid_to()); this->process(x509.valid_to());
@ -460,19 +457,65 @@ void Hash::visit(const x509& x509) {
void Hash::visit(const SignerInfo& signerinfo) { void Hash::visit(const SignerInfo& signerinfo) {
this->process(signerinfo.version()); 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.digest_algorithm());
this->process(signerinfo.authenticated_attributes());
this->process(signerinfo.signature_algorithm());
this->process(signerinfo.encrypted_digest()); 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()); void Hash::visit(const ContentInfo& info) {
this->process(auth.message_digest()); this->process(info.content_type());
this->process(u16tou8(auth.program_name())); this->process(info.digest_algorithm());
this->process(auth.more_info()); this->process(info.digest());
this->process(info.file());
}
void Hash::visit(const ContentType& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.oid());
}
void Hash::visit(const GenericType& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.raw_content());
this->process(attr.oid());
}
void Hash::visit(const MsSpcNestedSignature& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.sig());
}
void Hash::visit(const MsSpcStatementType& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.oid());
}
void Hash::visit(const PKCS9AtSequenceNumber& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.number());
}
void Hash::visit(const PKCS9CounterSignature& attr) {
this->visit(*attr.as<Attribute>());
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<Attribute>());
this->process(attr.digest());
}
void Hash::visit(const PKCS9SigningTime& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.time());
}
void Hash::visit(const SpcSpOpusInfo& attr) {
this->visit(*attr.as<Attribute>());
this->process(attr.program_name());
this->process(attr.more_info());
} }
void Hash::visit(const CodeIntegrity& code_integrity) { void Hash::visit(const CodeIntegrity& code_integrity) {

View File

@ -22,6 +22,8 @@
#include "LIEF/PE/json.hpp" #include "LIEF/PE/json.hpp"
#include "LIEF/PE.hpp" #include "LIEF/PE.hpp"
#include "Object.tcc"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
@ -165,11 +167,15 @@ void JsonVisitor::visit(const Binary& binary) {
} }
// Signature // Signatures
if (binary.has_signature()) { std::vector<json> sigs;
JsonVisitor visitor; if (binary.has_signatures()) {
visitor(binary.signature()); for (const Signature& sig : binary.signatures()) {
this->node_["signature"] = visitor.get(); JsonVisitor visitor;
visitor(sig);
sigs.push_back(std::move(visitor.get()));
}
this->node_["signatures"] = sigs;
} }
std::vector<json> symbols; std::vector<json> symbols;
@ -762,20 +768,25 @@ void JsonVisitor::visit(const Signature& signature) {
JsonVisitor content_info_visitor; JsonVisitor content_info_visitor;
content_info_visitor(signature.content_info()); content_info_visitor(signature.content_info());
JsonVisitor signer_info_visitor; std::vector<json> jsigners;
signer_info_visitor(signature.signer_info()); for (const SignerInfo& signer : signature.signers()) {
JsonVisitor visitor;
visitor(signer);
jsigners.emplace_back(std::move(visitor.get()));
}
std::vector<json> crts; std::vector<json> crts;
for (const x509& crt : signature.certificates()) { for (const x509& crt : signature.certificates()) {
JsonVisitor crt_visitor; JsonVisitor crt_visitor;
crt_visitor(crt); crt_visitor(crt);
crts.emplace_back(crt_visitor.get()); crts.emplace_back(std::move(crt_visitor.get()));
} }
this->node_["version"] = signature.version(); this->node_["digest_algorithm"] = to_string(signature.digest_algorithm());
this->node_["content_info"] = content_info_visitor.get(); this->node_["version"] = signature.version();
this->node_["signer_info"] = signer_info_visitor.get(); this->node_["content_info"] = content_info_visitor.get();
this->node_["certificates"] = crts; this->node_["signer_info"] = jsigners;
this->node_["certificates"] = crts;
} }
void JsonVisitor::visit(const x509& x509) { void JsonVisitor::visit(const x509& x509) {
@ -789,27 +800,93 @@ void JsonVisitor::visit(const x509& x509) {
} }
void JsonVisitor::visit(const SignerInfo& signerinfo) { void JsonVisitor::visit(const SignerInfo& signerinfo) {
JsonVisitor authenticated_attributes_visitor; std::vector<json> auth_attrs;
authenticated_attributes_visitor(signerinfo.authenticated_attributes()); for (const Attribute& attr : signerinfo.authenticated_attributes()) {
JsonVisitor visitor;
visitor(attr);
auth_attrs.emplace_back(std::move(visitor.get()));
}
this->node_["version"] = signerinfo.version(); std::vector<json> unauth_attrs;
this->node_["digest_algorithm"] = signerinfo.digest_algorithm(); for (const Attribute& attr : signerinfo.unauthenticated_attributes()) {
this->node_["signature_algorithm"] = signerinfo.signature_algorithm(); JsonVisitor visitor;
this->node_["authenticated_attributes"] = authenticated_attributes_visitor.get(); visitor(attr);
this->node_["issuer"] = std::get<0>(signerinfo.issuer()); 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) { void JsonVisitor::visit(const ContentInfo& contentinfo) {
this->node_["content_type"] = contentinfo.content_type(); this->node_["content_type"] = contentinfo.content_type();
this->node_["type"] = contentinfo.type(); this->node_["digest_algorithm"] = to_string(contentinfo.digest_algorithm());
this->node_["digest_algorithm"] = contentinfo.digest_algorithm(); this->node_["digest"] = contentinfo.digest();
this->node_["file"] = contentinfo.file();
} }
void JsonVisitor::visit(const AuthenticatedAttributes& auth) { void JsonVisitor::visit(const Attribute& auth) {
this->node_["content_type"] = auth.content_type(); this->node_["type"] = to_string(auth.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 ContentType& attr) {
this->visit(*attr.as<Attribute>());
this->node_["oid"] = attr.oid();
}
void JsonVisitor::visit(const GenericType& attr) {
this->visit(*attr.as<Attribute>());
this->node_["oid"] = attr.oid();
}
void JsonVisitor::visit(const MsSpcNestedSignature& attr) {
this->visit(*attr.as<Attribute>());
JsonVisitor visitor;
visitor(attr.sig());
this->node_["signature"] = std::move(visitor.get());
}
void JsonVisitor::visit(const MsSpcStatementType& attr) {
this->visit(*attr.as<Attribute>());
this->node_["oid"] = attr.oid();
}
void JsonVisitor::visit(const PKCS9AtSequenceNumber& attr) {
this->visit(*attr.as<Attribute>());
this->node_["number"] = attr.number();
}
void JsonVisitor::visit(const PKCS9CounterSignature& attr) {
this->visit(*attr.as<Attribute>());
std::vector<json> 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<Attribute>());
this->node_["digest"] = attr.digest();
}
void JsonVisitor::visit(const PKCS9SigningTime& attr) {
this->visit(*attr.as<Attribute>());
this->node_["time"] = attr.time();
}
void JsonVisitor::visit(const SpcSpOpusInfo& attr) {
this->visit(*attr.as<Attribute>());
this->node_["more_info"] = attr.more_info();
this->node_["program_name"] = attr.program_name();
} }
void JsonVisitor::visit(const CodeIntegrity& code_integrity) { void JsonVisitor::visit(const CodeIntegrity& code_integrity) {

View File

@ -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 <iomanip>
#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;
}
}
}

View File

@ -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 <iomanip>
#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<uint8_t>& 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<uint8_t>& 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;
}
}
}

View File

@ -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")

View File

@ -17,6 +17,8 @@
#include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/OIDToString.hpp"
#include "LIEF/PE/signature/ContentInfo.hpp" #include "LIEF/PE/signature/ContentInfo.hpp"
#include "LIEF/PE/EnumToString.hpp"
#include "LIEF/utils.hpp"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
@ -26,27 +28,6 @@ ContentInfo::ContentInfo(const ContentInfo&) = default;
ContentInfo& ContentInfo::operator=(const ContentInfo&) = default; ContentInfo& ContentInfo::operator=(const ContentInfo&) = default;
ContentInfo::~ContentInfo(void) = 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<uint8_t>& ContentInfo::digest(void) const {
return this->digest_;
}
const std::vector<uint8_t>& ContentInfo::raw(void) const {
return this->raw_;
}
void ContentInfo::accept(Visitor& visitor) const { void ContentInfo::accept(Visitor& visitor) const {
visitor.visit(*this); visitor.visit(*this);
@ -54,12 +35,8 @@ void ContentInfo::accept(Visitor& visitor) const {
std::ostream& operator<<(std::ostream& os, const ContentInfo& content_info) { std::ostream& operator<<(std::ostream& os, const ContentInfo& content_info) {
constexpr uint8_t wsize = 30; os << "Authentihash: " << hex_dump(content_info.digest())
<< "(" << to_string(content_info.digest_algorithm()) << ")\n";
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;
return os; return os;
} }

View File

@ -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.3", "REJECT" },
{ "1.2.840.10040.2.4", "PICKUP_TOKEN" }, { "1.2.840.10040.2.4", "PICKUP_TOKEN" },
{ "1.2.840.10040.3", "ATTRIBUTE" }, { "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.3.2", "ATTRIBUTE_CERT" },
{ "1.2.840.10040.4", "ALGORITHM" }, { "1.2.840.10040.4", "ALGORITHM" },
{ "1.2.840.10040.4.1", "DSA" }, { "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.3", "CONTENT_TYPE" },
{ "1.2.840.113549.1.9.4", "MESSAGE_DIGEST" }, { "1.2.840.113549.1.9.4", "MESSAGE_DIGEST" },
{ "1.2.840.113549.1.9.5", "SIGNING_TIME" }, { "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.7", "CHALLENGE_PASSWORD" },
{ "1.2.840.113549.1.9.8", "UNSTRUCTURED_ADDRESS" }, { "1.2.840.113549.1.9.8", "UNSTRUCTURED_ADDRESS" },
{ "1.2.840.113549.1.9.9", "EXTENDED_CERTIFICATE_ATTRIBUTES" }, { "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.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.2", "APPLE_CERTIFICATE_EXTENSION_ADC_DEVELOPER_SIGNING" },
{ "1.2.840.113635.100.6.1.3", "APPLE_CERTIFICATE_EXTENSION_ADC_APPLE_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.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.11", "SPC_STATEMENT_TYPE" },
{ "1.3.6.1.4.1.311.2.1.12", "SPC_SP_OPUS_INFO" }, { "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" }, { "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" }, { "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.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); 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;
} }
} }

View File

@ -0,0 +1,123 @@
#include "LIEF/PE/signature/RsaInfo.hpp"
#include <algorithm>
#include <fstream>
#include <mbedtls/x509.h>
#include <mbedtls/asn1.h>
#include <mbedtls/oid.h>
#include <mbedtls/rsa.h>
#include <mbedtls/pk.h>
namespace LIEF {
namespace PE {
RsaInfo::RsaInfo(void) = default;
RsaInfo::RsaInfo(const RsaInfo::rsa_ctx_handle ctx) {
const mbedtls_rsa_context* pctx = reinterpret_cast<const mbedtls_rsa_context*>(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<RsaInfo::rsa_ctx_handle>(local_ctx);
}
RsaInfo::RsaInfo(const RsaInfo& other)
{
if (other) {
const mbedtls_rsa_context* octx = reinterpret_cast<const mbedtls_rsa_context*>(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<RsaInfo::rsa_ctx_handle>(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<mbedtls_rsa_context*>(this->ctx_);
return mbedtls_rsa_check_pubkey(lctx) == 0;
}
bool RsaInfo::has_private_key(void) const {
mbedtls_rsa_context* lctx = reinterpret_cast<mbedtls_rsa_context*>(this->ctx_);
return mbedtls_rsa_check_privkey(lctx) == 0;
}
RsaInfo::bignum_wrapper_t RsaInfo::N(void) const {
mbedtls_rsa_context* lctx = reinterpret_cast<mbedtls_rsa_context*>(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<mbedtls_rsa_context*>(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<mbedtls_rsa_context*>(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<mbedtls_rsa_context*>(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<mbedtls_rsa_context*>(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<mbedtls_rsa_context*>(this->ctx_);
mbedtls_rsa_free(lctx);
delete lctx;
}
}
std::ostream& operator<<(std::ostream& os, const RsaInfo& info) {
if (not info) {
os << "<Empty>";
} else {
// TODO
}
return os;
}
}
}

View File

@ -14,39 +14,256 @@
* limitations under the License. * limitations under the License.
*/ */
#include <iomanip> #include <iomanip>
#include <fstream>
#include "logging.hpp"
#include "LIEF/utils.hpp"
#include "LIEF/PE/signature/Signature.hpp" #include "LIEF/PE/signature/Signature.hpp"
#include "LIEF/PE/signature/OIDToString.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 <mbedtls/sha512.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha1.h>
#include <mbedtls/md2.h>
#include <mbedtls/md4.h>
#include <mbedtls/md5.h>
#include "mbedtls/x509_crt.h"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
Signature::Signature(void) = default; // TODO
Signature::Signature(void) = default;
Signature::Signature(const Signature&) = default; Signature::Signature(const Signature&) = default;
Signature& Signature::operator=(const Signature&) = default; Signature& Signature::operator=(const Signature&) = default;
Signature::~Signature(void) = default; Signature::~Signature(void) = default;
std::vector<uint8_t> Signature::hash(const std::vector<uint8_t>& input, ALGORITHMS algo) {
switch (algo) {
case ALGORITHMS::SHA_512:
{
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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 { uint32_t Signature::version(void) const {
return this->version_; return this->version_;
} }
const oid_t& Signature::digest_algorithm(void) const {
return this->digest_algorithm_;
}
const ContentInfo& Signature::content_info(void) const { const ContentInfo& Signature::content_info(void) const {
return this->content_info_; return this->content_info_;
} }
it_const_crt Signature::certificates(void) const { it_const_crt Signature::certificates(void) const {
return {this->certificates_}; return this->certificates_;
} }
const SignerInfo& Signature::signer_info(void) const { it_const_signers_t Signature::signers(void) const {
return this->signer_info_; return this->signers_;
} }
const std::vector<uint8_t>& 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<const PKCS9MessageDigest&>(*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<uint8_t>& Signature::raw_der(void) const {
return this->original_raw_signature_; return this->original_raw_signature_;
} }
@ -54,28 +271,140 @@ void Signature::accept(Visitor& visitor) const {
visitor.visit(*this); visitor.visit(*this);
} }
std::ostream& operator<<(std::ostream& os, const Signature& signature) { inline void print_attr(it_const_attributes_t& attrs, std::ostream& os) {
constexpr uint8_t wsize = 30; for (const Attribute& attr : attrs) {
os << std::hex << std::left; std::string suffix;
os << std::setw(wsize) << std::setfill(' ') << "Version: " << signature.version() << std::endl; switch (attr.type()) {
os << std::setw(wsize) << std::setfill(' ') << "Digest Algorithm: " << oid_to_string(signature.digest_algorithm()) << std::endl; case SIG_ATTRIBUTE_TYPES::CONTENT_TYPE:
{
const auto& ct = reinterpret_cast<const ContentType&>(attr);
suffix = ct.oid() + " (" + oid_to_string(ct.oid()) + ")";
break;
}
os << "Content Info" << std::endl; case SIG_ATTRIBUTE_TYPES::MS_SPC_STATEMENT_TYPE:
os << "============" << std::endl; {
os << signature.content_info() << std::endl << std::endl; const auto& ct = reinterpret_cast<const MsSpcStatementType&>(attr);
suffix = ct.oid() + " (" + oid_to_string(ct.oid()) + ")";
break;
}
case SIG_ATTRIBUTE_TYPES::SPC_SP_OPUS_INFO:
{
const auto& ct = reinterpret_cast<const SpcSpOpusInfo&>(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<const PKCS9MessageDigest&>(attr);
suffix = hex_dump(ct.digest()).substr(0, 41) + "...";
break;
}
case SIG_ATTRIBUTE_TYPES::MS_SPC_NESTED_SIGN:
{
const auto& nested_attr = reinterpret_cast<const MsSpcNestedSignature&>(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<const GenericType&>(attr);
suffix = ct.oid();
break;
}
case SIG_ATTRIBUTE_TYPES::PKCS9_AT_SEQUENCE_NUMBER:
{
const auto& ct = reinterpret_cast<const PKCS9AtSequenceNumber&>(attr);
suffix = std::to_string(ct.number());
break;
}
case SIG_ATTRIBUTE_TYPES::PKCS9_COUNTER_SIGNATURE:
{
const auto& ct = reinterpret_cast<const PKCS9CounterSignature&>(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<const PKCS9SigningTime&>(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; std::ostream& operator<<(std::ostream& os, const Signature& signature) {
os << "===========" << std::endl; const ContentInfo& cinfo = signature.content_info();
os << signature.signer_info() << std::endl << std::endl; 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; return os;
} }

File diff suppressed because it is too large Load Diff

View File

@ -18,80 +18,132 @@
#include <numeric> #include <numeric>
#include <sstream> #include <sstream>
#include <spdlog/fmt/fmt.h>
#include "LIEF/PE/signature/x509.hpp"
#include "LIEF/PE/signature/OIDToString.hpp" #include "LIEF/PE/signature/OIDToString.hpp"
#include "LIEF/PE/signature/SignerInfo.hpp" #include "LIEF/PE/signature/SignerInfo.hpp"
#include "LIEF/PE/signature/Attribute.hpp"
#include "LIEF/PE/EnumToString.hpp"
namespace LIEF { namespace LIEF {
namespace PE { namespace PE {
SignerInfo::SignerInfo(void) = default; SignerInfo::SignerInfo(void) = default;
SignerInfo::SignerInfo(const SignerInfo&) = default;
SignerInfo& SignerInfo::operator=(const SignerInfo&) = default;
SignerInfo::~SignerInfo(void) = 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<Attribute>& attr : other.authenticated_attributes_) {
this->authenticated_attributes_.push_back(attr->clone());
}
for (const std::unique_ptr<Attribute>& attr : other.unauthenticated_attributes_) {
this->unauthenticated_attributes_.push_back(attr->clone());
}
if (other.cert_ != nullptr) {
this->cert_ = std::unique_ptr<x509>(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 { uint32_t SignerInfo::version(void) const {
return this->version_; return this->version_;
} }
ALGORITHMS SignerInfo::digest_algorithm(void) const {
const issuer_t& SignerInfo::issuer(void) const {
return this->issuer_;
}
const oid_t& SignerInfo::digest_algorithm(void) const {
return this->digest_algorithm_; return this->digest_algorithm_;
} }
ALGORITHMS SignerInfo::encryption_algorithm(void) const {
const AuthenticatedAttributes& SignerInfo::authenticated_attributes(void) const { return this->digest_enc_algorithm_;
return this->authenticated_attributes_;
} }
const SignerInfo::encrypted_digest_t& SignerInfo::encrypted_digest(void) const {
const oid_t& SignerInfo::signature_algorithm(void) const {
return this->signature_algorithm_;
}
const std::vector<uint8_t>& SignerInfo::encrypted_digest(void) const {
return this->encrypted_digest_; return this->encrypted_digest_;
} }
it_const_attributes_t SignerInfo::authenticated_attributes() const {
std::vector<Attribute*> 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<Attribute*> 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<Attribute>& 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<Attribute>& 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 { void SignerInfo::accept(Visitor& visitor) const {
visitor.visit(*this); visitor.visit(*this);
} }
std::ostream& operator<<(std::ostream& os, const SignerInfo& signer_info) { std::ostream& operator<<(std::ostream& os, const SignerInfo& signer_info) {
os << fmt::format("{}/{} - {} - {:d} auth attr - {:d} unauth attr",
constexpr uint8_t wsize = 30; to_string(signer_info.digest_algorithm()),
const issuer_t& issuer = signer_info.issuer(); to_string(signer_info.encryption_algorithm()),
std::string issuer_str = std::get<0>(issuer); signer_info.issuer(),
signer_info.authenticated_attributes().size(),
const std::vector<uint8_t>& sn = std::get<1>(issuer);; signer_info.unauthenticated_attributes().size());
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<uint32_t>(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;
return os; return os;
} }

View File

@ -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()

View File

@ -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<Attribute> ContentType::clone(void) const {
return std::unique_ptr<Attribute>(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;
}
}

View File

@ -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<Attribute> GenericType::clone(void) const {
return std::unique_ptr<Attribute>(new GenericType{*this});
}
GenericType::GenericType(oid_t oid, std::vector<uint8_t> 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;
}
}

Some files were not shown because too many files have changed in this diff Show More