Skip to content

Instantly share code, notes, and snippets.

@woodruffw
Created May 26, 2020 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save woodruffw/d163c761af63a94add73d125f210406a to your computer and use it in GitHub Desktop.
Save woodruffw/d163c761af63a94add73d125f210406a to your computer and use it in GitHub Desktop.
uthenticode snippets
auto *md = indir_data->messageDigest;
auto nid = OBJ_obj2nid(md->digestAlgorithm->algorithm);
auto digest = std::vector<std::uint8_t>(md->digest->data, md->digest->data + md->digest->length);
struct win_certificate {
uint32_t length; /* dwLength */
uint16_t revision; /* wRevision */
uint16_t certificate_type; /* wCertificateType */
uint8_t certificate[/* length */]; /* bCertificate */
} __attribute__((aligned (8)));
SpcSerializedObject ::= SEQUENCE {
classId SpcUuid,
serializedData Impl_SpcSerializedData
}
Impl_SpcSerializedData ::= SET OF Impl_SpcPageHash
Impl_SpcPageHash ::= SEQUENCE {
type OBJECT IDENTIFIER,
pageHashes OCTETSTRING
}
struct impl_page_hash {
/* page_offset corresponds to a real file offset within each section,
* and should be aligned by page size.
*/
uint32_t page_offset;
uint8_t page_hash[IMPL_PAGE_HASH_SIZE];
} __attribute__((packed));
typedef impl_page_hash *impl_page_hashes;
SpcIndirectDataContent ::= SEQUENCE {
data SpcAttributeTypeAndOptionalValue,
messageDigest DigestInfo
}
SpcAttributeTypeAndOptionalValue ::= SEQUENCE {
type OBJECT IDENTIFIER,
value [0] EXPLICIT ANY OPTIONAL
}
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTETSTRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters [0] EXPLICIT ANY OPTIONAL
}
typedef struct {
ASN1_OBJECT *type;
ASN1_TYPE *value;
} Authenticode_SpcAttributeTypeAndOptionalValue;
typedef struct {
X509_ALGOR *digestAlgorithm;
ASN1_OCTET_STRING *digest;
} Authenticode_DigestInfo;
typedef struct {
Authenticode_SpcAttributeTypeAndOptionalValue *data;
Authenticode_DigestInfo *messageDigest;
} Authenticode_SpcIndirectDataContent;
ASN1_SEQUENCE(Authenticode_SpcAttributeTypeAndOptionalValue) = {
ASN1_SIMPLE(Authenticode_SpcAttributeTypeAndOptionalValue, type, ASN1_OBJECT),
ASN1_OPT(Authenticode_SpcAttributeTypeAndOptionalValue, value, ASN1_ANY)
} ASN1_SEQUENCE_END(Authenticode_SpcAttributeTypeAndOptionalValue)
IMPLEMENT_ASN1_FUNCTIONS(Authenticode_SpcAttributeTypeAndOptionalValue)
ASN1_SEQUENCE(Authenticode_DigestInfo) = {
ASN1_SIMPLE(Authenticode_DigestInfo, digestAlgorithm, X509_ALGOR),
ASN1_SIMPLE(Authenticode_DigestInfo, digest, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(Authenticode_DigestInfo)
IMPLEMENT_ASN1_FUNCTIONS(Authenticode_DigestInfo)
ASN1_SEQUENCE(Authenticode_SpcIndirectDataContent) = {
ASN1_SIMPLE(Authenticode_SpcIndirectDataContent, data, Authenticode_SpcAttributeTypeAndOptionalValue),
ASN1_SIMPLE(Authenticode_SpcIndirectDataContent, messageDigest, Authenticode_DigestInfo)
} ASN1_SEQUENCE_END(Authenticode_SpcIndirectDataContent)
IMPLEMENT_ASN1_FUNCTIONS(Authenticode_SpcIndirectDataContent)
TimeStampRequest ::= SEQUENCE {
countersignatureType OBJECT IDENTIFIER,
attributes Attributes OPTIONAL,
content ContentInfo
}
#include <uthenticode.h>
#include <iostream>
int main(int argc, char **argv) {
auto *pe = peparse::ParsePEFromFile(argv[1]);
std::cout << argv[1] << " has a "
<< (uthenticode::verify(pe) ? "valid" : "invalid")
<< " signature!";
}
/* Assuming that buf is an OpenSSL BIO* containing the DER-encoded PKCS#7 object */
auto *p7 = d2i_PKCS7_bio(buf, nullptr);
auto *contents = p7->d.sign->contents;
/* The d2i_ family increments the pointer passed to it, so we make a copy. */
auto *indir_data_inc_ptr = contents->d.other->value.sequence->data;
auto *indir_data = d2i_Authenticode_SpcIndirectDataContent(
nullptr, &indir_data_inc_ptr, contents->d.other->value.sequence->length);
STACK_OF(X509) *certs = p7->d.sign->cert;
/* Re-serialize the SpcIndirectDataContent to DER... */
std::uint8_t indir_data_buf = nullptr;
i2d_Authenticode_SpcIndirectDataContent(indir_data, &indir_data_buf);
/* ...so that we can unwrap its sequence here. */
const auto *signed_data_seq = indir_data_buf;
long length = 0;
int tag = 0, tag_class = 0;
ASN1_get_object(&signed_data_seq, &length, &tag, &tag_class, buf_size);
assert(tag == V_ASN1_SEQUENCE);
auto *signed_data = BIO_new_mem_buf(signed_data_seq, length);
/* Our stack of certs isn't guaranteed to include the root cert,
* so pass PKCS7_NOVERIFY.
*/
PKCS7_verify(p7, certs, nullptr, signed_data, nullptr, PKCS7_NOVERIFY);
assert(status == 1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment