Fixed incorrect addresses in the directory table.

This commit is contained in:
Ylian Saint-Hilaire 2022-08-11 12:41:07 -07:00
parent ff67f6abc3
commit d2abcdc9d5
1 changed files with 40 additions and 24 deletions

View File

@ -600,6 +600,7 @@ function createAuthenticodeHandler(path) {
// Pad the resource section & allocate the buffer
const fileAlign = obj.header.peWindows.fileAlignment
var resSizeTotal = resSizes.tables + resSizes.items + resSizes.names + resSizes.data;
var resNoPadding = resSizeTotal + 4; // TODO: Not sure why this is off by 4
if ((resSizeTotal % fileAlign) != 0) { resSizeTotal += (fileAlign - (resSizeTotal % fileAlign)); }
const resSectionBuffer = Buffer.alloc(resSizeTotal);
@ -609,7 +610,7 @@ function createAuthenticodeHandler(path) {
//console.log('generateResourceSection', resPointers);
// Done, return the result
return resSectionBuffer;
return { size: resNoPadding, data: resSectionBuffer };
}
// Return the total size of a resource header, this is a recursive method
@ -828,7 +829,6 @@ function createAuthenticodeHandler(path) {
for (var j in iconInfo[i].icons) { xicons[nextIconNumber++] = iconInfo[i].icons[j]; }
iconInfo[i].icons = xicons;
}
console.log(iconInfo);
if (iconGroupCount == 0) return; // If there are no icon groups, we are done
// Add the new icons entry
@ -1657,6 +1657,16 @@ function createAuthenticodeHandler(path) {
fs.closeSync(output);
}
// Find where a directory value is in the old sections and map it to the new sections
function correctDirectoryValue(oldSections, newSections, value) {
for (var i in oldSections) {
if ((value >= oldSections[i].virtualAddr) && (value < (oldSections[i].virtualAddr + oldSections[i].virtualSize))) {
return newSections[i].virtualAddr + (value - oldSections[i].virtualAddr);
}
}
return 0;
}
// Save the executable
obj.writeExecutable = function (args, cert, func) {
// Open the file
@ -1667,11 +1677,10 @@ function createAuthenticodeHandler(path) {
var fullHeaderLen = obj.header.SectionHeadersPtr + (obj.header.coff.numberOfSections * 40);
var fullHeader = readFileSlice(written, fullHeaderLen);
// Create the resource section and pad to next 512 byte boundry
var rsrcSection = generateResourceSection(obj.resources);
var rsrcSectionVirtualSize = rsrcSection.length;
var x = (rsrcSection.length % 512);
if (x != 0) { rsrcSection = Buffer.concat([rsrcSection, Buffer.alloc(512 - x)]); }
// Create the resource section
const rsrcSectionX = generateResourceSection(obj.resources); // This section is created with padding already included
var rsrcSection = rsrcSectionX.data;
var rsrcSectionVirtualSize = rsrcSectionX.size;
var rsrcSectionRawSize = rsrcSection.length;
// Calculate the location and original and new size of the resource segment
@ -1699,28 +1708,15 @@ function createAuthenticodeHandler(path) {
// Update the checksum to zero
fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 64);
// Make change to the data directories header to fix resource segment size and add/remove signature
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.
if (obj.header.dataDirectories.exportTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.exportTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 96 + pePlusOffset); }
if (obj.header.dataDirectories.importTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.importTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 104 + pePlusOffset); }
//fullHeader.writeUInt32LE(obj.header.dataDirectories.resourceTable.size + resDeltaSize, obj.header.peOptionalHeaderLocation + 116 + pePlusOffset); // Change the resource segment size
if (obj.header.dataDirectories.exceptionTableAddr.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.exceptionTableAddr.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 120 + pePlusOffset); }
fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 128 + pePlusOffset); // certificate table addr (TODO)
fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 132 + pePlusOffset); // certificate table size (TODO)
if (obj.header.dataDirectories.baseRelocationTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.baseRelocationTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 136 + pePlusOffset); }
if (obj.header.dataDirectories.debug.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.debug.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 144 + pePlusOffset); }
if (obj.header.dataDirectories.globalPtr.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.globalPtr.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 160 + pePlusOffset); }
if (obj.header.dataDirectories.tLSTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.tLSTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 168 + pePlusOffset); }
if (obj.header.dataDirectories.loadConfigTable.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.loadConfigTable.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 176 + pePlusOffset); }
if (obj.header.dataDirectories.boundImport.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.boundImport.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 184 + pePlusOffset); }
if (obj.header.dataDirectories.iAT.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.iAT.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 192 + pePlusOffset); }
if (obj.header.dataDirectories.delayImportDescriptor.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.delayImportDescriptor.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 200 + pePlusOffset); }
if (obj.header.dataDirectories.clrRuntimeHeader.addr > resPtr) { fullHeader.writeUInt32LE(obj.header.dataDirectories.clrRuntimeHeader.addr + resDeltaSize, obj.header.peOptionalHeaderLocation + 208 + pePlusOffset); }
// We are going to setup the old a new sections here, we need this to correct directory values
var oldSections = obj.header.sections;
var newSections = {};
// Make changes to the segments table
var virtualAddress = 4096;
for (var i in obj.header.sections) {
const section = obj.header.sections[i];
newSections[i] = { virtualSize: section.virtualSize };
if (i == '.rsrc') {
// Change the size of the resource section
fullHeader.writeUInt32LE(rsrcSectionVirtualSize, section.ptr + 8); // virtualSize
@ -1728,6 +1724,7 @@ function createAuthenticodeHandler(path) {
// Set the virtual address of the section
fullHeader.writeUInt32LE(virtualAddress, section.ptr + 12); // Virtual address
newSections[i].virtualAddr = virtualAddress;
var virtualAddressPadding = (rsrcSectionVirtualSize % 4096);
virtualAddress += rsrcSectionVirtualSize;
if (virtualAddressPadding != 0) { virtualAddress += (4096 - virtualAddressPadding); }
@ -1737,12 +1734,31 @@ function createAuthenticodeHandler(path) {
// Set the virtual address of the section
fullHeader.writeUInt32LE(virtualAddress, section.ptr + 12); // Virtual address
newSections[i].virtualAddr = virtualAddress;
var virtualAddressPadding = (section.virtualSize % 4096);
virtualAddress += section.virtualSize;
if (virtualAddressPadding != 0) { virtualAddress += (4096 - virtualAddressPadding); }
}
}
// Make change to the data directories header to fix resource segment size and add/remove signature
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.
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.exportTable.addr), obj.header.peOptionalHeaderLocation + 96 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.importTable.addr), obj.header.peOptionalHeaderLocation + 104 + pePlusOffset);
fullHeader.writeUInt32LE(rsrcSectionVirtualSize, obj.header.peOptionalHeaderLocation + 116 + pePlusOffset); // Change the resource segment size
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.exceptionTableAddr.addr), obj.header.peOptionalHeaderLocation + 120 + pePlusOffset);
fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 128 + pePlusOffset); // certificate table addr (TODO)
fullHeader.writeUInt32LE(0, obj.header.peOptionalHeaderLocation + 132 + pePlusOffset); // certificate table size (TODO)
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.baseRelocationTable.addr), obj.header.peOptionalHeaderLocation + 136 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.debug.addr), obj.header.peOptionalHeaderLocation + 144 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.globalPtr.addr), obj.header.peOptionalHeaderLocation + 160 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.tLSTable.addr), obj.header.peOptionalHeaderLocation + 168 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.loadConfigTable.addr), obj.header.peOptionalHeaderLocation + 176 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.boundImport.addr), obj.header.peOptionalHeaderLocation + 184 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.iAT.addr), obj.header.peOptionalHeaderLocation + 192 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.delayImportDescriptor.addr), obj.header.peOptionalHeaderLocation + 200 + pePlusOffset);
fullHeader.writeUInt32LE(correctDirectoryValue(oldSections, newSections, obj.header.dataDirectories.clrRuntimeHeader.addr), obj.header.peOptionalHeaderLocation + 208 + pePlusOffset);
// Write size of image. We put the next virtual address.
fullHeader.writeUInt32LE(virtualAddress, obj.header.peOptionalHeaderLocation + 56); // sizeOfImage