Merge remote-tracking branch

'origin/GP-1177_dev747368_long_pe_sectionnames--SQUASHED' (Closes #1267)
This commit is contained in:
Ryan Kurtz 2021-08-05 09:39:31 -04:00
commit c60e595061
4 changed files with 86 additions and 60 deletions

View file

@ -356,9 +356,11 @@ public class FileHeader implements StructConverter {
Msg.error(this, "File alignment == 0: section processing skipped"); Msg.error(this, "File alignment == 0: section processing skipped");
} }
else { else {
long stringTableOffset = getStringTableOffset();
sectionHeaders = new SectionHeader[numberOfSections]; sectionHeaders = new SectionHeader[numberOfSections];
for (int i = 0; i < numberOfSections; ++i) { for (int i = 0; i < numberOfSections; ++i) {
sectionHeaders[i] = SectionHeader.createSectionHeader(reader, tmpIndex); sectionHeaders[i] =
SectionHeader.readSectionHeader(reader, tmpIndex, stringTableOffset);
// Ensure PointerToRawData + SizeOfRawData doesn't exceed the length of the file // Ensure PointerToRawData + SizeOfRawData doesn't exceed the length of the file
int pointerToRawData = sectionHeaders[i].getPointerToRawData(); int pointerToRawData = sectionHeaders[i].getPointerToRawData();
@ -439,7 +441,7 @@ public class FileHeader implements StructConverter {
return; return;
} }
int stringTableIndex = tmpIndex + DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL * numberOfSymbols; long stringTableOffset = getStringTableOffset();
for (int i = 0; i < numberOfSymbols; ++i) { for (int i = 0; i < numberOfSymbols; ++i) {
if (!ntHeader.checkRVA(tmpIndex)) { if (!ntHeader.checkRVA(tmpIndex)) {
@ -448,7 +450,7 @@ public class FileHeader implements StructConverter {
} }
DebugCOFFSymbol symbol = DebugCOFFSymbol symbol =
DebugCOFFSymbol.createDebugCOFFSymbol(reader, tmpIndex, stringTableIndex); DebugCOFFSymbol.createDebugCOFFSymbol(reader, tmpIndex, stringTableOffset);
tmpIndex += DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL; tmpIndex += DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL;
@ -464,6 +466,22 @@ public class FileHeader implements StructConverter {
reader.setPointerIndex(oldIndex); reader.setPointerIndex(oldIndex);
} }
/**
* Return the offset of the string table, or -1 if invalid or not present.
*
* @return long offset of string table, or -1 if invalid or not present
* @throws IOException if io error
*/
long getStringTableOffset() throws IOException {
if (pointerToSymbolTable <= 0 /* 0 is excluded because other stuff is there */ ||
!ntHeader.checkRVA(pointerToSymbolTable) || (numberOfSymbols < 0) ||
(pointerToSymbolTable + (numberOfSymbols * DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL) > reader
.length())) {
return -1;
}
return pointerToSymbolTable + (DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL * numberOfSymbols);
}
public boolean isLordPE() { public boolean isLordPE() {
if (getPointerToSymbolTable() == LORDPE_SYMBOL_TABLE && if (getPointerToSymbolTable() == LORDPE_SYMBOL_TABLE &&
getNumberOfSymbols() == LORDPE_NUMBER_OF_SYMBOLS) { getNumberOfSymbols() == LORDPE_NUMBER_OF_SYMBOLS) {

View file

@ -17,9 +17,7 @@ package ghidra.app.util.bin.format.pe;
import java.io.*; import java.io.*;
import ghidra.app.util.bin.ByteArrayConverter; import ghidra.app.util.bin.*;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
import ghidra.util.Conv; import ghidra.util.Conv;
@ -237,29 +235,53 @@ public class SectionHeader implements StructConverter, ByteArrayConverter {
private short numberOfLinenumbers; private short numberOfLinenumbers;
private int characteristics; private int characteristics;
private FactoryBundledWithBinaryReader reader; private BinaryReader reader;
private long index;
static SectionHeader createSectionHeader(FactoryBundledWithBinaryReader reader, long index)
throws IOException {
SectionHeader sectionHeader =
(SectionHeader) reader.getFactory().create(SectionHeader.class);
sectionHeader.initSectionHeader(reader, index);
return sectionHeader;
}
/** /**
* DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. * Read a {@link SectionHeader} from the specified stream starting at {@code index}.
*
* @param reader {@link BinaryReader} to read from
* @param index long offset in the reader where the section header starts
* @param stringTableOffset offset of the string table, or -1 if not available
* @return new {@link SectionHeader}
* @throws IOException if error reading data
*/ */
public SectionHeader() { public static SectionHeader readSectionHeader(BinaryReader reader, long index,
long stringTableOffset) throws IOException {
SectionHeader result = new SectionHeader();
result.reader = reader;
result.name = reader.readAsciiString(index, IMAGE_SIZEOF_SHORT_NAME).trim();
if (result.name.startsWith("/") && stringTableOffset != -1) {
try {
int nameOffset = Integer.parseInt(result.name.substring(1));
result.name = reader.readAsciiString(stringTableOffset + nameOffset);
}
catch (NumberFormatException nfe) {
// ignore error, section name will remain as it was
}
}
// we need to skip IMAGE_SIZEOF_SHORT_NAME chars no matter what,
// since those bytes are always allocated
reader.setPointerIndex(index + IMAGE_SIZEOF_SHORT_NAME);
result.physicalAddress = result.virtualSize = reader.readNextInt();
result.virtualAddress = reader.readNextInt();
result.sizeOfRawData = reader.readNextInt();
result.pointerToRawData = reader.readNextInt();
result.pointerToRelocations = reader.readNextInt();
result.pointerToLinenumbers = reader.readNextInt();
result.numberOfRelocations = reader.readNextShort();
result.numberOfLinenumbers = reader.readNextShort();
result.characteristics = reader.readNextInt();
return result;
} }
private void initSectionHeader(FactoryBundledWithBinaryReader reader, long index) private SectionHeader() {
throws IOException { // empty
this.reader = reader;
this.index = index;
parse();
} }
SectionHeader(MemoryBlock block, OptionalHeader optHeader, int ptr) { SectionHeader(MemoryBlock block, OptionalHeader optHeader, int ptr) {
@ -493,24 +515,6 @@ public class SectionHeader implements StructConverter, ByteArrayConverter {
return buff.toString(); return buff.toString();
} }
private void parse() throws IOException {
name = reader.readAsciiString(index, IMAGE_SIZEOF_SHORT_NAME).trim();
// we need to skip IMAGE_SIZEOF_SHORT_NAME chars no matter what,
// since those bytes are always allocated
reader.setPointerIndex(index + IMAGE_SIZEOF_SHORT_NAME);
physicalAddress = virtualSize = reader.readNextInt();
virtualAddress = reader.readNextInt();
sizeOfRawData = reader.readNextInt();
pointerToRawData = reader.readNextInt();
pointerToRelocations = reader.readNextInt();
pointerToLinenumbers = reader.readNextInt();
numberOfRelocations = reader.readNextShort();
numberOfLinenumbers = reader.readNextShort();
characteristics = reader.readNextInt();
}
@Override @Override
public DataType toDataType() throws DuplicateNameException { public DataType toDataType() throws DuplicateNameException {
UnionDataType union = new UnionDataType("Misc"); UnionDataType union = new UnionDataType("Misc");

View file

@ -15,6 +15,10 @@
*/ */
package ghidra.app.util.bin.format.pe; package ghidra.app.util.bin.format.pe;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import generic.continues.GenericFactory; import generic.continues.GenericFactory;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
@ -22,10 +26,6 @@ import ghidra.app.util.bin.format.pe.debug.DebugDirectoryParser;
import ghidra.util.Conv; import ghidra.util.Conv;
import ghidra.util.Msg; import ghidra.util.Msg;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/** /**
* <pre> * <pre>
* typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { * typedef struct _IMAGE_SEPARATE_DEBUG_HEADER {
@ -114,12 +114,12 @@ public class SeparateDebugHeader implements OffsetValidator {
sections = new SectionHeader[numberOfSections]; sections = new SectionHeader[numberOfSections];
for (int i = 0; i < numberOfSections; ++i) { for (int i = 0; i < numberOfSections; ++i) {
sections[i] = SectionHeader.createSectionHeader(reader, ptr); sections[i] = SectionHeader.readSectionHeader(reader, ptr, -1);
ptr += SectionHeader.IMAGE_SIZEOF_SECTION_HEADER; ptr += SectionHeader.IMAGE_SIZEOF_SECTION_HEADER;
} }
long tmp = ptr; long tmp = ptr;
List<String> exportedNameslist = new ArrayList<String>(); List<String> exportedNameslist = new ArrayList<>();
while (true) { while (true) {
String str = reader.readAsciiString(tmp); String str = reader.readAsciiString(tmp);
if (str == null || str.length() == 0) { if (str == null || str.length() == 0) {
@ -257,6 +257,7 @@ public class SeparateDebugHeader implements OffsetValidator {
return parser; return parser;
} }
@Override
public boolean checkPointer(long ptr) { public boolean checkPointer(long ptr) {
for (int i = 0; i < sections.length; ++i) { for (int i = 0; i < sections.length; ++i) {
long rawSize = sections[i].getSizeOfRawData() & Conv.INT_MASK; long rawSize = sections[i].getSizeOfRawData() & Conv.INT_MASK;
@ -269,6 +270,7 @@ public class SeparateDebugHeader implements OffsetValidator {
return false; return false;
} }
@Override
public boolean checkRVA(long rva) { public boolean checkRVA(long rva) {
return (0 <= rva) && (rva <= sizeOfImage); return (0 <= rva) && (rva <= sizeOfImage);
} }

View file

@ -15,13 +15,13 @@
*/ */
package ghidra.app.util.bin.format.pe.debug; package ghidra.app.util.bin.format.pe.debug;
import ghidra.app.util.bin.*; import java.io.IOException;
import ghidra.app.util.bin.format.*;
import ghidra.program.model.data.*;
import ghidra.util.*;
import ghidra.util.exception.*;
import java.io.*; import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.Conv;
import ghidra.util.exception.DuplicateNameException;
/** /**
* A class to represent the COFF symbol data structure. * A class to represent the COFF symbol data structure.
@ -135,10 +135,10 @@ public class DebugCOFFSymbol implements StructConverter {
return createDebugCOFFSymbol(reader, index, symbolTable.getStringTableIndex()); return createDebugCOFFSymbol(reader, index, symbolTable.getStringTableIndex());
} }
public static DebugCOFFSymbol createDebugCOFFSymbol( public static DebugCOFFSymbol createDebugCOFFSymbol(FactoryBundledWithBinaryReader reader,
FactoryBundledWithBinaryReader reader, int index, int index, long stringTableIndex) throws IOException {
int stringTableIndex) throws IOException { DebugCOFFSymbol debugCOFFSymbol =
DebugCOFFSymbol debugCOFFSymbol = (DebugCOFFSymbol) reader.getFactory().create(DebugCOFFSymbol.class); (DebugCOFFSymbol) reader.getFactory().create(DebugCOFFSymbol.class);
debugCOFFSymbol.initDebugCOFFSymbol(reader, index, stringTableIndex); debugCOFFSymbol.initDebugCOFFSymbol(reader, index, stringTableIndex);
return debugCOFFSymbol; return debugCOFFSymbol;
} }
@ -148,7 +148,8 @@ public class DebugCOFFSymbol implements StructConverter {
*/ */
public DebugCOFFSymbol() {} public DebugCOFFSymbol() {}
private void initDebugCOFFSymbol(FactoryBundledWithBinaryReader reader, int index, int stringTableIndex) throws IOException { private void initDebugCOFFSymbol(FactoryBundledWithBinaryReader reader, int index,
long stringTableIndex) throws IOException {
// read the union first... // read the union first...
// //
int shortVal = reader.readInt(index); int shortVal = reader.readInt(index);
@ -295,7 +296,8 @@ public class DebugCOFFSymbol implements StructConverter {
return numberOfAuxSymbols; return numberOfAuxSymbols;
} }
public DataType toDataType() throws DuplicateNameException, IOException { @Override
public DataType toDataType() throws DuplicateNameException, IOException {
String structureName = StructConverterUtil.parseName(DebugCOFFSymbol.class); String structureName = StructConverterUtil.parseName(DebugCOFFSymbol.class);
Structure structure = new StructureDataType(structureName + "_" +numberOfAuxSymbols, 0); Structure structure = new StructureDataType(structureName + "_" +numberOfAuxSymbols, 0);