mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
Merge remote-tracking branch 'origin/GP-51_ryanmkurtz_coff-check'
This commit is contained in:
commit
25a70bb719
3 changed files with 59 additions and 43 deletions
|
@ -30,7 +30,6 @@ import ghidra.program.flatapi.FlatProgramAPI;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.NotEmptyException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -52,10 +51,10 @@ public class CoffBinaryAnalysisCommand extends FlatProgramAPI
|
|||
if (!BinaryLoader.BINARY_NAME.equals(format)) {
|
||||
return false;
|
||||
}
|
||||
Memory memory = program.getMemory();
|
||||
short magic =
|
||||
memory.getShort(program.getAddressFactory().getDefaultAddressSpace().getAddress(0));
|
||||
return CoffMachineType.isMachineTypeDefined(magic);
|
||||
|
||||
ByteProvider provider =
|
||||
MemoryByteProvider.createDefaultAddressSpaceByteProvider(program, false);
|
||||
return CoffFileHeader.isValid(provider);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
|
|
|
@ -56,7 +56,7 @@ public class CoffFileHeader implements StructConverter {
|
|||
}
|
||||
}
|
||||
|
||||
private BinaryReader getBinaryReader(ByteProvider provider) {
|
||||
private static BinaryReader getBinaryReader(ByteProvider provider) {
|
||||
BinaryReader reader = new BinaryReader(provider, true/*COFF is always LE!!!*/);
|
||||
return reader;
|
||||
}
|
||||
|
@ -271,6 +271,46 @@ public class CoffFileHeader implements StructConverter {
|
|||
return _aoutHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given {@link ByteProvider} is a valid {@link CoffFileHeader}.
|
||||
* <p>
|
||||
* To avoid false positives when the machine type is
|
||||
* {@link CoffMachineType#IMAGE_FILE_MACHINE_UNKNOWN}, we do an additional check on some extra
|
||||
* bytes at the beginning of the given {@link ByteProvider} to make sure the entire file isn't
|
||||
* all 0's.
|
||||
*
|
||||
* @param provider The {@link ByteProvider} to check
|
||||
* @return True if this is a is a valid {@link CoffFileHeader}; otherwise, false
|
||||
* @throws IOException if there was an IO-related issue
|
||||
*/
|
||||
public static boolean isValid(ByteProvider provider) throws IOException {
|
||||
final int MIN_BYTE_LENGTH = 22;
|
||||
final int COFF_NULL_SANITY_CHECK_LEN = 64;
|
||||
|
||||
if (provider.length() < MIN_BYTE_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
short magic = getBinaryReader(provider).readShort(0);
|
||||
|
||||
if (magic == CoffMachineType.IMAGE_FILE_MACHINE_UNKNOWN /* ie. == 0 */ &&
|
||||
provider.length() > COFF_NULL_SANITY_CHECK_LEN) {
|
||||
byte[] headerBytes = provider.readBytes(0, COFF_NULL_SANITY_CHECK_LEN);
|
||||
boolean allZeros = true;
|
||||
for (byte b : headerBytes) {
|
||||
allZeros = (b == 0);
|
||||
if (!allZeros) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allZeros) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return CoffMachineType.isMachineTypeDefined(magic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure struct = new StructureDataType(StructConverterUtil.parseName(getClass()), 0);
|
||||
|
|
|
@ -46,15 +46,12 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
public final static String COFF_NAME = "Common Object File Format (COFF)";
|
||||
public static final String FAKE_LINK_OPTION_NAME = "Attempt to link sections located at 0x0";
|
||||
static final boolean FAKE_LINK_OPTION_DEFAULT = true;
|
||||
private static final int COFF_NULL_SANITY_CHECK_LEN = 64;
|
||||
|
||||
// where do sections start if they're all zero??? this affects object files
|
||||
// and if we're high enough (!!!) the scalar operand analyzer will work
|
||||
// properly with external symbols laid down
|
||||
private static final int EMPTY_START_OFFSET = 0x2000;
|
||||
|
||||
private static final long MIN_BYTE_LENGTH = 22;
|
||||
|
||||
/**
|
||||
* @return true if this loader assumes the Microsoft variant of the COFF format
|
||||
*/
|
||||
|
@ -97,47 +94,27 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
||||
List<LoadSpec> loadSpecs = new ArrayList<>();
|
||||
|
||||
if (provider.length() < MIN_BYTE_LENGTH) {
|
||||
if (!CoffFileHeader.isValid(provider)) {
|
||||
return loadSpecs;
|
||||
}
|
||||
|
||||
CoffFileHeader header = new CoffFileHeader(provider);
|
||||
header.parseSectionHeaders(provider);
|
||||
|
||||
// Check to prevent false positives when the file is full of '\0' bytes.
|
||||
// If the machine type is unknown (0), check the first 64 bytes of the file and bail if
|
||||
// they are also all 0.
|
||||
if (header.getMagic() == CoffMachineType.IMAGE_FILE_MACHINE_UNKNOWN /* ie. == 0 */ &&
|
||||
provider.length() > COFF_NULL_SANITY_CHECK_LEN) {
|
||||
byte[] headerBytes = provider.readBytes(0, COFF_NULL_SANITY_CHECK_LEN);
|
||||
boolean allZeros = true;
|
||||
for (byte b : headerBytes) {
|
||||
allZeros = (b == 0);
|
||||
if (!allZeros) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allZeros) {
|
||||
return loadSpecs;
|
||||
}
|
||||
if (isVisualStudio(header) != isMicrosoftFormat()) {
|
||||
// Only one of the CoffLoader/MSCoffLoader will survive this check
|
||||
return loadSpecs;
|
||||
}
|
||||
String secondary = isCLI(header) ? "cli" : Integer.toString(header.getFlags() & 0xffff);
|
||||
List<QueryResult> results =
|
||||
QueryOpinionService.query(getName(), header.getMachineName(), secondary);
|
||||
for (QueryResult result : results) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(isMicrosoftFormat()), result));
|
||||
}
|
||||
if (loadSpecs.isEmpty()) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(false), true));
|
||||
}
|
||||
|
||||
if (CoffMachineType.isMachineTypeDefined(header.getMagic())) {
|
||||
header.parseSectionHeaders(provider);
|
||||
|
||||
if (isVisualStudio(header) != isMicrosoftFormat()) {
|
||||
// Only one of the CoffLoader/MSCoffLoader will survive this check
|
||||
return loadSpecs;
|
||||
}
|
||||
String secondary = isCLI(header) ? "cli" : Integer.toString(header.getFlags() & 0xffff);
|
||||
List<QueryResult> results =
|
||||
QueryOpinionService.query(getName(), header.getMachineName(), secondary);
|
||||
for (QueryResult result : results) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(isMicrosoftFormat()), result));
|
||||
}
|
||||
if (loadSpecs.isEmpty()) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(false), true));
|
||||
}
|
||||
}
|
||||
return loadSpecs;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue