Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
097b35511e | ||
|
|
1dd7317a0c | ||
|
|
0e12916531 | ||
|
|
9fb11539da | ||
|
|
980ed6b3fb | ||
|
|
a6d9ea90a2 | ||
|
|
8d20b9ba65 | ||
|
|
eb24a317fa | ||
|
|
c0fa4a6455 | ||
|
|
3970c4d4e2 | ||
|
|
96c7e90231 | ||
|
|
badfcf69a7 | ||
|
|
d45e1946e3 | ||
|
|
62d4fb61ea | ||
|
|
0c88cc740f | ||
|
|
b2b7783ec0 | ||
|
|
9790ddfa82 | ||
|
|
986a30e014 | ||
|
|
03a18cb202 | ||
|
|
c37ee0742a | ||
|
|
2ab604d36f |
+1
-1
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,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 /
|
||||
)
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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]))
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user