diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java index d64ec828b0..a2a0370589 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java @@ -332,32 +332,43 @@ public class FileHeader implements StructConverter { long stringTableOffset = getStringTableOffset(); sectionHeaders = new SectionHeader[numberOfSections]; for (int i = 0; i < numberOfSections; ++i) { - sectionHeaders[i] = + SectionHeader section = SectionHeader.readSectionHeader(reader, tmpIndex, stringTableOffset); + sectionHeaders[i] = section; + + int pointerToRawData = section.getPointerToRawData(); + int sizeOfRawData = section.getSizeOfRawData(); // Ensure PointerToRawData + SizeOfRawData doesn't exceed the length of the file - int pointerToRawData = sectionHeaders[i].getPointerToRawData(); - int sizeOfRawData = (int) Math.min(reader.length() - pointerToRawData, - sectionHeaders[i].getSizeOfRawData()); + if (pointerToRawData >= reader.length()) { + sizeOfRawData = 0; + Msg.warn(this, "Section " + section.getName() + " begins after end of file!"); + } + else if (pointerToRawData + sizeOfRawData > reader.length()) { + sizeOfRawData = (int) (reader.length() - pointerToRawData); + Msg.warn(this, + String.format("Section %s exceeds file length...truncating from %d to %d", + section.getName(), section.getSizeOfRawData(), sizeOfRawData)); + } + section.setSizeOfRawData(sizeOfRawData); // Ensure VirtualSize is large enough to accommodate SizeOfRawData, but do not // exceed the next alignment boundary. We can only do this if the VirtualAddress is // already properly aligned, since we currently don't support moving sections to // different addresses to enforce alignment. - int virtualAddress = sectionHeaders[i].getVirtualAddress(); - int virtualSize = sectionHeaders[i].getVirtualSize(); + int virtualAddress = section.getVirtualAddress(); + int virtualSize = section.getVirtualSize(); int alignedVirtualAddress = PortableExecutable.computeAlignment(virtualAddress, optHeader.getSectionAlignment()); int alignedVirtualSize = PortableExecutable.computeAlignment(virtualSize, optHeader.getSectionAlignment()); if (virtualAddress == alignedVirtualAddress) { if (sizeOfRawData > virtualSize) { - sectionHeaders[i] - .setVirtualSize(Math.min(sizeOfRawData, alignedVirtualSize)); + section.setVirtualSize(Math.min(sizeOfRawData, alignedVirtualSize)); } } else { - Msg.warn(this, "Section " + sectionHeaders[i].getName() + " is not aligned!"); + Msg.warn(this, "Section " + section.getName() + " is not aligned!"); } tmpIndex += SectionHeader.IMAGE_SIZEOF_SECTION_HEADER; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java index 780b66d7cb..b7fa6cfd54 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java @@ -22,10 +22,11 @@ import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout; import ghidra.program.model.data.*; -import ghidra.util.*; +import ghidra.util.DataConverter; +import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.NotYetImplementedException; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; /** * A class to represent the IMAGE_NT_HEADERS32 and @@ -62,9 +63,11 @@ public class NTHeader implements StructConverter, OffsetValidator { * Constructs a new NT header. * @param reader the binary reader * @param index the index into the reader to the start of the NT header - * @param advancedProcess if true, information rafside of the base header will be processed + * @param layout The {@link SectionLayout} + * @param advancedProcess if true, information outside of the base header will be processed * @param parseCliHeaders if true, CLI headers are parsed (if present) * @throws InvalidNTHeaderException if the bytes the specified index + * @throws IOException if an IO-related exception occurred * do not constitute an accurate NT header. */ public NTHeader(BinaryReader reader, int index, SectionLayout layout, boolean advancedProcess, @@ -124,22 +127,26 @@ public class NTHeader implements StructConverter, OffsetValidator { /** * Converts a relative virtual address (RVA) into a pointer. - * @see #rvaToPointer(long) + * + * @param rva the relative virtual address + * @return the pointer into binary image, 0 if not valid */ public int rvaToPointer(int rva) { - return (int) rvaToPointer(rva & Conv.INT_MASK); + return (int) rvaToPointer(Integer.toUnsignedLong(rva)); } /** + * Converts a relative virtual address (RVA) into a pointer. + * @param rva the relative virtual address * @return the pointer into binary image, 0 if not valid */ public long rvaToPointer(long rva) { SectionHeader[] sections = fileHeader.getSectionHeaders(); for (SectionHeader section : sections) { - long sectionVA = section.getVirtualAddress() & Conv.INT_MASK; - long rawSize = section.getSizeOfRawData() & Conv.INT_MASK; - long rawPtr = section.getPointerToRawData() & Conv.INT_MASK; + long sectionVA = Integer.toUnsignedLong(section.getVirtualAddress()); + long rawSize = Integer.toUnsignedLong(section.getSizeOfRawData()); + long rawPtr = Integer.toUnsignedLong(section.getPointerToRawData()); switch (layout) { case MEMORY: @@ -169,10 +176,10 @@ public class NTHeader implements StructConverter, OffsetValidator { public boolean checkPointer(long ptr) { SectionHeader[] sections = fileHeader.getSectionHeaders(); for (SectionHeader section : sections) { - long virtPtr = section.getVirtualAddress() & Conv.INT_MASK; - long virtSize = section.getVirtualSize() & Conv.INT_MASK; - long rawSize = section.getSizeOfRawData() & Conv.INT_MASK; - long rawPtr = section.getPointerToRawData() & Conv.INT_MASK; + long virtPtr = Integer.toUnsignedLong(section.getVirtualAddress()); + long virtSize = Integer.toUnsignedLong(section.getVirtualSize()); + long rawSize = Integer.toUnsignedLong(section.getSizeOfRawData()); + long rawPtr = Integer.toUnsignedLong(section.getPointerToRawData()); long sectionBasePtr = layout == SectionLayout.MEMORY ? virtPtr : rawPtr; long sectionSize = layout == SectionLayout.MEMORY ? virtSize : rawSize; @@ -199,13 +206,17 @@ public class NTHeader implements StructConverter, OffsetValidator { /** * Converts a virtual address (VA) into a pointer. - * @see #vaToPointer(long) + * + * @param va the virtual address + * @return the pointer into binary image, 0 if not valid */ public int vaToPointer(int va) { - return (int) vaToPointer(va & Conv.INT_MASK); + return (int) vaToPointer(Integer.toUnsignedLong(va)); } /** + * Converts a virtual address (VA) into a pointer. + * * @param va the virtual address * @return the pointer into binary image, 0 if not valid */ @@ -213,10 +224,6 @@ public class NTHeader implements StructConverter, OffsetValidator { return rvaToPointer(va - getOptionalHeader().getImageBase()); } - /** - * @throws InvalidNTHeaderException - * @throws IOException - */ private void parse() throws InvalidNTHeaderException, IOException { if (index < 0 || index > reader.length()) { @@ -229,6 +236,7 @@ public class NTHeader implements StructConverter, OffsetValidator { signature = reader.readInt(tmpIndex); } catch (IndexOutOfBoundsException ioobe) { + // Handled below } // if not correct signature, then return... @@ -256,7 +264,7 @@ public class NTHeader implements StructConverter, OffsetValidator { fileHeader.processSymbols(); if (advancedProcess) { - optionalHeader.processDataDirectories(TaskMonitorAdapter.DUMMY_MONITOR); + optionalHeader.processDataDirectories(TaskMonitor.DUMMY); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/SectionHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/SectionHeader.java index 53e5570371..a06edc49b3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/SectionHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/SectionHeader.java @@ -20,7 +20,6 @@ import java.io.*; import ghidra.app.util.bin.*; import ghidra.program.model.data.*; import ghidra.program.model.mem.*; -import ghidra.util.Conv; import ghidra.util.DataConverter; import ghidra.util.exception.DuplicateNameException; @@ -535,7 +534,7 @@ public class SectionHeader implements StructConverter, ByteArrayConverter { EnumDataType characteristicsEnum = new EnumDataType("SectionFlags", 4); characteristicsEnum.setCategoryPath(new CategoryPath("/PE")); for (SectionFlags flag : SectionFlags.values()) { - characteristicsEnum.add(flag.name(), Conv.intToLong(flag.getMask())); + characteristicsEnum.add(flag.name(), Integer.toUnsignedLong(flag.getMask())); } struct.add(characteristicsEnum, "Characteristics", null); struct.setCategoryPath(new CategoryPath("/PE")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java index 6eb905a38d..2334248693 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java @@ -16,7 +16,6 @@ package ghidra.app.util.opinion; import java.io.IOException; -import java.math.BigInteger; import java.util.*; import ghidra.app.util.MemoryBlockUtils; @@ -36,8 +35,6 @@ import ghidra.program.database.function.OverlappingFunctionException; import ghidra.program.database.mem.FileBytes; import ghidra.program.model.address.*; import ghidra.program.model.data.*; -import ghidra.program.model.lang.Register; -import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.listing.*; import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryAccessException; @@ -109,7 +106,6 @@ public class PeLoader extends AbstractPeDebugLoader { return; } OptionalHeader optionalHeader = ntHeader.getOptionalHeader(); - FileHeader fileHeader = ntHeader.getFileHeader(); monitor.setMessage("Completing PE header parsing..."); FileBytes fileBytes = createFileBytes(provider, program, monitor); @@ -406,7 +402,7 @@ public class PeLoader extends AbstractPeDebugLoader { //than 32bit. On WindowsCE some sections are //declared to roll over. if (!optionalHeader.is64bit()) { - addr &= Conv.INT_MASK; + addr &= 0x00000000ffffffffL; } Address address = space.getAddress(addr); @@ -686,6 +682,11 @@ public class PeLoader extends AbstractPeDebugLoader { address = space.getAddress(addr); + String sectionName = sections[i].getReadableName(); + if (sectionName.isBlank()) { + sectionName = "SECTION." + i; + } + r = ((sections[i].getCharacteristics() & SectionFlags.IMAGE_SCN_MEM_READ.getMask()) != 0x0); w = ((sections[i].getCharacteristics() & @@ -707,10 +708,6 @@ public class PeLoader extends AbstractPeDebugLoader { Msg.warn(this, "OptionalHeader.SizeOfImage < size of " + sections[i].getName() + " section"); } - String sectionName = sections[i].getReadableName(); - if (sectionName.isBlank()) { - sectionName = "SECTION." + i; - } MemoryBlockUtils.createInitializedBlock(prog, false, sectionName, address, fileBytes, rawDataPtr, dataSize, "", "", r, w, x, log); sectionToAddress.put(sections[i], address); @@ -740,8 +737,8 @@ public class PeLoader extends AbstractPeDebugLoader { else { int dataSize = (virtualSize > 0 || rawDataSize < 0) ? virtualSize : 0; if (dataSize > 0) { - MemoryBlockUtils.createUninitializedBlock(prog, false, - sections[i].getReadableName(), address, dataSize, "", "", r, w, x, log); + MemoryBlockUtils.createUninitializedBlock(prog, false, sectionName, address, + dataSize, "", "", r, w, x, log); sectionToAddress.put(sections[i], address); } }