Updated padding, updated signing

Bryan Roe committed May 25, 2022 at 22:26 UTC 21b35662145cdb5533f3cb8e8c730bf523eaba82
1 file changed +49 -3
authenticode.js
+49 -3
@@ -53,6 +53,7 @@ function createAuthenticodeHandler(path) {
53 if (obj.fd != null) return;
54
55 // Open the file descriptor
56 + obj.path = path;
57 obj.fd = fs.openSync(path);
58 obj.stats = fs.fstatSync(obj.fd);
59 obj.filesize = obj.stats.size;
@@ -82,10 +83,20 @@ function createAuthenticodeHandler(path) {
83 obj.header.siglen = buf.readUInt32LE(4);
84 obj.header.signed = ((obj.header.sigpos != 0) && (obj.header.siglen != 0));
85
85 - if (obj.header.signed) {
86 + if (obj.header.signed)
87 + {
88 // Read signature block
87 - // TODO: The 3 bytes at the end may be padding we need to remove, not a contant.
88 - var pkcs7raw = readFileSlice(obj.header.sigpos + 8, obj.header.siglen - 8 - 3);
89 + // Check the last 8 bytes for padding (Quad-Aligned), and remove it
90 + var pkcs7raw = readFileSlice(obj.header.sigpos + 8, obj.header.siglen - 8);
91 + var i;
92 + for (i = 0; i < 8 && pkcs7raw[pkcs7raw.length - 1 - i] == 0; ++i)
93 + {
94 + }
95 + if (i > 0)
96 + {
97 + pkcs7raw = pkcs7raw.slice(0, pkcs7raw.length - i);
98 + }
99 +
100 var pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(pkcs7raw));
101
102 // To work around ForgeJS PKCS#7 limitation
@@ -198,6 +209,40 @@ function createAuthenticodeHandler(path) {
209 p7.sign();
210 var p7signature = Buffer.from(forge.pkcs7.messageToPem(p7).split('-----BEGIN PKCS7-----')[1].split('-----END PKCS7-----')[0], 'base64');
211 console.log('p7signature', p7signature.toString('base64'));
212 +
213 +
214 + var len = this.filesize + p7signature.length;
215 + var padding = (8 - ((len) % 8)) % 8; // Quad Align the results, adding padding if necessary
216 +
217 + var addresstable = Buffer.alloc(8);
218 + addresstable.writeUInt32LE(this.filesize);
219 + addresstable.writeUInt32LE(8 + p7signature.length + padding, 4);
220 +
221 + var b = this.path.split('.');
222 + b[b.length - 2] += '-jsigned';
223 +
224 + var output = fs.openSync(b.join('.'), 'w');
225 + var written = 0;
226 + var bytesLeft = this.filesize;
227 + var tmp;
228 +
229 + while ((this.filesize - written) > 0)
230 + {
231 + tmp = readFileSlice(written, (this.filesize - written) > 65535 ? 65535 : this.filesize - written);
232 + fs.writeSync(output, tmp);
233 + written += tmp.length;
234 + }
235 +
236 + var win = Buffer.alloc(8); // WIN CERTIFICATE Structure
237 + win.writeUInt32LE(p7signature.length + padding + 8); // DWORD length
238 + win.writeUInt16LE(512, 4); // WORD revision
239 + win.writeUInt16LE(2, 6); // WORD type
240 +
241 + fs.writeSync(output, win);
242 + fs.writeSync(output, p7signature);
243 + if (padding > 0) { fs.writeSync(output, Buffer.alloc(padding, 0)); }
244 + fs.writeSync(output, addresstable, 0, addresstable.length, this.header.header_size + 152 + (this.header.pe32plus * 16));
245 + fs.closeSync(output);
246 }
247
248 openFile();
@@ -241,6 +286,7 @@ function start() {
286 if (exe.fileHashSigned != null) { console.log('fileHashSigned', exe.fileHashSigned.toString('hex')); }
287 if (exe.fileHashActual != null) { console.log('fileHashActual', exe.fileHashActual.toString('hex')); }
288 if (exe.signatureBlock) { console.log('Signature', exe.signatureBlock.toString('hex')); }
289 + console.log('FileLen: ' + exe.filesize);
290 }
291
292 if (command == 'sign') {