Fixed incorrect addresses in the directory table.

Ylian Saint-Hilaire committed Aug 11, 2022 at 12:41 UTC d2abcdc9d5b7d02b2364e27bac0af7f08f7f1c20
1 file changed +40 -24
authenticode.js
+40 -24
@@ -600,6 +600,7 @@ function createAuthenticodeHandler(path) {
600 // Pad the resource section & allocate the buffer
601 const fileAlign = obj.header.peWindows.fileAlignment
602 var resSizeTotal = resSizes.tables + resSizes.items + resSizes.names + resSizes.data;
603 + var resNoPadding = resSizeTotal + 4; // TODO: Not sure why this is off by 4
604 if ((resSizeTotal % fileAlign) != 0) { resSizeTotal += (fileAlign - (resSizeTotal % fileAlign)); }
605 const resSectionBuffer = Buffer.alloc(resSizeTotal);
606
@@ -609,7 +610,7 @@ function createAuthenticodeHandler(path) {
610 //console.log('generateResourceSection', resPointers);
611
612 // Done, return the result
612 - return resSectionBuffer;
613 + return { size: resNoPadding, data: resSectionBuffer };
614 }
615
616 // Return the total size of a resource header, this is a recursive method
@@ -828,7 +829,6 @@ function createAuthenticodeHandler(path) {
829 for (var j in iconInfo[i].icons) { xicons[nextIconNumber++] = iconInfo[i].icons[j]; }
830 iconInfo[i].icons = xicons;
831 }
831 - console.log(iconInfo);
832 if (iconGroupCount == 0) return; // If there are no icon groups, we are done
833
834 // Add the new icons entry
@@ -1657,6 +1657,16 @@ function createAuthenticodeHandler(path) {
1657 fs.closeSync(output);
1658 }
1659
1660 + // Find where a directory value is in the old sections and map it to the new sections
1661 + function correctDirectoryValue(oldSections, newSections, value) {
1662 + for (var i in oldSections) {
1663 + if ((value >= oldSections[i].virtualAddr) && (value < (oldSections[i].virtualAddr + oldSections[i].virtualSize))) {
1664 + return newSections[i].virtualAddr + (value - oldSections[i].virtualAddr);
1665 + }
1666 + }
1667 + return 0;
1668 + }
1669 +
1670 // Save the executable
1671 obj.writeExecutable = function (args, cert, func) {
1672 // Open the file
@@ -1667,11 +1677,10 @@ function createAuthenticodeHandler(path) {
1677 var fullHeaderLen = obj.header.SectionHeadersPtr + (obj.header.coff.numberOfSections * 40);
1678 var fullHeader = readFileSlice(written, fullHeaderLen);
1679
1670 - // Create the resource section and pad to next 512 byte boundry
1671 - var rsrcSection = generateResourceSection(obj.resources);
1672 - var rsrcSectionVirtualSize = rsrcSection.length;
1673 - var x = (rsrcSection.length % 512);
1674 - if (x != 0) { rsrcSection = Buffer.concat([rsrcSection, Buffer.alloc(512 - x)]); }
1680 + // Create the resource section
1681 + const rsrcSectionX = generateResourceSection(obj.resources); // This section is created with padding already included
1682 + var rsrcSection = rsrcSectionX.data;
1683 + var rsrcSectionVirtualSize = rsrcSectionX.size;
1684 var rsrcSectionRawSize = rsrcSection.length;
1685
1686 // Calculate the location and original and new size of the resource segment
@@ -1699,28 +1708,15 @@ function createAuthenticodeHandler(path) {
1708 // Update the checksum to zero
1709 fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 64);
1710
1702 - // Make change to the data directories header to fix resource segment size and add/remove signature
1703 - const pePlusOffset = (obj.header.pe32plus == 0) ? 0 : 16; // This header is the same for 32 and 64 bit, but 64bit is offset by 16 bytes.
1704 - if (obj.header.dataDirectories.exportTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.exportTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 96 + pePlusOffset); }
1705 - if (obj.header.dataDirectories.importTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.importTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 104 + pePlusOffset); }
1706 - //fullHeader.writeUInt32LE(obj.header.dataDirectories.resourceTable.size + resDeltaSize, obj.header.peOptionalHeaderLocation + 116 + pePlusOffset); // Change the resource segment size
1707 - if (obj.header.dataDirectories.exceptionTableAddr.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.exceptionTableAddr.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 120 + pePlusOffset); }
1708 - fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 128 + pePlusOffset); // certificate table addr (TODO)
1709 - fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 132 + pePlusOffset); // certificate table size (TODO)
1710 - if (obj.header.dataDirectories.baseRelocationTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.baseRelocationTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 136 + pePlusOffset); }
1711 - if (obj.header.dataDirectories.debug.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.debug.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 144 + pePlusOffset); }
1712 - if (obj.header.dataDirectories.globalPtr.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.globalPtr.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 160 + pePlusOffset); }
1713 - if (obj.header.dataDirectories.tLSTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.tLSTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 168 + pePlusOffset); }
1714 - if (obj.header.dataDirectories.loadConfigTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.loadConfigTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 176 + pePlusOffset); }
1715 - if (obj.header.dataDirectories.boundImport.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.boundImport.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 184 + pePlusOffset); }
1716 - if (obj.header.dataDirectories.iAT.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.iAT.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 192 + pePlusOffset); }
1717 - if (obj.header.dataDirectories.delayImportDescriptor.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.delayImportDescriptor.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 200 + pePlusOffset); }
1718 - if (obj.header.dataDirectories.clrRuntimeHeader.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.clrRuntimeHeader.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 208 + pePlusOffset); }
1711 + // We are going to setup the old a new sections here, we need this to correct directory values
1712 + var oldSections = obj.header.sections;
1713 + var newSections = {};
1714
1715 // Make changes to the segments table
1716 var virtualAddress = 4096;
1717 for (var i in obj.header.sections) {
1718 const section = obj.header.sections[i];
1719 + newSections[i] = { virtualSize: section.virtualSize };
1720 if (i == '.rsrc') {
1721 // Change the size of the resource section
1722 fullHeader.writeUInt32LE(rsrcSectionVirtualSize, section.ptr + 8); // virtualSize
@@ -1728,6 +1724,7 @@ function createAuthenticodeHandler(path) {
1724
1725 // Set the virtual address of the section
1726 fullHeader.writeUInt32LE(virtualAddress, section.ptr + 12); // Virtual address
1727 + newSections[i].virtualAddr = virtualAddress;
1728 var virtualAddressPadding = (rsrcSectionVirtualSize % 4096);
1729 virtualAddress += rsrcSectionVirtualSize;
1730 if (virtualAddressPadding != 0) { virtualAddress += (4096 - virtualAddressPadding); }
@@ -1737,12 +1734,31 @@ function createAuthenticodeHandler(path) {
1734
1735 // Set the virtual address of the section
1736 fullHeader.writeUInt32LE(virtualAddress, section.ptr + 12); // Virtual address
1737 + newSections[i].virtualAddr = virtualAddress;
1738 var virtualAddressPadding = (section.virtualSize % 4096);
1739 virtualAddress += section.virtualSize;
1740 if (virtualAddressPadding != 0) { virtualAddress += (4096 - virtualAddressPadding); }
1741 }
1742 }
1743
1744 + // Make change to the data directories header to fix resource segment size and add/remove signature
1745 + const pePlusOffset = (obj.header.pe32plus == 0) ? 0 : 16; // This header is the same for 32 and 64 bit, but 64bit is offset by 16 bytes.
1746 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.exportTable.addr), obj.header.peOptionalHeaderLocation + 96 + pePlusOffset);
1747 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.importTable.addr), obj.header.peOptionalHeaderLocation + 104 + pePlusOffset);
1748 + fullHeader.writeUInt32LE(rsrcSectionVirtualSize, obj.header.peOptionalHeaderLocation + 116 + pePlusOffset); // Change the resource segment size
1749 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.exceptionTableAddr.addr), obj.header.peOptionalHeaderLocation + 120 + pePlusOffset);
1750 + fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 128 + pePlusOffset); // certificate table addr (TODO)
1751 + fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 132 + pePlusOffset); // certificate table size (TODO)
1752 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.baseRelocationTable.addr), obj.header.peOptionalHeaderLocation + 136 + pePlusOffset);
1753 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.debug.addr), obj.header.peOptionalHeaderLocation + 144 + pePlusOffset);
1754 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.globalPtr.addr), obj.header.peOptionalHeaderLocation + 160 + pePlusOffset);
1755 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.tLSTable.addr), obj.header.peOptionalHeaderLocation + 168 + pePlusOffset);
1756 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.loadConfigTable.addr), obj.header.peOptionalHeaderLocation + 176 + pePlusOffset);
1757 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.boundImport.addr), obj.header.peOptionalHeaderLocation + 184 + pePlusOffset);
1758 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.iAT.addr), obj.header.peOptionalHeaderLocation + 192 + pePlusOffset);
1759 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.delayImportDescriptor.addr), obj.header.peOptionalHeaderLocation + 200 + pePlusOffset);
1760 + fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.clrRuntimeHeader.addr), obj.header.peOptionalHeaderLocation + 208 + pePlusOffset);
1761 +
1762 // Write size of image. We put the next virtual address.
1763 fullHeader.writeUInt32LE(virtualAddress, obj.header.peOptionalHeaderLocation + 56); // sizeOfImage
1764