Authenticode.js can now fully decode and reencode a resource section.

Ylian Saint-Hilaire committed Jun 9, 2022 at 11:37 UTC d06ca601ffde4602f97147038616ed2331f01624
1 file changed +12 -35
authenticode.js
+12 -35
@@ -627,7 +627,7 @@ function createAuthenticodeHandler(path) {
627
628 // Decode the version information from the resource
629 obj.getVersionInfo = function () {
630 - console.log('READ', getVersionInfoData().toString('hex'));
630 + //console.log('READ', getVersionInfoData().toString('hex'));
631 var r = {}, info = readVersionInfo(getVersionInfoData(), 0);
632 if ((info == null) || (info.stringFiles == null)) return null;
633 var StringFileInfo = null;
@@ -661,6 +661,7 @@ function createAuthenticodeHandler(path) {
661 //console.log('--WRITE BUF ARRAY START--');
662 //for (var i in verInfoResBufArray) { console.log(verInfoResBufArray[i].toString('hex')); }
663 //console.log('--WRITE BUF ARRAY END--');
664 + //console.log('OUT', Buffer.concat(verInfoResBufArray).toString('hex'));
665
666 // Set the new buffer as part of the resources
667 for (var i = 0; i < obj.resources.entries.length; i++) {
@@ -724,8 +725,6 @@ function createAuthenticodeHandler(path) {
725
726 if (info.stringFiles != null) { wLength += writeStringFileInfo(bufArray, info.stringFiles); }
727
727 - console.log('@@@@@@Z', wLength, Buffer.concat(bufArray).length);
728 -
728 buf.writeUInt16LE(Buffer.concat(bufArray).length, 0); // wLength
729 buf.writeUInt16LE(wValueLength, 2); // wValueLength
730 return wLength;
@@ -733,10 +732,10 @@ function createAuthenticodeHandler(path) {
732
733 // StringFileInfo structure: https://docs.microsoft.com/en-us/windows/win32/menurc/stringfileinfo
734 function writeStringFileInfo(bufArray, stringFiles) {
736 - //console.log('writeStringFileInfo', stringFiles);
735 var totalLen = 0;
736 for (var i in stringFiles) {
737 var l = 6 + (stringFiles[i].szKey.length * 2);
738 + if (stringFiles[i].szKey == 'VarFileInfo') { l += 4; } // TODO: This is a hack, not sure what the correct code should be
739 const buf2 = Buffer.alloc(padPointer(l));
740 buf2.writeUInt16LE(1, 4); // wType
741 stringToUnicode(stringFiles[i].szKey, buf2, 6);
@@ -756,8 +755,7 @@ function createAuthenticodeHandler(path) {
755
756 // VarFileInfo structure: https://docs.microsoft.com/en-us/windows/win32/menurc/var-str
757 function writeVarFileInfoStruct(bufArray, varFileInfo) {
759 - console.log('*************writeVarFileInfoStruct', varFileInfo);
760 - var l = 6 + (varFileInfo.szKey.length * 2);
758 + var l = 8 + (varFileInfo.szKey.length * 2);
759 const buf = Buffer.alloc(padPointer(l));
760 buf.writeUInt16LE(0, 4); // wType
761 stringToUnicode(varFileInfo.szKey, buf, 6);
@@ -769,11 +767,10 @@ function createAuthenticodeHandler(path) {
767 if (varFileInfo.value) {
768 bufArray.push(varFileInfo.value);
769 wLength += varFileInfo.value.length;
770 + wValueLength += varFileInfo.value.length;
771 }
773 - buf.writeUInt16LE(l + wLength, 0); // wLength
772 + buf.writeUInt16LE(buf.length + wLength, 0); // wLength
773 buf.writeUInt16LE(wValueLength, 2); // wValueLength
775 -
776 - //console.log('WwriteVarFileInfoStruct', buf.toString('hex'));
774 return buf.length + wLength;
775 }
776
@@ -792,8 +789,6 @@ function createAuthenticodeHandler(path) {
789 if (stringTable.strings) { wLength += writeStringStructs(bufArray, stringTable.strings); }
790 buf.writeUInt16LE(l + wLength, 0); // wLength
791 buf.writeUInt16LE(wValueLength, 2); // wValueLength
795 -
796 - //console.log('WStringTableStruct', buf.toString('hex'));
792 return buf.length + wLength;
793 }
794
@@ -1166,9 +1161,8 @@ function createAuthenticodeHandler(path) {
1161 obj.writeExecutable = function (args) {
1162 // Get version information from the resource
1163 var versions = obj.getVersionInfo();
1169 - //versions['FileDescription'] = 'Mesh Agent Service';
1164 + versions['FileDescription'] = 'This is a test';
1165 obj.setVersionInfo(versions);
1171 - //var versions2 = obj.getVersionInfo();
1166
1167 // Open the file
1168 var output = fs.openSync(args.out, 'w');
@@ -1185,11 +1179,13 @@ function createAuthenticodeHandler(path) {
1179 var newResSize = obj.header.sections['.rsrc'].rawSize; // Testing 102400
1180 var resDeltaSize = newResSize - oldResSize;
1181
1182 + /*
1183 console.log('fileAlign', fileAlign);
1184 console.log('resPtr', resPtr);
1185 console.log('oldResSize', oldResSize);
1186 console.log('newResSize', newResSize);
1187 console.log('resDeltaSize', resDeltaSize);
1188 + */
1189
1190 // Change PE optional header sizeOfInitializedData standard field
1191 fullHeader.writeUInt32LE(obj.header.peStandard.sizeOfInitializedData + resDeltaSize, obj.header.peOptionalHeaderLocation + 8);
@@ -1232,13 +1228,13 @@ function createAuthenticodeHandler(path) {
1228 }
1229
1230 // Write the entire header to the destination file
1235 - console.log('Write header', fullHeader.length);
1231 + //console.log('Write header', fullHeader.length);
1232 fs.writeSync(output, fullHeader);
1233 written += fullHeader.length;
1234
1235 // Write the entire executable until the start to the resource segment
1236 var totalWrite = resPtr;
1241 - console.log('Write until res', totalWrite);
1237 + //console.log('Write until res', totalWrite);
1238 while ((totalWrite - written) > 0) {
1239 tmp = readFileSlice(written, Math.min(totalWrite - written, 65536));
1240 fs.writeSync(output, tmp);
@@ -1250,28 +1246,9 @@ function createAuthenticodeHandler(path) {
1246 fs.writeSync(output, rsrcSection);
1247 written += rsrcSection.length;
1248
1253 - /*
1254 - // Write the old resource segment (debug)
1255 - totalWrite = resPtr + oldResSize;
1256 - console.log('Write res', totalWrite);
1257 - while ((totalWrite - written) > 0) {
1258 - tmp = readFileSlice(written, Math.min(totalWrite - written, 65536));
1259 - fs.writeSync(output, tmp);
1260 - written += tmp.length;
1261 - }
1262 - */
1263 -
1264 - /*
1265 - // Write a dummy 102400 bytes
1266 - tmp = Buffer.alloc(resDeltaSize);
1267 - console.log('Write dummy', resDeltaSize);
1268 - fs.writeSync(output, tmp);
1269 - written += tmp.length;
1270 - */
1271 -
1249 // Write until the signature block
1250 totalWrite = obj.header.sigpos + resDeltaSize;
1274 - console.log('Write until signature', totalWrite);
1251 + //console.log('Write until signature', totalWrite);
1252 while ((totalWrite - written) > 0) {
1253 tmp = readFileSlice(written - resDeltaSize, Math.min(totalWrite - written, 65536));
1254 fs.writeSync(output, tmp);