Compare commits

...
21 Commits
Author SHA1 Message Date
Romain Thomas 097b35511e Fix error 2021-02-24 08:02:51 +01:00
Romain Thomas 1dd7317a0c Fix error 2021-02-24 07:36:09 +01:00
Romain Thomas 0e12916531 Bump version 2021-02-24 07:04:38 +01:00
Romain Thomas 9fb11539da Resolve #551 2021-02-24 07:01:49 +01:00
Romain Thomas 980ed6b3fb Update changelog 2021-02-22 13:38:24 +01:00
Romain Thomas a6d9ea90a2 Add more information than just BAD_SIGNATURE 2021-02-21 18:03:51 +01:00
Romain Thomas 8d20b9ba65 Resolve #532 2021-02-21 18:02:39 +01:00
Romain Thomas eb24a317fa Fix appveyor tag 2021-02-21 15:38:35 +01:00
Romain Thomas c0fa4a6455 Fix missing env variable 2021-02-21 13:03:37 +01:00
Romain Thomas 3970c4d4e2 update auditwheel command 2021-02-21 13:03:31 +01:00
Romain Thomas 96c7e90231 Fix typo 2021-02-21 13:03:24 +01:00
Romain Thomas badfcf69a7 Update Linux CI 2021-02-21 13:03:10 +01:00
Romain Thomas d45e1946e3 Fix typo 2021-02-21 13:01:41 +01:00
Romain Thomas 62d4fb61ea Fix error on Appveyor 2021-02-21 13:00:40 +01:00
Romain Thomas 0c88cc740f Fix condition 2021-02-21 12:57:45 +01:00
Romain Thomas b2b7783ec0 Fix related to #540 2021-02-21 12:57:14 +01:00
Romain Thomas 9790ddfa82 The last data directory might not be null
See: bc203f2b6a928f1457e9ca99456747bcb7adbbfff789d1c47e9479aac11598af
2021-02-21 12:56:01 +01:00
Romain Thomas 986a30e014 Do not take account sections with empty content 2021-02-21 12:55:54 +01:00
Romain Thomas 03a18cb202 Do not trunc section's name on a null char
If the section's name contains bytes after the null char, they should
be considered while computing the authentihash.
2021-02-21 12:55:38 +01:00
Romain Thomas c37ee0742a Handle content between two sections that is not wrapped by a section 2021-02-21 12:55:24 +01:00
Romain Thomas 2ab604d36f Resolve #548 2021-02-21 12:55:18 +01:00
26 changed files with 236 additions and 91 deletions
+1 -1
View File
@@ -91,7 +91,6 @@ install:
build_script:
- cd %APPVEYOR_BUILD_FOLDER%
- set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
- python.exe .\setup.py --ninja --lief-test build bdist_wheel --skip-build && exit 0 # Ignore warnings...
- ps: if ($env:PYTHON_VERSION -eq "3.9") { python.exe .\scripts\windows\package_sdk.py }
@@ -106,6 +105,7 @@ after_build:
-e APPVEYOR="true" `
-e APPVEYOR_PULL_REQUEST_NUMBER="$env:APPVEYOR_PULL_REQUEST_NUMBER" `
-e APPVEYOR_REPO_NAME="$env:APPVEYOR_REPO_NAME" `
-e APPVEYOR_REPO_TAG_NAME="$env:APPVEYOR_REPO_TAG_NAME" `
-e APPVEYOR_REPO_BRANCH="$env:APPVEYOR_REPO_BRANCH" `
-e APPVEYOR_BUILD_FOLDER="$env:APPVEYOR_BUILD_FOLDER" `
-e LIEF_AUTOMATIC_BUILDS_KEY="$env:LIEF_AUTOMATIC_BUILDS_KEY" `
+4 -7
View File
@@ -81,12 +81,9 @@ def get_tag(ci):
elif ci == CI.TRAVIS:
return os.getenv("TRAVIS_TAG", "")
elif ci == CI.APPVEYOR:
if os.getenv("APPVEYOR_REPO_TAG", "") in (None, ''):
return ""
if os.getenv("APPVEYOR_REPO_TAG", "").lower() == "false":
return ""
return os.getenv("APPVEYOR_REPO_TAG_NAME", "")
if "APPVEYOR_REPO_TAG_NAME" in os.environ:
return os.getenv("APPVEYOR_REPO_TAG_NAME", "")
return ""
elif ci == CI.GITHUB_ACTIONS:
ref = os.getenv("GITHUB_REF", "")
logger.info("Github Action tag: {}".format(ref))
@@ -130,7 +127,7 @@ logger.info("CI: %s", CI_PRETTY_NAME)
ALLOWED_BRANCHES = {"master", "deploy", "devel"}
BRANCH_NAME = get_branch(CURRENT_CI)
TAG_NAME = get_tag(CURRENT_CI)
IS_TAGGED = len(TAG_NAME) > 0
IS_TAGGED = TAG_NAME is not None and len(TAG_NAME) > 0
logger.info("Branch: %s", BRANCH_NAME)
logger.info("Tag: %s", TAG_NAME)
if BRANCH_NAME not in ALLOWED_BRANCHES and not IS_TAGGED:
+24 -17
View File
@@ -4,9 +4,6 @@ on: push
jobs:
linux-sdk:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v2
with:
@@ -23,45 +20,56 @@ jobs:
key: linux-x86-64-${{ runner.os }}-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-x86-64-${{ runner.os }}-
- name: Build Python ${{ matrix.python-version }} wheel
if: matrix.python-version == '3.7'
- name: Build Python 3.7 wheel
shell: bash
env:
PYTHON_VERSION: ${{ matrix.python-version }}
PYTHON_VERSION: 37
run: |
PYTHON_VERSION2=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION2}-cp${PYTHON_VERSION2}m/bin/python${PYTHON_VERSION} \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp37-cp37m/bin/python3.7 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux1_x86_64 bash /src/scripts/docker/travis-linux.sh
- name: Build Python ${{ matrix.python-version }} wheel
if: matrix.python-version != '3.7'
- name: Build Python 3.8 wheel
shell: bash
env:
PYTHON_VERSION: ${{ matrix.python-version }}
PYTHON_VERSION: 38
run: |
PYTHON_VERSION2=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION2}-cp${PYTHON_VERSION2}/bin/python${PYTHON_VERSION} \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp38-cp38/bin/python3.8 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux1_x86_64 bash /src/scripts/docker/travis-linux.sh
- name: Build Python 3.9 wheel
shell: bash
env:
PYTHON_VERSION: 39
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux1_x86_64 bash /src/scripts/docker/travis-linux.sh
- name: Build SDK
if: matrix.python-version == '3.9'
shell: bash
run: |
PYTHON_VERSION2=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run --name lief_sdk --rm \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION2}-cp${PYTHON_VERSION2}/bin/python${PYTHON_VERSION} \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_DIR=/ccache \
@@ -85,7 +93,6 @@ jobs:
--rm \
liefproject/deploy python3 /src/.github/deploy.py
- name: Trigger documentation
if: matrix.python-version == '3.9'
env:
CIRCLE_CI_TOKEN: ${{ secrets.CIRCLE_CI_TOKEN }}
shell: bash
+1 -1
View File
@@ -22,7 +22,7 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"
else()
set(LIEF_VERSION_MAJOR "0")
set(LIEF_VERSION_MINOR "11")
set(LIEF_VERSION_PATCH "0")
set(LIEF_VERSION_PATCH "2")
endif()
# LIEF Project
+4
View File
@@ -105,6 +105,10 @@ void create<Section>(py::module& m) {
&Section::characteristics_list,
":attr:`~lief.PE.Section.characteristics` as a ``list``")
.def_property_readonly("fullname",
&Section::fullname,
"Return the **fullname** of the section including the trailing bytes")
.def("has_characteristic",
&Section::has_characteristic,
"``True`` if the a section has the given " RST_CLASS_REF(lief.PE.SECTION_CHARACTERISTICS) "",
@@ -53,8 +53,37 @@ void create<Signature>(py::module& m) {
.value("BAD_SIGNATURE", Signature::VERIFICATION_FLAGS::BAD_SIGNATURE)
.value("NO_SIGNATURE", Signature::VERIFICATION_FLAGS::NO_SIGNATURE)
.value("CERT_EXPIRED", Signature::VERIFICATION_FLAGS::CERT_EXPIRED)
.value("CERT_FUTURE", Signature::VERIFICATION_FLAGS::CERT_FUTURE);
.value("CERT_FUTURE", Signature::VERIFICATION_FLAGS::CERT_FUTURE)
.def("__str__", [] (const Signature::VERIFICATION_FLAGS& flags) {
static const std::array<Signature::VERIFICATION_FLAGS, 13> FLAGS = {
Signature::VERIFICATION_FLAGS::OK,
Signature::VERIFICATION_FLAGS::INVALID_SIGNER,
Signature::VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM,
Signature::VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM,
Signature::VERIFICATION_FLAGS::CERT_NOT_FOUND,
Signature::VERIFICATION_FLAGS::CORRUPTED_CONTENT_INFO,
Signature::VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA,
Signature::VERIFICATION_FLAGS::MISSING_PKCS9_MESSAGE_DIGEST,
Signature::VERIFICATION_FLAGS::BAD_DIGEST,
Signature::VERIFICATION_FLAGS::BAD_SIGNATURE,
Signature::VERIFICATION_FLAGS::NO_SIGNATURE,
Signature::VERIFICATION_FLAGS::CERT_EXPIRED,
Signature::VERIFICATION_FLAGS::CERT_FUTURE,
};
if (flags == Signature::VERIFICATION_FLAGS::OK) {
return Signature::flag_to_string(flags);
}
std::string flags_str;
for (const Signature::VERIFICATION_FLAGS& flag : FLAGS) {
if ((flags & flag) == flag and flag != Signature::VERIFICATION_FLAGS::OK) {
if (not flags_str.empty()) {
flags_str += " | ";
}
flags_str += "VERIFICATION_FLAGS." + Signature::flag_to_string(flag);
}
}
return flags_str;
}, py::prepend{});
LIEF::enum_<Signature::VERIFICATION_CHECKS>(signature, "VERIFICATION_CHECKS", py::arithmetic(),
R"delim(
+1 -1
View File
@@ -1,6 +1,6 @@
include("static-release/CPackConfig.cmake")
set(CPACK_INSTALL_CMAKE_PROJECTS ${CPACK_INSTALL_CMAKE_PROJECTS}
static-release LIEF ALL /
shared-release LIEF ALL /
static-release LIEF ALL /
)
+21 -2
View File
@@ -1,10 +1,29 @@
Changelog
=========
0.11.2 - February 24, 2021
--------------------------
:PE:
* Fix regression in the behavior of the PE section's name. One can now access the full
section's name (with trailing bytes) through :attr:`lief.PE.Section.fullname` (see: :issue:`551`)
.. _release-0111:
0.11.1 - February 22, 2021
--------------------------
:PE:
* :meth:`lief.PE.x509.is_trusted_by` and :meth:`lief.PE.x509.verify` now return
a better :attr:`lief.PE.x509.VERIFICATION_FLAGS` instead of just :attr:`lief.PE.x509.VERIFICATION_FLAGS.BADCERT_NOT_TRUSTED`
(see: :issue:`532`)
* Fix errors in the computation of the Authentihash
.. _release-0110:
0.11.0 - Not Released
---------------------
0.11.0 - January 19, 2021
-------------------------
:ELF:
* :github_user:`mkomet` updated enums related to Android (see: :commit:`9dd641d380a5defd0a71a9f42dde2fe9c9cb1dbd`)
+4 -4
View File
@@ -250,7 +250,7 @@ if the signature is valid or another enum (see: :attr:`lief.PE.Signature.VERIFIC
.. code-block:: python
pe = lief.parse("avast_free_antivirus_setup_online.exe")
print(pe.verify_signature()) # lief.Signature.VERIFICATION_FLAGS.OK
print(pe.verify_signature()) # lief.PE.Signature.VERIFICATION_FLAGS.OK
We can also verify a PE binary with a **detached signature** by providing a :class:`signature <lief.PE.Signature>`
object to :meth:`~lief.PE.Binary.verify_signature`:
@@ -344,14 +344,14 @@ certificate is verified against a **list of certificates**:
.. code-block:: python
CA_BUNDLE = lief.x509.parse("ms_bundle.pem")
CA_BUNDLE = lief.PE.x509.parse("ms_bundle.pem")
signer = signature.signers[0]
print(signer.cert.is_trusted_by(CA_BUNDLE))
.. code-block:: python
cert1 = lief.x509.parse("ca1.crt")
cert2 = lief.x509.parse("ca2.crt")
cert1 = lief.PE.x509.parse("ca1.crt")
cert2 = lief.PE.x509.parse("ca2.crt")
print(signer.cert.is_trusted_by([cert1, cert2]))
+1 -1
View File
@@ -38,7 +38,7 @@ class LIEF_API Section : public Object {
Section(const Section&);
//! @brief section's name
virtual const std::string& name(void) const;
virtual std::string name(void) const;
//! @brief section's content
virtual std::vector<uint8_t> content(void) const;
+2
View File
@@ -20,6 +20,7 @@
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include "LIEF/visibility.h"
#include "LIEF/iostream.hpp"
@@ -103,6 +104,7 @@ class LIEF_API Builder {
template<typename T, typename HANDLER>
std::vector<std::string> optimize(const HANDLER& e,
std::function<std::string(const typename HANDLER::value_type)> getter,
std::unordered_map<std::string, size_t> *of_map_p=nullptr);
template<typename ELF_T>
+5
View File
@@ -71,6 +71,11 @@ class LIEF_API Section : public LIEF::Section {
uint16_t numberof_line_numbers(void) const;
uint32_t characteristics(void) const;
//! Return the **fullname** of the section including the trailing bytes
inline const std::string& fullname() const {
return this->name_;
}
bool is_type(PE_SECTION_TYPES type) const;
const std::set<PE_SECTION_TYPES>& types(void) const;
bool has_characteristic(SECTION_CHARACTERISTICS c) const;
+4
View File
@@ -62,6 +62,10 @@ class LIEF_API Signature : public Object {
CERT_FUTURE = 1 << 11,
};
//! Convert a verification flag into a humman representation.
//! e.g VERIFICATION_FLAGS.BAD_DIGEST | VERIFICATION_FLAGS.BAD_SIGNATURE | VERIFICATION_FLAGS.CERT_EXPIRED
static std::string flag_to_string(VERIFICATION_FLAGS flag);
//! Flags to tweak the verification process of the signature
//!
//! See Signature::check and LIEF::PE::Binary::verify_signature
+1 -1
View File
@@ -8,6 +8,6 @@ export LDFLAGS='-Wl,--gc-sections -Wl,--exclude-libs,ALL'
$PYTHON_BINARY setup.py --ninja --lief-test build \
bdist_wheel --skip-build --dist-dir wheel_stage
auditwheel repair -w dist --plat manylinux1_x86_64 wheel_stage/*.whl
find wheel_stage -iname "*-cp${PYTHON_VERSION}-*" -exec auditwheel repair -w dist --plat manylinux1_x86_64 {} \;
chown -R 1000:1000 build dist wheel_stage
+1 -1
View File
@@ -426,7 +426,7 @@ def get_pkg_info_version(pkg_info_file):
def get_version() -> str:
version = "0.11.0"
version = "0.11.2"
pkg_info = os.path.join(CURRENT_DIR, "{}.egg-info".format(PACKAGE_NAME), "PKG-INFO")
git_dir = os.path.join(CURRENT_DIR, ".git")
if os.path.isdir(git_dir):
+2 -2
View File
@@ -48,8 +48,8 @@ Section::~Section(void) = default;
Section& Section::operator=(const Section&) = default;
Section::Section(const Section&) = default;
const std::string& Section::name(void) const {
return this->name_;
std::string Section::name(void) const {
return this->name_.c_str();
}
+14 -13
View File
@@ -164,6 +164,7 @@ void Builder::build(void) {
template<typename T, typename HANDLER>
std::vector<std::string> Builder::optimize(const HANDLER& container,
std::function<std::string(const typename HANDLER::value_type)> getter,
std::unordered_map<std::string, size_t> *of_map_p) {
std::set<std::string> string_table;
@@ -173,12 +174,9 @@ std::vector<std::string> Builder::optimize(const HANDLER& container,
// reverse all symbol names and sort them so we can merge then in the linear time:
// aaa, aadd, aaaa, cca, ca -> aaaa, aaa, acc, ac ddaa
std::transform(
std::begin(container),
std::end(container),
std::inserter(
string_table,
std::end(string_table)),
std::mem_fn(static_cast<const std::string& (T::*)(void) const>(&T::name)));
std::begin(container), std::end(container),
std::inserter(string_table, std::end(string_table)),
getter);
for (auto &val: string_table) {
string_table_optimized.emplace_back(std::move(val));
@@ -302,7 +300,8 @@ void Builder::build_sections(void) {
const Elf_Off section_headers_offset = header.section_headers_offset();
std::vector<std::string> shstrtab_opt =
this->optimize<Section, decltype(this->binary_->sections_)>(this->binary_->sections_);
this->optimize<Section, decltype(this->binary_->sections_)>(this->binary_->sections_,
[] (const Section* sec) { return sec->name(); });
// Build section's name
std::vector<uint8_t> section_names;
@@ -377,12 +376,12 @@ void Builder::build_sections(void) {
for (size_t i = 0; i < this->binary_->sections_.size(); i++) {
const Section* section = this->binary_->sections_[i];
LIEF_DEBUG("Writing content of section '{}'", section->name());
const std::string name = section->name();
auto&& it_offset_name = std::search(
std::begin(section_names),
std::end(section_names),
section->name().c_str(),
section->name().c_str() + section->name().size() + 1);
const auto it_offset_name = std::search(
std::begin(section_names), std::end(section_names),
name.c_str(),
name.c_str() + name.size() + 1);
if (it_offset_name == std::end(section_names)) {
throw LIEF::not_found("Section name not found");
@@ -528,7 +527,8 @@ void Builder::build_static_symbols(void) {
// Container which will hold symbols name (optimized)
std::vector<std::string> string_table_optimize =
this->optimize<Symbol, decltype(this->binary_->static_symbols_)>(this->binary_->static_symbols_,
&offset_name_map);
[] (const Symbol* sym) { return sym->name(); },
&offset_name_map);
// We can't start with a symbol name
string_table_raw.push_back(0);
@@ -1131,6 +1131,7 @@ void Builder::build_dynamic_symbols(void) {
std::vector<std::string> string_table_optimized =
this->optimize<Symbol, decltype(this->binary_->dynamic_symbols_)>(this->binary_->dynamic_symbols_,
[] (const Symbol* sym) { return sym->name(); },
&offset_name_map);
for (const std::string& name : string_table_optimized) {
+6 -6
View File
@@ -57,9 +57,9 @@ void Builder::build_segments(void) {
segment_t segment_header;
segment_header.cmd = static_cast<uint32_t>(segment.command());
segment_header.cmdsize = static_cast<uint32_t>(segment.size());
const std::string& seg_name = segment.name();
std::copy(
segment.name().c_str(),
segment.name().c_str() + sizeof(segment_header.segname),
seg_name.c_str(), seg_name.c_str() + sizeof(segment_header.segname),
segment_header.segname);
segment_header.vmaddr = static_cast<uint__>(segment.virtual_address());
segment_header.vmsize = static_cast<uint__>(segment.virtual_size());
@@ -98,16 +98,16 @@ void Builder::build_segments(void) {
it_sections sections = segment.sections();
for (uint32_t i = 0; i < segment.numberof_sections(); ++i) {
const Section& section = sections[i];
const std::string& sec_name = section.name();
const std::string& segment_name = segment.name();
LIEF_DEBUG("{}", section);
section_t header;
std::copy(
section.name().c_str(),
section.name().c_str() + sizeof(header.sectname),
sec_name.c_str(), sec_name.c_str() + sizeof(header.sectname),
header.sectname);
std::copy(
segment.name().c_str(),
segment.name().c_str() + sizeof(header.segname),
segment_name.c_str(), segment_name.c_str() + sizeof(header.segname),
header.segname);
header.addr = static_cast<uint__>(section.address());
+22 -17
View File
@@ -1110,14 +1110,9 @@ std::vector<uint8_t> Binary::authentihash(ALGORITHMS algo) const {
.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();
const std::string& sec_name = sec->fullname();
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
@@ -1139,14 +1134,16 @@ std::vector<uint8_t> Binary::authentihash(ALGORITHMS algo) const {
// Sort by file offset
std::sort(
std::begin(sections),
std::end(sections),
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) {
if (sec->sizeof_raw_data() == 0) {
continue;
}
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}]",
@@ -1174,18 +1171,20 @@ std::vector<uint8_t> Binary::authentihash(ALGORITHMS algo) const {
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) {
if (cert_dir.RVA() > 0 and cert_dir.size() > 0 and cert_dir.RVA() >= this->overlay_offset_) {
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);
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);
} else {
ios.write(this->overlay());
}
}
//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};
@@ -1207,23 +1206,26 @@ Signature::VERIFICATION_FLAGS Binary::verify_signature(Signature::VERIFICATION_C
return Signature::VERIFICATION_FLAGS::NO_SIGNATURE;
}
Signature::VERIFICATION_FLAGS flags = Signature::VERIFICATION_FLAGS::OK;
for (size_t i = 0; i < this->signatures_.size(); ++i) {
const Signature& sig = this->signatures_[i];
Signature::VERIFICATION_FLAGS flags = this->verify_signature(sig, checks);
flags |= this->verify_signature(sig, checks);
if (flags != Signature::VERIFICATION_FLAGS::OK) {
LIEF_INFO("Verification failed for signature #{:d} (0b{:b})", i, static_cast<uintptr_t>(flags));
return flags;
break;
}
}
return Signature::VERIFICATION_FLAGS::OK;
return flags;
}
Signature::VERIFICATION_FLAGS Binary::verify_signature(const Signature& sig, Signature::VERIFICATION_CHECKS checks) const {
Signature::VERIFICATION_FLAGS flags = Signature::VERIFICATION_FLAGS::OK;
if (not is_true(checks & Signature::VERIFICATION_CHECKS::HASH_ONLY)) {
const Signature::VERIFICATION_FLAGS value = sig.check(checks);
if (value != Signature::VERIFICATION_FLAGS::OK) {
LIEF_INFO("Bad signature (0b{:b})", static_cast<uintptr_t>(value));
return value;
flags |= value;
}
}
@@ -1233,9 +1235,12 @@ Signature::VERIFICATION_FLAGS Binary::verify_signature(const Signature& sig, Sig
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;
flags |= Signature::VERIFICATION_FLAGS::BAD_DIGEST;
}
return Signature::VERIFICATION_FLAGS::OK;
if (flags != Signature::VERIFICATION_FLAGS::OK) {
flags |= Signature::VERIFICATION_FLAGS::BAD_SIGNATURE;
}
return flags;
}
+5 -9
View File
@@ -150,12 +150,6 @@ void Builder::build(void) {
*this << directory;
}
DataDirectory last_one;
last_one.RVA(0);
last_one.size(0);
*this << last_one;
LIEF_DEBUG("[+] Sections");
for (const Section& section : this->binary_->sections()) {
@@ -546,10 +540,12 @@ Builder& Builder::operator<<(const Section& section) {
header.NumberOfRelocations = static_cast<uint16_t>(section.numberof_relocations());
header.NumberOfLineNumbers = static_cast<uint16_t>(section.numberof_line_numbers());
header.Characteristics = static_cast<uint32_t>(section.characteristics());
const char* name = section.name().c_str();
uint32_t name_length = std::min<uint32_t>(section.name().size(), sizeof(header.Name));
std::copy(name, name + name_length, std::begin(header.Name));
std::array<char, 8> name = {0};
const std::string& sec_name = section.fullname();
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(header.Name));
this->ios_.write(reinterpret_cast<uint8_t*>(&header), sizeof(pe_section));
size_t pad_length = 0;
+14 -2
View File
@@ -252,9 +252,21 @@ void Parser::parse_sections(void) {
};
}
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);
// Treat content between two sections (that is not wrapped in a section) as 'padding'
uint64_t hole_size = 0;
if (i < numberof_sections - 1) {
const pe_section& next_section = sections[i + 1];
const uint64_t sec_offset = next_section.PointerToRawData;
if (offset + size_to_read + padding_size < sec_offset) {
hole_size = sec_offset - (offset + size_to_read + padding_size);
}
}
const uint8_t* ptr_to_padding = this->stream_->peek_array<uint8_t>(offset + size_to_read,
padding_size + hole_size,
/* check */false);
if (ptr_to_padding != nullptr) {
section->padding_ = {ptr_to_padding, ptr_to_padding + padding_size};
section->padding_ = {ptr_to_padding, ptr_to_padding + padding_size + hole_size};
}
}
this->binary_->sections_.push_back(section.release());
+6 -1
View File
@@ -108,7 +108,12 @@ void Parser::parse_data_directories(void) {
}
this->binary_->data_directories_.reserve(nbof_datadir);
for (size_t i = 0; i < nbof_datadir; ++i) {
// WARNING: The PE specifications require that the data directory table ends with a null entry (RVA / Size,
// set to 0).
// Nevertheless it seems that this requirement is not enforced by the PE loader.
// The binary bc203f2b6a928f1457e9ca99456747bcb7adbbfff789d1c47e9479aac11598af contains a non-null final
// data directory (watermarking?)
for (size_t i = 0; i < (nbof_datadir + 1); ++i) {
std::unique_ptr<DataDirectory> directory{new DataDirectory{&data_directory[i], static_cast<DATA_DIRECTORY>(i)}};
LIEF_DEBUG("Processing directory #{:d} ()", i, to_string(static_cast<DATA_DIRECTORY>(i)));
LIEF_DEBUG(" - RVA: 0x{:04x}", data_directory[i].RelativeVirtualAddress);
+1 -1
View File
@@ -46,7 +46,7 @@ Section::Section(const pe_section* header) :
characteristics_{header->Characteristics},
types_{PE_SECTION_TYPES::UNKNOWN}
{
this->name_ = std::string(header->Name, sizeof(header->Name)).c_str();
this->name_ = std::string(header->Name, sizeof(header->Name));
this->virtual_address_ = header->VirtualAddress;
this->size_ = header->SizeOfRawData;
this->offset_ = header->PointerToRawData;
+20
View File
@@ -40,6 +40,7 @@
#include "mbedtls/x509_crt.h"
#include "mbedtls/x509.h"
#include "frozen.hpp"
namespace LIEF {
namespace PE {
@@ -50,6 +51,25 @@ inline std::string time_to_string(const x509::date_t& date) {
date[3], date[4], date[5]);
}
std::string Signature::flag_to_string(Signature::VERIFICATION_FLAGS flag) {
CONST_MAP(VERIFICATION_FLAGS, const char*, 13) enumStrings {
{ Signature::VERIFICATION_FLAGS::OK, "OK"},
{ Signature::VERIFICATION_FLAGS::INVALID_SIGNER, "INVALID_SIGNER"},
{ Signature::VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM, "UNSUPPORTED_ALGORITHM"},
{ Signature::VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM, "INCONSISTENT_DIGEST_ALGORITHM"},
{ Signature::VERIFICATION_FLAGS::CERT_NOT_FOUND, "CERT_NOT_FOUND"},
{ Signature::VERIFICATION_FLAGS::CORRUPTED_CONTENT_INFO, "CORRUPTED_CONTENT_INFO"},
{ Signature::VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA, "CORRUPTED_AUTH_DATA"},
{ Signature::VERIFICATION_FLAGS::MISSING_PKCS9_MESSAGE_DIGEST, "MISSING_PKCS9_MESSAGE_DIGEST"},
{ Signature::VERIFICATION_FLAGS::BAD_DIGEST, "BAD_DIGEST"},
{ Signature::VERIFICATION_FLAGS::BAD_SIGNATURE, "BAD_SIGNATURE"},
{ Signature::VERIFICATION_FLAGS::NO_SIGNATURE, "NO_SIGNATURE"},
{ Signature::VERIFICATION_FLAGS::CERT_EXPIRED, "CERT_EXPIRED"},
{ Signature::VERIFICATION_FLAGS::CERT_FUTURE, "CERT_FUTURE"},
};
auto it = enumStrings.find(flag);
return it == enumStrings.end() ? "UNDEFINED" : it->second;
}
Signature::VERIFICATION_FLAGS verify_ts_counter_signature(const SignerInfo& signer,
const PKCS9CounterSignature& cs, Signature::VERIFICATION_CHECKS checks) {
+35 -2
View File
@@ -65,6 +65,39 @@ namespace {
namespace LIEF {
namespace PE {
static const std::map<uint32_t, x509::VERIFICATION_FLAGS> MBEDTLS_ERR_TO_LIEF = {
{ MBEDTLS_X509_BADCERT_EXPIRED, x509::VERIFICATION_FLAGS::BADCERT_EXPIRED},
{ MBEDTLS_X509_BADCERT_REVOKED, x509::VERIFICATION_FLAGS::BADCERT_REVOKED},
{ MBEDTLS_X509_BADCERT_CN_MISMATCH, x509::VERIFICATION_FLAGS::BADCERT_CN_MISMATCH},
{ MBEDTLS_X509_BADCERT_NOT_TRUSTED, x509::VERIFICATION_FLAGS::BADCERT_NOT_TRUSTED},
{ MBEDTLS_X509_BADCRL_NOT_TRUSTED, x509::VERIFICATION_FLAGS::BADCRL_NOT_TRUSTED},
{ MBEDTLS_X509_BADCRL_EXPIRED, x509::VERIFICATION_FLAGS::BADCRL_EXPIRED},
{ MBEDTLS_X509_BADCERT_MISSING, x509::VERIFICATION_FLAGS::BADCERT_MISSING},
{ MBEDTLS_X509_BADCERT_SKIP_VERIFY, x509::VERIFICATION_FLAGS::BADCERT_SKIP_VERIFY},
{ MBEDTLS_X509_BADCERT_OTHER, x509::VERIFICATION_FLAGS::BADCERT_OTHER},
{ MBEDTLS_X509_BADCERT_FUTURE, x509::VERIFICATION_FLAGS::BADCERT_FUTURE},
{ MBEDTLS_X509_BADCRL_FUTURE, x509::VERIFICATION_FLAGS::BADCRL_FUTURE},
{ MBEDTLS_X509_BADCERT_KEY_USAGE, x509::VERIFICATION_FLAGS::BADCERT_KEY_USAGE},
{ MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, x509::VERIFICATION_FLAGS::BADCERT_EXT_KEY_USAGE},
{ MBEDTLS_X509_BADCERT_NS_CERT_TYPE, x509::VERIFICATION_FLAGS::BADCERT_NS_CERT_TYPE},
{ MBEDTLS_X509_BADCERT_BAD_MD, x509::VERIFICATION_FLAGS::BADCERT_BAD_MD},
{ MBEDTLS_X509_BADCERT_BAD_PK, x509::VERIFICATION_FLAGS::BADCERT_BAD_PK},
{ MBEDTLS_X509_BADCERT_BAD_KEY, x509::VERIFICATION_FLAGS::BADCERT_BAD_KEY},
{ MBEDTLS_X509_BADCRL_BAD_MD, x509::VERIFICATION_FLAGS::BADCRL_BAD_MD},
{ MBEDTLS_X509_BADCRL_BAD_PK, x509::VERIFICATION_FLAGS::BADCRL_BAD_PK},
{ MBEDTLS_X509_BADCRL_BAD_KEY, x509::VERIFICATION_FLAGS::BADCRL_BAD_KEY},
};
inline x509::VERIFICATION_FLAGS from_mbedtls_err(uint32_t err) {
x509::VERIFICATION_FLAGS flags = x509::VERIFICATION_FLAGS::OK;
for (const auto& p : MBEDTLS_ERR_TO_LIEF) {
if ((err & p.first) == p.first) {
flags |= p.second;
}
}
return flags;
}
inline x509::date_t from_mbedtls(const mbedtls_x509_time& time) {
return {
time.year,
@@ -431,7 +464,7 @@ x509::VERIFICATION_FLAGS x509::is_trusted_by(const std::vector<x509>& ca) const
std::string out(1024, 0);
mbedtls_x509_crt_verify_info(const_cast<char*>(out.data()), out.size(), "", flags);
LIEF_WARN("X509 verify failed with: {} (0x{:x})\n{}", strerr, ret, out);
result = VERIFICATION_FLAGS::BADCERT_NOT_TRUSTED;
result = from_mbedtls_err(flags);
}
// Clear the chain since ~x509() will delete each object
@@ -471,7 +504,7 @@ x509::VERIFICATION_FLAGS x509::verify(const x509& ca) const {
std::string out(1024, 0);
mbedtls_x509_crt_verify_info(const_cast<char*>(out.data()), out.size(), "", flags);
LIEF_WARN("X509 verify failed with: {} (0x{:x})\n{}", strerr, ret, out);
result = VERIFICATION_FLAGS::BADCERT_NOT_TRUSTED;
result = from_mbedtls_err(flags);
}
return result;
}
+6
View File
@@ -129,6 +129,12 @@ class TestPe(TestCase):
self.assertEqual(pogo_entries[23].size, 820)
def test_sections(self):
path = get_sample("PE/PE32_x86_binary_PGO-LTCG.exe")
pe = lief.parse(path)
self.assertIsNotNone(pe.get_section(".text"))
self.assertEqual(pe.sections[0].name, ".text")
self.assertEqual(pe.sections[0].fullname.encode("utf8"), b".text\x00\x00\x00")
def tearDown(self):
# Delete it