@@ -1100,10 +1100,196 @@ EXPORT_FUNCTIONS* pe_parse_exports(
1100
1100
1101
1101
#if defined(HAVE_LIBCRYPTO )
1102
1102
1103
+ //
1104
+ // Parse a PKCS7 blob, looking for certs and nested PKCS7 blobs.
1105
+ //
1106
+
1107
+ void _parse_pkcs7 (
1108
+ PE * pe ,
1109
+ PKCS7 * pkcs7 ,
1110
+ int * counter )
1111
+ {
1112
+ int i ;
1113
+ STACK_OF (X509 )* certs ;
1114
+ certs = PKCS7_get0_signers (pkcs7 , NULL , 0 );
1115
+
1116
+ if (!certs )
1117
+ {
1118
+ return ;
1119
+ }
1120
+
1121
+ for (i = 0 ; i < sk_X509_num (certs ); i ++ )
1122
+ {
1123
+ time_t date_time ;
1124
+ const char * sig_alg ;
1125
+ char buffer [256 ];
1126
+ int bytes ;
1127
+ const EVP_MD * sha1_digest = EVP_sha1 ();
1128
+ const unsigned char * p ;
1129
+ unsigned char thumbprint [YR_SHA1_LEN ];
1130
+ char thumbprint_ascii [YR_SHA1_LEN * 2 + 1 ];
1131
+
1132
+ PKCS7_SIGNER_INFO * signer_info ;
1133
+ ASN1_INTEGER * serial ;
1134
+ ASN1_TYPE * nested ;
1135
+ ASN1_STRING * value ;
1136
+ PKCS7 * nested_pkcs7 ;
1137
+
1138
+ X509 * cert = sk_X509_value (certs , i );
1139
+
1140
+ X509_digest (cert , sha1_digest , thumbprint , NULL );
1141
+
1142
+ for (i = 0 ; i < YR_SHA1_LEN ; i ++ )
1143
+ sprintf (thumbprint_ascii + (i * 2 ), "%02x" , thumbprint [i ]);
1144
+
1145
+ set_string (
1146
+ (char * ) thumbprint_ascii ,
1147
+ pe -> object ,
1148
+ "signatures[%i].thumbprint" ,
1149
+ * counter );
1150
+
1151
+ X509_NAME_oneline (
1152
+ X509_get_issuer_name (cert ), buffer , sizeof (buffer ));
1153
+
1154
+ set_string (buffer , pe -> object , "signatures[%i].issuer" , * counter );
1155
+
1156
+ X509_NAME_oneline (
1157
+ X509_get_subject_name (cert ), buffer , sizeof (buffer ));
1158
+
1159
+ set_string (buffer , pe -> object , "signatures[%i].subject" , * counter );
1160
+
1161
+ set_integer (
1162
+ X509_get_version (cert ) + 1 , // Versions are zero based, so add one.
1163
+ pe -> object ,
1164
+ "signatures[%i].version" , * counter );
1165
+
1166
+ sig_alg = OBJ_nid2ln (X509_get_signature_nid (cert ));
1167
+
1168
+ set_string (sig_alg , pe -> object , "signatures[%i].algorithm" , * counter );
1169
+
1170
+ serial = X509_get_serialNumber (cert );
1171
+
1172
+ if (serial )
1173
+ {
1174
+ // ASN1_INTEGER can be negative (serial->type & V_ASN1_NEG_INTEGER),
1175
+ // in which case the serial number will be stored in 2's complement.
1176
+ //
1177
+ // Handle negative serial numbers, which are technically not allowed
1178
+ // by RFC5280, but do exist. An example binary which has a negative
1179
+ // serial number is: 4bfe05f182aa273e113db6ed7dae4bb8.
1180
+ //
1181
+ // Negative serial numbers are handled by calling i2d_ASN1_INTEGER()
1182
+ // with a NULL second parameter. This will return the size of the
1183
+ // buffer necessary to store the proper serial number.
1184
+ //
1185
+ // Do this even for positive serial numbers because it makes the code
1186
+ // cleaner and easier to read.
1187
+
1188
+ bytes = i2d_ASN1_INTEGER (serial , NULL );
1189
+
1190
+ // According to X.509 specification the maximum length for the
1191
+ // serial number is 20 octets. Add two bytes to account for
1192
+ // DER type and length information.
1193
+
1194
+ if (bytes > 2 && bytes <= 22 )
1195
+ {
1196
+ // Now that we know the size of the serial number allocate enough
1197
+ // space to hold it, and use i2d_ASN1_INTEGER() one last time to
1198
+ // hold it in the allocated buffer.
1199
+
1200
+ unsigned char * serial_der = (unsigned char * ) yr_malloc (bytes );
1201
+
1202
+ if (serial_der != NULL )
1203
+ {
1204
+ unsigned char * serial_bytes ;
1205
+ char * serial_ascii ;
1206
+
1207
+ bytes = i2d_ASN1_INTEGER (serial , & serial_der );
1208
+
1209
+ // i2d_ASN1_INTEGER() moves the pointer as it writes into
1210
+ // serial_bytes. Move it back.
1211
+
1212
+ serial_der -= bytes ;
1213
+
1214
+ // Skip over DER type, length information
1215
+ serial_bytes = serial_der + 2 ;
1216
+ bytes -= 2 ;
1217
+
1218
+ // Also allocate space to hold the "common" string format:
1219
+ // 00:01:02:03:04...
1220
+ //
1221
+ // For each byte in the serial to convert to hexlified format we
1222
+ // need three bytes, two for the byte itself and one for colon.
1223
+ // The last one doesn't have the colon, but the extra byte is used
1224
+ // for the NULL terminator.
1225
+
1226
+ serial_ascii = (char * ) yr_malloc (bytes * 3 );
1227
+
1228
+ if (serial_ascii )
1229
+ {
1230
+ int j ;
1231
+
1232
+ for (j = 0 ; j < bytes ; j ++ )
1233
+ {
1234
+ // Don't put the colon on the last one.
1235
+ if (j < bytes - 1 )
1236
+ snprintf (
1237
+ serial_ascii + 3 * j , 4 , "%02x:" , serial_bytes [j ]);
1238
+ else
1239
+ snprintf (
1240
+ serial_ascii + 3 * j , 3 , "%02x" , serial_bytes [j ]);
1241
+ }
1242
+
1243
+ set_string (
1244
+ serial_ascii ,
1245
+ pe -> object ,
1246
+ "signatures[%i].serial" ,
1247
+ * counter );
1248
+
1249
+ yr_free (serial_ascii );
1250
+ }
1251
+
1252
+ yr_free (serial_der );
1253
+ }
1254
+ }
1255
+ }
1256
+
1257
+ date_time = ASN1_get_time_t (X509_get_notBefore (cert ));
1258
+ set_integer (date_time , pe -> object , "signatures[%i].not_before" , * counter );
1259
+
1260
+ date_time = ASN1_get_time_t (X509_get_notAfter (cert ));
1261
+ set_integer (date_time , pe -> object , "signatures[%i].not_after" , * counter );
1262
+
1263
+ (* counter )++ ;
1264
+
1265
+ // See if there is a nested signature, which is apparently an authenticode
1266
+ // specific feature. See https://github.com/VirusTotal/yara/issues/515.
1267
+ signer_info = sk_PKCS7_SIGNER_INFO_value (pkcs7 -> d .sign -> signer_info , 0 );
1268
+ if (signer_info == NULL )
1269
+ continue ;
1270
+ nested = PKCS7_get_attribute (
1271
+ signer_info , OBJ_txt2nid (SPC_NESTED_SIGNATURE_OBJID ));
1272
+ if (nested != NULL )
1273
+ {
1274
+ value = nested -> value .sequence ;
1275
+ p = value -> data ;
1276
+ nested_pkcs7 = d2i_PKCS7 (NULL , & p , value -> length );
1277
+ if (nested_pkcs7 != NULL )
1278
+ {
1279
+ _parse_pkcs7 (pe , nested_pkcs7 , counter );
1280
+ PKCS7_free (nested_pkcs7 );
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ sk_X509_free (certs );
1286
+ }
1287
+
1288
+
1103
1289
void pe_parse_certificates (
1104
1290
PE * pe )
1105
1291
{
1106
- int i , counter = 0 ;
1292
+ int counter = 0 ;
1107
1293
1108
1294
const uint8_t * eod ;
1109
1295
uintptr_t end ;
@@ -1155,7 +1341,6 @@ void pe_parse_certificates(
1155
1341
{
1156
1342
BIO * cert_bio ;
1157
1343
PKCS7 * pkcs7 ;
1158
- STACK_OF (X509 )* certs ;
1159
1344
1160
1345
// Some sanity checks
1161
1346
@@ -1186,161 +1371,16 @@ void pe_parse_certificates(
1186
1371
break ;
1187
1372
1188
1373
pkcs7 = d2i_PKCS7_bio (cert_bio , NULL );
1189
- certs = PKCS7_get0_signers (pkcs7 , NULL , 0 );
1190
-
1191
- if (!certs )
1374
+ if (pkcs7 != NULL )
1192
1375
{
1193
- BIO_free ( cert_bio );
1376
+ _parse_pkcs7 ( pe , pkcs7 , & counter );
1194
1377
PKCS7_free (pkcs7 );
1195
- break ;
1196
- }
1197
-
1198
- for (i = 0 ; i < sk_X509_num (certs ); i ++ )
1199
- {
1200
- time_t date_time ;
1201
- const char * sig_alg ;
1202
- char buffer [256 ];
1203
- int bytes ;
1204
- const EVP_MD * sha1_digest = EVP_sha1 ();
1205
- unsigned char thumbprint [YR_SHA1_LEN ];
1206
- char thumbprint_ascii [YR_SHA1_LEN * 2 + 1 ];
1207
-
1208
- ASN1_INTEGER * serial ;
1209
-
1210
- X509 * cert = sk_X509_value (certs , i );
1211
-
1212
- X509_digest (cert , sha1_digest , thumbprint , NULL );
1213
-
1214
- for (i = 0 ; i < YR_SHA1_LEN ; i ++ )
1215
- sprintf (thumbprint_ascii + (i * 2 ), "%02x" , thumbprint [i ]);
1216
-
1217
- set_string (
1218
- (char * ) thumbprint_ascii ,
1219
- pe -> object ,
1220
- "signatures[%i].thumbprint" ,
1221
- counter );
1222
-
1223
- X509_NAME_oneline (
1224
- X509_get_issuer_name (cert ), buffer , sizeof (buffer ));
1225
-
1226
- set_string (buffer , pe -> object , "signatures[%i].issuer" , counter );
1227
-
1228
- X509_NAME_oneline (
1229
- X509_get_subject_name (cert ), buffer , sizeof (buffer ));
1230
-
1231
- set_string (buffer , pe -> object , "signatures[%i].subject" , counter );
1232
-
1233
- set_integer (
1234
- X509_get_version (cert ) + 1 , // Versions are zero based, so add one.
1235
- pe -> object ,
1236
- "signatures[%i].version" , counter );
1237
-
1238
- sig_alg = OBJ_nid2ln (X509_get_signature_nid (cert ));
1239
-
1240
- set_string (sig_alg , pe -> object , "signatures[%i].algorithm" , counter );
1241
-
1242
- serial = X509_get_serialNumber (cert );
1243
-
1244
- if (serial )
1245
- {
1246
- // ASN1_INTEGER can be negative (serial->type & V_ASN1_NEG_INTEGER),
1247
- // in which case the serial number will be stored in 2's complement.
1248
- //
1249
- // Handle negative serial numbers, which are technically not allowed
1250
- // by RFC5280, but do exist. An example binary which has a negative
1251
- // serial number is: 4bfe05f182aa273e113db6ed7dae4bb8.
1252
- //
1253
- // Negative serial numbers are handled by calling i2d_ASN1_INTEGER()
1254
- // with a NULL second parameter. This will return the size of the
1255
- // buffer necessary to store the proper serial number.
1256
- //
1257
- // Do this even for positive serial numbers because it makes the code
1258
- // cleaner and easier to read.
1259
-
1260
- bytes = i2d_ASN1_INTEGER (serial , NULL );
1261
-
1262
- // According to X.509 specification the maximum length for the
1263
- // serial number is 20 octets. Add two bytes to account for
1264
- // DER type and length information.
1265
-
1266
- if (bytes > 2 && bytes <= 22 )
1267
- {
1268
- // Now that we know the size of the serial number allocate enough
1269
- // space to hold it, and use i2d_ASN1_INTEGER() one last time to
1270
- // hold it in the allocated buffer.
1271
-
1272
- unsigned char * serial_der = (unsigned char * ) yr_malloc (bytes );
1273
-
1274
- if (serial_der != NULL )
1275
- {
1276
- unsigned char * serial_bytes ;
1277
- char * serial_ascii ;
1278
-
1279
- bytes = i2d_ASN1_INTEGER (serial , & serial_der );
1280
-
1281
- // i2d_ASN1_INTEGER() moves the pointer as it writes into
1282
- // serial_bytes. Move it back.
1283
-
1284
- serial_der -= bytes ;
1285
-
1286
- // Skip over DER type, length information
1287
- serial_bytes = serial_der + 2 ;
1288
- bytes -= 2 ;
1289
-
1290
- // Also allocate space to hold the "common" string format:
1291
- // 00:01:02:03:04...
1292
- //
1293
- // For each byte in the serial to convert to hexlified format we
1294
- // need three bytes, two for the byte itself and one for colon.
1295
- // The last one doesn't have the colon, but the extra byte is used
1296
- // for the NULL terminator.
1297
-
1298
- serial_ascii = (char * ) yr_malloc (bytes * 3 );
1299
-
1300
- if (serial_ascii )
1301
- {
1302
- int j ;
1303
-
1304
- for (j = 0 ; j < bytes ; j ++ )
1305
- {
1306
- // Don't put the colon on the last one.
1307
- if (j < bytes - 1 )
1308
- snprintf (
1309
- serial_ascii + 3 * j , 4 , "%02x:" , serial_bytes [j ]);
1310
- else
1311
- snprintf (
1312
- serial_ascii + 3 * j , 3 , "%02x" , serial_bytes [j ]);
1313
- }
1314
-
1315
- set_string (
1316
- serial_ascii ,
1317
- pe -> object ,
1318
- "signatures[%i].serial" ,
1319
- counter );
1320
-
1321
- yr_free (serial_ascii );
1322
- }
1323
-
1324
- yr_free (serial_der );
1325
- }
1326
- }
1327
- }
1328
-
1329
- date_time = ASN1_get_time_t (X509_get_notBefore (cert ));
1330
- set_integer (date_time , pe -> object , "signatures[%i].not_before" , counter );
1331
-
1332
- date_time = ASN1_get_time_t (X509_get_notAfter (cert ));
1333
- set_integer (date_time , pe -> object , "signatures[%i].not_after" , counter );
1334
-
1335
- counter ++ ;
1336
1378
}
1337
1379
1338
1380
end = (uintptr_t )((uint8_t * ) win_cert ) + yr_le32toh (win_cert -> Length );
1339
1381
win_cert = (PWIN_CERTIFICATE )(end + (end % 8 ));
1340
1382
1341
1383
BIO_free (cert_bio );
1342
- PKCS7_free (pkcs7 );
1343
- sk_X509_free (certs );
1344
1384
}
1345
1385
1346
1386
set_integer (counter , pe -> object , "number_of_signatures" );
@@ -2597,6 +2637,11 @@ end_declarations;
2597
2637
int module_initialize (
2598
2638
YR_MODULE * module )
2599
2639
{
2640
+ #if defined(HAVE_LIBCRYPTO )
2641
+ // Not checking return value here because if it fails we will not parse the
2642
+ // nested signature silently.
2643
+ OBJ_create (SPC_NESTED_SIGNATURE_OBJID , NULL , NULL );
2644
+ #endif
2600
2645
return ERROR_SUCCESS ;
2601
2646
}
2602
2647
0 commit comments