diff --git a/include/retdec/fileformat/types/certificate_table/certificate_table.h b/include/retdec/fileformat/types/certificate_table/certificate_table.h index 99460dd9e..762d3e6fa 100644 --- a/include/retdec/fileformat/types/certificate_table/certificate_table.h +++ b/include/retdec/fileformat/types/certificate_table/certificate_table.h @@ -51,6 +51,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 6328908e0..3a6ad5bb8 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 2ef5a9d25..5acf22a38 100644 --- a/src/fileinfo/file_presentation/json_presentation.cpp +++ b/src/fileinfo/file_presentation/json_presentation.cpp @@ -516,12 +516,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; } - writer.String("digitalSignatures"); + writer.StartObject(); writer.Key("numberOfSignatures"); writer.Int64(fileinfo.certificateTable->signatures.size()); diff --git a/src/fileinfo/file_presentation/plain_presentation.cpp b/src/fileinfo/file_presentation/plain_presentation.cpp index ee512197d..c8d77904c 100644 --- a/src/fileinfo/file_presentation/plain_presentation.cpp +++ b/src/fileinfo/file_presentation/plain_presentation.cpp @@ -770,16 +770,19 @@ static void printSignature(const DigitalSignature& signature, int indent) void PlainPresentation::presentSignatures() const { const CertificateTable* table = fileinfo.certificateTable; - if (!table) { + if (!table || !table->isOutsideImage) + { return; } Log::info() << "\n"; Log::info() << "Digital Signatures\n"; Log::info() << "------------------\n\n"; int indent = 4; + 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"; 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; + } }