Skip to content

Commit f925cc4

Browse files
committed
Don't use BIO interface, use d2i instead. Fix some other small bugs and don't recurse forever when parsing nested signatures.
1 parent a564309 commit f925cc4

File tree

2 files changed

+23
-27
lines changed

2 files changed

+23
-27
lines changed

libyara/include/yara/pe.h

+2
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@ typedef struct _VERSION_INFO {
464464
} VERSION_INFO, *PVERSION_INFO;
465465

466466

467+
#define MAX_PE_CERTS 16
468+
467469
#define WIN_CERT_REVISION_1_0 0x0100
468470
#define WIN_CERT_REVISION_2_0 0x0200
469471

libyara/modules/pe.c

+21-27
Original file line numberDiff line numberDiff line change
@@ -1109,14 +1109,16 @@ void _parse_pkcs7(
11091109
PKCS7* pkcs7,
11101110
int* counter)
11111111
{
1112-
int i;
1112+
int i, j;
11131113
STACK_OF(X509)* certs;
1114+
1115+
if (*counter >= MAX_PE_CERTS)
1116+
return;
1117+
11141118
certs = PKCS7_get0_signers(pkcs7, NULL, 0);
11151119

11161120
if (!certs)
1117-
{
11181121
return;
1119-
}
11201122

11211123
for (i = 0; i < sk_X509_num(certs); i++)
11221124
{
@@ -1129,18 +1131,18 @@ void _parse_pkcs7(
11291131
unsigned char thumbprint[YR_SHA1_LEN];
11301132
char thumbprint_ascii[YR_SHA1_LEN * 2 + 1];
11311133

1132-
PKCS7_SIGNER_INFO* signer_info;
1133-
ASN1_INTEGER* serial;
1134-
ASN1_TYPE* nested;
1135-
ASN1_STRING* value;
1136-
PKCS7* nested_pkcs7;
1134+
PKCS7_SIGNER_INFO* signer_info = NULL;
1135+
PKCS7* nested_pkcs7 = NULL;
1136+
ASN1_INTEGER* serial = NULL;
1137+
ASN1_TYPE* nested = NULL;
1138+
ASN1_STRING* value = NULL;
11371139

11381140
X509* cert = sk_X509_value(certs, i);
11391141

11401142
X509_digest(cert, sha1_digest, thumbprint, NULL);
11411143

1142-
for (i = 0; i < YR_SHA1_LEN; i++)
1143-
sprintf(thumbprint_ascii + (i * 2), "%02x", thumbprint[i]);
1144+
for (j = 0; j < YR_SHA1_LEN; j++)
1145+
sprintf(thumbprint_ascii + (j * 2), "%02x", thumbprint[j]);
11441146

11451147
set_string(
11461148
(char*) thumbprint_ascii,
@@ -1227,8 +1229,6 @@ void _parse_pkcs7(
12271229

12281230
if (serial_ascii)
12291231
{
1230-
int j;
1231-
12321232
for (j = 0; j < bytes; j++)
12331233
{
12341234
// Don't put the colon on the last one.
@@ -1292,6 +1292,7 @@ void pe_parse_certificates(
12921292
int counter = 0;
12931293

12941294
const uint8_t* eod;
1295+
const unsigned char* cert_p;
12951296
uintptr_t end;
12961297

12971298
PWIN_CERTIFICATE win_cert;
@@ -1339,7 +1340,6 @@ void pe_parse_certificates(
13391340
(uint8_t*) win_cert + sizeof(WIN_CERTIFICATE) < eod &&
13401341
(uint8_t*) win_cert + yr_le32toh(win_cert->Length) <= eod)
13411342
{
1342-
BIO* cert_bio;
13431343
PKCS7* pkcs7;
13441344

13451345
// Some sanity checks
@@ -1357,30 +1357,24 @@ void pe_parse_certificates(
13571357
if (yr_le16toh(win_cert->Revision) != WIN_CERT_REVISION_2_0 ||
13581358
yr_le16toh(win_cert->CertificateType) != WIN_CERT_TYPE_PKCS_SIGNED_DATA)
13591359
{
1360-
uintptr_t end = (uintptr_t)
1361-
((uint8_t *) win_cert) + yr_le32toh(win_cert->Length);
1360+
end = (uintptr_t)((uint8_t*) win_cert) + yr_le32toh(win_cert->Length);
13621361

13631362
win_cert = (PWIN_CERTIFICATE) (end + (end % 8));
13641363
continue;
13651364
}
13661365

1367-
cert_bio = BIO_new_mem_buf(
1368-
win_cert->Certificate, yr_le32toh(win_cert->Length) - WIN_CERTIFICATE_HEADER_SIZE);
1369-
1370-
if (!cert_bio)
1371-
break;
1372-
1373-
pkcs7 = d2i_PKCS7_bio(cert_bio, NULL);
1374-
if (pkcs7 != NULL)
1366+
cert_p = win_cert->Certificate;
1367+
end = (uintptr_t)((uint8_t*) win_cert) + yr_le32toh(win_cert->Length);
1368+
while ((uintptr_t) cert_p < end && counter < MAX_PE_CERTS)
13751369
{
1370+
pkcs7 = d2i_PKCS7(NULL, &cert_p, (win_cert->Length));
1371+
if (pkcs7 == NULL)
1372+
break;
13761373
_parse_pkcs7(pe, pkcs7, &counter);
13771374
PKCS7_free(pkcs7);
13781375
}
13791376

1380-
end = (uintptr_t)((uint8_t *) win_cert) + yr_le32toh(win_cert->Length);
1381-
win_cert = (PWIN_CERTIFICATE)(end + (end % 8));
1382-
1383-
BIO_free(cert_bio);
1377+
win_cert = (PWIN_CERTIFICATE) (end + (end % 8));
13841378
}
13851379

13861380
set_integer(counter, pe->object, "number_of_signatures");

0 commit comments

Comments
 (0)