More improvements to authenticode-js error handling.

Ylian Saint-Hilaire committed Jun 23, 2022 at 16:23 UTC 339e3efbefac28e2a24d88a00798e24fed95b223
1 file changed +99 -95
authenticode.js
+99 -95
@@ -415,91 +415,93 @@ function createAuthenticodeHandler(path) {
415
416 // Decode the timestamp signature block
417 var timepkcs7der = null;
418 - try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func('' + ex); return; }
418 + try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func("Unable to parse time-stamp response: " + ex); return; }
419
420 // Decode the executable signature block
421 var pkcs7der = null;
422 - try { pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(obj.getRawSignatureBlock(), 'base64').toString('binary'))); } catch (ex) { func('' + ex); return; }
423 -
424 - // Get the ASN1 certificates used to sign the timestamp and add them to the certs in the PKCS7 of the executable
425 - // TODO: We could look to see if the certificate is already present in the executable
426 - const timeasn1Certs = timepkcs7der.value[1].value[0].value[3].value;
427 - for (var i in timeasn1Certs) { pkcs7der.value[1].value[0].value[3].value.push(timeasn1Certs[i]); }
428 -
429 - // Remove any existing time stamp signatures
430 - var newValues = [];
431 - for (var i in pkcs7der.value[1].value[0].value[4].value[0].value) {
432 - const j = pkcs7der.value[1].value[0].value[4].value[0].value[i];
433 - if ((j.tagClass != 128) || (j.type != 1)) { newValues.push(j); } // If this is not a time stamp, add it to out new list.
434 - }
435 - pkcs7der.value[1].value[0].value[4].value[0].value = newValues; // Set the new list
422 + try {
423 + var pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(obj.getRawSignatureBlock(), 'base64').toString('binary')));
424
437 - // Get the time signature and add it to the executables PKCS7
438 - const timeasn1Signature = timepkcs7der.value[1].value[0].value[4];
439 - const countersignatureOid = asn1.oidToDer('1.2.840.113549.1.9.6').data;
440 - const asn1obj2 =
441 - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
442 - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
443 - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, countersignatureOid),
444 - timeasn1Signature
445 - ])
446 - ]);
447 - pkcs7der.value[1].value[0].value[4].value[0].value.push(asn1obj2);
448 -
449 - // Re-encode the executable signature block
450 - const p7signature = Buffer.from(forge.asn1.toDer(pkcs7der).data, 'binary');
425 + // Get the ASN1 certificates used to sign the timestamp and add them to the certs in the PKCS7 of the executable
426 + // TODO: We could look to see if the certificate is already present in the executable
427 + const timeasn1Certs = timepkcs7der.value[1].value[0].value[3].value;
428 + for (var i in timeasn1Certs) { pkcs7der.value[1].value[0].value[3].value.push(timeasn1Certs[i]); }
429
452 - // Open the output file
453 - var output = null;
454 - try { output = fs.openSync(args.out, 'w+'); } catch (ex) { }
455 - if (output == null) return false;
456 - var tmp, written = 0;
457 - var executableSize = obj.header.sigpos ? obj.header.sigpos : this.filesize;
430 + // Remove any existing time stamp signatures
431 + var newValues = [];
432 + for (var i in pkcs7der.value[1].value[0].value[4].value[0].value) {
433 + const j = pkcs7der.value[1].value[0].value[4].value[0].value[i];
434 + if ((j.tagClass != 128) || (j.type != 1)) { newValues.push(j); } // If this is not a time stamp, add it to out new list.
435 + }
436 + pkcs7der.value[1].value[0].value[4].value[0].value = newValues; // Set the new list
437
459 - // Compute pre-header length and copy that to the new file
460 - var preHeaderLen = (obj.header.peHeaderLocation + 152 + (obj.header.pe32plus * 16));
461 - var tmp = readFileSlice(written, preHeaderLen);
462 - fs.writeSync(output, tmp);
463 - written += tmp.length;
438 + // Get the time signature and add it to the executables PKCS7
439 + const timeasn1Signature = timepkcs7der.value[1].value[0].value[4];
440 + const countersignatureOid = asn1.oidToDer('1.2.840.113549.1.9.6').data;
441 + const asn1obj2 =
442 + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
443 + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
444 + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, countersignatureOid),
445 + timeasn1Signature
446 + ])
447 + ]);
448 + pkcs7der.value[1].value[0].value[4].value[0].value.push(asn1obj2);
449
465 - // Quad Align the results, adding padding if necessary
466 - var len = executableSize + p7signature.length;
467 - var padding = (8 - ((len) % 8)) % 8;
450 + // Re-encode the executable signature block
451 + const p7signature = Buffer.from(forge.asn1.toDer(pkcs7der).data, 'binary');
452
469 - // Write the signature header
470 - var addresstable = Buffer.alloc(8);
471 - addresstable.writeUInt32LE(executableSize);
472 - addresstable.writeUInt32LE(8 + p7signature.length + padding, 4);
473 - fs.writeSync(output, addresstable);
474 - written += addresstable.length;
453 + // Open the output file
454 + var output = null;
455 + try { output = fs.openSync(args.out, 'w+'); } catch (ex) { }
456 + if (output == null) return false;
457 + var tmp, written = 0;
458 + var executableSize = obj.header.sigpos ? obj.header.sigpos : this.filesize;
459
476 - // Copy the rest of the file until the start of the signature block
477 - while ((executableSize - written) > 0) {
478 - tmp = readFileSlice(written, Math.min(executableSize - written, 65536));
460 + // Compute pre-header length and copy that to the new file
461 + var preHeaderLen = (obj.header.peHeaderLocation + 152 + (obj.header.pe32plus * 16));
462 + var tmp = readFileSlice(written, preHeaderLen);
463 fs.writeSync(output, tmp);
464 written += tmp.length;
481 - }
465
483 - // Write the signature block header and signature
484 - var win = Buffer.alloc(8); // WIN CERTIFICATE Structure
485 - win.writeUInt32LE(p7signature.length + padding + 8); // DWORD length
486 - win.writeUInt16LE(512, 4); // WORD revision
487 - win.writeUInt16LE(2, 6); // WORD type
488 - fs.writeSync(output, win);
489 - fs.writeSync(output, p7signature);
490 - if (padding > 0) { fs.writeSync(output, Buffer.alloc(padding, 0)); }
491 - written += (p7signature.length + padding + 8);
492 -
493 - // Compute the checksum and write it in the PE header checksum location
494 - var tmp = Buffer.alloc(4);
495 - tmp.writeUInt32LE(runChecksumOnFile(output, written, ((obj.header.peOptionalHeaderLocation + 64) / 4)));
496 - fs.writeSync(output, tmp, 0, 4, obj.header.peOptionalHeaderLocation + 64);
497 -
498 - // Close the file
499 - fs.closeSync(output);
500 -
501 - // Indicate we are done
502 - func(null);
466 + // Quad Align the results, adding padding if necessary
467 + var len = executableSize + p7signature.length;
468 + var padding = (8 - ((len) % 8)) % 8;
469 +
470 + // Write the signature header
471 + var addresstable = Buffer.alloc(8);
472 + addresstable.writeUInt32LE(executableSize);
473 + addresstable.writeUInt32LE(8 + p7signature.length + padding, 4);
474 + fs.writeSync(output, addresstable);
475 + written += addresstable.length;
476 +
477 + // Copy the rest of the file until the start of the signature block
478 + while ((executableSize - written) > 0) {
479 + tmp = readFileSlice(written, Math.min(executableSize - written, 65536));
480 + fs.writeSync(output, tmp);
481 + written += tmp.length;
482 + }
483 +
484 + // Write the signature block header and signature
485 + var win = Buffer.alloc(8); // WIN CERTIFICATE Structure
486 + win.writeUInt32LE(p7signature.length + padding + 8); // DWORD length
487 + win.writeUInt16LE(512, 4); // WORD revision
488 + win.writeUInt16LE(2, 6); // WORD type
489 + fs.writeSync(output, win);
490 + fs.writeSync(output, p7signature);
491 + if (padding > 0) { fs.writeSync(output, Buffer.alloc(padding, 0)); }
492 + written += (p7signature.length + padding + 8);
493 +
494 + // Compute the checksum and write it in the PE header checksum location
495 + var tmp = Buffer.alloc(4);
496 + tmp.writeUInt32LE(runChecksumOnFile(output, written, ((obj.header.peOptionalHeaderLocation + 64) / 4)));
497 + fs.writeSync(output, tmp, 0, 4, obj.header.peOptionalHeaderLocation + 64);
498 +
499 + // Close the file
500 + fs.closeSync(output);
501 +
502 + // Indicate we are done
503 + func(null);
504 + } catch (ex) { func('' + ex); return; }
505 });
506 }
507
@@ -1315,30 +1317,32 @@ function createAuthenticodeHandler(path) {
1317
1318 // Decode the timestamp signature block
1319 var timepkcs7der = null;
1318 - try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func('' + ex); return; }
1320 + try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func("Unable to parse time-stamp response: " + ex); return; }
1321
1320 - // Get the ASN1 certificates used to sign the timestamp and add them to the certs in the PKCS7 of the executable
1321 - // TODO: We could look to see if the certificate is already present in the executable
1322 - const timeasn1Certs = timepkcs7der.value[1].value[0].value[3].value;
1323 - for (var i in timeasn1Certs) { pkcs7der.value[1].value[0].value[3].value.push(timeasn1Certs[i]); }
1324 -
1325 - // Get the time signature and add it to the executables PKCS7
1326 - const timeasn1Signature = timepkcs7der.value[1].value[0].value[4];
1327 - const countersignatureOid = asn1.oidToDer('1.2.840.113549.1.9.6').data;
1328 - const asn1obj2 =
1329 - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
1330 - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1331 - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, countersignatureOid),
1332 - timeasn1Signature
1333 - ])
1334 - ]);
1335 - pkcs7der.value[1].value[0].value[4].value[0].value.push(asn1obj2);
1322 + try {
1323 + // Get the ASN1 certificates used to sign the timestamp and add them to the certs in the PKCS7 of the executable
1324 + // TODO: We could look to see if the certificate is already present in the executable
1325 + const timeasn1Certs = timepkcs7der.value[1].value[0].value[3].value;
1326 + for (var i in timeasn1Certs) { pkcs7der.value[1].value[0].value[3].value.push(timeasn1Certs[i]); }
1327 +
1328 + // Get the time signature and add it to the executables PKCS7
1329 + const timeasn1Signature = timepkcs7der.value[1].value[0].value[4];
1330 + const countersignatureOid = asn1.oidToDer('1.2.840.113549.1.9.6').data;
1331 + const asn1obj2 =
1332 + asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
1333 + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1334 + asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, countersignatureOid),
1335 + timeasn1Signature
1336 + ])
1337 + ]);
1338 + pkcs7der.value[1].value[0].value[4].value[0].value.push(asn1obj2);
1339
1337 - // Re-encode the executable signature block
1338 - const p7signature = Buffer.from(forge.asn1.toDer(pkcs7der).data, 'binary');
1340 + // Re-encode the executable signature block
1341 + const p7signature = Buffer.from(forge.asn1.toDer(pkcs7der).data, 'binary');
1342
1340 - // Write the file with the signature block
1341 - signEx(args, p7signature, obj.filesize, func);
1343 + // Write the file with the signature block
1344 + signEx(args, p7signature, obj.filesize, func);
1345 + } catch (ex) { func('' + ex); }
1346 });
1347 }
1348 }
@@ -1715,7 +1719,7 @@ function createAuthenticodeHandler(path) {
1719
1720 // Decode the timestamp signature block
1721 var timepkcs7der = null;
1718 - try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func('' + ex); return; }
1722 + try { timepkcs7der = forge.asn1.fromDer(forge.util.createBuffer(Buffer.from(data, 'base64').toString('binary'))); } catch (ex) { func("Unable to parse time-stamp response: " + ex); return; }
1723
1724 // Get the ASN1 certificates used to sign the timestamp and add them to the certs in the PKCS7 of the executable
1725 // TODO: We could look to see if the certificate is already present in the executable