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