Fixed authenticode PS checksum calculation.

Ylian Saint-Hilaire committed Jun 8, 2022 at 14:52 UTC 85fc1a4d4ccc68522355f483d58103b37ebc899b
2 files changed +15 -38
authenticode.js
+13 -36
@@ -744,26 +744,26 @@ function createAuthenticodeHandler(path) {
744
745 // Checksum the file loading 64k chunks
746 function runChecksum() {
747 - var ptr = 0, c = createChecksum();
747 + var ptr = 0, c = createChecksum(((obj.header.peOptionalHeaderLocation + 64) / 4));
748 while (ptr < obj.filesize) { const buf = readFileSlice(ptr, Math.min(65536, obj.filesize - ptr)); c.update(buf); ptr += buf.length; }
749 return c.digest();
750 }
751
752 // Checksum the open file loading 64k chunks
753 - function runChecksumOnFile(fd, filesize) {
754 - var ptr = 0, c = createChecksum(), buf = Buffer.alloc(65536);
753 + function runChecksumOnFile(fd, filesize, checksumLocation) {
754 + var ptr = 0, c = createChecksum(checksumLocation), buf = Buffer.alloc(65536);
755 while (ptr < filesize) { var len = fs.readSync(fd, buf, 0, Math.min(65536, filesize - ptr), ptr); c.update(buf, len); ptr += len; }
756 return c.digest();
757 }
758
759 // Steaming checksum methods
760 // TODO: Works only with files padded to 4 byte.
761 - function createChecksum() {
761 + function createChecksum(checksumLocation) {
762 const obj = { checksum: 0, length: 0 };
763 obj.update = function (data, len) {
764 if (!len) { len = data.length; }
765 for (var i = 0; i < (len / 4) ; i++) {
766 - if (((obj.length / 4) + i) == 54) continue; // Skip PE checksum location
766 + if (((obj.length / 4) + i) == checksumLocation) continue; // Skip PE checksum location
767 const dword = data.readUInt32LE(i * 4);
768 var checksumlo = (obj.checksum > 4294967296) ? (obj.checksum - 4294967296) : obj.checksum;
769 var checksumhi = (obj.checksum > 4294967296) ? 1 : 0;
@@ -786,34 +786,11 @@ function createAuthenticodeHandler(path) {
786 return obj;
787 }
788
789 - // Simple checksum method that works on a complete file at once
790 - // TODO: Works only with files padded to 4 byte.
791 - function updateChecksum(data) {
792 - var checksum = 0;
793 - for (var i = 0; i < (data.length / 4) ; i++) {
794 - if (i == 54) continue; // Skip PE checksum location
795 - var dword = data.readUInt32LE(i * 4);
796 - var checksumlo = (checksum > 4294967296) ? (checksum - 4294967296) : checksum;
797 - var checksumhi = (checksum > 4294967296) ? 1 : 0;
798 - checksum = checksumlo + dword + checksumhi;
799 - if (checksum > 4294967296) {
800 - checksumlo = (checksum > 4294967296) ? (checksum - 4294967296) : checksum;
801 - checksumhi = (checksum > 4294967296) ? 1 : 0;
802 - checksum = checksumlo + checksumhi;
803 - }
804 - }
805 - checksum = (checksum & 0xffff) + (checksum >>> 16);
806 - checksum = (checksum) + (checksum >>> 16);
807 - checksum = checksum & 0xffff;
808 - checksum += data.length;
809 - return checksum;
810 - }
811 -
789 // Compute the PE checksum of an entire file
813 - function getChecksum(data) {
790 + function getChecksum(data, checksumLocation) {
791 var checksum = 0;
792 for (var i = 0; i < (data.length / 4) ; i++) {
816 - if (i == 54) continue; // Skip PE checksum location
793 + if (i == (checksumLocation / 4)) continue; // Skip PE checksum location
794 var dword = data.readUInt32LE(i * 4);
795 var checksumlo = (checksum > 4294967296) ? (checksum - 4294967296) : checksum;
796 var checksumhi = (checksum > 4294967296) ? 1 : 0;
@@ -920,12 +897,12 @@ function createAuthenticodeHandler(path) {
897 fs.writeSync(output, win);
898 fs.writeSync(output, p7signature);
899 if (padding > 0) { fs.writeSync(output, Buffer.alloc(padding, 0)); }
923 - written += p7signature.length + padding + 8;
900 + written += (p7signature.length + padding + 8);
901
925 - // Compute the checksum and write it in the PE header at position (54 * 4)
902 + // Compute the checksum and write it in the PE header checksum location
903 var tmp = Buffer.alloc(4);
927 - tmp.writeUInt32LE(runChecksumOnFile(output, written));
928 - fs.writeSync(output, tmp, 0, 4, 54 * 4);
904 + tmp.writeUInt32LE(runChecksumOnFile(output, written, ((obj.header.peOptionalHeaderLocation + 64) / 4)));
905 + fs.writeSync(output, tmp, 0, 4, obj.header.peOptionalHeaderLocation + 64);
906
907 // Close the file
908 fs.closeSync(output);
@@ -955,10 +932,10 @@ function createAuthenticodeHandler(path) {
932 written += tmp.length;
933 }
934
958 - // Compute the checksum and write it in the PE header at position (54 * 4)
935 + // Compute the checksum and write it in the PE checksum header at position
936 var tmp = Buffer.alloc(4);
937 tmp.writeUInt32LE(runChecksumOnFile(output, written));
961 - fs.writeSync(output, tmp, 0, 4, 54 * 4);
938 + fs.writeSync(output, tmp, 0, 4, obj.header.peOptionalHeaderLocation + 64);
939
940 fs.closeSync(output);
941 }
public/translate.bat
+2 -2
@@ -1,7 +1,7 @@
1 @ECHO OFF
2 CD ..\translate
3 %LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js minifyall
4 -REM %LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js translateall
5 -REM %LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js extractall
4 +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js translateall
5 +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js extractall
6 DEL ..\emails\translations\*-min_*
7 Pause
\ No newline at end of file