Merge pull request #317 from recvfrom/master

Update the PE Authenticode parsing code
This commit is contained in:
Romain 2019-07-10 06:54:08 +02:00 committed by GitHub
commit bab1c1d5b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 162 additions and 166 deletions

View File

@ -50,10 +50,22 @@ void AuthenticatedAttributes::accept(Visitor& visitor) const {
std::ostream& operator<<(std::ostream& os, const AuthenticatedAttributes& authenticated_attributes) {
constexpr uint8_t wsize = 30;
std::string content_type = authenticated_attributes.content_type();
if (content_type.empty()) {
content_type = "N/A";
}
std::string program_name = u16tou8(authenticated_attributes.program_name());
if (program_name.empty()) {
program_name = "N/A";
}
std::string url = authenticated_attributes.more_info();
if (url.empty()) {
url = "N/A";
}
os << std::hex << std::left;
os << std::setw(wsize) << std::setfill(' ') << "Content type: " << authenticated_attributes.content_type() << std::endl;
os << std::setw(wsize) << std::setfill(' ') << "Program name: " << u16tou8(authenticated_attributes.program_name()) << std::endl;
os << std::setw(wsize) << std::setfill(' ') << "URL : " << authenticated_attributes.more_info() << std::endl;
os << std::setw(wsize) << std::setfill(' ') << "Content type: " << content_type << std::endl;
os << std::setw(wsize) << std::setfill(' ') << "Program name: " << program_name << std::endl;
os << std::setw(wsize) << std::setfill(' ') << "URL : " << url << std::endl;
return os;
}

View File

@ -997,6 +997,7 @@ const char* oid_to_string(const oid_t& oid) {
{ "1.3.6.1.4.1.311.2.2.1", "CTL_TRUSTED_CODESIGNING_CA_LIST" },
{ "1.3.6.1.4.1.311.2.2.2", "CTL_TRUSTED_CLIENT_AUTH_CA_LIST" },
{ "1.3.6.1.4.1.311.2.2.3", "CTL_TRUSTED_SERVER_AUTH_CA_LIST" },
{ "1.3.6.1.4.1.311.2.4.1", "SPC_NESTED_SIGNATURES" },
{ "1.3.6.1.4.1.311.3.2.1", "TIMESTAMP_REQUEST" },
{ "1.3.6.1.4.1.311.10.1", "CERT_TRUST_LIST" },
{ "1.3.6.1.4.1.311.10.1.1", "SORTED_CTL" },

View File

@ -156,8 +156,11 @@ std::string SignatureParser::get_signed_data_digest_algorithms(void) {
ContentInfo SignatureParser::parse_content_info(void) {
VLOG(VDEBUG) << "Parse signed data - content info";
mbedtls_asn1_buf content_type_oid;
mbedtls_asn1_buf alg_oid;
int ret = 0;
size_t tag;
char oid_str[256] = { 0 };
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
@ -185,9 +188,6 @@ ContentInfo SignatureParser::parse_content_info(void) {
throw corrupted("Signature corrupted");
}
this->p_ += tag; // skip
return content_info;
#if 0
// SpcAttributeTypeAndOptionalValue
// |_ SPC_PE_IMAGE_DATAOBJ
// |_ SpcPeImageData
@ -270,7 +270,6 @@ ContentInfo SignatureParser::parse_content_info(void) {
this->p_ += tag;
return content_info;
#endif
}
@ -352,166 +351,139 @@ AuthenticatedAttributes SignatureParser::get_authenticated_attributes(void) {
throw corrupted("Authenticated attributes corrupted");
}
// contentType (1.2.840.113549.1.9.3)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
uint8_t* p_end = this->p_ + tag;
while(this->p_ < p_end) {
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
this->p_ += content_type_oid.len;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if (std::string(oid_str) == "1.2.840.113549.1.9.3") {
// contentType
// |_ OID (PKCS #9 Message Digest)
// |_ SET -> OID
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VLOG(VDEBUG) << "Parsing contentType (offset: "
<< std::dec << this->current_offset()
<< ")";
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
authenticated_attributes.content_type_ = oid_str;
this->p_ += content_type_oid.len;
continue;
} else if (std::string(oid_str) == "1.2.840.113549.1.9.4") {
// messageDigest (Octet string)
// |_ OID (PKCS #9 Message Digest)
// |_ SET -> OCTET STING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VLOG(VDEBUG) << "Parsing messageDigest (offset: "
<< std::dec << this->current_offset()
<< ")";
VLOG(VDEBUG) << oid_str << " (" << oid_to_string(oid_str) << ")"; // 1.2.840.113549.1.9.4
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
throw corrupted("Signature corrupted: Can't read 'ASN1_OCTET_STRING'");
}
authenticated_attributes.message_digest_ = {this->p_, this->p_ + tag};
this->p_ += tag;
continue;
} else if (std::string(oid_str) == "1.3.6.1.4.1.311.2.1.12") {
// SpcSpOpusInfo
// |_ programName (utf16)
// |_ moreInfo
// ~~~~~~~~~~~~~~~~~~~~~~
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if (tag == 0) {
VLOG(VDEBUG) << "No program name or more info specified ";
authenticated_attributes.program_name_ = u"";
authenticated_attributes.more_info_ = "";
continue;
}
uint8_t *seq_end = this->p_ + tag;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
VLOG(VDEBUG) << "Offset: " << std::dec << this->current_offset();
VLOG(VDEBUG) << "Size: " << std::dec << tag;
// u8 -> u16 due to endiness
std::string u8progname{reinterpret_cast<char*>(this->p_), tag};
std::u16string progname;
try {
utf8::unchecked::utf8to16(std::begin(u8progname), std::end(u8progname), std::back_inserter(progname));
} catch (const utf8::exception&) {
LOG(WARNING) << "utf8 error when parsing progname";
}
authenticated_attributes.program_name_ = progname;
VLOG(VDEBUG) << "ProgName " << u16tou8(progname);
this->p_ += tag;
if (this->p_ >= seq_end) {
VLOG(VDEBUG) << "No more info specified ";
authenticated_attributes.more_info_ = "";
continue;
}
// moreInfo
// ++++++++
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_BOOLEAN )) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
std::string more_info{reinterpret_cast<char*>(this->p_), tag}; // moreInfo
authenticated_attributes.more_info_ = more_info;
VLOG(VDEBUG) << more_info;
this->p_ += tag;
continue;
} else {
VLOG(VDEBUG) << "Skipping OID " << oid_str;
this->p_ += tag;
continue;
}
}
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
VLOG(VDEBUG) << oid_str; // 1.2.840.113549.1.9.3 (PKCS #9 contentType)
if (std::string(oid_str) != "1.2.840.113549.1.9.3") {
throw corrupted("Authenticated attributes corrupted: Wrong Content type OID (" + std::string(oid_str) + ")");
}
this->p_ += content_type_oid.len;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
VLOG(VDEBUG) << oid_str; // 1.2.840.113549.1.9.4
this->p_ += content_type_oid.len;
//authenticated_attributes.content_type_ = oid_str;
// TODO
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Signature corrupted");
}
this->p_ += tag;
// messageDigest (Octet string)
// |_ OID (PKCS #9 Message Disgest)
// |_ SET -> OCTET STING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VLOG(VDEBUG) << "Parsing messageDigest (offset: "
<< std::dec << this->current_offset()
<< ")";
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
VLOG(VDEBUG) << oid_str << " (" << oid_to_string(oid_str) << ")"; // 1.2.840.113549.1.9.4
this->p_ += content_type_oid.len;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
throw corrupted("Signature corrupted: Can't read 'ASN1_OCTET_STRING'");
}
authenticated_attributes.message_digest_ = {this->p_, this->p_ + tag};
this->p_ += tag;
// SpcSpOpusInfo
// |_ programName (utf16)
// |_ moreInfo
// ~~~~~~~~~~~~~~~~~~~~~~
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Signature corrupted");
}
content_type_oid.tag = *this->p_;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &content_type_oid.len, MBEDTLS_ASN1_OID)) != 0) {
throw corrupted("Signature corrupted");
}
content_type_oid.p = this->p_;
std::memset(oid_str, 0, sizeof(oid_str));
mbedtls_oid_get_numeric_string(oid_str, sizeof(oid_str), &content_type_oid);
VLOG(VDEBUG) << oid_str; // 1.3.6.1.4.1.311.2.1.12 (SpcSpOpusInfoObjId)
this->p_ += content_type_oid.len;
// programName
// +++++++++++
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SET | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
VLOG(VDEBUG) << "Offset: " << std::dec << this->current_offset();
VLOG(VDEBUG) << "Size: " << std::dec << tag;
// u8 -> u16 due to endiness
std::string u8progname{reinterpret_cast<char*>(this->p_), tag};
std::u16string progname;
try {
utf8::unchecked::utf8to16(std::begin(u8progname), std::end(u8progname), std::back_inserter(progname));
} catch (const utf8::exception&) {
LOG(WARNING) << "utf8 error when parsing progname";
}
authenticated_attributes.program_name_ = progname;
VLOG(VDEBUG) << "ProgName " << u16tou8(progname);
this->p_ += tag;
// moreInfo
// ++++++++
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_BOOLEAN )) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
throw corrupted("Authenticated attributes corrupted");
}
std::string more_info{reinterpret_cast<char*>(this->p_), tag}; // moreInfo
authenticated_attributes.more_info_ = more_info;
VLOG(VDEBUG) << more_info;
this->p_ += tag;
return authenticated_attributes;
}
@ -587,10 +559,21 @@ SignerInfo SignatureParser::get_signer_info(void) {
VLOG(VDEBUG) << "Component ID: " << oid_str;
this->p_ += content_type_oid.len;
if ((ret = mbedtls_asn1_get_tag(&(this->p_), this->end_, &tag, MBEDTLS_ASN1_PRINTABLE_STRING)) != 0) {
if ( (p_end - this->p_) < 1 ) {
throw corrupted("Signer info corrupted");
}
if (*this->p_ != MBEDTLS_ASN1_UTF8_STRING &&
*this->p_ != MBEDTLS_ASN1_PRINTABLE_STRING &&
*this->p_ != MBEDTLS_ASN1_IA5_STRING) {
throw corrupted("Signer info corrupted");
}
this->p_ += 1;
if ((ret = mbedtls_asn1_get_len(&(this->p_), this->end_, &tag)) != 0) {
throw corrupted("Signer info corrupted");
}
std::string name{reinterpret_cast<char*>(this->p_), tag};
issuer_name.emplace_back(oid_str, name);
VLOG(VDEBUG) << "Name: " << name;