diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/DOSHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/DOSHeader.java index 012f715b16..1292f6a306 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/DOSHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/DOSHeader.java @@ -19,11 +19,6 @@ import java.io.IOException; import java.io.RandomAccessFile; import ghidra.app.util.bin.BinaryReader; -import ghidra.app.util.bin.format.ne.InvalidWindowsHeaderException; -import ghidra.app.util.bin.format.ne.WindowsHeader; -import ghidra.app.util.bin.format.pe.InvalidNTHeaderException; -import ghidra.app.util.bin.format.pe.NTHeader; -import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout; import ghidra.program.model.data.*; import ghidra.util.DataConverter; import ghidra.util.exception.DuplicateNameException; @@ -62,7 +57,8 @@ import ghidra.util.exception.DuplicateNameException; public class DOSHeader extends OldDOSHeader { /** The name to use when converting into a structure data type. */ - public final static String NAME = "IMAGE_DOS_HEADER"; + @SuppressWarnings("hiding") + public final static String NAME = "IMAGE_DOS_HEADER"; public final static int SIZEOF_DOS_HEADER = 64; @@ -75,7 +71,8 @@ public class DOSHeader extends OldDOSHeader { private byte [] stubBytes; /** - * Constructs a new DOS header. + * Constructs a new {@link DOSHeader} + * * @param reader the binary reader * @throws IOException if there was an IO-related error */ @@ -84,87 +81,40 @@ public class DOSHeader extends OldDOSHeader { } /** - * Returns the reserved words. - * @return the reserved words - */ + * {@return the reserved words} + */ public short [] e_res() { return e_res; } - /** - * Returns the OEM identifier (for e_oeminfo). - * @return the OEM identifier (for e_oeminfo) - */ + + /** + * {@return the OEM identifier (for e_oeminfo)} + */ public short e_oemid() { return e_oemid; } - /** - * Returns the OEM information; e_oemid specific. - * @return the OEM information; e_oemid specific - */ + + /** + * {@return the OEM information; e_oemid specific} + */ public short e_oeminfo() { return e_oeminfo; } - /** - * Returns the reserved words (2). - * @return the reserved words (2) - */ + + /** + * {@return the reserved words (2)} + */ public short [] e_res2() { return e_res2; } - /** - * Returns the file address of new EXE header. - * @return the file address of new EXE header - */ + + /** + * {@return the file address of new EXE header} + */ public int e_lfanew() { return e_lfanew; } - /** - * Returns true if a new EXE header exists. - * @return true if a new EXE header exists - */ - @Override - public boolean hasNewExeHeader() { - if (e_lfanew >= 0 && e_lfanew <= 0x10000) { - if (e_lfarlc() == 0x40) { - // There are some non-NE files out there than may have e_lfarlc == 0x40, so we need - // to actually read the bytes at e_lfanew and check for the required NE signature. - try { - new WindowsHeader(reader, null, (short) e_lfanew); - return true; - } - catch (InvalidWindowsHeaderException | IOException e) { - return false; - } - } - } - return false; - } - - /** - * Returns true if a PE header exists. - * @return true if a PE header exists - */ - @Override - public boolean hasPeHeader() { - if (e_lfanew >= 0 && e_lfanew <= 0x1000000) { - try { - NTHeader ntHeader = - new NTHeader(reader, e_lfanew, SectionLayout.FILE, false); - if (ntHeader.getOptionalHeader() != null) { - return true; - } - } - catch (InvalidNTHeaderException | IOException e) { - // Fall through and return false - } - } - return false; - } - - /** - * @see ghidra.app.util.bin.StructConverter#toDataType() - */ @Override public DataType toDataType() throws DuplicateNameException { StructureDataType struct = (StructureDataType)super.toDataType(); @@ -199,24 +149,16 @@ public class DOSHeader extends OldDOSHeader { return struct; } - /** - * Helper to override the value of name - * @return The name of the header - */ @Override public String getName() { return NAME; } /** - * Returns the length (in bytes) of the DOS - * program. - *

- * In other words: - * e_lfanew() - SIZEOF_DOS_HEADER - * - * @return the length (in bytes) - */ + * {@return the length (in bytes) of the DOS program} + *

+ * In other words: {@code e_lfanew() - SIZEOF_DOS_HEADER} + */ public int getProgramLen() { return stubBytes == null ? 0 : stubBytes.length; } @@ -261,9 +203,6 @@ public class DOSHeader extends OldDOSHeader { } } - /** - * @see ghidra.app.util.bin.format.Writeable#write(java.io.RandomAccessFile, ghidra.util.DataConverter) - */ @Override public void write(RandomAccessFile raf, DataConverter dc) throws IOException { super.write(raf, dc); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/OldDOSHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/OldDOSHeader.java index d484fce451..d92ab3262e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/OldDOSHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/mz/OldDOSHeader.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -72,7 +72,8 @@ public class OldDOSHeader implements StructConverter, Writeable { protected BinaryReader reader; /** - * Constructs a new DOS header. + * Constructs a new {@link OldDOSHeader} + * * @param reader the binary reader * @throws IOException if there was an IO-related error */ @@ -82,32 +83,28 @@ public class OldDOSHeader implements StructConverter, Writeable { } /** - * Returns the processor name. - * @return the processor name + * {@return the processor name} */ public String getProcessorName() { return "x86"; } /** - * Returns the magic number. - * @return the magic number + * {@return the magic number} */ public short e_magic() { return e_magic; } /** - * Returns the number of bytes on the last page of file. - * @return the number of bytes on the last page of the file + * {@return the number of bytes on the last page of the file} */ public short e_cblp() { return e_cblp; } /** - * Returns the number of pages in the file. - * @return the number of pages in the file + * {@return the number of pages in the file} */ public short e_cp() { return e_cp; @@ -122,104 +119,77 @@ public class OldDOSHeader implements StructConverter, Writeable { } /** - * Returns the size of header in paragraphs. - * @return the size of header in paragraphs + * {@return the size of header in paragraphs} */ public short e_cparhdr() { return e_cparhdr; } /** - * Returns the minimum extra paragraphs needed. - * @return the minimum extra paragraphs needed + * {@return the minimum extra paragraphs needed} */ public short e_minalloc() { return e_minalloc; } /** - * Returns the maximum extra paragraphs needed. - * @return the maximum extra paragraphs needed + * {@return the maximum extra paragraphs needed} */ public short e_maxalloc() { return e_maxalloc; } /** - * Returns the initial (relative) SS value. - * @return the initial (relative) SS value + * {@return the initial (relative) SS value} */ public short e_ss() { return e_ss; } /** - * Returns the initial SP value. - * @return the initial SP value + * {@return the initial SP value} */ public short e_sp() { return e_sp; } /** - * Returns the checksum. - * @return the checksum + * {@return the checksum} */ public short e_csum() { return e_csum; } /** - * Returns the initial IP value. - * @return the initial IP value + * {@return the initial IP value} */ public short e_ip() { return e_ip; } /** - * Returns the initial (relative) CS value. - * @return the initial (relative) CS value + * {@return the initial (relative) CS value} */ public short e_cs() { return e_cs; } /** - * Returns the file address of relocation table. - * @return the file address of relocation table + * {@return the file address of relocation table} */ public short e_lfarlc() { return e_lfarlc; } /** - * Returns the overlay number. - * @return the overlay number + * {@return the overlay number} */ public short e_ovno() { return e_ovno; } /** - * Returns true if a new EXE header exists. - * @return true if a new EXE header exists - */ - public boolean hasNewExeHeader() { - return false; - } - - /** - * Returns true if a PE header exists. - * @return true if a PE header exists - */ - public boolean hasPeHeader() { - return false; - } - - /** - * Returns true if the DOS magic number is correct - * @return true if the DOS magic number is correct + * {@return true if the DOS magic number is correct} */ public boolean isDosSignature() { return e_magic == IMAGE_DOS_SIGNATURE; @@ -268,10 +238,6 @@ public class OldDOSHeader implements StructConverter, Writeable { return struct; } - /** - * Helper to override the value of name - * @return The name of the header - */ protected String getName() { return NAME; } @@ -317,5 +283,4 @@ public class OldDOSHeader implements StructConverter, Writeable { raf.write(dc.getBytes(e_lfarlc)); raf.write(dc.getBytes(e_ovno)); } - } 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 b789e89dd1..dcd5331435 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 @@ -27,18 +27,16 @@ import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; /** - * A class to represent the IMAGE_NT_HEADERS32 and - * IMAGE_NT_HEADERS64 structs as defined in - * winnt.h. - *

+ * A class to represent the {@code IMAGE_NT_HEADERS32} and {@code IMAGE_NT_HEADERS64} structs as 
+ * defined in {@code winnt.h}
+ * 
+ * 
{@code
  * typedef struct _IMAGE_NT_HEADERS {
  *    DWORD Signature;
  *    IMAGE_FILE_HEADER FileHeader;
  *    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
  * };
- * 
- * - * + * }
*/ public class NTHeader implements StructConverter, OffsetValidator { /** @@ -58,13 +56,14 @@ 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 layout The {@link SectionLayout} * @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. + * do not constitute an accurate NT header. */ public NTHeader(BinaryReader reader, int index, SectionLayout layout, boolean parseCliHeaders) throws InvalidNTHeaderException, IOException { @@ -77,8 +76,7 @@ public class NTHeader implements StructConverter, OffsetValidator { } /** - * Returns the name to use when converting into a structure data type. - * @return the name to use when converting into a structure data type + * {@return the name to use when converting into a structure data type} */ public String getName() { return "IMAGE_NT_HEADERS" + (optionalHeader.is64bit() ? "64" : "32"); @@ -89,24 +87,19 @@ public class NTHeader implements StructConverter, OffsetValidator { } /** - * Returns the file header. - * @return the file header + * {@return the file header} */ public FileHeader getFileHeader() { return fileHeader; } /** - * Returns the optional header. - * @return the optional header + * {@return the optional header} */ public OptionalHeader getOptionalHeader() { return optionalHeader; } - /** - * @see ghidra.app.util.bin.StructConverter#toDataType() - */ @Override public DataType toDataType() throws DuplicateNameException, IOException { StructureDataType struct = new StructureDataType(getName(), 0); @@ -121,20 +114,20 @@ public class NTHeader implements StructConverter, OffsetValidator { } /** - * Converts a relative virtual address (RVA) into a pointer. + * {@return the given relative virtual address (RVA) converted into a pointer into the binary + * image, or -1 if not valid} * * @param rva the relative virtual address - * @return the pointer into binary image, 0 if not valid */ public int rvaToPointer(int rva) { return (int) rvaToPointer(Integer.toUnsignedLong(rva)); } /** - * Converts a relative virtual address (RVA) into a pointer. + * {@return the given relative virtual address (RVA) converted into a pointer into the binary + * image, or -1 if not valid} * @param rva the relative virtual address - * @return the pointer into binary image, -1 if not valid */ public long rvaToPointer(long rva) { SectionHeader[] sections = fileHeader.getSectionHeaders(); @@ -212,31 +205,26 @@ public class NTHeader implements StructConverter, OffsetValidator { } /** - * Converts a virtual address (VA) into a pointer. + * {@return the given virtual address (VA) converted into a pointer into the binary + * image, or -1 if not valid} * * @param va the virtual address - * @return the pointer into binary image, 0 if not valid */ public int vaToPointer(int va) { return (int) vaToPointer(Integer.toUnsignedLong(va)); } /** - * Converts a virtual address (VA) into a pointer. + * {@return the given virtual address (VA) converted into a pointer into the binary + * image, or -1 if not valid} * * @param va the virtual address - * @return the pointer into binary image, 0 if not valid */ public long vaToPointer(long va) { return rvaToPointer(va - getOptionalHeader().getImageBase()); } private void parse() throws InvalidNTHeaderException, IOException { - - if (index < 0 || index > reader.length()) { - return; - } - int tmpIndex = index; try { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java index 45a6e88ccb..68f56b238b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java @@ -23,6 +23,9 @@ import ghidra.app.util.MemoryBlockUtils; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.format.mz.*; +import ghidra.app.util.bin.format.ne.NewExecutable; +import ghidra.app.util.bin.format.pe.PortableExecutable; +import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout; import ghidra.app.util.importer.MessageLog; import ghidra.program.database.mem.FileBytes; import ghidra.program.database.module.TreeManager; @@ -65,7 +68,7 @@ public class MzLoader extends AbstractLibrarySupportLoader { } MzExecutable mz = new MzExecutable(provider); OldDOSHeader header = mz.getHeader(); - if (header.isDosSignature() && !header.hasNewExeHeader() && !header.hasPeHeader()) { + if (header.isDosSignature() && !isPeOrNe(provider)) { List results = QueryOpinionService.query(getName(), "" + header.e_magic(), null); for (QueryResult result : results) { @@ -127,6 +130,28 @@ public class MzLoader extends AbstractLibrarySupportLoader { return 60; // we are less priority than PE! Important for ProgramLoader } + /** + * {@return true if the given {@link ByteProvider} contains a PE or NE binary} + * + * @param provider The {@link ByteProvider} to check + */ + private boolean isPeOrNe(ByteProvider provider) { + try { + new PortableExecutable(provider, SectionLayout.FILE, false, false); + return true; + } + catch (IOException e) { + try { + new NewExecutable(provider, null); + return true; + } + catch (IOException e2) { + // fall through + } + } + return false; + } + /** * Stores a relocation's fixup information *