From b6e09eca120c0e6fa12ed4c7fea6aef5c5cd17da Mon Sep 17 00:00:00 2001 From: houndthe Date: Tue, 13 Jul 2021 16:24:29 +0200 Subject: [PATCH 1/3] Check if certificate table is outside of the image and export the information --- .../certificate_table/certificate_table.h | 2 + include/retdec/pelib/SecurityDirectory.h | 6 +++ src/fileformat/file_format/pe/pe_format.cpp | 37 ++++++++++++++++--- .../file_presentation/json_presentation.cpp | 2 + .../file_presentation/plain_presentation.cpp | 4 +- src/pelib/SecurityDirectory.cpp | 14 +++++++ 6 files changed, 59 insertions(+), 6 deletions(-) diff --git a/include/retdec/fileformat/types/certificate_table/certificate_table.h b/include/retdec/fileformat/types/certificate_table/certificate_table.h index a6c279f36..2a9c545c3 100644 --- a/include/retdec/fileformat/types/certificate_table/certificate_table.h +++ b/include/retdec/fileformat/types/certificate_table/certificate_table.h @@ -50,6 +50,8 @@ class CertificateTable { public: std::vector signatures; + // if the certificates overlap any section then they are not visible for windows + bool isOutsideImage = false; CertificateTable(std::vector signatures); CertificateTable() = default; diff --git a/include/retdec/pelib/SecurityDirectory.h b/include/retdec/pelib/SecurityDirectory.h index e4b9c19e2..68c7e5170 100644 --- a/include/retdec/pelib/SecurityDirectory.h +++ b/include/retdec/pelib/SecurityDirectory.h @@ -7,6 +7,8 @@ #ifndef RETDEC_PELIB_SECURITYDIRECTORY_H #define RETDEC_PELIB_SECURITYDIRECTORY_H +#include + namespace PeLib { class SecurityDirectory @@ -14,9 +16,13 @@ namespace PeLib private: LoaderError m_ldrError; std::vector m_certs; + std::uint64_t offset = 0; + std::uint64_t size = 0; public: /// Constructor SecurityDirectory(); + std::uint64_t getOffset() const; + std::uint64_t getSize() const; /// Number of certificates in the directory. unsigned int calcNumberOfCertificates() const; // EXPORT /// Returns certificate at specified index. diff --git a/src/fileformat/file_format/pe/pe_format.cpp b/src/fileformat/file_format/pe/pe_format.cpp index 22dad022c..ed6ae2e22 100644 --- a/src/fileformat/file_format/pe/pe_format.cpp +++ b/src/fileformat/file_format/pe/pe_format.cpp @@ -1798,16 +1798,43 @@ void PeFormat::loadResources() */ void PeFormat::loadCertificates() { - const auto& securityDir = file->securityDir(); - if (securityDir.calcNumberOfCertificates() == 0) { + const SecurityDirectory& securityDir = file->securityDir(); + if (securityDir.calcNumberOfCertificates() == 0) + { return; } + // We always take the first one, there might be more WIN_CERT structures tho - auto certBytes = securityDir.getCertificate(0); + const std::vector& certBytes = securityDir.getCertificate(0); authenticode::Authenticode authenticode(certBytes); - - certificateTable = new CertificateTable(authenticode.getSignatures(this)); + + this->certificateTable = new CertificateTable(authenticode.getSignatures(this)); + + std::uint64_t dirOffset = securityDir.getOffset(); + std::uint64_t dirSize = securityDir.getSize(); + + std::vector sections = getSections(); + + certificateTable->isOutsideImage = true; + // check if the SecurityDir overlaps with any real part of section + // if it does, Windows ignores the certificates + for (const Section* sec : sections) + { + std::uint64_t realSize = sec->getSizeInFile(); + std::uint64_t realOffset = sec->getOffset(); + if (!realSize) + { + continue; + } + std::uint64_t realEndOffset = realOffset + realSize; + std::uint64_t dirEndOffset = dirOffset + dirOffset; + // if the intervals overlap + if (dirOffset < realEndOffset && realOffset < dirEndOffset) + { + certificateTable->isOutsideImage = false; + } + } } /** diff --git a/src/fileinfo/file_presentation/json_presentation.cpp b/src/fileinfo/file_presentation/json_presentation.cpp index 8f00afc97..d52746837 100644 --- a/src/fileinfo/file_presentation/json_presentation.cpp +++ b/src/fileinfo/file_presentation/json_presentation.cpp @@ -521,6 +521,8 @@ void JsonPresentation::presentCertificates(Writer& writer) const writer.String("digitalSignatures"); writer.StartObject(); + writer.Key("isOutsideImage"); + writer.Bool(fileinfo.certificateTable->isOutsideImage); writer.Key("numberOfSignatures"); writer.Int64(fileinfo.certificateTable->signatures.size()); writer.String("signatures"); diff --git a/src/fileinfo/file_presentation/plain_presentation.cpp b/src/fileinfo/file_presentation/plain_presentation.cpp index f948cc0d6..fcdd5462b 100644 --- a/src/fileinfo/file_presentation/plain_presentation.cpp +++ b/src/fileinfo/file_presentation/plain_presentation.cpp @@ -772,8 +772,10 @@ void PlainPresentation::presentSignatures() const if (!table) { return; } - Log::info() << "Digital Signatures:\n"; + Log::info() << "\nDigital Signatures:\n"; int indent = 4; + std::string isOutsideImage = table->isOutsideImage ? "True" : "False"; + Log::info() << std::string(indent, ' ') << "Is Outside of Image: " << isOutsideImage << "\n"; Log::info() << std::string(indent, ' ') << "Signature count: " << table->signatureCount() << "\n"; for (int idx = 0; idx < table->signatureCount(); idx++) { diff --git a/src/pelib/SecurityDirectory.cpp b/src/pelib/SecurityDirectory.cpp index b2a336695..80f897388 100644 --- a/src/pelib/SecurityDirectory.cpp +++ b/src/pelib/SecurityDirectory.cpp @@ -84,6 +84,20 @@ namespace PeLib m_certs.push_back(cert); } + // save the offset and size for future checks + this->offset = uiOffset; + this->size = size; + return ERROR_NONE; } + + std::uint64_t SecurityDirectory::getOffset() const + { + return offset; + } + + std::uint64_t SecurityDirectory::getSize() const + { + return size; + } } From 6c08b55b6623750cfc3d6fab884750a4965f1862 Mon Sep 17 00:00:00 2001 From: houndthe Date: Mon, 26 Jul 2021 23:57:59 +0200 Subject: [PATCH 2/3] Move signatures that are inside images into their own invalid signatures container --- .../file_presentation/json_presentation.cpp | 15 ++++++++++----- .../file_presentation/plain_presentation.cpp | 18 +++++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/fileinfo/file_presentation/json_presentation.cpp b/src/fileinfo/file_presentation/json_presentation.cpp index d52746837..37e1d85eb 100644 --- a/src/fileinfo/file_presentation/json_presentation.cpp +++ b/src/fileinfo/file_presentation/json_presentation.cpp @@ -514,15 +514,20 @@ void WriteSignature(JsonPresentation::Writer& writer, const DigitalSignature& si void JsonPresentation::presentCertificates(Writer& writer) const { - if(!fileinfo.certificateTable) + if (!fileinfo.certificateTable) { return; } - - writer.String("digitalSignatures"); + bool isOutside = fileinfo.certificateTable->isOutsideImage; + if (isOutside) + { + writer.String("digitalSignatures"); + } + else + { + writer.String("invalidSignatures"); + } writer.StartObject(); - writer.Key("isOutsideImage"); - writer.Bool(fileinfo.certificateTable->isOutsideImage); writer.Key("numberOfSignatures"); writer.Int64(fileinfo.certificateTable->signatures.size()); writer.String("signatures"); diff --git a/src/fileinfo/file_presentation/plain_presentation.cpp b/src/fileinfo/file_presentation/plain_presentation.cpp index fcdd5462b..7e03fcb16 100644 --- a/src/fileinfo/file_presentation/plain_presentation.cpp +++ b/src/fileinfo/file_presentation/plain_presentation.cpp @@ -769,16 +769,24 @@ static void printSignature(const DigitalSignature& signature, int indent) void PlainPresentation::presentSignatures() const { const CertificateTable* table = fileinfo.certificateTable; - if (!table) { + if (!table) + { return; } - Log::info() << "\nDigital Signatures:\n"; + if (table->isOutsideImage) + { + Log::info() << "\nDigital Signatures:\n"; + } + else + { + Log::info() << "\nInvalid Digital Signatures:\n"; + } int indent = 4; - std::string isOutsideImage = table->isOutsideImage ? "True" : "False"; - Log::info() << std::string(indent, ' ') << "Is Outside of Image: " << isOutsideImage << "\n"; + Log::info() << std::string(indent, ' ') << "Signature count: " << table->signatureCount() << "\n"; - for (int idx = 0; idx < table->signatureCount(); idx++) { + for (int idx = 0; idx < table->signatureCount(); idx++) + { Log::info() << std::string(indent, ' ') << "Signature #" << idx << ":\n"; printSignature(table->signatures[idx], indent + 4); Log::info() << "\n"; From cac59af4aa88baad29167540baecd2fed52e0705 Mon Sep 17 00:00:00 2001 From: houndthe Date: Fri, 13 Aug 2021 02:13:48 +0200 Subject: [PATCH 3/3] Don't output invalid signatures --- .../file_presentation/json_presentation.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/fileinfo/file_presentation/json_presentation.cpp b/src/fileinfo/file_presentation/json_presentation.cpp index 37e1d85eb..4b991a641 100644 --- a/src/fileinfo/file_presentation/json_presentation.cpp +++ b/src/fileinfo/file_presentation/json_presentation.cpp @@ -514,19 +514,12 @@ void WriteSignature(JsonPresentation::Writer& writer, const DigitalSignature& si void JsonPresentation::presentCertificates(Writer& writer) const { - if (!fileinfo.certificateTable) + if (!fileinfo.certificateTable || !fileinfo.certificateTable->isOutsideImage) { return; } - bool isOutside = fileinfo.certificateTable->isOutsideImage; - if (isOutside) - { - writer.String("digitalSignatures"); - } - else - { - writer.String("invalidSignatures"); - } + writer.String("digitalSignatures"); + writer.StartObject(); writer.Key("numberOfSignatures"); writer.Int64(fileinfo.certificateTable->signatures.size());