Skip to content

Commit

Permalink
Check if certificateTable overlaps a section and export the informati…
Browse files Browse the repository at this point in the history
…on (avast#986)

* Check if certificate table is outside of the image and export the information

* Move signatures that are inside images into their own invalid signatures container

* Don't output invalid signatures
  • Loading branch information
HoundThe authored Aug 30, 2021
1 parent 60e61fa commit bc7daac
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class CertificateTable
{
public:
std::vector<DigitalSignature> signatures;
// if the certificates overlap any section then they are not visible for windows
bool isOutsideImage = false;

CertificateTable(std::vector<DigitalSignature> signatures);
CertificateTable() = default;
Expand Down
6 changes: 6 additions & 0 deletions include/retdec/pelib/SecurityDirectory.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@
#ifndef RETDEC_PELIB_SECURITYDIRECTORY_H
#define RETDEC_PELIB_SECURITYDIRECTORY_H

#include <cstdint>

namespace PeLib
{
class SecurityDirectory
{
private:
LoaderError m_ldrError;
std::vector<PELIB_IMAGE_CERTIFICATE_ENTRY> 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.
Expand Down
35 changes: 31 additions & 4 deletions src/fileformat/file_format/pe/pe_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1799,16 +1799,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<unsigned char>& 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<Section*> 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;
}
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/fileinfo/file_presentation/json_presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
7 changes: 5 additions & 2 deletions src/fileinfo/file_presentation/plain_presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
14 changes: 14 additions & 0 deletions src/pelib/SecurityDirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit bc7daac

Please sign in to comment.