Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions pe.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,10 @@ static ASN1_OBJECT *pe_spc_image_data_get(u_char **p, int *plen, FILE_FORMAT_CTX
if (EVP_MD_size(ctx->options->md) > EVP_MD_size(EVP_sha1()))
phtype = NID_sha256;
link = pe_page_hash_link_get(ctx, phtype);
if (!link)
if (!link) {
SpcPeImageData_free(pid);
return NULL; /* FAILED */
}
pid->file = link;
} else {
pid->file = spc_link_obsolete_get();
Expand Down Expand Up @@ -404,6 +406,7 @@ static PKCS7 *pe_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
content = spc_indirect_data_content_get(hash, ctx);
if (!content) {
fprintf(stderr, "Failed to get spcIndirectDataContent\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!sign_spc_indirect_data_content(p7, content)) {
Expand Down Expand Up @@ -1044,7 +1047,7 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
return NULL; /* FAILED */
}
off = ctx->pe_ctx->header_size + 160 + (size_t)ctx->pe_ctx->pe32plus * 16;
if (hdrsize < off) {
if (hdrsize < off || hdrsize > filebound) {
BIO_free_all(bhash);
return NULL; /* FAILED: header too small */
}
Expand Down Expand Up @@ -1321,7 +1324,8 @@ static int pe_check_file(FILE_FORMAT_CTX *ctx)
{
uint32_t real_pe_checksum, sum = 0;

if (!ctx) {
if (ctx == NULL || ctx->pe_ctx == NULL || ctx->options == NULL
|| ctx->options->indata == NULL) {
fprintf(stderr, "Init error\n");
return 0; /* FAILED */
}
Expand All @@ -1333,25 +1337,52 @@ static int pe_check_file(FILE_FORMAT_CTX *ctx)
printf("Calculated PE checksum: %08X\n", real_pe_checksum);
printf("Warning: invalid PE checksum\n");
}
/* Signature directory bounds */
if (ctx->pe_ctx->sigpos == 0 || ctx->pe_ctx->siglen == 0
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend) {
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend
|| ctx->pe_ctx->siglen > ctx->pe_ctx->fileend - ctx->pe_ctx->sigpos) {
fprintf(stderr, "No signature found\n");
return 0; /* FAILED */
}
/*
* Validate WIN_CERTIFICATE chain.
* If the sum of the rounded dwLength values does not equal the Size value,
* then either the attribute certificate table or the Size field is corrupted.
*/
while (sum < ctx->pe_ctx->siglen) {
uint32_t len = GET_UINT32_LE(ctx->options->indata + ctx->pe_ctx->sigpos + sum);
if (ctx->pe_ctx->siglen - len > 8) {
uint32_t len, off;

/* Prevent overflow in sigpos + sum */
if (sum > UINT32_MAX - ctx->pe_ctx->sigpos) {
fprintf(stderr, "Corrupted attribute certificate table\n");
fprintf(stderr, "Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
fprintf(stderr, "Attribute certificate entry length: %08X\n\n", len);
return 0; /* FAILED */
}
/* quadword align data */
len += len % 8 ? 8 - len % 8 : 0;
off = ctx->pe_ctx->sigpos + sum;

/* Need at least 4 bytes to read dwLength */
if (off > ctx->pe_ctx->fileend || ctx->pe_ctx->fileend - off < 4) {
fprintf(stderr, "Corrupted attribute certificate table\n");
return 0; /* FAILED */
}
len = GET_UINT32_LE(ctx->options->indata + off);

/* dwLength must include the 8-byte WIN_CERTIFICATE header */
if (len < 8 || len > ctx->pe_ctx->siglen - sum || len > ctx->pe_ctx->fileend - off) {
fprintf(stderr, "Corrupted attribute certificate table\n");
return 0; /* FAILED */
}

/* Quadword align data */
if (len % 8) {
uint32_t pad = 8 - (len % 8);

/* Ensure quadword alignment does not overflow or exceed remaining table size */
if (pad > ctx->pe_ctx->siglen - sum - len) {
fprintf(stderr, "Corrupted attribute certificate table\n");
return 0; /* FAILED */
}
len += pad;
}
sum += len;
}
if (sum != ctx->pe_ctx->siglen) {
Expand Down
Loading